From 192228edb1c08ca11da2df959072bcaa99eacd63 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 16 Jan 2011 05:28:59 +0000 Subject: [PATCH] enhance FoldOpIntoPhi in instcombine to try harder when a phi has 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 --- .../InstCombine/InstructionCombining.cpp | 22 ++++++++++++++++--- .../Scalar/ScalarReplAggregates.cpp | 1 + test/Transforms/InstCombine/phi.ll | 22 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index 6d05466b9be..23e76ee499f 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -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(*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(*UI++); + if (User == &I) continue; + ReplaceInstUsesWith(*User, NewPN); + EraseInstFromFunction(*User); + } return ReplaceInstUsesWith(I, NewPN); } diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 13902552ebd..0375d826f6b 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -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(User)) { const Type *LIType = LI->getType(); + if (isCompatibleAggregate(LIType, AI->getAllocatedType())) { // Replace: // %res = load { i32, i32 }* %alloc diff --git a/test/Transforms/InstCombine/phi.ll b/test/Transforms/InstCombine/phi.ll index ff0b43c4ab6..ad71ba68331 100644 --- a/test/Transforms/InstCombine/phi.ll +++ b/test/Transforms/InstCombine/phi.ll @@ -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 +} -- 2.34.1