diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index a127f0b391d767..f6a6b4807adf35 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -247,6 +247,15 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) { if (!Br || !Br->isConditional()) continue; + // Returns true if we can add a known condition from BB to its successor + // block Succ. Each predecessor of Succ can either be BB or be dominated by + // Succ (e.g. the case when adding a condition from a pre-header to a loop + // header). + auto CanAdd = [&BB, &DT](BasicBlock *Succ) { + return all_of(predecessors(Succ), [&BB, &DT, Succ](BasicBlock *Pred) { + return Pred == &BB || DT.dominates(Succ, Pred); + }); + }; // If the condition is an OR of 2 compares and the false successor only has // the current block as predecessor, queue both negated conditions for the // false successor. @@ -254,7 +263,7 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) { if (match(Br->getCondition(), m_LogicalOr(m_Value(Op0), m_Value(Op1))) && match(Op0, m_Cmp()) && match(Op1, m_Cmp())) { BasicBlock *FalseSuccessor = Br->getSuccessor(1); - if (FalseSuccessor->getSinglePredecessor()) { + if (CanAdd(FalseSuccessor)) { WorkList.emplace_back(DT.getNode(FalseSuccessor), cast(Op0), true); WorkList.emplace_back(DT.getNode(FalseSuccessor), cast(Op1), @@ -269,7 +278,7 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) { if (match(Br->getCondition(), m_LogicalAnd(m_Value(Op0), m_Value(Op1))) && match(Op0, m_Cmp()) && match(Op1, m_Cmp())) { BasicBlock *TrueSuccessor = Br->getSuccessor(0); - if (TrueSuccessor->getSinglePredecessor()) { + if (CanAdd(TrueSuccessor)) { WorkList.emplace_back(DT.getNode(TrueSuccessor), cast(Op0), false); WorkList.emplace_back(DT.getNode(TrueSuccessor), cast(Op1), @@ -281,9 +290,9 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) { auto *CmpI = dyn_cast(Br->getCondition()); if (!CmpI) continue; - if (Br->getSuccessor(0)->getSinglePredecessor()) + if (CanAdd(Br->getSuccessor(0))) WorkList.emplace_back(DT.getNode(Br->getSuccessor(0)), CmpI, false); - if (Br->getSuccessor(1)->getSinglePredecessor()) + if (CanAdd(Br->getSuccessor(1))) WorkList.emplace_back(DT.getNode(Br->getSuccessor(1)), CmpI, true); } diff --git a/llvm/test/Transforms/ConstraintElimination/dom.ll b/llvm/test/Transforms/ConstraintElimination/dom.ll index 424e98742289ed..1c3e120a8962d3 100644 --- a/llvm/test/Transforms/ConstraintElimination/dom.ll +++ b/llvm/test/Transforms/ConstraintElimination/dom.ll @@ -146,9 +146,9 @@ define void @test_cond_from_preheader(i32 %x, i1 %c) { ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP:%.*]], label [[BB2]] ; CHECK: loop: ; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[F_1:%.*]] = icmp ugt i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[C_2:%.*]] = icmp ule i32 [[X]], 9 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[X]], 9 @@ -156,7 +156,7 @@ define void @test_cond_from_preheader(i32 %x, i1 %c) { ; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: [[C_4:%.*]] = icmp ule i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: bb2: ; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i32 [[X]], 10 @@ -203,9 +203,9 @@ define void @test_cond_from_preheader_successors_flipped(i32 %x, i1 %c) { ; CHECK-NEXT: br i1 [[C_1]], label [[BB2]], label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[F_1:%.*]] = icmp ule i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_2:%.*]] = icmp ule i32 [[X]], 11 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[X]], 11 @@ -213,7 +213,7 @@ define void @test_cond_from_preheader_successors_flipped(i32 %x, i1 %c) { ; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: [[F_2:%.*]] = icmp ule i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: ret void ; CHECK: bb2: ; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i32 [[X]], 10 @@ -266,17 +266,17 @@ define void @test_cond_from_preheader_and(i32 %x, i32 %y, i1 %c) { ; CHECK-NEXT: br i1 [[AND]], label [[LOOP:%.*]], label [[EXIT_1:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[F_1:%.*]] = icmp ugt i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[C_1:%.*]] = icmp ule i32 [[X]], 9 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[X]], 9 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[T_2:%.*]] = icmp ugt i32 [[Y]], 99 -; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[F_2:%.*]] = icmp ule i32 [[Y]], 99 -; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[Y]], 100 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i32 [[Y]], 100 @@ -425,17 +425,17 @@ define void @test_cond_from_preheader_or(i32 %x, i32 %y, i1 %c) { ; CHECK-NEXT: br i1 [[OR]], label [[EXIT_1:%.*]], label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[F_1:%.*]] = icmp ule i32 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i32 [[X]], 11 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ule i32 [[X]], 11 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[T_2:%.*]] = icmp ule i32 [[Y]], 99 -; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[F_2:%.*]] = icmp ugt i32 [[Y]], 99 -; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[C_3:%.*]] = icmp ule i32 [[Y]], 98 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp ule i32 [[Y]], 98