aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-04-17 18:16:10 +0000
committerChris Lattner <sabre@nondot.org>2004-04-17 18:16:10 +0000
commit4f1134e51ae293536843dcd7fa1147acdc39dec7 (patch)
treec22aabc0eff0abf58adced8c759b089b3695436f
parentf50af088f19f525f3d1026eb61db77e0037a9f43 (diff)
Fix a HUGE pessimization on X86. The indvars pass was taking this
(familiar) function: int _strlen(const char *str) { int len = 0; while (*str++) len++; return len; } And transforming it to use a ulong induction variable, because the type of the pointer index was left as a constant long. This is obviously very bad. The fix is to shrink long constants in getelementptr instructions to intptr_t, making the indvars pass insert a uint induction variable, which is much more efficient. Here's the before code for this function: int %_strlen(sbyte* %str) { entry: %tmp.13 = load sbyte* %str ; <sbyte> [#uses=1] %tmp.24 = seteq sbyte %tmp.13, 0 ; <bool> [#uses=1] br bool %tmp.24, label %loopexit, label %no_exit no_exit: ; preds = %entry, %no_exit *** %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %entry ] ; <uint> [#uses=2] *** %indvar = phi ulong [ %indvar.next, %no_exit ], [ 0, %entry ] ; <ulong> [#uses=2] %indvar1 = cast ulong %indvar to uint ; <uint> [#uses=1] %inc.02.sum = add uint %indvar1, 1 ; <uint> [#uses=1] %inc.0.0 = getelementptr sbyte* %str, uint %inc.02.sum ; <sbyte*> [#uses=1] %tmp.1 = load sbyte* %inc.0.0 ; <sbyte> [#uses=1] %tmp.2 = seteq sbyte %tmp.1, 0 ; <bool> [#uses=1] %indvar.next = add ulong %indvar, 1 ; <ulong> [#uses=1] %indvar.next = add uint %indvar, 1 ; <uint> [#uses=1] br bool %tmp.2, label %loopexit.loopexit, label %no_exit loopexit.loopexit: ; preds = %no_exit %indvar = cast uint %indvar to int ; <int> [#uses=1] %inc.1 = add int %indvar, 1 ; <int> [#uses=1] ret int %inc.1 loopexit: ; preds = %entry ret int 0 } Here's the after code: int %_strlen(sbyte* %str) { entry: %inc.02 = getelementptr sbyte* %str, uint 1 ; <sbyte*> [#uses=1] %tmp.13 = load sbyte* %str ; <sbyte> [#uses=1] %tmp.24 = seteq sbyte %tmp.13, 0 ; <bool> [#uses=1] br bool %tmp.24, label %loopexit, label %no_exit no_exit: ; preds = %entry, %no_exit *** %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %entry ] ; <uint> [#uses=3] %indvar = cast uint %indvar to int ; <int> [#uses=1] %inc.0.0 = getelementptr sbyte* %inc.02, uint %indvar ; <sbyte*> [#uses=1] %inc.1 = add int %indvar, 1 ; <int> [#uses=1] %tmp.1 = load sbyte* %inc.0.0 ; <sbyte> [#uses=1] %tmp.2 = seteq sbyte %tmp.1, 0 ; <bool> [#uses=1] %indvar.next = add uint %indvar, 1 ; <uint> [#uses=1] br bool %tmp.2, label %loopexit, label %no_exit loopexit: ; preds = %entry, %no_exit %len.0.1 = phi int [ 0, %entry ], [ %inc.1, %no_exit ] ; <int> [#uses=1] ret int %len.0.1 } git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13016 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp5
1 files changed, 4 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 6b7f20a73c..52b861da15 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2580,7 +2580,10 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// obvious.
Value *Op = GEP.getOperand(i);
if (Op->getType()->getPrimitiveSize() > TD->getPointerSize())
- if (!isa<Constant>(Op)) {
+ if (Constant *C = dyn_cast<Constant>(Op)) {
+ GEP.setOperand(i, ConstantExpr::getCast(C, TD->getIntPtrType()));
+ MadeChange = true;
+ } else {
Op = InsertNewInstBefore(new CastInst(Op, TD->getIntPtrType(),
Op->getName()), GEP);
GEP.setOperand(i, Op);