Add LLVMExtractVectorInts() function, use it in the opt code.

This commit is contained in:
Matt Pharr
2012-03-19 11:46:32 -07:00
parent 17c6a19527
commit 0664f5a724
3 changed files with 96 additions and 82 deletions

View File

@@ -589,18 +589,6 @@ lGetIntValue(llvm::Value *offset) {
}
/** This function takes chains of InsertElement instructions along the
lines of:
%v0 = insertelement undef, value_0, i32 index_0
%v1 = insertelement %v1, value_1, i32 index_1
...
%vn = insertelement %vn-1, value_n-1, i32 index_n-1
and initializes the provided elements array such that the i'th
llvm::Value * in the array is the element that was inserted into the
i'th element of the vector.
*/
void
LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
llvm::Value **elements) {
@@ -612,17 +600,32 @@ LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
Assert(iOffset >= 0 && iOffset < vectorWidth);
Assert(elements[iOffset] == NULL);
// Get the scalar value from this insert
elements[iOffset] = ie->getOperand(1);
// Do we have another insert?
llvm::Value *insertBase = ie->getOperand(0);
ie = llvm::dyn_cast<llvm::InsertElementInst>(insertBase);
if (ie == NULL) {
if (llvm::isa<llvm::UndefValue>(insertBase))
return;
// Get the value out of a constant vector if that's what we
// have
llvm::ConstantVector *cv =
llvm::dyn_cast<llvm::ConstantVector>(insertBase);
// FIXME: this assert is a little questionable; we probably
// shouldn't fail in this case but should just return an
// incomplete result. But there aren't currently any known
// 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);
}
@@ -630,6 +633,49 @@ LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
}
bool
LLVMExtractVectorInts(llvm::Value *v, int64_t ret[], int *nElts) {
// Make sure we do in fact have a vector of integer values here
LLVM_TYPE_CONST llvm::VectorType *vt =
llvm::dyn_cast<LLVM_TYPE_CONST llvm::VectorType>(v->getType());
Assert(vt != NULL);
Assert(llvm::isa<llvm::IntegerType>(vt->getElementType()));
*nElts = (int)vt->getNumElements();
if (llvm::isa<llvm::ConstantAggregateZero>(v)) {
for (int i = 0; i < (int)vt->getNumElements(); ++i)
ret[i] = 0;
return true;
}
// Deal with the fact that LLVM3.1 and previous versions have different
// representations for vectors of constant ints...
#ifdef LLVM_3_1svn
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(v);
if (cv == NULL)
return false;
for (int i = 0; i < (int)cv->getNumElements(); ++i)
ret[i] = cv->getElementAsInteger(i);
return true;
#else
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(v);
if (cv == NULL)
return false;
llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements;
cv->getVectorElements(elements);
for (int i = 0; i < (int)vt->getNumElements(); ++i) {
llvm::ConstantInt *ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
Assert(ci != NULL);
ret[i] = ci->getSExtValue();
}
return true;
#endif // LLVM_3_1svn
}
/** Tests to see if all of the elements of the vector in the 'v' parameter
are equal. Like lValuesAreEqual(), this is a conservative test and may
return false for arrays where the values are actually all equal. */

View File

