Add LLVMExtractVectorInts() function, use it in the opt code.
This commit is contained in:
70
llvmutil.cpp
70
llvmutil.cpp
@@ -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
|
void
|
||||||
LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
|
LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
|
||||||
llvm::Value **elements) {
|
llvm::Value **elements) {
|
||||||
@@ -612,17 +600,32 @@ LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
|
|||||||
Assert(iOffset >= 0 && iOffset < vectorWidth);
|
Assert(iOffset >= 0 && iOffset < vectorWidth);
|
||||||
Assert(elements[iOffset] == NULL);
|
Assert(elements[iOffset] == NULL);
|
||||||
|
|
||||||
|
// Get the scalar value from this insert
|
||||||
elements[iOffset] = ie->getOperand(1);
|
elements[iOffset] = ie->getOperand(1);
|
||||||
|
|
||||||
|
// 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))
|
if (llvm::isa<llvm::UndefValue>(insertBase))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Get the value out of a constant vector if that's what we
|
||||||
|
// have
|
||||||
llvm::ConstantVector *cv =
|
llvm::ConstantVector *cv =
|
||||||
llvm::dyn_cast<llvm::ConstantVector>(insertBase);
|
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(cv != NULL);
|
||||||
|
|
||||||
Assert(iOffset < (int)cv->getNumOperands());
|
Assert(iOffset < (int)cv->getNumOperands());
|
||||||
elements[iOffset] = cv->getOperand((int32_t)iOffset);
|
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
|
/** 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
|
are equal. Like lValuesAreEqual(), this is a conservative test and may
|
||||||
return false for arrays where the values are actually all equal. */
|
return false for arrays where the values are actually all equal. */
|
||||||
|
|||||||
29
llvmutil.h
29
llvmutil.h
@@ -231,8 +231,33 @@ extern llvm::Constant *LLVMMaskAllOff;
|
|||||||
extern bool LLVMVectorValuesAllEqual(llvm::Value *v, int vectorLength,
|
extern bool LLVMVectorValuesAllEqual(llvm::Value *v, int vectorLength,
|
||||||
std::vector<llvm::PHINode *> &seenPhis);
|
std::vector<llvm::PHINode *> &seenPhis);
|
||||||
|
|
||||||
void LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
|
/** Given a vector-typed value v, if the vector is a vector with constant
|
||||||
llvm::Value **elements);
|
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
|
/** 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
|
||||||
|
|||||||
79
opt.cpp
79
opt.cpp
@@ -1647,51 +1647,11 @@ lExtractUniformsFromOffset(llvm::Value **basePtr, llvm::Value **offsetVector,
|
|||||||
#endif
|
#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
|
static bool
|
||||||
lVectorIs32BitInts(llvm::Value *v) {
|
lVectorIs32BitInts(llvm::Value *v) {
|
||||||
int nElts;
|
int nElts;
|
||||||
int64_t elts[ISPC_MAX_NVEC];
|
int64_t elts[ISPC_MAX_NVEC];
|
||||||
if (!lExtractVectorInts(v, elts, &nElts))
|
if (!LLVMExtractVectorInts(v, elts, &nElts))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < nElts; ++i)
|
for (int i = 0; i < nElts; ++i)
|
||||||
@@ -3546,36 +3506,19 @@ lComputeBasePtr(llvm::CallInst *gatherInst, llvm::Instruction *insertBefore) {
|
|||||||
static void
|
static void
|
||||||
lExtractConstOffsets(const std::vector<llvm::CallInst *> &coalesceGroup,
|
lExtractConstOffsets(const std::vector<llvm::CallInst *> &coalesceGroup,
|
||||||
int elementSize, std::vector<int64_t> *constOffsets) {
|
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);
|
llvm::Value *offsets = coalesceGroup[i]->getArgOperand(3);
|
||||||
|
int nElts;
|
||||||
#ifdef LLVM_3_1svn
|
bool ok = LLVMExtractVectorInts(offsets, endPtr, &nElts);
|
||||||
llvm::ConstantDataVector *cv =
|
Assert(ok && nElts == width);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)constOffsets->size(); ++i)
|
||||||
|
(*constOffsets)[i] /= elementSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user