diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3822,8 +3822,18 @@ // See if we can trivially sink this instruction to its user if we can // prove that the successor is not executed more frequently than our block. - if (EnableCodeSinking) - if (Use *SingleUse = I->getSingleUndroppableUse()) { + if (EnableCodeSinking) { + FreezeInst* FI = nullptr; + Use *SingleUse = I->getSingleUndroppableUse(); + + // If single use of I is fr(I), try to sink I and fr(I) simultaneously. + if (SingleUse) { + User *U = SingleUse->getUser(); + FI = dyn_cast(U); + if (FI) + SingleUse = FI->getSingleUndroppableUse(); + } + if (SingleUse) { BasicBlock *BB = I->getParent(); Instruction *UserInst = cast(SingleUse->getUser()); BasicBlock *UserParent; @@ -3853,9 +3863,22 @@ if (ShouldSink) { assert(DT.dominates(BB, UserParent) && "Dominance relation broken?"); + bool Sinked = false; + // Okay, the CFG is simple enough, try to sink this instruction. - if (TryToSinkInstruction(I, UserParent)) { + if (FI) { + if (TryToSinkInstruction(FI, UserParent) && TryToSinkInstruction(I, UserParent)) { + LLVM_DEBUG(dbgs() << "IC: Sink: " << *FI << '\n'); + LLVM_DEBUG(dbgs() << "IC: Sink: " << *I << '\n'); + Sinked = true; + } + } + else if (TryToSinkInstruction(I, UserParent)) { LLVM_DEBUG(dbgs() << "IC: Sink: " << *I << '\n'); + Sinked = true; + } + + if (Sinked) { MadeIRChange = true; // We'll add uses of the sunk instruction below, but since sinking // can expose opportunities for it's *operands* add them to the @@ -3867,6 +3890,7 @@ } } } + } // Now that we have an instruction, try combining it to simplify it. Builder.SetInsertPoint(I); diff --git a/llvm/test/Transforms/InstCombine/sink_instruction.ll b/llvm/test/Transforms/InstCombine/sink_instruction.ll --- a/llvm/test/Transforms/InstCombine/sink_instruction.ll +++ b/llvm/test/Transforms/InstCombine/sink_instruction.ll @@ -77,3 +77,59 @@ %sum.0 = phi i32 [ %add, %sw.bb ], [ 0, %entry ] ret i32 %sum.0 } + +declare void @f() + +declare void @use(i32) + +define void @test4(i32* %ptr, i1 %cond0) { +entry: +; CHECK-LABEL: entry: +; CHECK-NEXT: %temp = load i32, i32* %ptr, align 4 + %temp = load i32, i32* %ptr, align 4 + %cond1 = icmp eq i32 %temp, 0 + br i1 %cond0, label %split, label %end + +split: ; preds = %entry +; CHECK-LABEL: split: +; CHECK-NEXT: %cond1 = icmp eq i32 %temp, 0 + br i1 %cond1, label %body1, label %body2 + +body1: ; preds = %split + call void @f() + br label %end + +body2: ; preds = %split + call void @use(i32 %temp) + br label %end + +end: ; preds = %body2, %body1, %entry + ret void +} + +define void @test4.freeze(i32* %ptr, i1 %cond0) { +entry: +; CHECK-LABEL: entry: +; CHECK-NEXT: %temp = load i32, i32* %ptr, align 4 + %temp = load i32, i32* %ptr, align 4 + %cond1 = icmp eq i32 %temp, 0 + %cond1.fr = freeze i1 %cond1 + br i1 %cond0, label %split, label %end + +split: ; preds = %entry +; CHECK-LABEL: split: +; CHECK-NEXT: %temp.fr = freeze i32 %temp +; CHECK-NEXT: %cond1 = icmp eq i32 %temp.fr, 0 + br i1 %cond1.fr, label %body1, label %body2 + +body1: ; preds = %split + call void @f() + br label %end + +body2: ; preds = %split + call void @use(i32 %temp) + br label %end + +end: ; preds = %body2, %body1, %entry + ret void +} \ No newline at end of file