[llvm] acd2580 - [MachineOutliner][AArch64] Save + restore LR in noreturn functions

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 7 11:27:37 PST 2020


Author: Jessica Paquette
Date: 2020-01-07T11:27:25-08:00
New Revision: acd258082477b8a4edf3037127efb5fed4494da3

URL: https://github.com/llvm/llvm-project/commit/acd258082477b8a4edf3037127efb5fed4494da3
DIFF: https://github.com/llvm/llvm-project/commit/acd258082477b8a4edf3037127efb5fed4494da3.diff

LOG: [MachineOutliner][AArch64] Save + restore LR in noreturn functions

Conservatively always save + restore LR in noreturn functions.

These functions do not end in a RET, and so they aren't guaranteed to have an
instruction which uses LR in any way. So, as a result, you can end up in
unfortunate situations where you can't backtrace out of these functions in a
debugger.

Remove the old noreturn test, and add a new one which is more descriptive.

Remove the restriction that we can't outline from noreturn functions as well
since we now do the right thing.

Added: 
    llvm/test/CodeGen/AArch64/machine-outliner-noreturn-save-lr.mir

Modified: 
    llvm/lib/CodeGen/MachineOutliner.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Removed: 
    llvm/test/CodeGen/AArch64/machine-outliner-noreturn.mir


################################################################################
diff  --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index f742ac6b55c1..d6ce08a00976 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -1306,12 +1306,6 @@ 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/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index abde3e500212..54f3f7c10132 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -5868,11 +5868,21 @@ outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo(
     unsigned NumBytesNoStackCalls = 0;
     std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
 
+    // Check if we have to save LR.
     for (outliner::Candidate &C : RepeatedSequenceLocs) {
       C.initLRU(TRI);
 
+      // If we have a noreturn caller, then we're going to be conservative and
+      // say that we have to save LR. If we don't have a ret at the end of the
+      // block, then we can't reason about liveness accurately.
+      //
+      // FIXME: We can probably do better than always disabling this in
+      // noreturn functions by fixing up the liveness info.
+      bool IsNoReturn =
+          C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
+
       // Is LR available? If so, we don't need a save.
-      if (C.LRU.available(AArch64::LR)) {
+      if (C.LRU.available(AArch64::LR) && !IsNoReturn) {
         NumBytesNoStackCalls += 4;
         C.setCallInfo(MachineOutlinerNoLRSave, 4);
         CandidatesWithoutStackFixups.push_back(C);

diff  --git a/llvm/test/CodeGen/AArch64/machine-outliner-noreturn-save-lr.mir b/llvm/test/CodeGen/AArch64/machine-outliner-noreturn-save-lr.mir
new file mode 100644
index 000000000000..000752acb014
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-noreturn-save-lr.mir
@@ -0,0 +1,103 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=aarch64-unknown-unknown -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s
+
+# Verify that we save + restore LR around calls to outlined functions from
+# noreturn parents. LR isn't actually used, but debuggers need LR in this case
+# to get a backtrace.
+
+--- |
+  define void @save_lr_1() #0 { ret void }
+  define void @save_lr_2() #0 { ret void }
+  define void @save_lr_3() #0 { ret void }
+  define void @save_lr_4() #0 { ret void }
+  attributes #0 = { noredzone noreturn }
+...
+---
+
+name:            save_lr_1
+alignment:       4
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $lr
+    ; CHECK-LABEL: name: save_lr_1
+    ; CHECK: liveins: $lr
+    ; CHECK: $x0 = ORRXrs $xzr, $lr, 0
+    ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6
+    ; CHECK: $lr = ORRXrs $xzr, $x0, 0
+    $w3 = ORRWri $wzr, 1
+    $w4 = ORRWri $wzr, 1
+    BRK 1
+    $w5 = ORRWri $wzr, 1
+    $w6 = ORRWri $wzr, 1
+...
+---
+name:            save_lr_2
+alignment:       4
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $lr
+    ; CHECK-LABEL: name: save_lr_2
+    ; CHECK: liveins: $lr
+    ; CHECK: $x0 = ORRXrs $xzr, $lr, 0
+    ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6
+    ; CHECK: $lr = ORRXrs $xzr, $x0, 0
+    $w3 = ORRWri $wzr, 1
+    $w4 = ORRWri $wzr, 1
+    BRK 1
+    $w5 = ORRWri $wzr, 1
+    $w6 = ORRWri $wzr, 1
+...
+---
+name:            save_lr_3
+alignment:       4
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $lr
+    ; CHECK-LABEL: name: save_lr_3
+    ; CHECK: liveins: $lr
+    ; CHECK: $x0 = ORRXrs $xzr, $lr, 0
+    ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6
+    ; CHECK: $lr = ORRXrs $xzr, $x0, 0
+    $w3 = ORRWri $wzr, 1
+    $w4 = ORRWri $wzr, 1
+    BRK 1
+    $w5 = ORRWri $wzr, 1
+    $w6 = ORRWri $wzr, 1
+...
+---
+name:            save_lr_4
+alignment:       4
+tracksRegLiveness: true
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $lr
+    ; CHECK-LABEL: name: save_lr_4
+    ; CHECK: liveins: $lr
+    ; CHECK: $x0 = ORRXrs $xzr, $lr, 0
+    ; CHECK: BL @OUTLINED_FUNCTION_0, implicit-def $lr, implicit $sp, implicit-def $lr, implicit-def $lr, implicit-def $w3, implicit-def $w4, implicit-def $w5, implicit-def $w6
+    ; CHECK: $lr = ORRXrs $xzr, $x0, 0
+    $w3 = ORRWri $wzr, 1
+    $w4 = ORRWri $wzr, 1
+    BRK 1
+    $w5 = ORRWri $wzr, 1
+    $w6 = ORRWri $wzr, 1
+...

diff  --git a/llvm/test/CodeGen/AArch64/machine-outliner-noreturn.mir b/llvm/test/CodeGen/AArch64/machine-outliner-noreturn.mir
deleted file mode 100644
index 29166f9f12d8..000000000000
--- a/llvm/test/CodeGen/AArch64/machine-outliner-noreturn.mir
+++ /dev/null
@@ -1,56 +0,0 @@
-# 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
-...


        


More information about the llvm-commits mailing list