Handle more forms of constant vectors in lGetMask().

Various optimization passes depend on turning a compile-time constant
mask into a bit vector; it turns out that in LLVM3.1, constant vectors
of ints/floats are represented with llvM::ConstantDataVector, but
constant vectors of bools use llvm::ConstantVector (which is what LLVM
3.0 uses for all constant vectors).  Now lGetMask() always does the
llvm::ConstantVector path, to cover this case.

This improves generated C++ code by eliminating things like select
with an all on/off mask, turning movmask calls with constants into
constant values, etc.
This commit is contained in:
Matt Pharr
2012-04-18 11:34:28 -07:00
parent c202e9e106
commit 7c91b01125

87
opt.cpp
View File

@@ -586,6 +586,40 @@ IntrinsicsOpt::IntrinsicsOpt()
} }
/** Given a vector of constant values (int, float, or bool) representing an
execution mask, convert it to a bitvector where the 0th bit corresponds
to the first vector value and so forth.
*/
static int
lConstElementsToMask(const llvm::SmallVector<llvm::Constant *,
ISPC_MAX_NVEC> &elements) {
Assert(elements.size() <= 32);
int mask = 0;
for (unsigned int i = 0; i < elements.size(); ++i) {
llvm::APInt intMaskValue;
// SSE has the "interesting" approach of encoding blending
// masks as <n x float>.
llvm::ConstantFP *cf = llvm::dyn_cast<llvm::ConstantFP>(elements[i]);
if (cf != NULL) {
llvm::APFloat apf = cf->getValueAPF();
intMaskValue = apf.bitcastToAPInt();
}
else {
// Otherwise get it as an int
llvm::ConstantInt *ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
Assert(ci != NULL); // vs return -1 if NULL?
intMaskValue = ci->getValue();
}
// Is the high-bit set? If so, OR in the appropriate bit in
// the result mask
if (intMaskValue.countLeadingOnes() > 0)
mask |= (1 << i);
}
return mask;
}
/** Given an llvm::Value represinting a vector mask, see if the value is a /** Given an llvm::Value represinting a vector mask, see if the value is a
constant. If so, return the integer mask found by taking the high bits constant. If so, return the integer mask found by taking the high bits
of the mask values in turn and concatenating them into a single integer. of the mask values in turn and concatenating them into a single integer.
@@ -600,41 +634,30 @@ lGetMask(llvm::Value *factor) {
Assert(g->target.vectorWidth < 32); Assert(g->target.vectorWidth < 32);
#ifdef LLVM_3_1svn #ifdef LLVM_3_1svn
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(factor); llvm::ConstantDataVector *cdv = llvm::dyn_cast<llvm::ConstantDataVector>(factor);
#else if (cdv != NULL) {
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(factor);
#endif
if (cv) {
int mask = 0;
llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements; llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements;
#ifdef LLVM_3_1svn for (int i = 0; i < (int)cdv->getNumElements(); ++i)
for (int i = 0; i < (int)cv->getNumElements(); ++i) elements.push_back(cdv->getElementAsConstant(i));
elements.push_back(cv->getElementAsConstant(i)); return lConstElementsToMask(elements);
}
#endif
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(factor);
if (cv != NULL) {
llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements;
#ifdef LLVM_3_1svn
for (int i = 0; i < (int)cv->getNumOperands(); ++i) {
llvm::Constant *c =
llvm::dyn_cast<llvm::Constant>(cv->getOperand(i));
if (c == NULL)
return NULL;
elements.push_back(c);
}
#else #else
cv->getVectorElements(elements); cv->getVectorElements(elements);
#endif #endif
return lConstElementsToMask(elements);
for (unsigned int i = 0; i < elements.size(); ++i) {
llvm::APInt intMaskValue;
// SSE has the "interesting" approach of encoding blending
// masks as <n x float>.
llvm::ConstantFP *cf = llvm::dyn_cast<llvm::ConstantFP>(elements[i]);
if (cf) {
llvm::APFloat apf = cf->getValueAPF();
intMaskValue = apf.bitcastToAPInt();
}
else {
// Otherwise get it as an int
llvm::ConstantInt *ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
Assert(ci != NULL); // vs return -1 if NULL?
intMaskValue = ci->getValue();
}
// Is the high-bit set? If so, OR in the appropriate bit in
// the result mask
if (intMaskValue.countLeadingOnes() > 0)
mask |= (1 << i);
}
return mask;
} }
else if (llvm::isa<llvm::ConstantAggregateZero>(factor)) else if (llvm::isa<llvm::ConstantAggregateZero>(factor))
return 0; return 0;
@@ -1149,7 +1172,7 @@ lGetBasePtrAndOffsets(llvm::Value *ptrs, llvm::Value **offsets,
// Indexing into global arrays can lead to this form, with // Indexing into global arrays can lead to this form, with
// ConstantVectors.. // ConstantVectors..
llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements; llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements;
#ifdef LLVM_3_1svn #ifdef LLVM_3_1svn
for (int i = 0; i < (int)cv->getNumOperands(); ++i) { for (int i = 0; i < (int)cv->getNumOperands(); ++i) {
llvm::Constant *c = llvm::Constant *c =
llvm::dyn_cast<llvm::Constant>(cv->getOperand(i)); llvm::dyn_cast<llvm::Constant>(cv->getOperand(i));