From 4f1134e51ae293536843dcd7fa1147acdc39dec7 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 17 Apr 2004 18:16:10 +0000 Subject: [PATCH] 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 ; [#uses=1] %tmp.24 = seteq sbyte %tmp.13, 0 ; [#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 ] ; [#uses=2] *** %indvar = phi ulong [ %indvar.next, %no_exit ], [ 0, %entry ] ; [#uses=2] %indvar1 = cast ulong %indvar to uint ; [#uses=1] %inc.02.sum = add uint %indvar1, 1 ; [#uses=1] %inc.0.0 = getelementptr sbyte* %str, uint %inc.02.sum ; [#uses=1] %tmp.1 = load sbyte* %inc.0.0 ; [#uses=1] %tmp.2 = seteq sbyte %tmp.1, 0 ; [#uses=1] %indvar.next = add ulong %indvar, 1 ; [#uses=1] %indvar.next = add uint %indvar, 1 ; [#uses=1] br bool %tmp.2, label %loopexit.loopexit, label %no_exit loopexit.loopexit: ; preds = %no_exit %indvar = cast uint %indvar to int ; [#uses=1] %inc.1 = add int %indvar, 1 ; [#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 ; [#uses=1] %tmp.13 = load sbyte* %str ; [#uses=1] %tmp.24 = seteq sbyte %tmp.13, 0 ; [#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 ] ; [#uses=3] %indvar = cast uint %indvar to int ; [#uses=1] %inc.0.0 = getelementptr sbyte* %inc.02, uint %indvar ; [#uses=1] %inc.1 = add int %indvar, 1 ; [#uses=1] %tmp.1 = load sbyte* %inc.0.0 ; [#uses=1] %tmp.2 = seteq sbyte %tmp.1, 0 ; [#uses=1] %indvar.next = add uint %indvar, 1 ; [#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 ] ; [#uses=1] ret int %len.0.1 } git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13016 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/InstructionCombining.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 6b7f20a73cf..52b861da156 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(Op)) { + if (Constant *C = dyn_cast(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);