Skip to content

Commit 35aa07d

Browse files
committed
implement another approach; reset existing tests
1 parent e0ccb61 commit 35aa07d

File tree

10 files changed

+142
-101
lines changed

10 files changed

+142
-101
lines changed

llvm/include/llvm/Transforms/Scalar/JumpThreading.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,7 @@ class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
169169
bool processGuards(BasicBlock *BB);
170170
bool threadGuard(BasicBlock *BB, IntrinsicInst *Guard, BranchInst *BI);
171171

172-
// Determine unreachability with a possibly not up-to-date DominatorTree.
173-
// If BB is unreachable, return a list of BB and all its predecessors.
174-
// Otherwise, return an empty list.
175-
SmallVector<BasicBlock *, 32> unreachableFromBB(BasicBlock *BB,
176-
DomTreeUpdater *DTU);
172+
bool preserveLoopPreHeader(BasicBlock *BB);
177173

178174
private:
179175
BasicBlock *splitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,

llvm/lib/Transforms/Scalar/JumpThreading.cpp

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -335,19 +335,15 @@ bool JumpThreadingPass::runImpl(Function &F_, FunctionAnalysisManager *FAM_,
335335
if (&BB == &F->getEntryBlock() || DTU->isBBPendingDeletion(&BB))
336336
continue;
337337

338-
if (SmallVector<BasicBlock *, 32> Unreachable =
339-
unreachableFromBB(&BB, DTU.get());
340-
!Unreachable.empty()) {
338+
if (pred_empty(&BB) && !preserveLoopPreHeader(&BB)) {
341339
// When processBlock makes BB unreachable it doesn't bother to fix up
342340
// the instructions in it. We must remove BB to prevent invalid IR.
343-
for (BasicBlock *UBB : Unreachable) {
344-
LLVM_DEBUG(dbgs()
345-
<< " JT: Deleting dead block '" << UBB->getName()
346-
<< "' with terminator: " << *UBB->getTerminator() << '\n');
347-
LoopHeaders.erase(UBB);
348-
LVI->eraseBlock(UBB);
349-
}
350-
DeleteDeadBlocks(Unreachable, DTU.get());
341+
LLVM_DEBUG(dbgs() << " JT: Deleting dead block '" << BB.getName()
342+
<< "' with terminator: " << *BB.getTerminator()
343+
<< '\n');
344+
LoopHeaders.erase(&BB);
345+
LVI->eraseBlock(&BB);
346+
DeleteDeadBlock(&BB, DTU.get());
351347
Changed = ChangedSinceLastAnalysisUpdate = true;
352348
continue;
353349
}
@@ -385,26 +381,6 @@ bool JumpThreadingPass::runImpl(Function &F_, FunctionAnalysisManager *FAM_,
385381
return EverChanged;
386382
}
387383

388-
SmallVector<BasicBlock *, 32>
389-
JumpThreadingPass::unreachableFromBB(BasicBlock *BB, DomTreeUpdater *DTU) {
390-
if (BB->isEntryBlock() || DTU->isBBPendingDeletion(BB))
391-
return {};
392-
393-
SmallVector<BasicBlock *, 32> Unreachable({BB});
394-
SmallPtrSet<BasicBlock *, 32> Seen({BB});
395-
396-
for (unsigned U = 0; U < Unreachable.size(); ++U) {
397-
for (BasicBlock *Pred : predecessors(Unreachable[U])) {
398-
if (Pred->isEntryBlock())
399-
return {};
400-
if (Seen.insert(Pred).second && !DTU->isBBPendingDeletion(Pred))
401-
Unreachable.push_back(Pred);
402-
}
403-
}
404-
405-
return Unreachable;
406-
}
407-
408384
// Replace uses of Cond with ToVal when safe to do so. If all uses are
409385
// replaced, we can remove Cond. We cannot blindly replace all uses of Cond
410386
// because we may incorrectly replace uses when guards/assumes are uses of
@@ -1238,6 +1214,41 @@ static bool isOpDefinedInBlock(Value *Op, BasicBlock *BB) {
12381214
return false;
12391215
}
12401216

1217+
// Check if BB is a loop pre-header and if it has to be preserved to avoid
1218+
// invalid IR.
1219+
bool JumpThreadingPass::preserveLoopPreHeader(BasicBlock *BB) {
1220+
BasicBlock *Succ = BB->getUniqueSuccessor();
1221+
// Check if BB is a pre-header
1222+
if (!LoopHeaders.contains(Succ))
1223+
return false;
1224+
// Check for each PHI node in Succ if it uses BB.
1225+
// For each PHI node fulfilling this check, check if it is used by one of its
1226+
// operands, so if there is a circular use. Only verify this for non-PHI
1227+
// instructions since self-references are OK for PHIs. And only verify this
1228+
// for instructions that are defined in BB.
1229+
// If we find corresponding instructions, preserve the pre-header because
1230+
// otherwise, the PHI node may become constant and may be removed, which could
1231+
// lead to a circular reference.
1232+
return llvm::any_of(Succ->phis(), [BB](PHINode &PHI) {
1233+
if (PHI.getBasicBlockIndex(BB) == -1)
1234+
return false;
1235+
bool HasValueDefinedInPreHeader = false;
1236+
bool HasPotentialSelfReference = false;
1237+
for (Value *Op : PHI.operand_values()) {
1238+
Instruction *Inst = dyn_cast<Instruction>(Op);
1239+
if (!Inst)
1240+
continue;
1241+
if (isOpDefinedInBlock(Op, BB))
1242+
HasValueDefinedInPreHeader = true;
1243+
else if (!isa<PHINode>(Inst) &&
1244+
llvm::any_of(Inst->operand_values(),
1245+
[&PHI](Value *V) { return V == &PHI; }))
1246+
HasPotentialSelfReference = true;
1247+
}
1248+
return HasValueDefinedInPreHeader && HasPotentialSelfReference;
1249+
});
1250+
}
1251+
12411252
/// simplifyPartiallyRedundantLoad - If LoadI is an obviously partially
12421253
/// redundant load instruction, eliminate it by replacing it with a PHI node.
12431254
/// This is an important optimization that encourages jump threading, and needs

llvm/test/Transforms/JumpThreading/PR33357-lvi-recursion.ll

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
21
; RUN: opt -S -passes=jump-threading,verify -o - %s | FileCheck %s
32
@a = external global i16, align 1
43

4+
; CHECK-LABEL: f
5+
; CHECK: bb6:
6+
; CHECK: bb2:
7+
; CHECK: bb3:
8+
; CHECK-NOT: bb0:
9+
; CHECK-NOT: bb1:
10+
; CHECK-NOT: bb4:
11+
; CHECK-NOT: bb5:
512
define void @f(i32 %p1) {
6-
; CHECK-LABEL: define void @f(
7-
; CHECK-SAME: i32 [[P1:%.*]]) {
8-
; CHECK-NEXT: [[BB6:.*:]]
9-
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[P1]], 0
10-
; CHECK-NEXT: ret void
11-
;
1213
bb0:
1314
%0 = icmp eq i32 %p1, 0
1415
br i1 true, label %bb6, label %bb1

llvm/test/Transforms/JumpThreading/ne-undef.ll

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,20 @@ declare i1 @cond()
55

66
define hidden void @hoge(i1 %c1, i32 %x) {
77
; CHECK-LABEL: @hoge(
8-
; CHECK-NEXT: bb13:
8+
; CHECK-NEXT: bb:
9+
; CHECK-NEXT: br label [[BB13:%.*]]
10+
; CHECK: bb4:
11+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP7:%.*]], undef
12+
; CHECK-NEXT: br i1 [[TMP3]], label [[BB5:%.*]], label [[BB13]]
13+
; CHECK: bb5:
14+
; CHECK-NEXT: br label [[BB6:%.*]]
15+
; CHECK: bb6:
16+
; CHECK-NEXT: [[TMP7]] = phi i32 [ [[TMP7]], [[BB5]] ], [ [[X:%.*]], [[BB8:%.*]] ]
17+
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
18+
; CHECK-NEXT: br i1 [[C]], label [[BB4:%.*]], label [[BB8]]
19+
; CHECK: bb8:
20+
; CHECK-NEXT: br label [[BB6]]
21+
; CHECK: bb13:
922
; CHECK-NEXT: ret void
1023
;
1124
bb:

llvm/test/Transforms/JumpThreading/phi-xor-branch.ll

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@
55

66
define void @test() {
77
; CHECK-LABEL: @test(
8-
; CHECK-NEXT: exit:
8+
; CHECK-NEXT: entry:
9+
; CHECK-NEXT: br label [[EXIT:%.*]]
10+
; CHECK: loop:
11+
; CHECK-NEXT: [[DUMMY:%.*]] = phi i16 [ 0, [[LOOP:%.*]] ]
12+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 0, 1
13+
; CHECK-NEXT: [[XOR:%.*]] = xor i1 false, [[XOR]]
14+
; CHECK-NEXT: br i1 [[XOR]], label [[LOOP]], label [[EXIT]]
15+
; CHECK: exit:
916
; CHECK-NEXT: ret void
1017
;
1118
entry:

llvm/test/Transforms/JumpThreading/pr62908.ll

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,18 @@
55

66
define i32 @test() {
77
; CHECK-LABEL: define i32 @test() {
8-
; CHECK-NEXT: end:
8+
; CHECK-NEXT: join.thread:
9+
; CHECK-NEXT: br label [[END:%.*]]
10+
; CHECK: unreachable:
11+
; CHECK-NEXT: [[SH_PROM:%.*]] = zext i32 -1 to i64
12+
; CHECK-NEXT: [[SHL:%.*]] = shl nsw i64 -1, [[SH_PROM]]
13+
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[SHL]] to i32
14+
; CHECK-NEXT: br label [[JOIN:%.*]]
15+
; CHECK: join:
16+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[CONV]], [[UNREACHABLE:%.*]] ]
17+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI]], 0
18+
; CHECK-NEXT: br i1 [[CMP]], label [[END]], label [[END]]
19+
; CHECK: end:
920
; CHECK-NEXT: ret i32 0
1021
;
1122
entry:

llvm/test/Transforms/JumpThreading/pr9331.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ define void @func(i8 zeroext %p_44) nounwind {
55
; CHECK-LABEL: @func(
66
; CHECK-NEXT: return:
77
; CHECK-NEXT: ret void
8+
; CHECK: for.inc46:
9+
; CHECK-NEXT: br label [[FOR_INC46:%.*]]
810
;
911
entry:
1012
br i1 false, label %for.cond2, label %if.end50

llvm/test/Transforms/JumpThreading/preserving-debugloc-br.ll

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
21
; RUN: opt -S -passes=jump-threading < %s | FileCheck %s
32

4-
; @process_block_branch checks that JumpThreading's processBlock() propagates
3+
; @process_block_branch checks that JumpThreading's processBlock() propagates
54
; the debug location to the new branch instruction.
65

76
; @process_threadable_edges_branch checks that JumpThreading's processThreadableEdges()
87
; propagates the debug location to the new branch instruction.
98

109
define i32 @process_block_branch(i32 %action) #0 !dbg !5 {
1110
; CHECK-LABEL: define i32 @process_block_branch(
12-
; CHECK-SAME: i32 [[ACTION:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG5:![0-9]+]] {
13-
; CHECK-NEXT: [[ENTRY:.*:]]
14-
; CHECK-NEXT: switch i32 [[ACTION]], label %[[IF_THEN:.*]] [
15-
; CHECK-NEXT: i32 1, label %[[IF_THEN]]
16-
; CHECK-NEXT: i32 0, label %[[IF_THEN]]
17-
; CHECK-NEXT: ], !dbg [[DBG8:![0-9]+]]
18-
; CHECK: [[IF_THEN]]:
19-
; CHECK-NEXT: ret i32 0, !dbg [[DBG9:![0-9]+]]
11+
; CHECK: for.cond:
12+
; CHECK-NEXT: br label %for.cond, !dbg [[DBG10:![0-9]+]]
2013
;
2114
entry:
2215
switch i32 %action, label %lor.rhs [
@@ -25,7 +18,7 @@ entry:
2518
], !dbg !8
2619

2720
if.then: ; preds = %for.cond, %lor.end, %entry
28-
ret i32 0, !dbg !9
21+
ret i32 undef, !dbg !9
2922

3023
lor.rhs: ; preds = %entry
3124
br label %lor.end, !dbg !10
@@ -42,18 +35,8 @@ for.body: ; preds = %for.cond
4235

4336
define void @process_threadable_edges_branch(i32 %value) #0 !dbg !15 {
4437
; CHECK-LABEL: define void @process_threadable_edges_branch(
45-
; CHECK-SAME: i32 [[VALUE:%.*]]) #[[ATTR0]] !dbg [[DBG10:![0-9]+]] {
46-
; CHECK-NEXT: [[ENTRY:.*:]]
47-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VALUE]], 32, !dbg [[DBG11:![0-9]+]]
48-
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[VALUE]], 64, !dbg [[DBG12:![0-9]+]]
49-
; CHECK-NEXT: br i1 [[CMP]], label %[[L0:.*]], label %[[L2:.*]], !dbg [[DBG13:![0-9]+]]
50-
; CHECK: [[L0]]:
51-
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f2(), !dbg [[DBG14:![0-9]+]]
52-
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f2(), !dbg [[DBG15:![0-9]+]]
53-
; CHECK-NEXT: br label %[[L2]], !dbg [[DBG16:![0-9]+]]
54-
; CHECK: [[L2]]:
55-
; CHECK-NEXT: call void @f4(i32 [[ADD]]), !dbg [[DBG17:![0-9]+]]
56-
; CHECK-NEXT: ret void, !dbg [[DBG18:![0-9]+]]
38+
; CHECK: L0:
39+
; CHECK: br label %L2, !dbg [[DBG17:![0-9]+]]
5740
;
5841
entry:
5942
%cmp = icmp eq i32 %value, 32, !dbg !16
@@ -95,6 +78,10 @@ attributes #0 = { nounwind }
9578
!llvm.debugify = !{!2, !3}
9679
!llvm.module.flags = !{!4}
9780

81+
;.
82+
; CHECK: [[DBG10]] = !DILocation(line: 6,
83+
; CHECK: [[DBG17]] = !DILocation(line: 13,
84+
;.
9885

9986
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
10087
!1 = !DIFile(filename: "temp.ll", directory: "/")
@@ -124,21 +111,3 @@ attributes #0 = { nounwind }
124111
!25 = !DILocation(line: 17, column: 1, scope: !15)
125112
!26 = !DILocation(line: 18, column: 1, scope: !15)
126113
!27 = !DILocation(line: 19, column: 1, scope: !15)
127-
;.
128-
; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
129-
; CHECK: [[META1]] = !DIFile(filename: "temp.ll", directory: {{.*}})
130-
; CHECK: [[DBG5]] = distinct !DISubprogram(name: "process_block_branch", linkageName: "process_block_branch", scope: null, file: [[META1]], line: 1, type: [[META6:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]])
131-
; CHECK: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]])
132-
; CHECK: [[META7]] = !{}
133-
; CHECK: [[DBG8]] = !DILocation(line: 1, column: 1, scope: [[DBG5]])
134-
; CHECK: [[DBG9]] = !DILocation(line: 2, column: 1, scope: [[DBG5]])
135-
; CHECK: [[DBG10]] = distinct !DISubprogram(name: "process_threadable_edges_branch", linkageName: "process_threadable_edges_branch", scope: null, file: [[META1]], line: 8, type: [[META6]], scopeLine: 8, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]])
136-
; CHECK: [[DBG11]] = !DILocation(line: 8, column: 1, scope: [[DBG10]])
137-
; CHECK: [[DBG12]] = !DILocation(line: 9, column: 1, scope: [[DBG10]])
138-
; CHECK: [[DBG13]] = !DILocation(line: 10, column: 1, scope: [[DBG10]])
139-
; CHECK: [[DBG14]] = !DILocation(line: 11, column: 1, scope: [[DBG10]])
140-
; CHECK: [[DBG15]] = !DILocation(line: 12, column: 1, scope: [[DBG10]])
141-
; CHECK: [[DBG16]] = !DILocation(line: 13, column: 1, scope: [[DBG10]])
142-
; CHECK: [[DBG17]] = !DILocation(line: 16, column: 1, scope: [[DBG10]])
143-
; CHECK: [[DBG18]] = !DILocation(line: 17, column: 1, scope: [[DBG10]])
144-
;.

