[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner lattner at cs.uiuc.edu
Tue Sep 21 14:35:41 PDT 2004



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.244 -> 1.245
---
Log message:

Do not fold (X + C1 != C2) if there are other users of the add.  Doing 
this transformation used to take a loop like this:

int Array[1000];
void test(int X) {
  int i;
  for (i = 0; i < 1000; ++i)
    Array[i] += X;
}

Compiled to LLVM is:

no_exit:                ; preds = %entry, %no_exit
        %indvar = phi uint [ 0, %entry ], [ %indvar.next, %no_exit ]            ; <uint> [#uses=2]
        %tmp.4 = getelementptr [1000 x int]* %Array, int 0, uint %indvar                ; <int*> [#uses=2]
        %tmp.7 = load int* %tmp.4               ; <int> [#uses=1]
        %tmp.9 = add int %tmp.7, %X             ; <int> [#uses=1]
        store int %tmp.9, int* %tmp.4
***     %indvar.next = add uint %indvar, 1              ; <uint> [#uses=2]
***     %exitcond = seteq uint %indvar.next, 1000               ; <bool> [#uses=1]
        br bool %exitcond, label %return, label %no_exit

and turn it into a loop like this:

no_exit:                ; preds = %entry, %no_exit
        %indvar = phi uint [ 0, %entry ], [ %indvar.next, %no_exit ]            ; <uint> [#uses=3]
        %tmp.4 = getelementptr [1000 x int]* %Array, int 0, uint %indvar                ; <int*> [#uses=2]
        %tmp.7 = load int* %tmp.4               ; <int> [#uses=1]
        %tmp.9 = add int %tmp.7, %X             ; <int> [#uses=1]
        store int %tmp.9, int* %tmp.4
***     %indvar.next = add uint %indvar, 1              ; <uint> [#uses=1]
***     %exitcond = seteq uint %indvar, 999             ; <bool> [#uses=1]
        br bool %exitcond, label %return, label %no_exit

Note that indvar.next and indvar can no longer be coallesced.  In machine
code terms, this patch changes this code:

.LBBtest_1:     # no_exit
        mov %EDX, OFFSET Array
        mov %ESI, %EAX
        add %ESI, DWORD PTR [%EDX + 4*%ECX]
        mov %EDX, OFFSET Array
        mov DWORD PTR [%EDX + 4*%ECX], %ESI
        mov %EDX, %ECX
        inc %EDX
        cmp %ECX, 999
        mov %ECX, %EDX
        jne .LBBtest_1  # no_exit

into this:

.LBBtest_1:     # no_exit
        mov %EDX, OFFSET Array
        mov %ESI, %EAX
        add %ESI, DWORD PTR [%EDX + 4*%ECX]
        mov %EDX, OFFSET Array
        mov DWORD PTR [%EDX + 4*%ECX], %ESI
        inc %ECX
        cmp %ECX, 1000
        jne .LBBtest_1  # no_exit

We need better instruction selection to get this:

.LBBtest_1:     # no_exit
        add DWORD PTR [Array + 4*%ECX], EAX
        inc %ECX
        cmp %ECX, 1000
        jne .LBBtest_1  # no_exit

... but at least there is less register juggling



---
Diffs of the changes:  (+3 -2)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.244 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.245
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.244	Mon Sep 20 05:15:10 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Tue Sep 21 16:35:23 2004
@@ -1546,8 +1546,9 @@
         case Instruction::Add:
           // Replace ((add A, B) != C) with (A != C-B) if B & C are constants.
           if (ConstantInt *BOp1C = dyn_cast<ConstantInt>(BO->getOperand(1))) {
-            return new SetCondInst(I.getOpcode(), BO->getOperand(0),
-                                   ConstantExpr::getSub(CI, BOp1C));
+            if (BO->hasOneUse())
+              return new SetCondInst(I.getOpcode(), BO->getOperand(0),
+                                     ConstantExpr::getSub(CI, BOp1C));
           } else if (CI->isNullValue()) {
             // Replace ((add A, B) != 0) with (A != -B) if A or B is
             // efficiently invertible, or if the add has just this one use.






More information about the llvm-commits mailing list