Skip to content

Commit 0141187

Browse files
committed
llvm-reduce: Support exotic terminators in instructions-to-return
Use splitBasicBlock and avoid directly dealing with the specific of how to trim the existing terminators. We just need to deal with unconditional branch to return.
1 parent 1277837 commit 0141187

File tree

5 files changed

+126
-41
lines changed

5 files changed

+126
-41
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions-to-return --test FileCheck --test-arg --check-prefix=INTERESTING --test-arg %s --test-arg --input-file %s -o %t
2+
; RUN: FileCheck --check-prefix=RESULT %s < %t
3+
4+
@gv = global i32 0, align 4
5+
6+
; INTERESTING-LABEL: @callbr0(
7+
; INTERESTING: %load0 = load i32, ptr %arg0
8+
; INTERESTING: store i32 %load0, ptr @gv
9+
10+
; RESULT-LABEL: define void @callbr0(ptr %arg0) {
11+
; RESULT: %load0 = load i32, ptr %arg0, align 4
12+
; RESULT-NEXT: %callbr = callbr i32 asm
13+
define void @callbr0(ptr %arg0) {
14+
entry:
15+
%load0 = load i32, ptr %arg0
16+
%callbr = callbr i32 asm "", "=r,r,!i,!i"(i32 %load0)
17+
to label %one [label %two, label %three]
18+
one:
19+
store i32 %load0, ptr @gv
20+
ret void
21+
22+
two:
23+
store i32 %load0, ptr @gv
24+
ret void
25+
26+
three:
27+
store i32 %load0, ptr @gv
28+
ret void
29+
}
30+
31+
; INTERESTING-LABEL: @callbr1(
32+
; INTERESTING: %load0 = load i32, ptr %arg0
33+
34+
; RESULT-LABEL: define i32 @callbr1(ptr %arg0) {
35+
; RESULT-NEXT: entry:
36+
; RESULT-NEXT: %load0 = load i32, ptr %arg0
37+
; RESULT-NEXT: ret i32 %load0
38+
define void @callbr1(ptr %arg0) {
39+
entry:
40+
%load0 = load i32, ptr %arg0
41+
%callbr = callbr i32 asm "", "=r,r,!i,!i"(i32 %load0)
42+
to label %one [label %two, label %three]
43+
one:
44+
store i32 %load0, ptr @gv
45+
ret void
46+
47+
two:
48+
store i32 %load0, ptr @gv
49+
ret void
50+
51+
three:
52+
store i32 %load0, ptr @gv
53+
ret void
54+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions-to-return --test FileCheck --test-arg --check-prefix=INTERESTING --test-arg %s --test-arg --input-file %s -o %t
2+
; RUN: FileCheck --check-prefix=RESULT %s < %t
3+
4+
@gv = global i32 0, align 4
5+
6+
7+
define i32 @has_invoke_user(ptr %arg) {
8+
%load = load i32, ptr %arg
9+
store i32 %load, ptr @gv
10+
ret i32 9
11+
}
12+
13+
declare i32 @__gxx_personality_v0(...)
14+
15+
; INTERESTING-LABEL: @invoker_keep_invoke(
16+
; INTERESTING: %invoke
17+
; RESULT: %invoke = invoke i32 @has_invoke_user(ptr %arg)
18+
define void @invoker_keep_invoke(ptr %arg) personality ptr @__gxx_personality_v0 {
19+
bb:
20+
%invoke = invoke i32 @has_invoke_user(ptr %arg)
21+
to label %bb3 unwind label %bb1
22+
23+
bb1:
24+
landingpad { ptr, i32 }
25+
catch ptr null
26+
ret void
27+
28+
bb3:
29+
store i32 %invoke, ptr null
30+
ret void
31+
}
32+
33+
; INTERESTING-LABEL: @invoker_drop_invoke(
34+
; INTERESTING: %add = add i32
35+
36+
; RESULT-LABEL: define i32 @invoker_drop_invoke(i32 %arg0, ptr %arg1) personality ptr @__gxx_personality_v0 {
37+
; RESULT-NEXT: bb:
38+
; RESULT-NEXT: %add = add i32 %arg0, 9
39+
; RESULT-NEXT: ret i32 %add
40+
; RESULT-NEXT: }
41+
define void @invoker_drop_invoke(i32 %arg0, ptr %arg1) personality ptr @__gxx_personality_v0 {
42+
bb:
43+
%add = add i32 %arg0, 9
44+
%invoke = invoke i32 @has_invoke_user(ptr %arg1)
45+
to label %bb3 unwind label %bb1
46+
47+
bb1:
48+
landingpad { ptr, i32 }
49+
catch ptr null
50+
br label %bb3
51+
52+
bb3:
53+
%phi = phi i32 [ %invoke, %bb ], [ %add, %bb1 ]
54+
store i32 %phi, ptr null
55+
ret void
56+
}

llvm/test/tools/llvm-reduce/remove-bb-switch-default.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
; RESULT0-NEXT: br i1 %arg0, label %bb1, label %bb2
1717

1818
; RESULT0: bb1:
19-
; RESULT0: %bb1.phi = phi i32 [ %bb.load, %bb ], [ %bb.load, %bb2 ], [ %bb.load, %bb2 ]
19+
; RESULT0: %bb1.phi = phi i32 [ %bb.load, %bb ], [ %bb2.phi, %bb2 ], [ %bb2.phi, %bb2 ]
2020
; RESULT0-NEXT: store i32 1, ptr null, align 4
2121
; RESULT0-NEXT: ret void
2222

2323
; RESULT0: bb2: ; preds = %bb
24+
; RESULT0-NEXT: %bb2.phi = phi i32 [ %bb.load, %bb ]
2425
; RESULT0-NEXT: store i32 2, ptr null, align 4
25-
; RESULT0-NEXT: switch i32 %bb.load, label %bb1 [
26+
; RESULT0-NEXT: switch i32 %bb2.phi, label %bb1 [
2627
; RESULT0-NEXT: i32 0, label %bb1
2728
; RESULT0-NEXT: ]
2829

@@ -33,6 +34,7 @@
3334
; RESULT1-NEXT: br label %bb2
3435

3536
; RESULT1: bb2:
37+
; RESULT1-NEXT: %bb2.phi = phi i32 [ %bb.load, %bb ]
3638
; RESULT1-NEXT: store i32 2, ptr null, align 4
3739
; RESULT1-NEXT: ret void
3840
define void @main(i1 %arg0) {

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

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static void rewriteFuncWithReturnType(Function &OldF, Value *NewRetValue) {
5555
BasicBlock *NewRetBlock = NewRetI ? NewRetI->getParent() : &EntryBB;
5656

5757
BasicBlock::iterator NewValIt =
58-
NewRetI ? NewRetI->getIterator() : EntryBB.end();
58+
NewRetI ? std::next(NewRetI->getIterator()) : EntryBB.begin();
5959

6060
Type *OldRetTy = OldFuncTy->getReturnType();
6161

@@ -73,28 +73,16 @@ static void rewriteFuncWithReturnType(Function &OldF, Value *NewRetValue) {
7373
}
7474
}
7575

76-
// Now prune any CFG edges we have to deal with.
77-
//
78-
// Use KeepOneInputPHIs in case the instruction we are using for the return is
79-
// that phi.
80-
// TODO: Could avoid this with fancier iterator management.
81-
for (BasicBlock *Succ : successors(NewRetBlock))
82-
Succ->removePredecessor(NewRetBlock, /*KeepOneInputPHIs=*/true);
83-
84-
// Now delete the tail of this block, in reverse to delete uses before defs.
85-
for (Instruction &I : make_early_inc_range(
86-
make_range(NewRetBlock->rbegin(), NewValIt.getReverse()))) {
87-
Value *Replacement = getDefaultValue(I.getType());
88-
I.replaceAllUsesWith(Replacement);
89-
I.eraseFromParent();
90-
}
76+
// If we're returning an instruction, split the basic block so we can let
77+
// EliminateUnreachableBlocks cleanup the successors.
78+
BasicBlock *TailBB = NewRetBlock->splitBasicBlock(NewValIt);
9179

80+
// Replace the unconditional branch splitBasicBlock created
81+
NewRetBlock->getTerminator()->eraseFromParent();
9282
ReturnInst::Create(Ctx, NewRetValue, NewRetBlock);
9383

94-
// TODO: We may be eliminating blocks that were originally unreachable. We
95-
// probably ought to only be pruning blocks that became dead directly as a
96-
// result of our pruning here.
97-
EliminateUnreachableBlocks(OldF);
84+
// Now prune any CFG edges we have to deal with.
85+
simpleSimplifyCFG(OldF, {TailBB}, /*FoldBlockIntoPredecessor=*/false);
9886

9987
// Drop the incompatible attributes before we copy over to the new function.
10088
if (OldRetTy != NewRetTy) {
@@ -196,20 +184,6 @@ static bool shouldReplaceNonVoidReturnValue(const BasicBlock &BB,
196184
return true;
197185
}
198186

199-
static bool canHandleSuccessors(const BasicBlock &BB) {
200-
// TODO: Handle invoke and other exotic terminators
201-
if (!isa<ReturnInst, UnreachableInst, BranchInst, SwitchInst>(
202-
BB.getTerminator()))
203-
return false;
204-
205-
for (const BasicBlock *Succ : successors(&BB)) {
206-
if (!Succ->canSplitPredecessors())
207-
return false;
208-
}
209-
210-
return true;
211-
}
212-
213187
static bool shouldForwardValueToReturn(const BasicBlock &BB, const Value *V,
214188
Type *RetTy) {
215189
if (!isReallyValidReturnType(V->getType()))
@@ -228,10 +202,9 @@ static bool tryForwardingInstructionsToReturn(
228202
Type *RetTy = F.getReturnType();
229203

230204
for (BasicBlock &BB : F) {
231-
if (!canHandleSuccessors(BB))
232-
continue;
233-
234-
for (Instruction &I : BB) {
205+
// Skip the terminator, we can't insert a second terminator to return its
206+
// value.
207+
for (Instruction &I : make_range(BB.begin(), std::prev(BB.end()))) {
235208
if (shouldForwardValueToReturn(BB, &I, RetTy) && !O.shouldKeep()) {
236209
FuncsToReplace.emplace_back(&F, &I);
237210
return true;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void llvm::simpleSimplifyCFG(Function &F, ArrayRef<BasicBlock *> BBs,
7373
for (BasicBlock *BB : Unreachable) {
7474
for (BasicBlock *Successor : successors(&*BB))
7575
if (Visited.count(Successor))
76-
Successor->removePredecessor(&*BB);
76+
Successor->removePredecessor(&*BB, /*KeepOneInputPHIs=*/true);
7777
BB->dropAllReferences();
7878
}
7979

0 commit comments

Comments
 (0)