@@ -231,8 +231,33 @@ extern llvm::Constant *LLVMMaskAllOff;
extern bool LLVMVectorValuesAllEqual(llvm::Value *v, int vectorLength,
std::vector<llvm::PHINode *> &seenPhis);
void LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
llvm::Value **elements);
/** Given a vector-typed value v, if the vector is a vector with constant
element values, this function extracts those element values into the
ret[] array and returns the number of elements (i.e. the vector type's
width) in *nElts. It returns true if successful and false if the given
vector is not in fact a vector of constants. */
extern bool LLVMExtractVectorInts(llvm::Value *v, int64_t ret[], int *nElts);
/** This function takes chains of InsertElement instructions along the
lines of:
%v0 = insertelement undef, value_0, i32 index_0
%v1 = insertelement %v1, value_1, i32 index_1
...
%vn = insertelement %vn-1, value_n-1, i32 index_n-1
and initializes the provided elements array such that the i'th
llvm::Value * in the array is the element that was inserted into the
i'th element of the vector.
When the chain of insertelement instruction comes to an end, the only
base case that this function handles is the initial value being a
constant vector. For anything more complex (e.g. some other arbitrary
value, it doesn't try to extract element values into the returned
array.
*/
extern void LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
llvm::Value **elements);
/** 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

79
opt.cpp
View File

@@ -1647,51 +1647,11 @@ lExtractUniformsFromOffset(llvm::Value **basePtr, llvm::Value **offsetVector,
#endif
static bool
lExtractVectorInts(llvm::Value *v, int64_t ret[], int *nElts) {
LLVM_TYPE_CONST llvm::VectorType *vt =
llvm::dyn_cast<LLVM_TYPE_CONST llvm::VectorType>(v->getType());
Assert(vt != NULL);
Assert(llvm::isa<llvm::IntegerType>(vt->getElementType()));
*nElts = (int)vt->getNumElements();
if (llvm::isa<llvm::ConstantAggregateZero>(v)) {
for (int i = 0; i < (int)vt->getNumElements(); ++i)
ret[i] = 0;
return true;
}
#ifdef LLVM_3_1svn
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(v);
if (cv == NULL)
return false;
for (int i = 0; i < (int)cv->getNumElements(); ++i)
ret[i] = cv->getElementAsInteger(i);
return true;
#else
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(v);
if (cv == NULL)
return false;
llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements;
cv->getVectorElements(elements);
for (int i = 0; i < (int)vt->getNumElements(); ++i) {
llvm::ConstantInt *ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
Assert(ci != NULL);
ret[i] = ci->getSExtValue();
}
return true;
#endif // LLVM_3_1svn
}
static bool
lVectorIs32BitInts(llvm::Value *v) {
int nElts;
int64_t elts[ISPC_MAX_NVEC];
if (!lExtractVectorInts(v, elts, &nElts))
if (!LLVMExtractVectorInts(v, elts, &nElts))
return false;
for (int i = 0; i < nElts; ++i)
@@ -3546,36 +3506,19 @@ lComputeBasePtr(llvm::CallInst *gatherInst, llvm::Instruction *insertBefore) {
static void
lExtractConstOffsets(const std::vector<llvm::CallInst *> &coalesceGroup,
int elementSize, std::vector<int64_t> *constOffsets) {
constOffsets->reserve(coalesceGroup.size() * g->target.vectorWidth);
int width = g->target.vectorWidth;
*constOffsets = std::vector<int64_t>(coalesceGroup.size() * width, 0);
for (int i = 0; i < (int)coalesceGroup.size(); ++i) {
int64_t *endPtr = &((*constOffsets)[0]);
for (int i = 0; i < (int)coalesceGroup.size(); ++i, endPtr += width) {
llvm::Value *offsets = coalesceGroup[i]->getArgOperand(3);
#ifdef LLVM_3_1svn
llvm::ConstantDataVector *cv =
llvm::dyn_cast<llvm::ConstantDataVector>(offsets);
Assert(cv != NULL);
for (int j = 0; j < g->target.vectorWidth; ++j) {
Assert((cv->getElementAsInteger(j) % elementSize) == 0);
constOffsets->push_back((int64_t)cv->getElementAsInteger(j) /
elementSize);
}
#else
llvm::ConstantVector *cv =
llvm::dyn_cast<llvm::ConstantVector>(offsets);
Assert(cv != NULL);
for (int j = 0; j < g->target.vectorWidth; ++j) {
llvm::ConstantInt *ci =
llvm::dyn_cast<llvm::ConstantInt>(cv->getOperand(j));
Assert(ci != NULL);
int64_t value = ci->getValue().getSExtValue();
Assert((value % elementSize) == 0);
constOffsets->push_back(value / elementSize);
}
#endif
int nElts;
bool ok = LLVMExtractVectorInts(offsets, endPtr, &nElts);
Assert(ok && nElts == width);
}
for (int i = 0; i < (int)constOffsets->size(); ++i)
(*constOffsets)[i] /= elementSize;
}