Skip to content

Commit 70aca7b

Browse files
committed
[InstCombine] Explicitly track dead edges
This allows us to handle dead blocks with multiple incoming edges, where we can determine that all of those edges are dead (or cycles). This allows InstCombine to handle certain dead code patterns that can be produced by LoopVectorize in a single iteration. This is in preparation for D154579.
1 parent ac6e9e6 commit 70aca7b

File tree

5 files changed

+70
-71
lines changed

5 files changed

+70
-71
lines changed

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
8383

8484
bool MadeIRChange = false;
8585

86+
/// Edges that are known to never be taken.
87+
SmallDenseSet<std::pair<BasicBlock *, BasicBlock *>, 8> DeadEdges;
88+
8689
public:
8790
InstCombiner(InstructionWorklist &Worklist, BuilderTy &Builder,
8891
bool MinimizeSize, AAResults *AA, AssumptionCache &AC,

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
667667
bool tryToSinkInstruction(Instruction *I, BasicBlock *DestBlock);
668668

669669
bool removeInstructionsBeforeUnreachable(Instruction &I);
670-
bool handleUnreachableFrom(Instruction *I);
670+
bool handleUnreachableFrom(Instruction *I,
671+
SmallVectorImpl<BasicBlock *> &Worklist);
672+
bool handlePotentiallyDeadBlocks(SmallVectorImpl<BasicBlock *> &Worklist);
671673
bool handlePotentiallyDeadSuccessors(BasicBlock *BB, BasicBlock *LiveSucc);
672674
void freelyInvertAllUsersOf(Value *V, Value *IgnoredUser = nullptr);
673675
};

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,10 +1560,16 @@ Instruction *InstCombinerImpl::visitStoreInst(StoreInst &SI) {
15601560

15611561
// This is a non-terminator unreachable marker. Don't remove it.
15621562
if (isa<UndefValue>(Ptr)) {
1563-
// Remove all instructions after the marker and guaranteed-to-transfer
1564-
// instructions before the marker.
1565-
if (handleUnreachableFrom(SI.getNextNode()) ||
1566-
removeInstructionsBeforeUnreachable(SI))
1563+
// Remove guaranteed-to-transfer instructions before the marker.
1564+
if (removeInstructionsBeforeUnreachable(SI))
1565+
return &SI;
1566+
1567+
// Remove all instructions after the marker and handle dead blocks this
1568+
// implies.
1569+
SmallVector<BasicBlock *> Worklist;
1570+
bool Changed = handleUnreachableFrom(SI.getNextNode(), Worklist);
1571+
Changed |= handlePotentiallyDeadBlocks(Worklist);
1572+
if (Changed)
15671573
return &SI;
15681574
return nullptr;
15691575
}

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,7 +2748,8 @@ Instruction *InstCombinerImpl::visitUnconditionalBranchInst(BranchInst &BI) {
27482748

27492749
// Under the assumption that I is unreachable, remove it and following
27502750
// instructions.
2751-
bool InstCombinerImpl::handleUnreachableFrom(Instruction *I) {
2751+
bool InstCombinerImpl::handleUnreachableFrom(
2752+
Instruction *I, SmallVectorImpl<BasicBlock *> &Worklist) {
27522753
bool Changed = false;
27532754
BasicBlock *BB = I->getParent();
27542755
for (Instruction &Inst : make_early_inc_range(
@@ -2774,27 +2775,41 @@ bool InstCombinerImpl::handleUnreachableFrom(Instruction *I) {
27742775
Changed = true;
27752776
}
27762777

2777-
// TODO: Successor blocks may also be dead.
2778+
// Handle potentially dead successors.
2779+
for (BasicBlock *Succ : successors(BB))
2780+
if (DeadEdges.insert({BB, Succ}).second)
2781+
Worklist.push_back(Succ);
2782+
return Changed;
2783+
}
2784+
2785+
bool InstCombinerImpl::handlePotentiallyDeadBlocks(
2786+
SmallVectorImpl<BasicBlock *> &Worklist) {
2787+
bool Changed = false;
2788+
while (!Worklist.empty()) {
2789+
BasicBlock *BB = Worklist.pop_back_val();
2790+
if (!all_of(predecessors(BB), [&](BasicBlock *Pred) {
2791+
return DeadEdges.contains({Pred, BB}) || DT.dominates(BB, Pred);
2792+
}))
2793+
continue;
2794+
2795+
Changed |= handleUnreachableFrom(&BB->front(), Worklist);
2796+
}
27782797
return Changed;
27792798
}
27802799

27812800
bool InstCombinerImpl::handlePotentiallyDeadSuccessors(BasicBlock *BB,
27822801
BasicBlock *LiveSucc) {
2783-
bool Changed = false;
2802+
SmallVector<BasicBlock *> Worklist;
27842803
for (BasicBlock *Succ : successors(BB)) {
27852804
// The live successor isn't dead.
27862805
if (Succ == LiveSucc)
27872806
continue;
27882807

2789-
if (!all_of(predecessors(Succ), [&](BasicBlock *Pred) {
2790-
return DT.dominates(BasicBlockEdge(BB, Succ),
2791-
BasicBlockEdge(Pred, Succ));
2792-
}))
2793-
continue;
2794-
2795-
Changed |= handleUnreachableFrom(&Succ->front());
2808+
if (DeadEdges.insert({BB, Succ}).second)
2809+
Worklist.push_back(Succ);
27962810
}
2797-
return Changed;
2811+
2812+
return handlePotentiallyDeadBlocks(Worklist);
27982813
}
27992814

28002815
Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) {

llvm/test/Transforms/InstCombine/unreachable-code.ll

Lines changed: 28 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ define i32 @br_undef(i1 %x) {
6969
; CHECK: else:
7070
; CHECK-NEXT: br label [[JOIN]]
7171
; CHECK: join:
72-
; CHECK-NEXT: ret i32 undef
72+
; CHECK-NEXT: ret i32 poison
7373
;
7474
%c = xor i1 %x, undef
7575
br i1 %c, label %if, label %else
@@ -234,10 +234,8 @@ define void @non_term_unreachable_following_blocks() {
234234
; CHECK-NEXT: store i1 true, ptr poison, align 1
235235
; CHECK-NEXT: br label [[SPLIT:%.*]]
236236
; CHECK: split:
237-
; CHECK-NEXT: call void @dummy()
238237
; CHECK-NEXT: br label [[LOOP:%.*]]
239238
; CHECK: loop:
240-
; CHECK-NEXT: call void @dummy()
241239
; CHECK-NEXT: br label [[LOOP]]
242240
;
243241
call void @dummy()
@@ -299,28 +297,16 @@ exit:
299297
}
300298

301299
define void @two_br_not_into_loop(i1 %x) {
302-
; DEFAULT_ITER-LABEL: define void @two_br_not_into_loop
303-
; DEFAULT_ITER-SAME: (i1 [[X:%.*]]) {
304-
; DEFAULT_ITER-NEXT: br i1 true, label [[BB2:%.*]], label [[LOOP:%.*]]
305-
; DEFAULT_ITER: bb2:
306-
; DEFAULT_ITER-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
307-
; DEFAULT_ITER: loop:
308-
; DEFAULT_ITER-NEXT: br label [[LOOP]]
309-
; DEFAULT_ITER: exit:
310-
; DEFAULT_ITER-NEXT: call void @dummy()
311-
; DEFAULT_ITER-NEXT: ret void
312-
;
313-
; MAX1-LABEL: define void @two_br_not_into_loop
314-
; MAX1-SAME: (i1 [[X:%.*]]) {
315-
; MAX1-NEXT: br i1 true, label [[BB2:%.*]], label [[LOOP:%.*]]
316-
; MAX1: bb2:
317-
; MAX1-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
318-
; MAX1: loop:
319-
; MAX1-NEXT: call void @dummy()
320-
; MAX1-NEXT: br label [[LOOP]]
321-
; MAX1: exit:
322-
; MAX1-NEXT: call void @dummy()
323-
; MAX1-NEXT: ret void
300+
; CHECK-LABEL: define void @two_br_not_into_loop
301+
; CHECK-SAME: (i1 [[X:%.*]]) {
302+
; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[LOOP:%.*]]
303+
; CHECK: bb2:
304+
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
305+
; CHECK: loop:
306+
; CHECK-NEXT: br label [[LOOP]]
307+
; CHECK: exit:
308+
; CHECK-NEXT: call void @dummy()
309+
; CHECK-NEXT: ret void
324310
;
325311
%c = or i1 %x, true
326312
br i1 %c, label %bb2, label %loop
@@ -367,36 +353,20 @@ exit:
367353
}
368354

369355
define void @two_br_not_into_loop_with_split(i1 %x) {
370-
; DEFAULT_ITER-LABEL: define void @two_br_not_into_loop_with_split
371-
; DEFAULT_ITER-SAME: (i1 [[X:%.*]]) {
372-
; DEFAULT_ITER-NEXT: br i1 true, label [[BB2:%.*]], label [[SPLIT1:%.*]]
373-
; DEFAULT_ITER: bb2:
374-
; DEFAULT_ITER-NEXT: br i1 true, label [[EXIT:%.*]], label [[SPLIT2:%.*]]
375-
; DEFAULT_ITER: split1:
376-
; DEFAULT_ITER-NEXT: br label [[LOOP:%.*]]
377-
; DEFAULT_ITER: split2:
378-
; DEFAULT_ITER-NEXT: br label [[LOOP]]
379-
; DEFAULT_ITER: loop:
380-
; DEFAULT_ITER-NEXT: br label [[LOOP]]
381-
; DEFAULT_ITER: exit:
382-
; DEFAULT_ITER-NEXT: call void @dummy()
383-
; DEFAULT_ITER-NEXT: ret void
384-
;
385-
; MAX1-LABEL: define void @two_br_not_into_loop_with_split
386-
; MAX1-SAME: (i1 [[X:%.*]]) {
387-
; MAX1-NEXT: br i1 true, label [[BB2:%.*]], label [[SPLIT1:%.*]]
388-
; MAX1: bb2:
389-
; MAX1-NEXT: br i1 true, label [[EXIT:%.*]], label [[SPLIT2:%.*]]
390-
; MAX1: split1:
391-
; MAX1-NEXT: br label [[LOOP:%.*]]
392-
; MAX1: split2:
393-
; MAX1-NEXT: br label [[LOOP]]
394-
; MAX1: loop:
395-
; MAX1-NEXT: call void @dummy()
396-
; MAX1-NEXT: br label [[LOOP]]
397-
; MAX1: exit:
398-
; MAX1-NEXT: call void @dummy()
399-
; MAX1-NEXT: ret void
356+
; CHECK-LABEL: define void @two_br_not_into_loop_with_split
357+
; CHECK-SAME: (i1 [[X:%.*]]) {
358+
; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[SPLIT1:%.*]]
359+
; CHECK: bb2:
360+
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SPLIT2:%.*]]
361+
; CHECK: split1:
362+
; CHECK-NEXT: br label [[LOOP:%.*]]
363+
; CHECK: split2:
364+
; CHECK-NEXT: br label [[LOOP]]
365+
; CHECK: loop:
366+
; CHECK-NEXT: br label [[LOOP]]
367+
; CHECK: exit:
368+
; CHECK-NEXT: call void @dummy()
369+
; CHECK-NEXT: ret void
400370
;
401371
%c = or i1 %x, true
402372
br i1 %c, label %bb2, label %split1
@@ -422,3 +392,6 @@ exit:
422392
ret void
423393
}
424394

395+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
396+
; DEFAULT_ITER: {{.*}}
397+
; MAX1: {{.*}}

0 commit comments

Comments
 (0)