[llvm-commits] [129557] implement test/CFrontend/exact-div-expr.c by compiling
clattner at apple.com
clattner at apple.com
Sun Jul 15 15:30:13 PDT 2007
Revision: 129557
Author: clattner
Date: 2007-07-15 15:30:12 -0700 (Sun, 15 Jul 2007)
Log Message:
-----------
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 Paths:
--------------
apple-local/branches/llvm/gcc/llvm-convert.cpp
apple-local/branches/llvm/gcc/llvm-internal.h
Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-07-14 18:57:56 UTC (rev 129556)
+++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-07-15 22:30:12 UTC (rev 129557)
@@ -865,8 +865,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
@@ -3314,6 +3314,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: apple-local/branches/llvm/gcc/llvm-internal.h
===================================================================
--- apple-local/branches/llvm/gcc/llvm-internal.h 2007-07-14 18:57:56 UTC (rev 129556)
+++ apple-local/branches/llvm/gcc/llvm-internal.h 2007-07-15 22:30:12 UTC (rev 129557)
@@ -511,6 +511,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