summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-12-11 07:49:37 +0000
committerChris Lattner <sabre@nondot.org>2007-12-11 07:49:37 +0000
commit8e6a8f984cfd23049acdaea900c5f473f5bf7fc4 (patch)
tree7e7d6f0b006597bc2835686f6332ef9c3fd2ce30 /llvm/lib
parent6a6b3fb62b4f1f0a1d6153da4a5453746e3b3034 (diff)
downloadbcm5719-llvm-8e6a8f984cfd23049acdaea900c5f473f5bf7fc4.tar.gz
bcm5719-llvm-8e6a8f984cfd23049acdaea900c5f473f5bf7fc4.zip
Teach VMCore to constant fold shufflevectors with constant operands.
This allows us to compile: #include <emmintrin.h> typedef __m128i VSInt16; typedef short vSInt16 __attribute__ ((__vector_size__ (16))); VSInt16 t3() { return (VSInt16)((vSInt16)_mm_set1_epi16(6518)); } into: _t3: movaps LCPI1_0, %xmm0 ret instead of: _t3: movl $6518, %eax movd %eax, %xmm0 pextrw $0, %xmm0, %eax xorps %xmm0, %xmm0 pinsrw $0, %eax, %xmm0 punpcklwd %xmm0, %xmm0 pshufd $0, %xmm0, %xmm0 ret llvm-svn: 44856
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/VMCore/ConstantFold.cpp47
1 files changed, 45 insertions, 2 deletions
diff --git a/llvm/lib/VMCore/ConstantFold.cpp b/llvm/lib/VMCore/ConstantFold.cpp
index 6660c8d3e2f..a99ae9ded8a 100644
--- a/llvm/lib/VMCore/ConstantFold.cpp
+++ b/llvm/lib/VMCore/ConstantFold.cpp
@@ -396,11 +396,54 @@ Constant *llvm::ConstantFoldInsertElementInstruction(const Constant *Val,
return 0;
}
+/// GetVectorElement - If C is a ConstantVector, ConstantAggregateZero or Undef
+/// return the specified element value. Otherwise return null.
+static Constant *GetVectorElement(const Constant *C, unsigned EltNo) {
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(C))
+ return const_cast<Constant*>(CV->getOperand(EltNo));
+
+ const Type *EltTy = cast<VectorType>(C->getType())->getElementType();
+ if (isa<ConstantAggregateZero>(C))
+ return Constant::getNullValue(EltTy);
+ if (isa<UndefValue>(C))
+ return UndefValue::get(EltTy);
+ return 0;
+}
+
Constant *llvm::ConstantFoldShuffleVectorInstruction(const Constant *V1,
const Constant *V2,
const Constant *Mask) {
- // TODO:
- return 0;
+ // Undefined shuffle mask -> undefined value.
+ if (isa<UndefValue>(Mask)) return UndefValue::get(V1->getType());
+
+ unsigned NumElts = cast<VectorType>(V1->getType())->getNumElements();
+ const Type *EltTy = cast<VectorType>(V1->getType())->getElementType();
+
+ // Loop over the shuffle mask, evaluating each element.
+ SmallVector<Constant*, 32> Result;
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *InElt = GetVectorElement(Mask, i);
+ if (InElt == 0) return 0;
+
+ if (isa<UndefValue>(InElt))
+ InElt = UndefValue::get(EltTy);
+ else if (ConstantInt *CI = dyn_cast<ConstantInt>(InElt)) {
+ unsigned Elt = CI->getZExtValue();
+ if (Elt >= NumElts*2)
+ InElt = UndefValue::get(EltTy);
+ else if (Elt >= NumElts)
+ InElt = GetVectorElement(V2, Elt-NumElts);
+ else
+ InElt = GetVectorElement(V1, Elt);
+ if (InElt == 0) return 0;
+ } else {
+ // Unknown value.
+ return 0;
+ }
+ Result.push_back(InElt);
+ }
+
+ return ConstantVector::get(&Result[0], Result.size());
}
/// EvalVectorOp - Given two vector constants and a function pointer, apply the
OpenPOWER on IntegriCloud