diff options
| author | Chris Lattner <sabre@nondot.org> | 2004-04-17 18:16:10 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2004-04-17 18:16:10 +0000 | 
| commit | 1e9ac1a45e7a84fec8ebad9aeebdbea21ebdbc06 (patch) | |
| tree | ca6ddd0752cda836a7f2d13d0e68d464d6eaf9b6 /llvm/lib/Transforms | |
| parent | 885a6eb74d95ce72090bff2e59a0231be2ea2283 (diff) | |
| download | bcm5719-llvm-1e9ac1a45e7a84fec8ebad9aeebdbea21ebdbc06.tar.gz bcm5719-llvm-1e9ac1a45e7a84fec8ebad9aeebdbea21ebdbc06.zip | |
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
}
llvm-svn: 13016
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/InstructionCombining.cpp | 5 | 
1 files changed, 4 insertions, 1 deletions
| diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 6b7f20a73cf..52b861da156 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/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); | 

