From 7c91b01125bf99b9a908a89d33c653f82a2af39b Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Wed, 18 Apr 2012 11:34:28 -0700 Subject: [PATCH] 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. --- opt.cpp | 87 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/opt.cpp b/opt.cpp index f83b961e..a5158375 100644 --- a/opt.cpp +++ b/opt.cpp @@ -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 &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 . + llvm::ConstantFP *cf = llvm::dyn_cast(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(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 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. @@ -600,41 +634,30 @@ lGetMask(llvm::Value *factor) { Assert(g->target.vectorWidth < 32); #ifdef LLVM_3_1svn - llvm::ConstantDataVector *cv = llvm::dyn_cast(factor); -#else - llvm::ConstantVector *cv = llvm::dyn_cast(factor); -#endif - if (cv) { - int mask = 0; + llvm::ConstantDataVector *cdv = llvm::dyn_cast(factor); + if (cdv != NULL) { llvm::SmallVector elements; -#ifdef LLVM_3_1svn - for (int i = 0; i < (int)cv->getNumElements(); ++i) - elements.push_back(cv->getElementAsConstant(i)); + for (int i = 0; i < (int)cdv->getNumElements(); ++i) + elements.push_back(cdv->getElementAsConstant(i)); + return lConstElementsToMask(elements); + } +#endif + + llvm::ConstantVector *cv = llvm::dyn_cast(factor); + if (cv != NULL) { + llvm::SmallVector elements; + #ifdef LLVM_3_1svn + for (int i = 0; i < (int)cv->getNumOperands(); ++i) { + llvm::Constant *c = + llvm::dyn_cast(cv->getOperand(i)); + if (c == NULL) + return NULL; + elements.push_back(c); + } #else cv->getVectorElements(elements); #endif - - for (unsigned int i = 0; i < elements.size(); ++i) { - llvm::APInt intMaskValue; - // SSE has the "interesting" approach of encoding blending - // masks as . - llvm::ConstantFP *cf = llvm::dyn_cast(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(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; + return lConstElementsToMask(elements); } else if (llvm::isa(factor)) return 0; @@ -1149,7 +1172,7 @@ lGetBasePtrAndOffsets(llvm::Value *ptrs, llvm::Value **offsets, // Indexing into global arrays can lead to this form, with // ConstantVectors.. llvm::SmallVector elements; -#ifdef LLVM_3_1svn + #ifdef LLVM_3_1svn for (int i = 0; i < (int)cv->getNumOperands(); ++i) { llvm::Constant *c = llvm::dyn_cast(cv->getOperand(i));