[llvm-commits] [llvm-gcc-4-2] r39883 - in /llvm-gcc-4-2/trunk/gcc: llvm-convert.cpp llvm-internal.h

Chris Lattner sabre at nondot.org
Sun Jul 15 15:53:54 PDT 2007


Author: lattner
Date: Sun Jul 15 17:53:54 2007
New Revision: 39883

URL: http://llvm.org/viewvc/llvm-project?rev=39883&view=rev
Log:
implement test/CFrontend/exact-div-expr.c by compiling
a pointer difference into a shift, instead of a divide.
This was actually a feature of llvm-gcc3 that was never
reimplemented in llvm-gcc4.  This commonly occurs in C++
code that is using iterators.


Modified:
    llvm-gcc-4-2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4-2/trunk/gcc/llvm-internal.h

Modified: llvm-gcc-4-2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4-2/trunk/gcc/llvm-convert.cpp?rev=39883&r1=39882&r2=39883&view=diff

==============================================================================
--- llvm-gcc-4-2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4-2/trunk/gcc/llvm-convert.cpp Sun Jul 15 17:53:54 2007
@@ -864,8 +864,8 @@
   case PLUS_EXPR: Result = EmitBinOp(exp, DestLoc, Instruction::Add);break;
   case MINUS_EXPR:Result = EmitBinOp(exp, DestLoc, Instruction::Sub);break;
   case MULT_EXPR: Result = EmitBinOp(exp, DestLoc, Instruction::Mul);break;
+  case EXACT_DIV_EXPR: Result = EmitEXACT_DIV_EXPR(exp, DestLoc); break;
   case TRUNC_DIV_EXPR: 
-  case EXACT_DIV_EXPR:   // TODO: Optimize EXACT_DIV_EXPR.
     if (TYPE_UNSIGNED(TREE_TYPE(exp)))
       Result = EmitBinOp(exp, DestLoc, Instruction::UDiv);
     else 
@@ -3313,6 +3313,29 @@
                               TREE_CODE(exp) == MAX_EXPR ? "max" : "min");
 }
 
+Value *TreeToLLVM::EmitEXACT_DIV_EXPR(tree exp, Value *DestLoc) {
+  // Unsigned EXACT_DIV_EXPR -> normal udiv.
+  if (TYPE_UNSIGNED(TREE_TYPE(exp)))
+    return EmitBinOp(exp, DestLoc, Instruction::UDiv);
+  
+  // If this is a signed EXACT_DIV_EXPR by a constant, and we know that
+  // the RHS is a multiple of two, we strength reduce the result to use
+  // a signed SHR here.  We have no way in LLVM to represent EXACT_DIV_EXPR
+  // precisely, so this transform can't currently be performed at the LLVM
+  // level.  This is commonly used for pointer subtraction. 
+  if (TREE_CODE(TREE_OPERAND(exp, 1)) == INTEGER_CST) {
+    uint64_t IntValue = getINTEGER_CSTVal(TREE_OPERAND(exp, 1));
+    if (isPowerOf2_64(IntValue)) {
+      // Create an ashr instruction, by the log of the division amount.
+      Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
+      return Builder.CreateAShr(LHS, ConstantInt::get(LHS->getType(),
+                                                      Log2_64(IntValue)),"tmp");
+    }
+  }
+  
+  // Otherwise, emit this as a normal signed divide.
+  return EmitBinOp(exp, DestLoc, Instruction::SDiv);
+}
 
 Value *TreeToLLVM::EmitFLOOR_MOD_EXPR(tree exp, Value *DestLoc) {
   // Notation: FLOOR_MOD_EXPR <-> Mod, TRUNC_MOD_EXPR <-> Rem.

Modified: llvm-gcc-4-2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4-2/trunk/gcc/llvm-internal.h?rev=39883&r1=39882&r2=39883&view=diff

==============================================================================
--- llvm-gcc-4-2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4-2/trunk/gcc/llvm-internal.h Sun Jul 15 17:53:54 2007
@@ -521,6 +521,7 @@
   Value *EmitABS_EXPR(tree_node *exp);
   Value *EmitBIT_NOT_EXPR(tree_node *exp);
   Value *EmitTRUTH_NOT_EXPR(tree_node *exp);
+  Value *EmitEXACT_DIV_EXPR(tree_node *exp, Value *DestLoc);
   Value *EmitCompare(tree_node *exp, unsigned UIPred, unsigned SIPred, 
                      unsigned FPOpc);
   Value *EmitBinOp(tree_node *exp, Value *DestLoc, unsigned Opc);





More information about the llvm-commits mailing list