changes in function LLVMFlattenInsertChain

This commit is contained in:
Ilia Filippov
2013-06-14 15:21:45 +04:00
parent 560acd5017
commit d92f9df17c
3 changed files with 95 additions and 78 deletions

View File

@@ -600,9 +600,10 @@ lGetIntValue(llvm::Value *offset) {
} }
void llvm::Value *
LLVMFlattenInsertChain(llvm::Value *inst, int vectorWidth, LLVMFlattenInsertChain(llvm::Value *inst, int vectorWidth,
llvm::Value **elements) { bool compare, bool undef) {
llvm::Value ** elements = new llvm::Value*[vectorWidth];
for (int i = 0; i < vectorWidth; ++i) { for (int i = 0; i < vectorWidth; ++i) {
elements[i] = NULL; elements[i] = NULL;
} }
@@ -610,43 +611,90 @@ LLVMFlattenInsertChain(llvm::Value *inst, int vectorWidth,
// Catch a pattern of InsertElement chain. // Catch a pattern of InsertElement chain.
if (llvm::InsertElementInst *ie = if (llvm::InsertElementInst *ie =
llvm::dyn_cast<llvm::InsertElementInst>(inst)) { llvm::dyn_cast<llvm::InsertElementInst>(inst)) {
//Gather elements of vector
while (ie != NULL) { while (ie != NULL) {
int64_t iOffset = lGetIntValue(ie->getOperand(2)); int64_t iOffset = lGetIntValue(ie->getOperand(2));
Assert(iOffset >= 0 && iOffset < vectorWidth); Assert(iOffset >= 0 && iOffset < vectorWidth);
Assert(elements[iOffset] == NULL);
// Get the scalar value from this insert // Get the scalar value from this insert
elements[iOffset] = ie->getOperand(1); if (elements[iOffset] == NULL) {
elements[iOffset] = ie->getOperand(1);
}
// Do we have another insert? // Do we have another insert?
llvm::Value *insertBase = ie->getOperand(0); llvm::Value *insertBase = ie->getOperand(0);
ie = llvm::dyn_cast<llvm::InsertElementInst>(insertBase); ie = llvm::dyn_cast<llvm::InsertElementInst>(insertBase);
if (ie == NULL) { if (ie != NULL) {
if (llvm::isa<llvm::UndefValue>(insertBase)) { continue;
return; }
if (llvm::isa<llvm::UndefValue>(insertBase)) {
break;
}
if (llvm::isa<llvm::ConstantVector>(insertBase) ||
llvm::isa<llvm::ConstantAggregateZero>(insertBase)) {
llvm::Constant *cv = llvm::dyn_cast<llvm::Constant>(insertBase);
Assert(vectorWidth == (int)(cv->getNumOperands()));
for (int i=0; i<vectorWidth; i++) {
if (elements[i] == NULL) {
elements[i] = cv->getOperand(i);
}
} }
break;
}
else {
// Here chain ends in llvm::LoadInst or some other.
// They are not equal to each other so we should return NULL if compare
// and first element if we have it.
Assert(compare == true || elements[0] != NULL);
if (compare)
return NULL;
else
return elements[0];
}
// TODO: Also, should we handle some other values like
// ConstantDataVectors.
}
if (compare == false)
//We simply want first element
return elements[0];
// Get the value out of a constant vector if that's what we int null_number = 0;
// have int NonNull = 0;
llvm::ConstantVector *cv = for(int i = 0; i < vectorWidth; i++) {
llvm::dyn_cast<llvm::ConstantVector>(insertBase); if (elements[i] == NULL) {
null_number++;
// FIXME: this assert is a little questionable; we probably }
// shouldn't fail in this case but should just return an else {
// incomplete result. But there aren't currently any known NonNull = i;
// cases where we have anything other than an undef value or a
// constant vector at the base, so if that ever does happen,
// it'd be nice to know what happend so that perhaps we can
// handle it.
// FIXME: Also, should we handle ConstantDataVectors with
// LLVM3.1? What about ConstantAggregateZero values??
Assert(cv != NULL);
Assert(iOffset < (int)cv->getNumOperands());
elements[iOffset] = cv->getOperand((int32_t)iOffset);
} }
} }
if (null_number == vectorWidth) {
//All of elements are NULLs
return NULL;
}
if ((undef == false) && (null_number != 0)) {
//We don't want NULLs in chain, but we have them
return NULL;
}
// Compare elements of vector
for (int i = 0; i < vectorWidth; i++) {
if (elements[i] == NULL) {
continue;
}
std::vector<llvm::PHINode *> seenPhi0;
std::vector<llvm::PHINode *> seenPhi1;
if (lValuesAreEqual(elements[NonNull], elements[i],
seenPhi0, seenPhi1) == false) {
return NULL;
}
}
return elements[NonNull];
} }
// Catch a pattern of broadcast implemented as InsertElement + Shuffle: // Catch a pattern of broadcast implemented as InsertElement + Shuffle:
// %broadcast_init.0 = insertelement <4 x i32> undef, i32 %val, i32 0 // %broadcast_init.0 = insertelement <4 x i32> undef, i32 %val, i32 0
// %broadcast.1 = shufflevector <4 x i32> %smear.0, <4 x i32> undef, // %broadcast.1 = shufflevector <4 x i32> %smear.0, <4 x i32> undef,
@@ -663,14 +711,12 @@ LLVMFlattenInsertChain(llvm::Value *inst, int vectorWidth,
llvm::dyn_cast<llvm::ConstantInt>(ie->getOperand(2)); llvm::dyn_cast<llvm::ConstantInt>(ie->getOperand(2));
if (ci->isZero()) { if (ci->isZero()) {
for (int i = 0; i < vectorWidth; ++i) { return ie->getOperand(1);
elements[i] = ie->getOperand(1);
}
return;
} }
} }
} }
} }
return NULL;
} }
@@ -726,12 +772,10 @@ lIsExactMultiple(llvm::Value *val, int baseValue, int vectorLength,
if (llvm::isa<llvm::InsertElementInst>(val) || if (llvm::isa<llvm::InsertElementInst>(val) ||
llvm::isa<llvm::ShuffleVectorInst>(val)) { llvm::isa<llvm::ShuffleVectorInst>(val)) {
llvm::Value *elts[ISPC_MAX_NVEC]; llvm::Value *element = LLVMFlattenInsertChain(val, g->target->getVectorWidth());
LLVMFlattenInsertChain(val, g->target->getVectorWidth(), elts);
// We just need to check the scalar first value, since we know that // We just need to check the scalar first value, since we know that
// all elements are equal // all elements are equal
return lIsExactMultiple(elts[0], baseValue, vectorLength, return lIsExactMultiple(element, baseValue, vectorLength, seenPhis);
seenPhis);
} }
llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(val); llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(val);
@@ -995,32 +1039,7 @@ lVectorValuesAllEqual(llvm::Value *v, int vectorLength,
llvm::InsertElementInst *ie = llvm::dyn_cast<llvm::InsertElementInst>(v); llvm::InsertElementInst *ie = llvm::dyn_cast<llvm::InsertElementInst>(v);
if (ie != NULL) { if (ie != NULL) {
llvm::Value *elements[ISPC_MAX_NVEC]; return (LLVMFlattenInsertChain(ie, vectorLength) != NULL);
LLVMFlattenInsertChain(ie, vectorLength, elements);
// We will ignore any values of elements[] that are NULL; as they
// correspond to undefined values--we just want to see if all of
// the defined values have the same value.
int lastNonNull = 0;
while (lastNonNull < vectorLength && elements[lastNonNull] == NULL)
++lastNonNull;
if (lastNonNull == vectorLength)
// all of them are undef!
return true;
for (int i = lastNonNull; i < vectorLength; ++i) {
if (elements[i] == NULL)
continue;
std::vector<llvm::PHINode *> seenPhi0;
std::vector<llvm::PHINode *> seenPhi1;
if (lValuesAreEqual(elements[lastNonNull], elements[i], seenPhi0,
seenPhi1) == false)
return false;
lastNonNull = i;
}
return true;
} }
llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(v); llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(v);
@@ -1472,9 +1491,7 @@ lExtractFirstVectorElement(llvm::Value *v,
// flatten them out and grab the value for the first one. // flatten them out and grab the value for the first one.
if (llvm::isa<llvm::InsertElementInst>(v) || if (llvm::isa<llvm::InsertElementInst>(v) ||
llvm::isa<llvm::ShuffleVectorInst>(v)) { llvm::isa<llvm::ShuffleVectorInst>(v)) {
llvm::Value *elements[ISPC_MAX_NVEC]; return LLVMFlattenInsertChain(v, vt->getNumElements(), false);
LLVMFlattenInsertChain(v, vt->getNumElements(), elements);
return elements[0];
} }
// Worst case, for everything else, just do a regular extract element // Worst case, for everything else, just do a regular extract element

View File

@@ -269,9 +269,14 @@ extern bool LLVMExtractVectorInts(llvm::Value *v, int64_t ret[], int *nElts);
%broadcast_init.0 = insertelement <4 x i32> undef, i32 %val, i32 0 %broadcast_init.0 = insertelement <4 x i32> undef, i32 %val, i32 0
%broadcast.1 = shufflevector <4 x i32> %smear.0, <4 x i32> undef, %broadcast.1 = shufflevector <4 x i32> %smear.0, <4 x i32> undef,
<4 x i32> zeroinitializer <4 x i32> zeroinitializer
Function returns:
First element of array if compare is false,
NonNull element only if all elements are equal or NULL if compare is true,
NonNull element only if all elements are equal if compare is true and undef is false,
NULL if all elements are NULLs
*/ */
extern void LLVMFlattenInsertChain(llvm::Value *inst, int vectorWidth, extern llvm::Value * LLVMFlattenInsertChain (llvm::Value *inst, int vectorWidth,
llvm::Value **elements); bool compare = true, bool undef = true);
/** This is a utility routine for debugging that dumps out the given LLVM /** This is a utility routine for debugging that dumps out the given LLVM
value as well as (recursively) all of the other values that it depends value as well as (recursively) all of the other values that it depends

23
opt.cpp
View File

@@ -1060,23 +1060,18 @@ static llvm::Value *
lGetBasePointer(llvm::Value *v) { lGetBasePointer(llvm::Value *v) {
if (llvm::isa<llvm::InsertElementInst>(v) || if (llvm::isa<llvm::InsertElementInst>(v) ||
llvm::isa<llvm::ShuffleVectorInst>(v)) { llvm::isa<llvm::ShuffleVectorInst>(v)) {
llvm::Value *elements[ISPC_MAX_NVEC]; llvm::Value *element = LLVMFlattenInsertChain
LLVMFlattenInsertChain(v, g->target->getVectorWidth(), elements); (v, g->target->getVectorWidth(), true, false);
// Make sure none of the elements is undefined.
// TODO: it's probably ok to allow undefined elements and return // TODO: it's probably ok to allow undefined elements and return
// the base pointer if all of the other elements have the same // the base pointer if all of the other elements have the same
// value. // value.
for (int i = 0; i < g->target->getVectorWidth(); ++i) if (element != NULL) {
if (elements[i] == NULL) //all elements are the same and not NULLs
return NULL; return lCheckForActualPointer(element);
}
// Do all of the elements have the same value? else {
for (int i = 0; i < g->target->getVectorWidth()-1; ++i) return NULL;
if (elements[i] != elements[i+1]) }
return NULL;
return lCheckForActualPointer(elements[0]);
} }
// This case comes up with global/static arrays // This case comes up with global/static arrays