diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -318,53 +318,63 @@ Value *LHS, *RHS; BasicBlock *IfTrue, *IfFalse; auto *Term = BB->getTerminator(); - // TODO: Handle switch. - if (!match(Term, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), - m_BasicBlock(IfTrue), m_BasicBlock(IfFalse)))) { - MarkAllSuccessorsLive(BB); - continue; - } - - if (!LHS->getType()->isIntegerTy()) { - MarkAllSuccessorsLive(BB); - continue; - } + if (match(Term, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), + m_BasicBlock(IfTrue), m_BasicBlock(IfFalse)))) { + if (!LHS->getType()->isIntegerTy()) { + MarkAllSuccessorsLive(BB); + continue; + } - // Can we prove constant true or false for this condition? - LHS = getValueOnFirstIteration(LHS, FirstIterValue, SQ); - RHS = getValueOnFirstIteration(RHS, FirstIterValue, SQ); - auto *KnownCondition = SimplifyICmpInst(Pred, LHS, RHS, SQ); - if (!KnownCondition) { - // Failed to simplify. - MarkAllSuccessorsLive(BB); - continue; - } - if (isa(KnownCondition)) { - // TODO: According to langref, branching by undef is undefined behavior. - // It means that, theoretically, we should be able to just continue - // without marking any successors as live. However, we are not certain - // how correct our compiler is at handling such cases. So we are being - // very conservative here. - // - // If there is a non-loop successor, always assume this branch leaves the - // loop. Otherwise, arbitrarily take IfTrue. - // - // Once we are certain that branching by undef is handled correctly by - // other transforms, we should not mark any successors live here. - if (L->contains(IfTrue) && L->contains(IfFalse)) + // Can we prove constant true or false for this condition? + LHS = getValueOnFirstIteration(LHS, FirstIterValue, SQ); + RHS = getValueOnFirstIteration(RHS, FirstIterValue, SQ); + auto *KnownCondition = SimplifyICmpInst(Pred, LHS, RHS, SQ); + if (!KnownCondition) { + // Failed to simplify. + MarkAllSuccessorsLive(BB); + continue; + } + if (isa(KnownCondition)) { + // TODO: According to langref, branching by undef is undefined behavior. + // It means that, theoretically, we should be able to just continue + // without marking any successors as live. However, we are not certain + // how correct our compiler is at handling such cases. So we are being + // very conservative here. + // + // If there is a non-loop successor, always assume this branch leaves the + // loop. Otherwise, arbitrarily take IfTrue. + // + // Once we are certain that branching by undef is handled correctly by + // other transforms, we should not mark any successors live here. + 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); - continue; - } - auto *ConstCondition = dyn_cast(KnownCondition); - if (!ConstCondition) { - // Non-constant condition, cannot analyze any further. + else + MarkLiveEdge(BB, IfFalse); + } else if (SwitchInst *SI = dyn_cast(Term)) { + auto *SwitchValue = SI->getCondition(); + auto *SwitchValueOnFirstIter = + getValueOnFirstIteration(SwitchValue, FirstIterValue, SQ); + auto *ConstSwitchValue = dyn_cast(SwitchValueOnFirstIter); + if (!ConstSwitchValue) { + MarkAllSuccessorsLive(BB); + continue; + } + auto CaseIterator = SI->findCaseValue(ConstSwitchValue); + MarkLiveEdge(BB, CaseIterator->getCaseSuccessor()); + } else { MarkAllSuccessorsLive(BB); continue; } - if (ConstCondition->isAllOnesValue()) - MarkLiveEdge(BB, IfTrue); - else - MarkLiveEdge(BB, IfFalse); } // We can break the latch if it wasn't live. diff --git a/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll b/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll --- a/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll +++ b/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll @@ -1057,7 +1057,7 @@ ; 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: switch i32 [[SUB]], label [[DEFAULT:%.*]] [ ; CHECK-NEXT: i32 0, label [[ONZERO:%.*]] @@ -1065,7 +1065,7 @@ ; CHECK-NEXT: i32 2, label [[ONTWO:%.*]] ; CHECK-NEXT: ] ; CHECK: default: -; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK-NEXT: br label [[BACKEDGE:%.*]] ; CHECK: onzero: ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: onone: @@ -1074,9 +1074,11 @@ ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: backedge: ; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ [[SUB]], [[DEFAULT]] ], [ 0, [[ONZERO]] ], [ 1, [[ONONE]] ], [ 2, [[ONTWO]] ] -; 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]] @@ -1122,7 +1124,7 @@ ; 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: switch i32 [[SUB]], label [[DEFAULT:%.*]] [ ; CHECK-NEXT: i32 0, label [[ONZERO:%.*]] @@ -1130,7 +1132,7 @@ ; CHECK-NEXT: i32 4, label [[ONTWO:%.*]] ; CHECK-NEXT: ] ; CHECK: default: -; CHECK-NEXT: br label [[BACKEDGE]] +; CHECK-NEXT: br label [[BACKEDGE:%.*]] ; CHECK: onzero: ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: onone: @@ -1139,9 +1141,11 @@ ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: backedge: ; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 2, [[DEFAULT]] ], [ 0, [[ONZERO]] ], [ 1, [[ONONE]] ], [ [[SUB]], [[ONTWO]] ] -; 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]] @@ -1187,11 +1191,11 @@ ; 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 2, [[SUM]] ; CHECK-NEXT: switch i32 [[SUB]], label [[DEFAULT:%.*]] [ ; CHECK-NEXT: i32 0, label [[FIRST_BLOCK:%.*]] -; CHECK-NEXT: i32 1, label [[BACKEDGE]] +; CHECK-NEXT: i32 1, label [[BACKEDGE:%.*]] ; CHECK-NEXT: i32 2, label [[BACKEDGE]] ; CHECK-NEXT: ] ; CHECK: default: @@ -1200,9 +1204,11 @@ ; CHECK-NEXT: br label [[BACKEDGE]] ; CHECK: backedge: ; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[DEFAULT]] ], [ 1, [[FIRST_BLOCK]] ], [ [[SUB]], [[LOOP]] ], [ [[SUB]], [[LOOP]] ] -; 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]], 2 -; 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]]