Index: llvm/lib/Transforms/Scalar/LoopDeletion.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -250,20 +250,28 @@ // (non-latch) predecessors. auto GetSoleInputOnFirstIteration = [&](PHINode & PN)->Value * { BasicBlock *BB = PN.getParent(); + bool HasLivePreds = false; + (void)HasLivePreds; if (BB == Header) return PN.getIncomingValueForBlock(L->getLoopPredecessor()); Value *OnlyInput = nullptr; for (auto *Pred : predecessors(BB)) if (LiveEdges.count({ Pred, BB })) { + HasLivePreds = true; Value *Incoming = PN.getIncomingValueForBlock(Pred); + // Skip undefs. If they are present, we can assume they equal to the + // non-undef input. + if (isa(Incoming)) + continue; // Two inputs. if (OnlyInput && OnlyInput != Incoming) return nullptr; OnlyInput = Incoming; } - assert(OnlyInput && "No live predecessors?"); - return OnlyInput; + assert(HasLivePreds && "No live predecessors?"); + // If all incoming live value were undefs, return undef. + return OnlyInput ? OnlyInput : UndefValue::get(PN.getType()); }; DenseMap FirstIterValue; @@ -324,13 +332,26 @@ // Can we prove constant true or false for this condition? LHS = getValueOnFirstIteration(LHS, FirstIterValue, SQ); RHS = getValueOnFirstIteration(RHS, FirstIterValue, SQ); - auto *KnownCondition = - dyn_cast_or_null(SimplifyICmpInst(Pred, LHS, RHS, SQ)); + auto *KnownCondition = SimplifyICmpInst(Pred, LHS, RHS, SQ); if (!KnownCondition) { + // Failed to simplify. MarkAllSuccessorsLive(BB); continue; } - if (KnownCondition->isAllOnesValue()) + if (isa(KnownCondition)) { + // If there is a non-loop successor, always assume this branch leaves the + // loop. Otherwise, arbitrarily take IfTrue. + if (L->contains(IfTrue) && L->contains(IfFalse)) + MarkLiveEdge(BB, IfTrue); + continue; + } + auto *ConstCondition = dyn_cast(KnownCondition); + if (!ConstCondition) { + // Non-constant condition, cannot analyze any further. + MarkAllSuccessorsLive(BB); + continue; + } + if (ConstCondition->isAllOnesValue()) MarkLiveEdge(BB, IfTrue); else MarkLiveEdge(BB, IfFalse); Index: llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll =================================================================== --- llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll +++ llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll @@ -731,20 +731,19 @@ unreachable } -; TODO: We can break the backedge here by assuming that undef = sub. define i32 @test_multiple_pred_undef_1() { ; CHECK-LABEL: @test_multiple_pred_undef_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]] ; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0 ; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] ; CHECK: if.true: ; CHECK-NEXT: br i1 undef, label [[IF_TRUE_1:%.*]], label [[IF_TRUE_2:%.*]] ; CHECK: if.true.1: -; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK-NEXT: br label [[BACKEDGE:%.*]] ; CHECK: if.true.2: ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: if.false: @@ -755,9 +754,11 @@ ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: backedge: ; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE_1]] ], [ 0, [[IF_FALSE_2]] ], [ [[SUB]], [[IF_TRUE_1]] ], [ undef, [[IF_TRUE_2]] ] -; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]] +; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]] ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[SUM_NEXT]], 4 -; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]] +; CHECK: backedge.loop_crit_edge: +; CHECK-NEXT: unreachable ; CHECK: done: ; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]] @@ -805,20 +806,19 @@ unreachable } -; TODO: We can break the backedge here by assuming that undef = sub. define i32 @test_multiple_pred_undef_2() { ; CHECK-LABEL: @test_multiple_pred_undef_2( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]] ; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0 ; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] ; CHECK: if.true: ; CHECK-NEXT: br i1 undef, label [[IF_TRUE_1:%.*]], label [[IF_TRUE_2:%.*]] ; CHECK: if.true.1: -; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK-NEXT: br label [[BACKEDGE:%.*]] ; CHECK: if.true.2: ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: if.false: @@ -829,9 +829,11 @@ ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: backedge: ; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE_1]] ], [ 0, [[IF_FALSE_2]] ], [ undef, [[IF_TRUE_1]] ], [ [[SUB]], [[IF_TRUE_2]] ] -; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]] +; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]] ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[SUM_NEXT]], 4 -; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]] +; CHECK: backedge.loop_crit_edge: +; CHECK-NEXT: unreachable ; CHECK: done: ; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]] @@ -879,20 +881,19 @@ unreachable } -; TODO: We can break the backedge here by exploiting undef. define i32 @test_multiple_pred_undef_3() { ; CHECK-LABEL: @test_multiple_pred_undef_3( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]] ; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0 ; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] ; CHECK: if.true: ; CHECK-NEXT: br i1 undef, label [[IF_TRUE_1:%.*]], label [[IF_TRUE_2:%.*]] ; CHECK: if.true.1: -; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK-NEXT: br label [[BACKEDGE:%.*]] ; CHECK: if.true.2: ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: if.false: @@ -903,9 +904,11 @@ ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: backedge: ; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE_1]] ], [ 0, [[IF_FALSE_2]] ], [ undef, [[IF_TRUE_1]] ], [ undef, [[IF_TRUE_2]] ] -; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]] +; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]] ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[SUM_NEXT]], 4 -; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] +; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]] +; CHECK: backedge.loop_crit_edge: +; CHECK-NEXT: unreachable ; CHECK: done: ; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ] ; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]