[llvm-commits] [dragonegg] r132339 - in /dragonegg/trunk: include/dragonegg/Internals.h src/Convert.cpp

Duncan Sands baldrick at free.fr
Tue May 31 09:06:43 PDT 2011


Author: baldrick
Date: Tue May 31 11:06:43 2011
New Revision: 132339

URL: http://llvm.org/viewvc/llvm-project?rev=132339&view=rev
Log:
In practice VEC_RSHIFT_EXPR always shifts by a multiple of the
element size, in which case it can be turned into a vector shuffle,
resulting in nicer code.

Modified:
    dragonegg/trunk/include/dragonegg/Internals.h
    dragonegg/trunk/src/Convert.cpp

Modified: dragonegg/trunk/include/dragonegg/Internals.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Internals.h?rev=132339&r1=132338&r2=132339&view=diff
==============================================================================
--- dragonegg/trunk/include/dragonegg/Internals.h (original)
+++ dragonegg/trunk/include/dragonegg/Internals.h Tue May 31 11:06:43 2011
@@ -698,7 +698,7 @@
   Value *EmitReg_RotateOp(tree_node *type, tree_node *op0, tree_node *op1,
                           unsigned Opc1, unsigned Opc2);
   Value *EmitReg_ShiftOp(tree_node *op0, tree_node *op1, unsigned Opc);
-  Value *EmitReg_VecShiftOp(tree_node *op0, tree_node *op1, unsigned Opc);
+  Value *EmitReg_VecShiftOp(tree_node *op0, tree_node *op1, bool isLeftShift);
   Value *EmitReg_TruthOp(tree_node *type, tree_node *op0, tree_node *op1,
                          unsigned Opc);
   Value *EmitReg_BIT_AND_EXPR(tree_node *op0, tree_node *op1);

Modified: dragonegg/trunk/src/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=132339&r1=132338&r2=132339&view=diff
==============================================================================
--- dragonegg/trunk/src/Convert.cpp (original)
+++ dragonegg/trunk/src/Convert.cpp Tue May 31 11:06:43 2011
@@ -6796,13 +6796,51 @@
   return Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS);
 }
 
-Value *TreeToLLVM::EmitReg_VecShiftOp(tree op0, tree op1, unsigned Opc) {
+Value *TreeToLLVM::EmitReg_VecShiftOp(tree op0, tree op1, bool isLeftShift) {
   Value *LHS = EmitRegister(op0); // A vector.
   Value *Amt = EmitRegister(op1); // An integer.
-  const Type *VecTy = LHS->getType();
+  const VectorType *VecTy = cast<VectorType>(LHS->getType());
+  unsigned Bits = VecTy->getPrimitiveSizeInBits();
+
+  // If the shift is by a multiple of the element size then emit a shuffle.
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(Amt)) {
+    // The GCC docs are not clear whether the bits shifted in must be zero or if
+    // they can be anything.  Since these expressions are currently only used in
+    // situations which make no assumptions about the shifted in bits, we choose
+    // to consider them to be undefined since this results in better code.
+    unsigned ShiftAmt = CI->getLimitedValue(Bits);
+    if (ShiftAmt >= Bits)
+      // Shifting by more than the width of the vector is documented as giving
+      // an undefined result.
+      return UndefValue::get(VecTy);
+    unsigned EltBits = VecTy->getElementType()->getPrimitiveSizeInBits();
+    if (!(ShiftAmt % EltBits)) {
+      // A shift by an integral number of elements.
+      unsigned EltOffset = ShiftAmt / EltBits; // Shift by this many elements.
+      // Shuffle the elements sideways by the appropriate number of elements.
+      unsigned Length = VecTy->getNumElements();
+      SmallVector<Constant*, 8> Mask;
+      Mask.reserve(Length);
+      const Type *Int32Ty = Type::getInt32Ty(Context);
+      if (isLeftShift) {
+        // shl <4 x i32> %v, 32 ->
+        // shufflevector <4 x i32> %v, <4 x i32> undef, <undef, 0, 1, 2>
+        Mask.append(Length - EltOffset, UndefValue::get(Int32Ty));
+        for (unsigned i = 0; i != EltOffset; ++i)
+          Mask.push_back(ConstantInt::get(Int32Ty, i));
+      } else {
+        // shr <4 x i32> %v, 32 ->
+        // shufflevector <4 x i32> %v, <4 x i32> undef, <1, 2, 3, undef>
+        for (unsigned i = EltOffset; i != Length; ++i)
+          Mask.push_back(ConstantInt::get(Int32Ty, i));
+        Mask.append(EltOffset, UndefValue::get(Int32Ty));
+      }
+      return Builder.CreateShuffleVector(LHS, UndefValue::get(VecTy),
+                                         ConstantVector::get(Mask));
+    }
+  }
 
   // Turn the vector into a mighty integer of the same size.
-  unsigned Bits = VecTy->getPrimitiveSizeInBits();
   LHS = Builder.CreateBitCast(LHS, IntegerType::get(Context, Bits));
 
   // Ensure the shift amount has the same type.
@@ -6811,7 +6849,8 @@
                                 Amt->getName()+".cast");
 
   // Perform the shift.
-  LHS = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, Amt);
+  LHS = Builder.CreateBinOp(isLeftShift ? Instruction::Shl : Instruction::LShr,
+                            LHS, Amt);
 
   // Turn the result back into a vector.
   return Builder.CreateBitCast(LHS, VecTy);
@@ -8339,12 +8378,11 @@
   case VEC_INTERLEAVE_LOW_EXPR:
     RHS = EmitReg_VEC_INTERLEAVE_LOW_EXPR(rhs1, rhs2); break;
   case VEC_LSHIFT_EXPR:
-    RHS = EmitReg_VecShiftOp(rhs1, rhs2, Instruction::Shl); break;
+    RHS = EmitReg_VecShiftOp(rhs1, rhs2, /*isLeftShift*/true); break;
   case VEC_PACK_TRUNC_EXPR:
     RHS = EmitReg_VEC_PACK_TRUNC_EXPR(type, rhs1, rhs2); break;
   case VEC_RSHIFT_EXPR:
-    RHS = EmitReg_VecShiftOp(rhs1, rhs2, Instruction::LShr);
-    break;
+    RHS = EmitReg_VecShiftOp(rhs1, rhs2, /*isLeftShift*/false); break;
   case VEC_UNPACK_HI_EXPR:
     RHS = EmitReg_VEC_UNPACK_HI_EXPR(type, rhs1); break;
   case VEC_UNPACK_LO_EXPR:





More information about the llvm-commits mailing list