diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -736,11 +736,16 @@ if (!SI->getParent()->hasNPredecessorsOrMore(128 / SI->getNumSuccessors())) CV = SI->getCondition(); } else if (BranchInst *BI = dyn_cast(TI)) - if (BI->isConditional() && BI->getCondition()->hasOneUse()) - if (ICmpInst *ICI = dyn_cast(BI->getCondition())) { - if (ICI->isEquality() && GetConstantInt(ICI->getOperand(1), DL)) - CV = ICI->getOperand(0); - } + if (BI->isConditional() && BI->getCondition()->hasOneUse()) { + ICmpInst *ICI = nullptr; + if (FreezeInst *FR = dyn_cast(BI->getCondition())) + ICI = dyn_cast(FR->getOperand(0)); + else + ICI = dyn_cast(BI->getCondition()); + + if (ICI && ICI->isEquality() && GetConstantInt(ICI->getOperand(1), DL)) + CV = ICI->getOperand(0); + } // Unwrap any lossless ptrtoint cast. if (CV) { @@ -766,7 +771,11 @@ } BranchInst *BI = cast(TI); - ICmpInst *ICI = cast(BI->getCondition()); + ICmpInst *ICI; + if (FreezeInst *FR = dyn_cast(BI->getCondition())) + ICI = dyn_cast(FR->getOperand(0)); + else + ICI = dyn_cast(BI->getCondition()); BasicBlock *Succ = BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE); Cases.push_back(ValueEqualityComparisonCase( GetConstantInt(ICI->getOperand(1), DL), Succ)); diff --git a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll --- a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll +++ b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll @@ -114,3 +114,48 @@ call void @foo() ret void } + +declare void @foo1() +declare void @foo2() +declare void @foo3() +; Fold even if the condition is frozen. +define void @test4(i32 %v) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND1:%.*]] = icmp ne i32 [[V:%.*]], 0 +; CHECK-NEXT: [[COND1_FR:%.*]] = freeze i1 [[COND1]] +; CHECK-NEXT: br i1 [[COND1_FR]], label [[BODY1:%.*]], label [[BODY2:%.*]] +; CHECK: body1: +; CHECK-NEXT: call void @foo1() +; CHECK-NEXT: br label [[END:%.*]] +; CHECK: body2: +; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; +entry: + %cond1 = icmp ne i32 %v, 0 + %cond2 = icmp eq i32 %v, 0 + %cond1.fr = freeze i1 %cond1 + br i1 %cond1.fr, label %body1, label %split + +split: + %cond2.fr = freeze i1 %cond2 + br i1 %cond2.fr, label %body2, label %body3 + +body1: + call void @foo1() + br label %end + +body2: + call void @foo2() + br label %end + +body3: + call void @foo3() + br label %end + +end: + ret void +}