diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -1197,11 +1197,14 @@ if (ProcessThreadableEdges(CondInst, BB, Preference, Terminator)) return true; - // If this is an otherwise-unfoldable branch on a phi node in the current - // block, see if we can simplify. - if (PHINode *PN = dyn_cast(CondInst)) - if (PN->getParent() == BB && isa(BB->getTerminator())) - return ProcessBranchOnPHI(PN); + // If this is an otherwise-unfoldable branch on a phi node or freeze(phi) in + // the current block, see if we can simplify. + PHINode *PN = dyn_cast( + isa(CondInst) ? cast(CondInst)->getOperand(0) + : CondInst); + + if (PN && PN->getParent() == BB && isa(BB->getTerminator())) + return ProcessBranchOnPHI(PN); // If this is an otherwise-unfoldable branch on a XOR, see if we can simplify. if (CondInst->getOpcode() == Instruction::Xor && @@ -1757,8 +1760,8 @@ } /// ProcessBranchOnPHI - We have an otherwise unthreadable conditional branch on -/// a PHI node in the current block. See if there are any simplifications we -/// can do based on inputs to the phi node. +/// a PHI node (or freeze PHI) in the current block. See if there are any +/// simplifications we can do based on inputs to the phi node. bool JumpThreadingPass::ProcessBranchOnPHI(PHINode *PN) { BasicBlock *BB = PN->getParent(); @@ -1771,6 +1774,22 @@ // *duplicate* the conditional branch into that block in order to further // encourage jump threading and to eliminate cases where we have branch on a // phi of an icmp (branch on icmp is much better). + // This transformation is correct when a frozen PN is used as a branch + // condition as well, because it does not remove the freeze instruction. + // + // p = phi [a, pred1] [b, pred2] + // p.fr = freeze p + // br p.fr, ... + // => + // pred1: + // p.fr = freeze a + // br p.fr, ... + // pred2: + // p.fr2 = freeze b + // br p.fr2, ... + // + // This is beneficial because when a and b are icmps CodeGenPrepare can + // canonicalize them to br(freeze(icmp)). for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { BasicBlock *PredBB = PN->getIncomingBlock(i); if (BranchInst *PredBr = dyn_cast(PredBB->getTerminator())) diff --git a/llvm/test/Transforms/JumpThreading/phi-copy-to-pred.ll b/llvm/test/Transforms/JumpThreading/phi-copy-to-pred.ll --- a/llvm/test/Transforms/JumpThreading/phi-copy-to-pred.ll +++ b/llvm/test/Transforms/JumpThreading/phi-copy-to-pred.ll @@ -37,17 +37,15 @@ define i32 @test2(i1 %cond, i1 %a, i1 %b) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[A:%.*]], label [[C:%.*]] ; CHECK: A: ; CHECK-NEXT: call void @f() -; CHECK-NEXT: br label [[C:%.*]] -; CHECK: B: -; CHECK-NEXT: call void @g() -; CHECK-NEXT: br label [[C]] +; CHECK-NEXT: [[P_FR1:%.*]] = freeze i1 [[A:%.*]] +; CHECK-NEXT: br i1 [[P_FR1]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] ; CHECK: C: -; CHECK-NEXT: [[P:%.*]] = phi i1 [ [[A:%.*]], [[A]] ], [ [[B:%.*]], [[B]] ] -; CHECK-NEXT: [[P_FR:%.*]] = freeze i1 [[P]] -; CHECK-NEXT: br i1 [[P_FR]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] +; CHECK-NEXT: call void @g() +; CHECK-NEXT: [[P_FR:%.*]] = freeze i1 [[B:%.*]] +; CHECK-NEXT: br i1 [[P_FR]], label [[EXIT1]], label [[EXIT2]] ; CHECK: EXIT1: ; CHECK-NEXT: ret i32 0 ; CHECK: EXIT2: