Skip to content

Commit 3a0c95f

Browse files
authored
llvm-reduce: Fix introducing unreachable code in simplify conditionals (#133842)
After replacing the branch condition, this was calling simplifyCFG to perform the cleanups of the branch. This is far too heavy of a hammer. We do not want all of the extra optimizations in simplifyCFG, and this could also leave behind dead code. Instead, minimally fold the terminator and try to delete the newly dead code. This is pretty much a direct copy of what bugpoint does.
1 parent 3f4e4e0 commit 3a0c95f

File tree

4 files changed

+182
-14
lines changed

4 files changed

+182
-14
lines changed
Lines changed: 124 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=simplify-conditionals-true --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
2-
; RUN: FileCheck --check-prefixes=RESULT-TRUE %s < %t
1+
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=simplify-conditionals-true --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS,CHECK --test-arg %s --test-arg --input-file %s -o %t
2+
; RUN: FileCheck --check-prefixes=RESULT-TRUE,RESULT,CHECK %s < %t
33

4-
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=simplify-conditionals-false --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
5-
; RUN: FileCheck --check-prefixes=RESULT-FALSE %s < %t
4+
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=simplify-conditionals-false --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS,CHECK --test-arg %s --test-arg --input-file %s -o %t
5+
; RUN: FileCheck --check-prefixes=RESULT-FALSE,RESULT,CHECK %s < %t
66

7-
; CHECK-INTERESTINGNESS-LABEL: @func(
7+
; Make sure there is no unreachable code introduced by the reduction
8+
9+
; CHECK-LABEL: @func_simplifies_true(
810
; CHECK-INTERESTINGNESS: store i32 1,
911

1012
; RESULT-TRUE: bb0:
@@ -13,15 +15,98 @@
1315
; RESULT-TRUE-NEXT: br label %bb2
1416
; RESULT-TRUE-NOT: bb1
1517

18+
; RESULT-FALSE: bb0:
19+
; RESULT-FALSE-NEXT: store i32 0, ptr null, align 4
20+
; RESULT-FALSE-NEXT: br i1 %cond0, label %bb1, label %bb2
21+
22+
; RESULT-FALSE: bb1: ; preds = %bb0
23+
; RESULT-FALSE-NEXT: store i32 1, ptr null, align 4
24+
; RESULT-FALSE-NEXT: br label %bb3
25+
26+
; RESULT-FALSE: bb2: ; preds = %bb0
27+
; RESULT-FALSE-NEXT: store i32 2, ptr null, align 4
28+
; RESULT-FALSE-NEXT: br label %bb3
29+
30+
; RESULT-FALSE: bb3: ; preds = %bb1, %bb2
31+
; RESULT-FALSE-NEXT: ret void
32+
define void @func_simplifies_true(i1 %cond0, i1 %cond1) {
33+
bb0:
34+
store i32 0, ptr null
35+
br i1 %cond0, label %bb1, label %bb2
36+
37+
bb1:
38+
store i32 1, ptr null
39+
br i1 %cond1, label %bb2, label %bb3
40+
41+
bb2:
42+
store i32 2, ptr null
43+
br label %bb3
44+
45+
bb3:
46+
ret void
47+
}
48+
49+
; CHECK-LABEL: @func_simplifies_false(
50+
; CHECK-INTERESTINGNESS: store i32 0,
51+
52+
; RESULT-TRUE: bb0:
53+
; RESULT-TRUE: store i32 0, ptr null, align 4
54+
; RESULT-TRUE-NEXT: store i32 1, ptr null, align 4
55+
; RESULT-TRUE-NEXT: br label %bb2
56+
; RESULT-TRUE-NOT: bb1
57+
1658

1759
; RESULT-FALSE: bb0:
1860
; RESULT-FALSE: store i32 0, ptr null, align 4
1961
; RESULT-FALSE-NEXT: br label %bb2
2062

21-
; RESULT-FALSE: bb1: ; No predecessors!
22-
; RESULT-FALSE-NEXT: store i32 1, ptr null, align 4
63+
; RESULT-FALSE: bb2: ; preds = %bb0
64+
; RESULT-FALSE-NEXT: store i32 2, ptr null, align 4
2365
; RESULT-FALSE-NEXT: br label %bb3
24-
define void @func(i1 %cond0, i1 %cond1) {
66+
67+
; RESULT-FALSE: bb3: ; preds = %bb2
68+
; RESULT-FALSE-NEXT: ret void
69+
define void @func_simplifies_false(i1 %cond0, i1 %cond1) {
70+
bb0:
71+
store i32 0, ptr null
72+
br i1 %cond0, label %bb1, label %bb2
73+
74+
bb1:
75+
store i32 1, ptr null
76+
br i1 %cond1, label %bb2, label %bb3
77+
78+
bb2:
79+
store i32 2, ptr null
80+
br label %bb3
81+
82+
bb3:
83+
ret void
84+
}
85+
86+
; Make sure we don't break the reduction in the other functions by
87+
; having something interesting in unrelated unreachable code.
88+
89+
; CHECK-LABEL: @func_simplifies_true_with_interesting_unreachable_code(
90+
; CHECK-INTERESTINGNESS: store i32 0,
91+
; CHECK-INTERESTINGNESS: store i32 %arg,
92+
93+
94+
; RESULT: bb0:
95+
; RESULT-NEXT: store i32 0
96+
; RESULT-NEXT: br i1 %cond0, label %bb1, label %bb2
97+
98+
; RESULT: bb1:
99+
; RESULT-NEXT: store i32 1
100+
; RESULT-NEXT: br i1 %cond1, label %bb2, label %bb3
101+
102+
; RESULT: bb2:
103+
; RESULT-NEXT: store i32 2
104+
; RESULT-NEXT: br label %bb3
105+
106+
; RESULT: dead_code: ; preds = %dead_code
107+
; RESULT-NEXT: store i32 %arg,
108+
; RESULT-NEXT: br label %dead_code
109+
define void @func_simplifies_true_with_interesting_unreachable_code(i1 %cond0, i1 %cond1, i32 %arg) {
25110
bb0:
26111
store i32 0, ptr null
27112
br i1 %cond0, label %bb1, label %bb2
@@ -36,4 +121,35 @@ bb2:
36121

37122
bb3:
38123
ret void
124+
125+
dead_code:
126+
store i32 %arg, ptr null
127+
br label %dead_code
128+
}
129+
130+
@block_address_user = constant [1 x ptr] [ptr blockaddress(@will_be_unreachable_blockaddress_use, %will_be_unreachable)]
131+
132+
; CHECK-LABEL: @will_be_unreachable_blockaddress_use(
133+
; CHECK-INTERESTINGNESS: inttoptr
134+
135+
; RESULT-FALSE: entry:
136+
; RESULT-FALSE-NEXT: %i2p = inttoptr i64 %int to ptr
137+
; RESULT-FALSE-NEXT: br label %exit
138+
139+
; RESULT-FALSE: exit: ; preds = %entry
140+
; RESULT-FALSE-NEXT: ret i1 false
141+
define i1 @will_be_unreachable_blockaddress_use(i1 %cond, i64 %int) {
142+
entry:
143+
%i2p = inttoptr i64 %int to ptr
144+
br i1 %cond, label %will_be_unreachable, label %exit
145+
146+
will_be_unreachable:
147+
%load = load ptr, ptr %i2p, align 8
148+
br label %for.body
149+
150+
for.body:
151+
br label %for.body
152+
153+
exit:
154+
ret i1 false
39155
}

llvm/tools/llvm-reduce/deltas/ReduceUsingSimplifyCFG.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "ReduceUsingSimplifyCFG.h"
15+
#include "Utils.h"
1516
#include "llvm/Analysis/TargetTransformInfo.h"
1617
#include "llvm/IR/Constants.h"
1718
#include "llvm/IR/Instructions.h"
@@ -35,13 +36,17 @@ void llvm::reduceUsingSimplifyCFGDeltaPass(Oracle &O,
3536
static void reduceConditionals(Oracle &O, ReducerWorkItem &WorkItem,
3637
bool Direction) {
3738
Module &M = WorkItem.getModule();
38-
SmallVector<BasicBlock *, 16> ToSimplify;
3939

4040
LLVMContext &Ctx = M.getContext();
4141
ConstantInt *ConstValToSet =
4242
Direction ? ConstantInt::getTrue(Ctx) : ConstantInt::getFalse(Ctx);
4343

44-
for (auto &F : M) {
44+
for (Function &F : M) {
45+
if (F.isDeclaration())
46+
continue;
47+
48+
SmallVector<BasicBlock *, 16> ToSimplify;
49+
4550
for (auto &BB : F) {
4651
auto *BR = dyn_cast<BranchInst>(BB.getTerminator());
4752
if (!BR || !BR->isConditional() || BR->getCondition() == ConstValToSet ||
@@ -51,11 +56,13 @@ static void reduceConditionals(Oracle &O, ReducerWorkItem &WorkItem,
5156
BR->setCondition(ConstValToSet);
5257
ToSimplify.push_back(&BB);
5358
}
54-
}
5559

56-
TargetTransformInfo TTI(M.getDataLayout());
57-
for (auto *BB : ToSimplify)
58-
simplifyCFG(BB, TTI);
60+
if (!ToSimplify.empty()) {
61+
// TODO: Should probably leave MergeBlockIntoPredecessor for a separate
62+
// reduction
63+
simpleSimplifyCFG(F, ToSimplify);
64+
}
65+
}
5966
}
6067

6168
void llvm::reduceConditionalsTrueDeltaPass(Oracle &O,

llvm/tools/llvm-reduce/deltas/Utils.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "llvm/IR/Constants.h"
1515
#include "llvm/IR/GlobalAlias.h"
1616
#include "llvm/IR/GlobalIFunc.h"
17+
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
18+
#include "llvm/Transforms/Utils/Local.h"
1719

1820
using namespace llvm;
1921

@@ -47,3 +49,40 @@ bool llvm::hasAliasOrBlockAddressUse(Function &F) {
4749
return isa<GlobalAlias, GlobalIFunc, BlockAddress>(U);
4850
});
4951
}
52+
53+
void llvm::simpleSimplifyCFG(Function &F, ArrayRef<BasicBlock *> BBs,
54+
bool FoldBlockIntoPredecessor) {
55+
56+
for (BasicBlock *BB : BBs) {
57+
ConstantFoldTerminator(BB);
58+
if (FoldBlockIntoPredecessor)
59+
MergeBlockIntoPredecessor(BB);
60+
}
61+
62+
// Remove unreachable blocks
63+
//
64+
// removeUnreachableBlocks can't be used here, it will turn various undefined
65+
// behavior into unreachables, but llvm-reduce was the thing that generated
66+
// the undefined behavior, and we don't want it to kill the entire program.
67+
SmallPtrSet<BasicBlock *, 16> Visited(llvm::from_range,
68+
depth_first(&F.getEntryBlock()));
69+
70+
SmallVector<BasicBlock *, 16> Unreachable;
71+
for (BasicBlock &BB : F) {
72+
if (!Visited.count(&BB))
73+
Unreachable.push_back(&BB);
74+
}
75+
76+
// The dead BB's may be in a dead cycle or otherwise have references to each
77+
// other. Because of this, we have to drop all references first, then delete
78+
// them all at once.
79+
for (BasicBlock *BB : Unreachable) {
80+
for (BasicBlock *Successor : successors(&*BB))
81+
if (Visited.count(Successor))
82+
Successor->removePredecessor(&*BB);
83+
BB->dropAllReferences();
84+
}
85+
86+
for (BasicBlock *BB : Unreachable)
87+
BB->eraseFromParent();
88+
}

llvm/tools/llvm-reduce/deltas/Utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/Support/CommandLine.h"
1717

1818
namespace llvm {
19+
class BasicBlock;
1920
class Function;
2021
class Type;
2122
class Value;
@@ -26,6 +27,11 @@ Value *getDefaultValue(Type *T);
2627
bool hasAliasUse(Function &F);
2728
bool hasAliasOrBlockAddressUse(Function &F);
2829

30+
// Constant fold terminators in \p and minimally prune unreachable code from the
31+
// function.
32+
void simpleSimplifyCFG(Function &F, ArrayRef<BasicBlock *> BBs,
33+
bool FoldBlockIntoPredecessor = true);
34+
2935
} // namespace llvm
3036

3137
#endif

0 commit comments

Comments
 (0)