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

Duncan Sands baldrick at free.fr
Sun May 15 13:04:52 PDT 2011


Author: baldrick
Date: Sun May 15 15:04:51 2011
New Revision: 131389

URL: http://llvm.org/viewvc/llvm-project?rev=131389&view=rev
Log:
Implement REDUC_PLUS_EXPR (i.e. form the sum of the elements of a vector).

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=131389&r1=131388&r2=131389&view=diff
==============================================================================
--- dragonegg/trunk/include/dragonegg/Internals.h (original)
+++ dragonegg/trunk/include/dragonegg/Internals.h Sun May 15 15:04:51 2011
@@ -712,6 +712,7 @@
   Value *EmitReg_PLUS_EXPR(tree_node *op0, tree_node *op1);
   Value *EmitReg_POINTER_PLUS_EXPR(tree_node *op0, tree_node *op1);
   Value *EmitReg_RDIV_EXPR(tree_node *op0, tree_node *op1);
+  Value *EmitReg_REDUC_PLUS_EXPR(tree_node *op);
   Value *EmitReg_ROUND_DIV_EXPR(tree_node *op0, tree_node *op1);
   Value *EmitReg_TRUNC_DIV_EXPR(tree_node *op0, tree_node *op1, bool isExact);
   Value *EmitReg_TRUNC_MOD_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=131389&r1=131388&r2=131389&view=diff
==============================================================================
--- dragonegg/trunk/src/Convert.cpp (original)
+++ dragonegg/trunk/src/Convert.cpp Sun May 15 15:04:51 2011
@@ -6537,6 +6537,48 @@
   return Val;
 }
 
+Value *TreeToLLVM::EmitReg_REDUC_PLUS_EXPR(tree op) {
+  // In the bottom half of the vector, form the sum of the bottom and top halves
+  // of the vector.  Rinse and repeat on the just computed bottom half: in the
+  // bottom quarter of the vector, form the sum of the bottom and top halves of
+  // the bottom half.  Continue until only the first element of the vector is
+  // computed.  For example, reduc-plus <x0, x1, x2, x3> becomes
+  //   v = <x0, x1, undef, undef> + <x2, x3, undef, undef>
+  //   w = <v0, undef, undef, undef> + <v1, undef, undef, undef>
+  // where v = <v0, v1, undef, undef>.  The first element of w is x0+x1+x2+x3.
+  Value *Val = EmitRegister(op);
+  const Type *Ty = Val->getType();
+
+  unsigned Length = TYPE_VECTOR_SUBPARTS(TREE_TYPE(op));
+  assert(Length > 1 && !(Length & (Length - 1)) && "Length not a power of 2!");
+  SmallVector<Constant*, 8> Mask(Length);
+  const Type *Int32Ty = Type::getInt32Ty(Context);
+  Constant *UndefIndex = UndefValue::get(Int32Ty);
+  for (unsigned Elts = Length >> 1; Elts; Elts >>= 1) {
+    // In the extracted vectors, elements with index Elts and on are undefined.
+    for (unsigned i = Elts; i != Length; ++i)
+      Mask[i] = UndefIndex;
+    // Extract elements [0, Elts) from Val.
+    for (unsigned i = 0; i != Elts; ++i)
+      Mask[i] = ConstantInt::get(Int32Ty, i);
+    Value *LHS = Builder.CreateShuffleVector(Val, UndefValue::get(Ty),
+                                             ConstantVector::get(Mask));
+    // Extract elements [Elts, 2*Elts) from Val.
+    for (unsigned i = 0; i != Elts; ++i)
+      Mask[i] = ConstantInt::get(Int32Ty, Elts + i);
+    Value *RHS = Builder.CreateShuffleVector(Val, UndefValue::get(Ty),
+                                             ConstantVector::get(Mask));
+
+    // Replace Val with the sum of the extracted elements.
+    // TODO: Are nsw/nuw flags valid here?
+    Val = Builder.CreateAdd(LHS, RHS);
+
+    // Repeat, using half as many elements.
+  }
+
+  return Val;
+}
+
 Value *TreeToLLVM::EmitReg_RotateOp(tree type, tree op0, tree op1,
                                     unsigned Opc1, unsigned Opc2) {
   Value *In  = EmitRegister(op0);
@@ -8064,6 +8106,9 @@
     RHS = EmitReg_ReducMinMaxExpr(rhs1, ICmpInst::ICMP_ULE, ICmpInst::ICMP_SLE,
                                   FCmpInst::FCMP_OLE);
     break;
+  case REDUC_PLUS_EXPR:
+    RHS = EmitReg_REDUC_PLUS_EXPR(rhs1);
+    break;
   case ROUND_DIV_EXPR:
     RHS = EmitReg_ROUND_DIV_EXPR(rhs1, rhs2); break;
   case RROTATE_EXPR:





More information about the llvm-commits mailing list