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 +}