enhance FoldOpIntoPhi in instcombine to try harder when a phi has
authorChris Lattner <sabre@nondot.org>
Sun, 16 Jan 2011 05:28:59 +0000 (05:28 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 16 Jan 2011 05:28:59 +0000 (05:28 +0000)
multiple uses.  In some cases, all the uses are the same operation,
so instcombine can go ahead and promote the phi.  In the testcase
this pushes an add out of the loop.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123568 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstructionCombining.cpp
lib/Transforms/Scalar/ScalarReplAggregates.cpp
test/Transforms/InstCombine/phi.ll

index 6d05466b9becb8639f9ac60b748815771c034a83..23e76ee499f04b3549aea1733f46266d5a59c285 100644 (file)
@@ -519,9 +519,17 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
     return 0;
   
   // We normally only transform phis with a single use, unless we're trying
-  // hard to make jump threading happen.
-  if (!PN->hasOneUse())
-    return 0;
+  // hard to make jump threading happen.  However, if a PHI has multiple uses
+  // and they are all the same operation, we can fold *all* of the uses into the
+  // PHI.
+  if (!PN->hasOneUse()) {
+    // Walk the use list for the instruction, comparing them to I.
+    for (Value::use_iterator UI = PN->use_begin(), E = PN->use_end();
+         UI != E; ++UI)
+      if (!I.isIdenticalTo(cast<Instruction>(*UI))) 
+        return 0;
+    // Otherwise, we can replace *all* users with the new PHI we form.
+  }
   
   // Check to see if all of the operands of the PHI are simple constants
   // (constantint/constantfp/undef).  If there is one non-constant value,
@@ -628,6 +636,14 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
       NewPN->addIncoming(InV, PN->getIncomingBlock(i));
     }
   }
+  
+  for (Value::use_iterator UI = PN->use_begin(), E = PN->use_end();
+       UI != E; ) {
+    Instruction *User = cast<Instruction>(*UI++);
+    if (User == &I) continue;
+    ReplaceInstUsesWith(*User, NewPN);
+    EraseInstFromFunction(*User);
+  }
   return ReplaceInstUsesWith(I, NewPN);
 }
 
index 13902552ebdb8195446dc7aca78001285214138c..0375d826f6b44e5c65a38c99345dfbddf89ab5cc 100644 (file)
@@ -1279,6 +1279,7 @@ void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,
       // address operand will be updated, so nothing else needs to be done.
     } else if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
       const Type *LIType = LI->getType();
+      
       if (isCompatibleAggregate(LIType, AI->getAllocatedType())) {
         // Replace:
         //   %res = load { i32, i32 }* %alloc
index ff0b43c4ab6b969ffe4cb53aa98a3db629cc8b13..ad71ba683314cb550e7647b585d9ffd7f32b0d29 100644 (file)
@@ -503,3 +503,25 @@ loop:
 ret:
   ret void
 }
+
+define i32 @test23(i32 %A, i1 %b, i32 * %P) {
+BB0:
+        br label %Loop
+
+Loop:           ; preds = %Loop, %BB0
+        ; PHI has same value always.
+        %B = phi i32 [ %A, %BB0 ], [ 42, %Loop ]
+        %D = add i32 %B, 19
+        store i32 %D, i32* %P
+        br i1 %b, label %Loop, label %Exit
+
+Exit:           ; preds = %Loop
+        %E = add i32 %B, 19
+        ret i32 %E
+; CHECK: @test23
+; CHECK: %phitmp = add i32 %A, 19
+; CHECK: Loop:
+; CHECK-NEXT: %B = phi i32 [ %phitmp, %BB0 ], [ 61, %Loop ]
+; CHECK: Exit:
+; CHECK-NEXT: ret i32 %B
+}