Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/include/llvm/Transforms/Scalar/JumpThreading.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
bool processGuards(BasicBlock *BB);
bool threadGuard(BasicBlock *BB, IntrinsicInst *Guard, BranchInst *BI);

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

private:
BasicBlock *splitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
const char *Suffix);
Expand Down
10 changes: 2 additions & 8 deletions llvm/lib/IR/BasicBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,8 @@ void BasicBlock::removePredecessor(BasicBlock *Pred,
if (NumPreds == 1)
continue;

// Try to replace the PHI node with a constant value, but make sure that
// this value isn't using the PHI node. (Except it's a PHI node itself. PHI
// nodes are allowed to reference themselves.)
if (Value *PhiConstant = Phi.hasConstantValue();
PhiConstant &&
(!isa<Instruction>(PhiConstant) || isa<PHINode>(PhiConstant) ||
llvm::all_of(Phi.users(),
[PhiConstant](User *U) { return U != PhiConstant; }))) {
// Try to replace the PHI node with a constant value.
if (Value *PhiConstant = Phi.hasConstantValue()) {
Phi.replaceAllUsesWith(PhiConstant);
Phi.eraseFromParent();
}
Expand Down
38 changes: 31 additions & 7 deletions llvm/lib/Transforms/Scalar/JumpThreading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,15 +335,19 @@ bool JumpThreadingPass::runImpl(Function &F_, FunctionAnalysisManager *FAM_,
if (&BB == &F->getEntryBlock() || DTU->isBBPendingDeletion(&BB))
continue;

if (pred_empty(&BB)) {
if (SmallVector<BasicBlock *, 32> Unreachable =
unreachableFromBB(&BB, DTU.get());
!Unreachable.empty()) {
// When processBlock makes BB unreachable it doesn't bother to fix up
// the instructions in it. We must remove BB to prevent invalid IR.
LLVM_DEBUG(dbgs() << " JT: Deleting dead block '" << BB.getName()
<< "' with terminator: " << *BB.getTerminator()
<< '\n');
LoopHeaders.erase(&BB);
LVI->eraseBlock(&BB);
DeleteDeadBlock(&BB, DTU.get());
for (BasicBlock *UBB : Unreachable) {
LLVM_DEBUG(dbgs()
<< " JT: Deleting dead block '" << UBB->getName()
<< "' with terminator: " << *UBB->getTerminator() << '\n');
LoopHeaders.erase(UBB);
LVI->eraseBlock(UBB);
}
DeleteDeadBlocks(Unreachable, DTU.get());
Changed = ChangedSinceLastAnalysisUpdate = true;
continue;
}
Expand Down Expand Up @@ -381,6 +385,26 @@ bool JumpThreadingPass::runImpl(Function &F_, FunctionAnalysisManager *FAM_,
return EverChanged;
}

SmallVector<BasicBlock *, 32>
JumpThreadingPass::unreachableFromBB(BasicBlock *BB, DomTreeUpdater *DTU) {
if (BB->isEntryBlock() || DTU->isBBPendingDeletion(BB))
return {};

SmallVector<BasicBlock *, 32> Unreachable({BB});
SmallPtrSet<BasicBlock *, 32> Seen({BB});

for (unsigned U = 0; U < Unreachable.size(); ++U) {
for (BasicBlock *Pred : predecessors(Unreachable[U])) {
if (Pred->isEntryBlock())
return {};
if (Seen.insert(Pred).second && !DTU->isBBPendingDeletion(Pred))
Unreachable.push_back(Pred);
}
}

return Unreachable;
}

// Replace uses of Cond with ToVal when safe to do so. If all uses are
// replaced, we can remove Cond. We cannot blindly replace all uses of Cond
// because we may incorrectly replace uses when guards/assumes are uses of
Expand Down
15 changes: 7 additions & 8 deletions llvm/test/Transforms/JumpThreading/PR33357-lvi-recursion.ll
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=jump-threading,verify -o - %s | FileCheck %s
@a = external global i16, align 1

; CHECK-LABEL: f
; CHECK: bb6:
; CHECK: bb2:
; CHECK: bb3:
; CHECK-NOT: bb0:
; CHECK-NOT: bb1:
; CHECK-NOT: bb4:
; CHECK-NOT: bb5:
define void @f(i32 %p1) {
; CHECK-LABEL: define void @f(
; CHECK-SAME: i32 [[P1:%.*]]) {
; CHECK-NEXT: [[BB6:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[P1]], 0
; CHECK-NEXT: ret void
;
bb0:
%0 = icmp eq i32 %p1, 0
br i1 true, label %bb6, label %bb1
Expand Down
15 changes: 1 addition & 14 deletions llvm/test/Transforms/JumpThreading/ne-undef.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,7 @@ declare i1 @cond()

define hidden void @hoge(i1 %c1, i32 %x) {
; CHECK-LABEL: @hoge(
; CHECK-NEXT: bb:
; CHECK-NEXT: br label [[BB13:%.*]]
; CHECK: bb4:
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP7:%.*]], undef
; CHECK-NEXT: br i1 [[TMP3]], label [[BB5:%.*]], label [[BB13]]
; CHECK: bb5:
; CHECK-NEXT: br label [[BB6:%.*]]
; CHECK: bb6:
; CHECK-NEXT: [[TMP7]] = phi i32 [ [[TMP7]], [[BB5]] ], [ [[X:%.*]], [[BB8:%.*]] ]
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C]], label [[BB4:%.*]], label [[BB8]]
; CHECK: bb8:
; CHECK-NEXT: br label [[BB6]]
; CHECK: bb13:
; CHECK-NEXT: bb13:
; CHECK-NEXT: ret void
;
bb:
Expand Down
9 changes: 1 addition & 8 deletions llvm/test/Transforms/JumpThreading/phi-xor-branch.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@

define void @test() {
; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[DUMMY:%.*]] = phi i16 [ 0, [[LOOP:%.*]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 0, 1
; CHECK-NEXT: [[XOR:%.*]] = xor i1 false, [[XOR]]
; CHECK-NEXT: br i1 [[XOR]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: exit:
; CHECK-NEXT: ret void
;
entry:
Expand Down
13 changes: 1 addition & 12 deletions llvm/test/Transforms/JumpThreading/pr62908.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,7 @@

define i32 @test() {
; CHECK-LABEL: define i32 @test() {
; CHECK-NEXT: join.thread:
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: unreachable:
; CHECK-NEXT: [[SH_PROM:%.*]] = zext i32 -1 to i64
; CHECK-NEXT: [[SHL:%.*]] = shl nsw i64 -1, [[SH_PROM]]
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[SHL]] to i32
; CHECK-NEXT: br label [[JOIN:%.*]]
; CHECK: join:
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[CONV]], [[UNREACHABLE:%.*]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[END]], label [[END]]
; CHECK: end:
; CHECK-NEXT: end:
; CHECK-NEXT: ret i32 0
;
entry:
Expand Down
2 changes: 0 additions & 2 deletions llvm/test/Transforms/JumpThreading/pr9331.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ define void @func(i8 zeroext %p_44) nounwind {
; CHECK-LABEL: @func(
; CHECK-NEXT: return:
; CHECK-NEXT: ret void
; CHECK: for.inc46:
; CHECK-NEXT: br label [[FOR_INC46:%.*]]
;
entry:
br i1 false, label %for.cond2, label %if.end50
Expand Down
49 changes: 40 additions & 9 deletions llvm/test/Transforms/JumpThreading/preserving-debugloc-br.ll
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=jump-threading < %s | FileCheck %s

; @process_block_branch checks that JumpThreading's processBlock() propagates
; @process_block_branch checks that JumpThreading's processBlock() propagates
; the debug location to the new branch instruction.

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

define i32 @process_block_branch(i32 %action) #0 !dbg !5 {
; CHECK-LABEL: define i32 @process_block_branch(
; CHECK: for.cond:
; CHECK-NEXT: br label %for.cond, !dbg [[DBG10:![0-9]+]]
; CHECK-SAME: i32 [[ACTION:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG5:![0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: switch i32 [[ACTION]], label %[[IF_THEN:.*]] [
; CHECK-NEXT: i32 1, label %[[IF_THEN]]
; CHECK-NEXT: i32 0, label %[[IF_THEN]]
; CHECK-NEXT: ], !dbg [[DBG8:![0-9]+]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: ret i32 undef, !dbg [[DBG9:![0-9]+]]
;
entry:
switch i32 %action, label %lor.rhs [
Expand All @@ -35,8 +42,18 @@ for.body: ; preds = %for.cond

define void @process_threadable_edges_branch(i32 %value) #0 !dbg !15 {
; CHECK-LABEL: define void @process_threadable_edges_branch(
; CHECK: L0:
; CHECK: br label %L2, !dbg [[DBG17:![0-9]+]]
; CHECK-SAME: i32 [[VALUE:%.*]]) #[[ATTR0]] !dbg [[DBG10:![0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VALUE]], 32, !dbg [[DBG11:![0-9]+]]
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[VALUE]], 64, !dbg [[DBG12:![0-9]+]]
; CHECK-NEXT: br i1 [[CMP]], label %[[L0:.*]], label %[[L2:.*]], !dbg [[DBG13:![0-9]+]]
; CHECK: [[L0]]:
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f2(), !dbg [[DBG14:![0-9]+]]
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f2(), !dbg [[DBG15:![0-9]+]]
; CHECK-NEXT: br label %[[L2]], !dbg [[DBG16:![0-9]+]]
; CHECK: [[L2]]:
; CHECK-NEXT: call void @f4(i32 [[ADD]]), !dbg [[DBG17:![0-9]+]]
; CHECK-NEXT: ret void, !dbg [[DBG18:![0-9]+]]
;
entry:
%cmp = icmp eq i32 %value, 32, !dbg !16
Expand Down Expand Up @@ -78,10 +95,6 @@ attributes #0 = { nounwind }
!llvm.debugify = !{!2, !3}
!llvm.module.flags = !{!4}

;.
; CHECK: [[DBG10]] = !DILocation(line: 6,
; CHECK: [[DBG17]] = !DILocation(line: 13,
;.

!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
!1 = !DIFile(filename: "temp.ll", directory: "/")
Expand Down Expand Up @@ -111,3 +124,21 @@ attributes #0 = { nounwind }
!25 = !DILocation(line: 17, column: 1, scope: !15)
!26 = !DILocation(line: 18, column: 1, scope: !15)
!27 = !DILocation(line: 19, column: 1, scope: !15)
;.
; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
; CHECK: [[META1]] = !DIFile(filename: "temp.ll", directory: {{.*}})
; 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]])
; CHECK: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]])
; CHECK: [[META7]] = !{}
; CHECK: [[DBG8]] = !DILocation(line: 1, column: 1, scope: [[DBG5]])
; CHECK: [[DBG9]] = !DILocation(line: 2, column: 1, scope: [[DBG5]])
; 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]])
; CHECK: [[DBG11]] = !DILocation(line: 8, column: 1, scope: [[DBG10]])
; CHECK: [[DBG12]] = !DILocation(line: 9, column: 1, scope: [[DBG10]])
; CHECK: [[DBG13]] = !DILocation(line: 10, column: 1, scope: [[DBG10]])
; CHECK: [[DBG14]] = !DILocation(line: 11, column: 1, scope: [[DBG10]])
; CHECK: [[DBG15]] = !DILocation(line: 12, column: 1, scope: [[DBG10]])
; CHECK: [[DBG16]] = !DILocation(line: 13, column: 1, scope: [[DBG10]])
; CHECK: [[DBG17]] = !DILocation(line: 16, column: 1, scope: [[DBG10]])
; CHECK: [[DBG18]] = !DILocation(line: 17, column: 1, scope: [[DBG10]])
;.
18 changes: 11 additions & 7 deletions llvm/test/Transforms/JumpThreading/removed-use.ll
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S < %s -passes=jump-threading | FileCheck %s
; CHECK-LABEL: @foo
; CHECK: bb6:
; CHECK-NEXT: ret void
; CHECK: bb3:
; CHECK: br label %bb3
define void @foo() {
; CHECK-LABEL: define void @foo() {
; CHECK-NEXT: [[BB6:.*:]]
; CHECK-NEXT: ret void
;
entry:
br i1 true, label %bb6, label %bb3

Expand All @@ -27,9 +27,13 @@ bb6:
ret void
}

; CHECK-LABEL: @bar
; Just check that we don't crash on this test.
define void @bar(i1 %p) {
; CHECK-LABEL: define void @bar(
; CHECK-SAME: i1 [[P:%.*]]) {
; CHECK-NEXT: [[EXIT:.*:]]
; CHECK-NEXT: ret void
;
entry:
br i1 false, label %bb2, label %exit

Expand All @@ -46,7 +50,7 @@ bb4:
bb5:
%x1 = phi i32 [ %x0, %bb3 ], [ 0, %bb4 ]
switch i32 %x1, label %exit [
i32 10, label %bb2
i32 10, label %bb2
]

exit:
Expand Down
36 changes: 2 additions & 34 deletions llvm/test/Transforms/JumpThreading/unreachable-loops.ll
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ define void @unreachable_single_bb_loop() {
; CHECK-NEXT: [[TMP:%.*]] = call i32 @a()
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP]], 1
; CHECK-NEXT: br i1 [[TMP1]], label [[BB8:%.*]], label [[BB8]]
; CHECK: bb2:
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP]], 1
; CHECK-NEXT: switch i1 [[TMP4]], label [[BB2:%.*]] [
; CHECK-NEXT: i1 false, label [[BB8]]
; CHECK-NEXT: i1 true, label [[BB8]]
; CHECK-NEXT: ]
; CHECK: bb8:
; CHECK-NEXT: ret void
;
Expand Down Expand Up @@ -52,14 +46,6 @@ define void @unreachable_multi_bbs_loop() {
; CHECK-NEXT: [[TMP:%.*]] = call i32 @a()
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP]], 1
; CHECK-NEXT: br i1 [[TMP1]], label [[BB8:%.*]], label [[BB8]]
; CHECK: bb3:
; CHECK-NEXT: br label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP]], 1
; CHECK-NEXT: switch i1 [[TMP4]], label [[BB3:%.*]] [
; CHECK-NEXT: i1 false, label [[BB8]]
; CHECK-NEXT: i1 true, label [[BB8]]
; CHECK-NEXT: ]
; CHECK: bb8:
; CHECK-NEXT: ret void
;
Expand Down Expand Up @@ -99,10 +85,6 @@ define void @PR48362(i1 %arg) {
; CHECK-LABEL: @PR48362(
; CHECK-NEXT: cleanup.cont1500:
; CHECK-NEXT: unreachable
; CHECK: if.end1733:
; CHECK-NEXT: [[I82:%.*]] = load i32, ptr undef, align 1
; CHECK-NEXT: [[TOBOOL1731_NOT:%.*]] = icmp eq i32 [[I82]], 0
; CHECK-NEXT: br label [[IF_END1733:%.*]]
;
cleanup1491: ; preds = %for.body1140
switch i32 0, label %cleanup2343.loopexit4 [
Expand Down Expand Up @@ -189,23 +171,9 @@ cleanup2343.loopexit4: ; preds = %cleanup1491

define i32 @constant_phi_leads_to_self_reference(ptr %ptr) {
; CHECK-LABEL: @constant_phi_leads_to_self_reference(
; CHECK-NEXT: [[A10:%.*]] = alloca i1, align 1
; CHECK-NEXT: br label [[F6:%.*]]
; CHECK: T3:
; CHECK-NEXT: [[L6:%.*]] = phi i1 [ [[C4:%.*]], [[BB6:%.*]] ]
; CHECK-NEXT: br label [[BB5:%.*]]
; CHECK: BB5:
; CHECK-NEXT: [[L10:%.*]] = load i1, ptr [[A10]], align 1
; CHECK-NEXT: br i1 [[L10]], label [[BB6]], label [[F6]]
; CHECK: BB6:
; CHECK-NEXT: [[LGV3:%.*]] = load i1, ptr [[A7:%.*]], align 1
; CHECK-NEXT: [[C4]] = icmp sle i1 [[L6]], true
; CHECK-NEXT: store i1 [[C4]], ptr [[A7]], align 1
; CHECK-NEXT: br i1 [[L6]], label [[F6]], label [[T3:%.*]]
; CHECK: F6:
; CHECK-NEXT: F6:
; CHECK-NEXT: [[A9:%.*]] = alloca i1, align 1
; CHECK-NEXT: ret i32 0
; CHECK: F7:
; CHECK-NEXT: br label [[BB5]]
;
%A9 = alloca i1, align 1
br i1 false, label %BB4, label %F6
Expand Down
Loading