Vector codegen improvements
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62458 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 6877b31..6e140da 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -631,6 +631,8 @@
case X86::BI__builtin_ia32_vec_ext_v2di:
case X86::BI__builtin_ia32_vec_ext_v4sf:
case X86::BI__builtin_ia32_vec_ext_v4si:
+ case X86::BI__builtin_ia32_vec_ext_v8hi:
+ case X86::BI__builtin_ia32_vec_ext_v4hi:
case X86::BI__builtin_ia32_vec_ext_v2df:
return Builder.CreateExtractElement(Ops[0], Ops[1], "result");
case X86::BI__builtin_ia32_cmpordss:
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 2d51efa..5c304d1 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -309,8 +309,8 @@
return EmitObjCPropertyGet(LV.getKVCRefExpr());
}
-// If this is a reference to a subset of the elements of a vector, either
-// shuffle the input or extract/insert them as appropriate.
+// If this is a reference to a subset of the elements of a vector, create an
+// appropriate shufflevector.
RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
QualType ExprType) {
llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(),
@@ -326,41 +326,21 @@
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp"));
}
-
- // If the source and destination have the same number of elements, use a
- // vector shuffle instead of insert/extracts.
+
+ // Always use shuffle vector to try to retain the original program structure
unsigned NumResultElts = ExprVT->getNumElements();
- unsigned NumSourceElts =
- cast<llvm::VectorType>(Vec->getType())->getNumElements();
- if (NumResultElts == NumSourceElts) {
- llvm::SmallVector<llvm::Constant*, 4> Mask;
- for (unsigned i = 0; i != NumResultElts; ++i) {
- unsigned InIdx = getAccessedFieldNo(i, Elts);
- Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
- }
-
- llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
- Vec = Builder.CreateShuffleVector(Vec,
- llvm::UndefValue::get(Vec->getType()),
- MaskV, "tmp");
- return RValue::get(Vec);
- }
-
- // Start out with an undef of the result type.
- llvm::Value *Result = llvm::UndefValue::get(ConvertType(ExprType));
-
- // Extract/Insert each element of the result.
+ llvm::SmallVector<llvm::Constant*, 4> Mask;
for (unsigned i = 0; i != NumResultElts; ++i) {
unsigned InIdx = getAccessedFieldNo(i, Elts);
- llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
- Elt = Builder.CreateExtractElement(Vec, Elt, "tmp");
-
- llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
- Result = Builder.CreateInsertElement(Result, Elt, OutIdx, "tmp");
+ Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
}
- return RValue::get(Result);
+ llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
+ Vec = Builder.CreateShuffleVector(Vec,
+ llvm::UndefValue::get(Vec->getType()),
+ MaskV, "tmp");
+ return RValue::get(Vec);
}
@@ -548,15 +528,54 @@
if (const VectorType *VTy = Ty->getAsVectorType()) {
unsigned NumSrcElts = VTy->getNumElements();
-
- // Extract/Insert each element.
- for (unsigned i = 0; i != NumSrcElts; ++i) {
- llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
- Elt = Builder.CreateExtractElement(SrcVal, Elt, "tmp");
-
- unsigned Idx = getAccessedFieldNo(i, Elts);
- llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Idx);
- Vec = Builder.CreateInsertElement(Vec, Elt, OutIdx, "tmp");
+ unsigned NumDstElts =
+ cast<llvm::VectorType>(Vec->getType())->getNumElements();
+ if (NumDstElts == NumSrcElts) {
+ // Use shuffle vector is the src and destination are the same number
+ // of elements
+ llvm::SmallVector<llvm::Constant*, 4> Mask;
+ for (unsigned i = 0; i != NumSrcElts; ++i) {
+ unsigned InIdx = getAccessedFieldNo(i, Elts);
+ Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
+ }
+
+ llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
+ Vec = Builder.CreateShuffleVector(SrcVal,
+ llvm::UndefValue::get(Vec->getType()),
+ MaskV, "tmp");
+ }
+ else if (NumDstElts > NumSrcElts) {
+ // Extended the source vector to the same length and then shuffle it
+ // into the destination.
+ // FIXME: since we're shuffling with undef, can we just use the indices
+ // into that? This could be simpler.
+ llvm::SmallVector<llvm::Constant*, 4> ExtMask;
+ unsigned i;
+ for (i = 0; i != NumSrcElts; ++i)
+ ExtMask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i));
+ for (; i != NumDstElts; ++i)
+ ExtMask.push_back(llvm::UndefValue::get(llvm::Type::Int32Ty));
+ llvm::Value *ExtMaskV = llvm::ConstantVector::get(&ExtMask[0],
+ ExtMask.size());
+ llvm::Value *ExtSrcVal = Builder.CreateShuffleVector(SrcVal,
+ llvm::UndefValue::get(SrcVal->getType()),
+ ExtMaskV, "tmp");
+ // build identity
+ llvm::SmallVector<llvm::Constant*, 4> Mask;
+ for (unsigned i = 0; i != NumDstElts; ++i) {
+ Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i));
+ }
+ // modify when what gets shuffled in
+ for (unsigned i = 0; i != NumSrcElts; ++i) {
+ unsigned Idx = getAccessedFieldNo(i, Elts);
+ Mask[Idx] =llvm::ConstantInt::get(llvm::Type::Int32Ty, i+NumDstElts);
+ }
+ llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
+ Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV, "tmp");
+ }
+ else {
+ // We should never shorten the vector
+ assert(0 && "unexpected shorten vector length");
}
} else {
// If the Src is a scalar (not a vector) it must be updating one element.
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index d6cc16c..e6eb9c0b 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -409,10 +409,26 @@
}
// A scalar can be splatted to an extended vector of the same element type
- if (DstType->isExtVectorType() && !isa<VectorType>(SrcType) &&
- cast<llvm::VectorType>(DstTy)->getElementType() == Src->getType())
- return CGF.EmitVector(&Src, DstType->getAsVectorType()->getNumElements(),
- true);
+ if (DstType->isExtVectorType() && !isa<VectorType>(SrcType)) {
+ // Cast the scalar to element type
+ QualType EltTy = DstType->getAsExtVectorType()->getElementType();
+ llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy);
+
+ // Insert the element in element zero of an undef vector
+ llvm::Value *UnV = llvm::UndefValue::get(DstTy);
+ llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+ UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp");
+
+ // Splat the element across to all elements
+ llvm::SmallVector<llvm::Constant*, 16> Args;
+ unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
+ for (unsigned i = 0; i < NumElements; i++)
+ Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
+
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements);
+ llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
+ return Yay;
+ }
// Allow bitcast from vector to integer/fp of the same size.
if (isa<llvm::VectorType>(Src->getType()) ||