Skip to content

Commit ff63d62

Browse files
committed
[CodeExtractor] Terminate callsite blocks to new noreturn functions with unreachable
Since some of the users of `CodeExtractor` like `HotColdSplitting` run late in the pipeline, returns are not cleaned to `unreachable`. So, just emit `unreachable` directly if the function is `noreturn`. Closes #84682
1 parent 9936ac3 commit ff63d62

11 files changed

+45
-39
lines changed

llvm/lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,18 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
10101010

10111011
newFunction->addFnAttr(Attr);
10121012
}
1013+
1014+
if (NumExitBlocks == 0) {
1015+
// Mark the new function `noreturn` if applicable. Terminators which resume
1016+
// exception propagation are treated as returning instructions. This is to
1017+
// avoid inserting traps after calls to outlined functions which unwind.
1018+
if (none_of(Blocks, [](const BasicBlock *BB) {
1019+
const Instruction *Term = BB->getTerminator();
1020+
return isa<ReturnInst>(Term) || isa<ResumeInst>(Term);
1021+
}))
1022+
newFunction->setDoesNotReturn();
1023+
}
1024+
10131025
newFunction->insert(newFunction->end(), newRootNode);
10141026

10151027
// Create scalar and aggregate iterators to name all of the arguments we
@@ -1392,19 +1404,23 @@ CallInst *CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
13921404
case 0:
13931405
// There are no successors (the block containing the switch itself), which
13941406
// means that previously this was the last part of the function, and hence
1395-
// this should be rewritten as a `ret'
1396-
1397-
// Check if the function should return a value
1398-
if (OldFnRetTy->isVoidTy()) {
1399-
ReturnInst::Create(Context, nullptr, TheSwitch->getIterator()); // Return void
1407+
// this should be rewritten as a `ret` or `unreachable`.
1408+
if (newFunction->doesNotReturn()) {
1409+
// If fn is no return, end with an unreachable terminator.
1410+
(void)new UnreachableInst(Context, TheSwitch->getIterator());
1411+
} else if (OldFnRetTy->isVoidTy()) {
1412+
// We have no return value.
1413+
ReturnInst::Create(Context, nullptr,
1414+
TheSwitch->getIterator()); // Return void
14001415
} else if (OldFnRetTy == TheSwitch->getCondition()->getType()) {
14011416
// return what we have
1402-
ReturnInst::Create(Context, TheSwitch->getCondition(), TheSwitch->getIterator());
1417+
ReturnInst::Create(Context, TheSwitch->getCondition(),
1418+
TheSwitch->getIterator());
14031419
} else {
14041420
// Otherwise we must have code extracted an unwind or something, just
14051421
// return whatever we want.
1406-
ReturnInst::Create(Context,
1407-
Constant::getNullValue(OldFnRetTy), TheSwitch->getIterator());
1422+
ReturnInst::Create(Context, Constant::getNullValue(OldFnRetTy),
1423+
TheSwitch->getIterator());
14081424
}
14091425

14101426
TheSwitch->eraseFromParent();
@@ -1895,16 +1911,6 @@ CodeExtractor::extractCodeRegion(const CodeExtractorAnalysisCache &CEAC,
18951911

18961912
fixupDebugInfoPostExtraction(*oldFunction, *newFunction, *TheCall);
18971913

1898-
// Mark the new function `noreturn` if applicable. Terminators which resume
1899-
// exception propagation are treated as returning instructions. This is to
1900-
// avoid inserting traps after calls to outlined functions which unwind.
1901-
bool doesNotReturn = none_of(*newFunction, [](const BasicBlock &BB) {
1902-
const Instruction *Term = BB.getTerminator();
1903-
return isa<ReturnInst>(Term) || isa<ResumeInst>(Term);
1904-
});
1905-
if (doesNotReturn)
1906-
newFunction->setDoesNotReturn();
1907-
19081914
LLVM_DEBUG(if (verifyFunction(*newFunction, &errs())) {
19091915
newFunction->dump();
19101916
report_fatal_error("verification of newFunction failed!");

llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
; CHECK-LABEL: define {{.*}}@fun
44
; CHECK: call {{.*}}@fun.cold.1(
5-
; CHECK-NEXT: ret void
5+
; CHECK-NEXT: unreachable
66
; CHECK: call {{.*}}@fun.cold.2(
7-
; CHECK-NEXT: ret void
7+
; CHECK-NEXT: unreachable
88
define void @fun() {
99
entry:
1010
br i1 undef, label %A.then, label %A.else

llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,19 @@ bb1:
2929
; CHECK-LABEL: @f1(
3030
; CHECK-NEXT: bb:
3131
; CHECK-NEXT: call void @outlined_ir_func_0()
32-
; CHECK-NEXT: ret void
32+
; CHECK-NEXT: unreachable
3333
;
3434
;
3535
; CHECK-LABEL: @f2(
3636
; CHECK-NEXT: bb:
3737
; CHECK-NEXT: call void @outlined_ir_func_0()
38-
; CHECK-NEXT: ret void
38+
; CHECK-NEXT: unreachable
3939
;
4040
;
4141
; CHECK-LABEL: @f3(
4242
; CHECK-NEXT: bb:
4343
; CHECK-NEXT: call void @outlined_ir_func_0()
44-
; CHECK-NEXT: ret void
44+
; CHECK-NEXT: unreachable
4545
;
4646
;
4747
; CHECK-LABEL: define internal void @outlined_ir_func_0(

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ declare void @_Z10sideeffectv()
4141
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
4242
; CHECK: codeRepl:
4343
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
44-
; CHECK-NEXT: ret void
44+
; CHECK-NEXT: unreachable
4545
; CHECK: exit:
4646
; CHECK-NEXT: ret void
4747
;
@@ -52,7 +52,7 @@ declare void @_Z10sideeffectv()
5252
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
5353
; CHECK: codeRepl:
5454
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
55-
; CHECK-NEXT: ret void
55+
; CHECK-NEXT: unreachable
5656
; CHECK: exit:
5757
; CHECK-NEXT: ret void
5858
;

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ declare void @_Z10sideeffectv()
4444
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
4545
; CHECK: codeRepl:
4646
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
47-
; CHECK-NEXT: ret void
47+
; CHECK-NEXT: unreachable
4848
; CHECK: exit:
4949
; CHECK-NEXT: ret void
5050
;
@@ -55,7 +55,7 @@ declare void @_Z10sideeffectv()
5555
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
5656
; CHECK: codeRepl:
5757
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
58-
; CHECK-NEXT: ret void
58+
; CHECK-NEXT: unreachable
5959
; CHECK: exit:
6060
; CHECK-NEXT: ret void
6161
;

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ define void @foo(i32) {
1212
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
1313
; CHECK: codeRepl:
1414
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
15-
; CHECK-NEXT: ret void
15+
; CHECK-NEXT: unreachable
1616
; CHECK: exit:
1717
; CHECK-NEXT: ret void
1818
;
@@ -36,7 +36,7 @@ define void @bar(i32) {
3636
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
3737
; CHECK: codeRepl:
3838
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
39-
; CHECK-NEXT: ret void
39+
; CHECK-NEXT: unreachable
4040
; CHECK: exit:
4141
; CHECK-NEXT: ret void
4242
;

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ define void @foo(i32) {
1515
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
1616
; CHECK: codeRepl:
1717
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
18-
; CHECK-NEXT: ret void
18+
; CHECK-NEXT: unreachable
1919
; CHECK: exit:
2020
; CHECK-NEXT: ret void
2121
;
@@ -39,7 +39,7 @@ define void @bar(i32) {
3939
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
4040
; CHECK: codeRepl:
4141
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
42-
; CHECK-NEXT: ret void
42+
; CHECK-NEXT: unreachable
4343
; CHECK: exit:
4444
; CHECK-NEXT: ret void
4545
;

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ declare void @_Z10sideeffectv()
4242
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
4343
; REUSE: codeRepl:
4444
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
45-
; REUSE-NEXT: ret void
45+
; REUSE-NEXT: unreachable
4646
; REUSE: exit:
4747
; REUSE-NEXT: ret void
4848
;
@@ -53,7 +53,7 @@ declare void @_Z10sideeffectv()
5353
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
5454
; REUSE: codeRepl:
5555
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
56-
; REUSE-NEXT: ret void
56+
; REUSE-NEXT: unreachable
5757
; REUSE: exit:
5858
; REUSE-NEXT: ret void
5959
;

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ declare void @_Z10sideeffectv()
4545
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
4646
; REUSE: codeRepl:
4747
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
48-
; REUSE-NEXT: ret void
48+
; REUSE-NEXT: unreachable
4949
; REUSE: exit:
5050
; REUSE-NEXT: ret void
5151
;
@@ -56,7 +56,7 @@ declare void @_Z10sideeffectv()
5656
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
5757
; REUSE: codeRepl:
5858
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
59-
; REUSE-NEXT: ret void
59+
; REUSE-NEXT: unreachable
6060
; REUSE: exit:
6161
; REUSE-NEXT: ret void
6262
;

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ define void @foo(i32) {
1313
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
1414
; REUSE: codeRepl:
1515
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
16-
; REUSE-NEXT: ret void
16+
; REUSE-NEXT: unreachable
1717
; REUSE: exit:
1818
; REUSE-NEXT: ret void
1919
;
@@ -37,7 +37,7 @@ define void @bar(i32) {
3737
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
3838
; REUSE: codeRepl:
3939
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
40-
; REUSE-NEXT: ret void
40+
; REUSE-NEXT: unreachable
4141
; REUSE: exit:
4242
; REUSE-NEXT: ret void
4343
;

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ define void @foo(i32) {
1616
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
1717
; REUSE: codeRepl:
1818
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
19-
; REUSE-NEXT: ret void
19+
; REUSE-NEXT: unreachable
2020
; REUSE: exit:
2121
; REUSE-NEXT: ret void
2222
;
@@ -40,7 +40,7 @@ define void @bar(i32) {
4040
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
4141
; REUSE: codeRepl:
4242
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
43-
; REUSE-NEXT: ret void
43+
; REUSE-NEXT: unreachable
4444
; REUSE: exit:
4545
; REUSE-NEXT: ret void
4646
;

0 commit comments

Comments
 (0)