[llvm-commits] [dragonegg] r159542 - /dragonegg/trunk/src/Convert.cpp
Duncan Sands
baldrick at free.fr
Mon Jul 2 11:10:45 PDT 2012
Author: baldrick
Date: Mon Jul 2 13:10:45 2012
New Revision: 159542
URL: http://llvm.org/viewvc/llvm-project?rev=159542&view=rev
Log:
Handle all cases of VEC_PERM_EXPR, not just those that correspond directly to LLVM's
shufflevector (the issue here is that the mask may not be constant).
Modified:
dragonegg/trunk/src/Convert.cpp
Modified: dragonegg/trunk/src/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=159542&r1=159541&r2=159542&view=diff
==============================================================================
--- dragonegg/trunk/src/Convert.cpp (original)
+++ dragonegg/trunk/src/Convert.cpp Mon Jul 2 13:10:45 2012
@@ -7640,19 +7640,55 @@
// The shuffle mask.
Value *Mask = EmitRegister(op2);
- assert(isa<Constant>(Mask) && "Only constant permutation masks supported!");
-
- // Convert to a vector of i32, as required by the shufflevector instruction.
- Type *MaskTy = VectorType::get(Builder.getInt32Ty(), Length);
- tree mask_elt_type = TREE_TYPE(TREE_TYPE(op2));
- Mask = Builder.CreateIntCast(Mask, MaskTy, !TYPE_UNSIGNED(mask_elt_type));
// The GCC semantics are that mask indices off the end are wrapped back into
// range, so reduce the mask modulo 2*Length.
assert(!(Length & (Length - 1)) && "Vector length not a power of two!");
Mask = Builder.CreateAnd(Mask, ConstantInt::get(Mask->getType(), 2*Length-1));
- return Builder.CreateShuffleVector(V0, V1, Mask);
+ // Convert to a vector of i32, as required by the shufflevector instruction.
+ Type *MaskTy = VectorType::get(Builder.getInt32Ty(), Length);
+ tree mask_elt_type = TREE_TYPE(TREE_TYPE(op2));
+ Value *Mask32 = Builder.CreateIntCast(Mask, MaskTy,
+ !TYPE_UNSIGNED(mask_elt_type));
+
+ // Use a shufflevector instruction if this directly corresponds to one, i.e.
+ // if the mask is a vector of constant integers or undef.
+ if (ShuffleVectorInst::isValidOperands(V0, V1, Mask32))
+ return Builder.CreateShuffleVector(V0, V1, Mask32);
+
+ // Store the vectors to successive memory locations in a temporary.
+ tree elt_type = TREE_TYPE(TREE_TYPE(op0));
+ Type *EltTy = ConvertType(elt_type);
+ unsigned Align = TD.getABITypeAlignment(EltTy);
+ // The temporary is a struct containing the pair of input vectors.
+ Type *TmpTy = StructType::get(ConvertType(TREE_TYPE(op0)),
+ ConvertType(TREE_TYPE(op1)), NULL);
+ AllocaInst *Tmp = CreateTemporary(TmpTy, Align);
+ // Store the first vector to the first element of the pair.
+ Value *Tmp0 = Builder.CreateStructGEP(Tmp, 0);
+ StoreRegisterToMemory(V0, MemRef(Tmp0, Align, /*Volatile*/false),
+ TREE_TYPE(op0), 0, Builder);
+ // Store the second vector to the second element of the pair.
+ Value *Tmp1 = Builder.CreateStructGEP(Tmp, 1);
+ StoreRegisterToMemory(V1, MemRef(Tmp1, Align, /*Volatile*/false),
+ TREE_TYPE(op1), 0, Builder);
+
+ // Load out the components according to the mask.
+ Value *Result = UndefValue::get(V0->getType());
+ Value *BaseAddr = Builder.CreateBitCast(Tmp, EltTy->getPointerTo());
+ for (unsigned i = 0; i != Length; ++i) {
+ // Extract from the mask the index of the element to load.
+ Value *MaskIdx = Builder.getInt32(i);
+ Value *Idx = Builder.CreateExtractElement(Mask, MaskIdx);
+ // Advance that many elements from the start of the temporary and load it.
+ Value *Ptr = Builder.CreateInBoundsGEP(BaseAddr, Idx);
+ Value *Elt = LoadRegisterFromMemory(MemRef(Ptr, Align, false), elt_type, 0,
+ Builder);
+ // Insert it into the result.
+ Result = Builder.CreateInsertElement(Result, Elt, MaskIdx);
+ }
+ return Result;
}
#endif
More information about the llvm-commits
mailing list