aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Goldstein <goldstein.w.n@gmail.com>2024-03-10 11:48:10 -0500
committerNoah Goldstein <goldstein.w.n@gmail.com>2024-03-18 15:11:55 -0500
commitff63d628c46459437df21e09f70993685eba4bc3 (patch)
treec54ba37ad51c8944a4192285cee4b9f937ac3dbb
parent9936ac308332796bf16024ce30a4aa1fba2cce66 (diff)
downloadllvm-ff63d628c46459437df21e09f70993685eba4bc3.zip
llvm-ff63d628c46459437df21e09f70993685eba4bc3.tar.gz
llvm-ff63d628c46459437df21e09f70993685eba4bc3.tar.bz2
[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
-rw-r--r--llvm/lib/Transforms/Utils/CodeExtractor.cpp42
-rw-r--r--llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll4
-rw-r--r--llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll6
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected4
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected4
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected4
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected4
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected4
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected4
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected4
-rw-r--r--llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected4
11 files changed, 45 insertions, 39 deletions
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
index 0fac5fc..a43e2ce 100644
--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -1010,6 +1010,18 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
newFunction->addFnAttr(Attr);
}
+
+ if (NumExitBlocks == 0) {
+ // Mark the new function `noreturn` if applicable. Terminators which resume
+ // exception propagation are treated as returning instructions. This is to
+ // avoid inserting traps after calls to outlined functions which unwind.
+ if (none_of(Blocks, [](const BasicBlock *BB) {
+ const Instruction *Term = BB->getTerminator();
+ return isa<ReturnInst>(Term) || isa<ResumeInst>(Term);
+ }))
+ newFunction->setDoesNotReturn();
+ }
+
newFunction->insert(newFunction->end(), newRootNode);
// Create scalar and aggregate iterators to name all of the arguments we
@@ -1392,19 +1404,23 @@ CallInst *CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
case 0:
// There are no successors (the block containing the switch itself), which
// means that previously this was the last part of the function, and hence
- // this should be rewritten as a `ret'
-
- // Check if the function should return a value
- if (OldFnRetTy->isVoidTy()) {
- ReturnInst::Create(Context, nullptr, TheSwitch->getIterator()); // Return void
+ // this should be rewritten as a `ret` or `unreachable`.
+ if (newFunction->doesNotReturn()) {
+ // If fn is no return, end with an unreachable terminator.
+ (void)new UnreachableInst(Context, TheSwitch->getIterator());
+ } else if (OldFnRetTy->isVoidTy()) {
+ // We have no return value.
+ ReturnInst::Create(Context, nullptr,
+ TheSwitch->getIterator()); // Return void
} else if (OldFnRetTy == TheSwitch->getCondition()->getType()) {
// return what we have
- ReturnInst::Create(Context, TheSwitch->getCondition(), TheSwitch->getIterator());
+ ReturnInst::Create(Context, TheSwitch->getCondition(),
+ TheSwitch->getIterator());
} else {
// Otherwise we must have code extracted an unwind or something, just
// return whatever we want.
- ReturnInst::Create(Context,
- Constant::getNullValue(OldFnRetTy), TheSwitch->getIterator());
+ ReturnInst::Create(Context, Constant::getNullValue(OldFnRetTy),
+ TheSwitch->getIterator());
}
TheSwitch->eraseFromParent();
@@ -1895,16 +1911,6 @@ CodeExtractor::extractCodeRegion(const CodeExtractorAnalysisCache &CEAC,
fixupDebugInfoPostExtraction(*oldFunction, *newFunction, *TheCall);
- // Mark the new function `noreturn` if applicable. Terminators which resume
- // exception propagation are treated as returning instructions. This is to
- // avoid inserting traps after calls to outlined functions which unwind.
- bool doesNotReturn = none_of(*newFunction, [](const BasicBlock &BB) {
- const Instruction *Term = BB.getTerminator();
- return isa<ReturnInst>(Term) || isa<ResumeInst>(Term);
- });
- if (doesNotReturn)
- newFunction->setDoesNotReturn();
-
LLVM_DEBUG(if (verifyFunction(*newFunction, &errs())) {
newFunction->dump();
report_fatal_error("verification of newFunction failed!");
diff --git a/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll b/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll
index 0c05598..55013aa 100644
--- a/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll
+++ b/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll
@@ -2,9 +2,9 @@
; CHECK-LABEL: define {{.*}}@fun
; CHECK: call {{.*}}@fun.cold.1(
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: call {{.*}}@fun.cold.2(
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
define void @fun() {
entry:
br i1 undef, label %A.then, label %A.else
diff --git a/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll b/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll
index 6b12207..d2c4137 100644
--- a/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll
+++ b/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll
@@ -29,19 +29,19 @@ bb1:
; CHECK-LABEL: @f1(
; CHECK-NEXT: bb:
; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
;
;
; CHECK-LABEL: @f2(
; CHECK-NEXT: bb:
; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
;
;
; CHECK-LABEL: @f3(
; CHECK-NEXT: bb:
; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
;
;
; CHECK-LABEL: define internal void @outlined_ir_func_0(
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected
index 02d8870..775649c 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected
@@ -41,7 +41,7 @@ declare void @_Z10sideeffectv()
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -52,7 +52,7 @@ declare void @_Z10sideeffectv()
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected
index 05e5777..a8086ae 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected
@@ -44,7 +44,7 @@ declare void @_Z10sideeffectv()
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -55,7 +55,7 @@ declare void @_Z10sideeffectv()
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected
index 36bcbe3..57de350 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected
@@ -12,7 +12,7 @@ define void @foo(i32) {
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -36,7 +36,7 @@ define void @bar(i32) {
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected
index db7c692..696d5c6e 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected
@@ -15,7 +15,7 @@ define void @foo(i32) {
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -39,7 +39,7 @@ define void @bar(i32) {
; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; CHECK: codeRepl:
; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; CHECK-NEXT: ret void
+; CHECK-NEXT: unreachable
; CHECK: exit:
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected
index 1039995..5275870 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected
@@ -42,7 +42,7 @@ declare void @_Z10sideeffectv()
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;
@@ -53,7 +53,7 @@ declare void @_Z10sideeffectv()
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected
index 0001790..712ccb2 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected
@@ -45,7 +45,7 @@ declare void @_Z10sideeffectv()
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;
@@ -56,7 +56,7 @@ declare void @_Z10sideeffectv()
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected
index e05a57d..b5b12b7 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected
@@ -13,7 +13,7 @@ define void @foo(i32) {
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;
@@ -37,7 +37,7 @@ define void @bar(i32) {
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected
index 17be222..7e2b991 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected
@@ -16,7 +16,7 @@ define void @foo(i32) {
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;
@@ -40,7 +40,7 @@ define void @bar(i32) {
; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]]
; REUSE: codeRepl:
; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]]
-; REUSE-NEXT: ret void
+; REUSE-NEXT: unreachable
; REUSE: exit:
; REUSE-NEXT: ret void
;