summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.cpp58
-rw-r--r--llvm/test/CodeGen/AArch64/machine-outliner-regsave.mir36
2 files changed, 52 insertions, 42 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 837c6e7c356..784a4b02e6a 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -5165,42 +5165,36 @@ AArch64InstrInfo::getOutliningCandidateInfo(
SetCandidateCallInfo(MachineOutlinerThunk, 4);
}
- // Make sure that LR isn't live on entry to this candidate. The only
- // instructions that use LR that could possibly appear in a repeated sequence
- // are calls. Therefore, we only have to check and see if LR is dead on entry
- // to (or exit from) some candidate.
- else if (std::all_of(RepeatedSequenceLocs.begin(),
- RepeatedSequenceLocs.end(),
- [&TRI](outliner::Candidate &C) {
- C.initLRU(TRI);
- return C.LRU.available(AArch64::LR);
- })) {
- FrameID = MachineOutlinerNoLRSave;
- NumBytesToCreateFrame = 4;
- SetCandidateCallInfo(MachineOutlinerNoLRSave, 4);
- }
-
- // LR is live, so we need to save it. Decide whether it should be saved to
- // the stack, or if it can be saved to a register.
else {
- if (all_of(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
- C.initLRU(TRI);
- return findRegisterToSaveLRTo(C);
- })) {
- // Every candidate has an available callee-saved register for the save.
- // We can save LR to a register.
- FrameID = MachineOutlinerRegSave;
- NumBytesToCreateFrame = 4;
- SetCandidateCallInfo(MachineOutlinerRegSave, 12);
+ // We need to decide how to emit calls + frames. We can always emit the same
+ // frame if we don't need to save to the stack. If we have to save to the
+ // stack, then we need a different frame.
+ unsigned NumNoStackSave = 0;
+
+ for (outliner::Candidate &C : RepeatedSequenceLocs) {
+ C.initLRU(TRI);
+
+ // Is LR available? If so, we don't need a save.
+ if (C.LRU.available(AArch64::LR)) {
+ C.setCallInfo(MachineOutlinerNoLRSave, 4);
+ ++NumNoStackSave;
+ }
+
+ // Is an unused register available? If so, we won't modify the stack, so
+ // we can outline with the same frame type as those that don't save LR.
+ else if (findRegisterToSaveLRTo(C)) {
+ C.setCallInfo(MachineOutlinerRegSave, 12);
+ ++NumNoStackSave;
+ }
}
- else {
- // At least one candidate does not have an available callee-saved
- // register. We must save LR to the stack.
- FrameID = MachineOutlinerDefault;
- NumBytesToCreateFrame = 4;
+ // If there are no places where we have to save LR, then note that we don't
+ // have to update the stack. Otherwise, give every candidate the default
+ // call type.
+ if (NumNoStackSave == RepeatedSequenceLocs.size())
+ FrameID = MachineOutlinerNoLRSave;
+ else
SetCandidateCallInfo(MachineOutlinerDefault, 12);
- }
}
// Does every candidate's MBB contain a call? If so, then we might have a call
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-regsave.mir b/llvm/test/CodeGen/AArch64/machine-outliner-regsave.mir
index 6d00bd39cde..d05cbddbb32 100644
--- a/llvm/test/CodeGen/AArch64/machine-outliner-regsave.mir
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-regsave.mir
@@ -2,8 +2,8 @@
# RUN: -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s
# Check that we save LR to a callee-saved register when possible.
# foo() should use a callee-saved register. However, bar() should not.
---- |
-
+--- |
+
define void @foo() #0 {
ret void
}
@@ -17,33 +17,40 @@
---
# Make sure that when we outline and a register is available, we
# use it to save + restore LR instead of SP.
+# Also make sure that we can call functions that require no save as the same
+# outlined function.
# CHECK: name: foo
-# CHECK-DAG: bb.0
+# CHECK-DAG: bb.1
# CHECK-DAG: $x[[REG:[0-9]+]] = ORRXrs $xzr, $lr, 0
# CHECK-NEXT: BL
# CHECK-NEXT: $lr = ORRXrs $xzr, $x[[REG]], 0
-# CHECK-DAG: bb.1
+# CHECK-DAG: bb.2
# CHECK-DAG: $x[[REG]] = ORRXrs $xzr, $lr, 0
# CHECK-NEXT: BL
# CHECK-NEXT: $lr = ORRXrs $xzr, $x[[REG]], 0
-# CHECK-DAG: bb.2
+# CHECK-DAG: bb.3
# CHECK-DAG: $x[[REG]] = ORRXrs $xzr, $lr, 0
# CHECK-NEXT: BL
# CHECK-NEXT: $lr = ORRXrs $xzr, $x[[REG]], 0
+# CHECK-DAG: bb.4
+# CHECK-NOT: $x[[REG]] = ORRXrs $xzr, $lr, 0
+# CHECK-DAG: BL
name: foo
tracksRegLiveness: true
-fixedStack:
+fixedStack:
body: |
bb.0:
- liveins: $lr, $w9
$x25 = ORRXri $xzr, 1
+ $lr = ORRXri $xzr, 1
+ bb.1:
+ liveins: $lr, $w9
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 2
- bb.1:
+ bb.2:
liveins: $lr, $w9
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
@@ -51,7 +58,15 @@ body: |
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 2
- bb.2:
+ bb.3:
+ liveins: $lr, $w9
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 1
+ $w9 = ORRWri $wzr, 2
+ bb.4:
liveins: $lr, $w9
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
@@ -59,6 +74,8 @@ body: |
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 1
$w9 = ORRWri $wzr, 2
+ bb.5:
+ liveins: $w9
RET undef $lr
...
@@ -109,4 +126,3 @@ body: |
bb.3:
liveins: $lr, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x19, $x20, $x21, $x22, $x23, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28
RET undef $lr
-
OpenPOWER on IntegriCloud