llvm/test/Transforms/JumpThreading/removed-use.ll

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
21
; RUN: opt -S < %s -passes=jump-threading | FileCheck %s
2+
; CHECK-LABEL: @foo
3+
; CHECK: bb6:
4+
; CHECK-NEXT: ret void
5+
; CHECK: bb3:
6+
; CHECK: br label %bb3
37
define void @foo() {
4-
; CHECK-LABEL: define void @foo() {
5-
; CHECK-NEXT: [[BB6:.*:]]
6-
; CHECK-NEXT: ret void
7-
;
88
entry:
99
br i1 true, label %bb6, label %bb3
1010

@@ -27,13 +27,9 @@ bb6:
2727
ret void
2828
}
2929

30+
; CHECK-LABEL: @bar
3031
; Just check that we don't crash on this test.
3132
define void @bar(i1 %p) {
32-
; CHECK-LABEL: define void @bar(
33-
; CHECK-SAME: i1 [[P:%.*]]) {
34-
; CHECK-NEXT: [[EXIT:.*:]]
35-
; CHECK-NEXT: ret void
36-
;
3733
entry:
3834
br i1 false, label %bb2, label %exit
3935

@@ -50,7 +46,7 @@ bb4:
5046
bb5:
5147
%x1 = phi i32 [ %x0, %bb3 ], [ 0, %bb4 ]
5248
switch i32 %x1, label %exit [
53-
i32 10, label %bb2
49+
i32 10, label %bb2
5450
]
5551

5652
exit:

0 commit comments

Comments
 (0)