]> granicus.if.org Git - llvm/commitdiff
[MachineOutliner] Disable outlining from noreturn functions
authorJessica Paquette <jpaquette@apple.com>
Fri, 4 Oct 2019 21:24:12 +0000 (21:24 +0000)
committerJessica Paquette <jpaquette@apple.com>
Fri, 4 Oct 2019 21:24:12 +0000 (21:24 +0000)
Outlining from noreturn functions doesn't do the correct thing right now. The
outliner should respect that the caller is marked noreturn. In the event that
we have a noreturn function, and the outlined code is in tail position, the
outliner will not see that the outlined function should be tail called. As a
result, you end up with a regular call containing a return.

Fixing this requires that we check that all candidates live inside noreturn
functions. So, for the sake of correctness, don't outline from noreturn
functions right now.

Add machine-outliner-noreturn.mir to test this.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@373791 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MachineOutliner.cpp
test/CodeGen/AArch64/machine-outliner-noreturn.mir [new file with mode: 0644]

index 533cce57adc8444b519e1dc8663c39facc0ecc26..60eeefba9d6fef8b0a4d62d4bba5586252eb2601 100644 (file)
@@ -1303,6 +1303,12 @@ void MachineOutliner::populateMapper(InstructionMapper &Mapper, Module &M,
     if (F.empty())
       continue;
 
+    // Disable outlining from noreturn functions right now. Noreturn requires
+    // special handling for the case where what we are outlining could be a
+    // tail call.
+    if (F.hasFnAttribute(Attribute::NoReturn))
+      continue;
+
     // There's something in F. Check if it has a MachineFunction associated with
     // it.
     MachineFunction *MF = MMI.getMachineFunction(F);
diff --git a/test/CodeGen/AArch64/machine-outliner-noreturn.mir b/test/CodeGen/AArch64/machine-outliner-noreturn.mir
new file mode 100644 (file)
index 0000000..29166f9
--- /dev/null
@@ -0,0 +1,56 @@
+# RUN: llc -mtriple=aarch64-unknown-unknown -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s
+
+--- |
+  define void @foo() #0 { ret void }
+  define void @bar(i32 %a) #0 { ret void }
+  define void @baz(i32 %a) #0 { ret void }
+  attributes #0 = { noredzone noreturn }
+...
+---
+
+# Temporarily disable outlining from noreturn functions. To do this, we need
+# to verify thst every function we want to outline from is noreturn.
+
+# CHECK-NOT: OUTLINED_FUNCTION
+
+name:            foo
+alignment:       4
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    $w3 = ORRWri $wzr, 1
+    $w4 = ORRWri $wzr, 1
+    BRK 1
+...
+---
+name:            bar
+alignment:       4
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    $w3 = ORRWri $wzr, 1
+    $w4 = ORRWri $wzr, 1
+    BRK 1
+...
+---
+name:            baz
+alignment:       4
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    $w3 = ORRWri $wzr, 1
+    $w4 = ORRWri $wzr, 1
+    BRK 1
+...