[llvm-commits] [dragonegg] r94966 - in /dragonegg/trunk: llvm-convert.cpp llvm-internal.h

Duncan Sands baldrick at free.fr
Sun Jan 31 12:45:06 PST 2010


Author: baldrick
Date: Sun Jan 31 14:45:05 2010
New Revision: 94966

URL: http://llvm.org/viewvc/llvm-project?rev=94966&view=rev
Log:
Handle TRUNC_DIV_EXPR and EXACT_DIV_EXPR directly, rather than going via
EmitReg_BinOp.  Implement complex integer division while there (amusingly,
llvm-gcc will crash if you try to divide two complex integers...).

Modified:
    dragonegg/trunk/llvm-convert.cpp
    dragonegg/trunk/llvm-internal.h

Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=94966&r1=94965&r2=94966&view=diff

==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Sun Jan 31 14:45:05 2010
@@ -6035,7 +6035,6 @@
   bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op0));
   bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op1));
   bool TyIsSigned  = !TYPE_UNSIGNED(type);
-  bool IsExactDiv  = code == EXACT_DIV_EXPR;
 
   const Type *Ty = GetRegType(type);
   LHS = CastToAnyType(LHS, LHSIsSigned, Ty, TyIsSigned);
@@ -6055,11 +6054,7 @@
     RHS = UselesslyTypeConvert(RHS, Ty);
   }
 
-  Value *V;
-  if (Opc == Instruction::SDiv && IsExactDiv)
-    V = Builder.CreateExactSDiv(LHS, RHS);
-  else
-    V = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS);
+  Value *V = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS);
 
   return UselesslyTypeConvert(V, ResTy);
 }
@@ -6540,6 +6535,53 @@
                            "rdiv");
 }
 
+Value *TreeToLLVM::EmitReg_TRUNC_DIV_EXPR(tree op0, tree op1, bool isExact) {
+  Value *LHS = EmitRegister(op0);
+  Value *RHS = EmitRegister(op1);
+  tree type = TREE_TYPE(op0);
+
+  if (TREE_CODE(type) == COMPLEX_TYPE) {
+    tree elt_type = TREE_TYPE(type);
+    Value *LHSr, *LHSi; SplitComplex(LHS, LHSr, LHSi, elt_type);
+    Value *RHSr, *RHSi; SplitComplex(RHS, RHSr, RHSi, elt_type);
+    Value *DSTr, *DSTi;
+
+    // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+    assert (LHSr->getType()->isInteger() &&
+            "TRUNC_DIV_EXPR not integer!");
+    Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c
+    Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d
+    Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd
+
+    Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c
+    Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d
+    Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd
+    DSTr = TYPE_UNSIGNED(elt_type) ?
+      Builder.CreateUDiv(Tmp3, Tmp6) : Builder.CreateSDiv(Tmp3, Tmp6);
+
+    Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c
+    Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d
+    Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad
+    DSTi = TYPE_UNSIGNED(elt_type) ?
+      Builder.CreateUDiv(Tmp9, Tmp6) : Builder.CreateSDiv(Tmp9, Tmp6);
+
+    return CreateComplex(DSTr, DSTi, elt_type);
+  }
+
+  assert(LHS->getType()->isIntOrIntVector() && "TRUNC_DIV_EXPR not integer!");
+  if (TYPE_UNSIGNED(type)) {
+//    if (isExact)
+//      return Builder.CreateExactUDiv(LHS, RHS);
+//    else
+      return Builder.CreateUDiv(LHS, RHS);
+  } else {
+    if (isExact)
+      return Builder.CreateExactSDiv(LHS, RHS);
+    else
+      return Builder.CreateSDiv(LHS, RHS);
+  }
+}
+
 
 //===----------------------------------------------------------------------===//
 //                        ... Exception Handling ...
@@ -7251,9 +7293,7 @@
   case COMPLEX_EXPR:
     RHS = EmitReg_COMPLEX_EXPR(rhs1, rhs2); break;
   case EXACT_DIV_EXPR:
-    RHS = EmitReg_BinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
-                        Instruction::UDiv : Instruction::SDiv);
-    break;
+    RHS = EmitReg_TRUNC_DIV_EXPR(rhs1, rhs2, /*isExact*/true); break;
   case FLOOR_DIV_EXPR:
     RHS = EmitReg_FLOOR_DIV_EXPR(type, rhs1, rhs2); break;
   case FLOOR_MOD_EXPR:
@@ -7293,9 +7333,7 @@
                           Instruction::LShr : Instruction::AShr);
     break;
   case TRUNC_DIV_EXPR:
-    RHS = EmitReg_BinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
-                        Instruction::UDiv : Instruction::SDiv);
-    break;
+    RHS = EmitReg_TRUNC_DIV_EXPR(rhs1, rhs2, /*isExact*/false); break;
   case TRUNC_MOD_EXPR:
     RHS = EmitReg_BinOp(type, code, rhs1, rhs2, TYPE_UNSIGNED(type) ?
                         Instruction::URem : Instruction::SRem);

Modified: dragonegg/trunk/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-internal.h?rev=94966&r1=94965&r2=94966&view=diff

==============================================================================
--- dragonegg/trunk/llvm-internal.h (original)
+++ dragonegg/trunk/llvm-internal.h Sun Jan 31 14:45:05 2010
@@ -652,6 +652,7 @@
   Value *EmitReg_RDIV_EXPR(tree_node *op0, tree_node *op1);
   Value *EmitReg_ROUND_DIV_EXPR(tree_node *type, tree_node *op0,
                                 tree_node *op1);
+  Value *EmitReg_TRUNC_DIV_EXPR(tree_node *op0, tree_node *op1, bool isExact);
 
 
   Value *EmitLoadOfLValue(tree_node *exp);





More information about the llvm-commits mailing list