205 строки
8.9 KiB
Diff
205 строки
8.9 KiB
Diff
|
Modified for Mariner by corvus-callidus:
|
||
|
Removed changes to non-vendored files
|
||
|
Fixed paths to match vendored code
|
||
|
Backported patch to apply to version shipped with rust package
|
||
|
Adjusted checksums to account for applied patches
|
||
|
|
||
|
From b1a5ee1febd8a903cec3dfdad61d57900dc3823e Mon Sep 17 00:00:00 2001
|
||
|
From: Florian Hahn <flo@fhahn.com>
|
||
|
Date: Wed, 20 Dec 2023 16:56:15 +0100
|
||
|
Subject: [PATCH] [ARM] Check all terms in emitPopInst when clearing Restored
|
||
|
for LR. (#75527)
|
||
|
|
||
|
emitPopInst checks a single function exit MBB. If other paths also exit
|
||
|
the function and any of there terminators uses LR implicitly, it is not
|
||
|
save to clear the Restored bit.
|
||
|
|
||
|
Check all terminators for the function before clearing Restored.
|
||
|
|
||
|
This fixes a mis-compile in outlined-fn-may-clobber-lr-in-caller.ll
|
||
|
where the machine-outliner previously introduced BLs that clobbered LR
|
||
|
which in turn is used by the tail call return.
|
||
|
|
||
|
Alternative to #73553
|
||
|
---
|
||
|
src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp | 30 +++++++++++++++++--
|
||
|
src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h | 3 ++
|
||
|
.../outlined-fn-may-clobber-lr-in-caller.ll | 14 ++++++---
|
||
|
3 files changed, 40 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp
|
||
|
index a3a71a8ec09a4..10d9c7f275beb 100644
|
||
|
--- a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp
|
||
|
+++ b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp
|
||
|
@@ -1645,9 +1645,6 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
|
||
|
// Fold the return instruction into the LDM.
|
||
|
DeleteRet = true;
|
||
|
LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
|
||
|
- // We 'restore' LR into PC so it is not live out of the return block:
|
||
|
- // Clear Restored bit.
|
||
|
- Info.setRestored(false);
|
||
|
}
|
||
|
|
||
|
// If NoGap is true, pop consecutive registers and then leave the rest
|
||
|
@@ -2785,6 +2782,33 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
|
||
|
AFI->setLRIsSpilled(SavedRegs.test(ARM::LR));
|
||
|
}
|
||
|
|
||
|
+void ARMFrameLowering::processFunctionBeforeFrameFinalized(
|
||
|
+ MachineFunction &MF, RegScavenger *RS) const {
|
||
|
+ TargetFrameLowering::processFunctionBeforeFrameFinalized(MF, RS);
|
||
|
+
|
||
|
+ MachineFrameInfo &MFI = MF.getFrameInfo();
|
||
|
+ if (!MFI.isCalleeSavedInfoValid())
|
||
|
+ return;
|
||
|
+
|
||
|
+ // Check if all terminators do not implicitly use LR. Then we can 'restore' LR
|
||
|
+ // into PC so it is not live out of the return block: Clear the Restored bit
|
||
|
+ // in that case.
|
||
|
+ for (CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
|
||
|
+ if (Info.getReg() != ARM::LR)
|
||
|
+ continue;
|
||
|
+ if (all_of(MF, [](const MachineBasicBlock &MBB) {
|
||
|
+ return all_of(MBB.terminators(), [](const MachineInstr &Term) {
|
||
|
+ return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
|
||
|
+ Term.getOpcode() == ARM::t2LDMIA_RET ||
|
||
|
+ Term.getOpcode() == ARM::tPOP_RET;
|
||
|
+ });
|
||
|
+ })) {
|
||
|
+ Info.setRestored(false);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
void ARMFrameLowering::getCalleeSaves(const MachineFunction &MF,
|
||
|
BitVector &SavedRegs) const {
|
||
|
TargetFrameLowering::getCalleeSaves(MF, SavedRegs);
|
||
|
diff --git a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h
|
||
|
index 16f2ce6bea6f1..8d2b8beb9a58f 100644
|
||
|
--- a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h
|
||
|
+++ b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h
|
||
|
@@ -59,6 +59,9 @@ class ARMFrameLowering : public TargetFrameLowering {
|
||
|
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
|
||
|
RegScavenger *RS) const override;
|
||
|
|
||
|
+ void processFunctionBeforeFrameFinalized(
|
||
|
+ MachineFunction &MF, RegScavenger *RS = nullptr) const override;
|
||
|
+
|
||
|
void adjustForSegmentedStacks(MachineFunction &MF,
|
||
|
MachineBasicBlock &MBB) const override;
|
||
|
|
||
|
|
||
|
From 749384c08e042739342c88b521c8ba5dac1b9276 Mon Sep 17 00:00:00 2001
|
||
|
From: ostannard <oliver.stannard@arm.com>
|
||
|
Date: Mon, 26 Feb 2024 12:23:25 +0000
|
||
|
Subject: [PATCH] [ARM] Update IsRestored for LR based on all returns (#82745)
|
||
|
|
||
|
PR #75527 fixed ARMFrameLowering to set the IsRestored flag for LR based
|
||
|
on all of the return instructions in the function, not just one.
|
||
|
However, there is also code in ARMLoadStoreOptimizer which changes
|
||
|
return instructions, but it set IsRestored based on the one instruction
|
||
|
it changed, not the whole function.
|
||
|
|
||
|
The fix is to factor out the code added in #75527, and also call it from
|
||
|
ARMLoadStoreOptimizer if it made a change to return instructions.
|
||
|
|
||
|
Fixes #80287.
|
||
|
---
|
||
|
src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp | 11 +++++----
|
||
|
src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h | 4 ++++
|
||
|
src/llvm-project/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 23 ++++++++-----------
|
||
|
4 files changed, 27 insertions(+), 22 deletions(-)
|
||
|
|
||
|
diff --git a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp
|
||
|
index eeb7f64aa5810..9b54dd4e4e618 100644
|
||
|
--- a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp
|
||
|
+++ b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp
|
||
|
@@ -2781,10 +2781,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
|
||
|
AFI->setLRIsSpilled(SavedRegs.test(ARM::LR));
|
||
|
}
|
||
|
|
||
|
-void ARMFrameLowering::processFunctionBeforeFrameFinalized(
|
||
|
- MachineFunction &MF, RegScavenger *RS) const {
|
||
|
- TargetFrameLowering::processFunctionBeforeFrameFinalized(MF, RS);
|
||
|
-
|
||
|
+void ARMFrameLowering::updateLRRestored(MachineFunction &MF) {
|
||
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
||
|
if (!MFI.isCalleeSavedInfoValid())
|
||
|
return;
|
||
|
@@ -2808,6 +2805,12 @@ void ARMFrameLowering::processFunctionBeforeFrameFinalized(
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+void ARMFrameLowering::processFunctionBeforeFrameFinalized(
|
||
|
+ MachineFunction &MF, RegScavenger *RS) const {
|
||
|
+ TargetFrameLowering::processFunctionBeforeFrameFinalized(MF, RS);
|
||
|
+ updateLRRestored(MF);
|
||
|
+}
|
||
|
+
|
||
|
void ARMFrameLowering::getCalleeSaves(const MachineFunction &MF,
|
||
|
BitVector &SavedRegs) const {
|
||
|
TargetFrameLowering::getCalleeSaves(MF, SavedRegs);
|
||
|
diff --git a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h
|
||
|
index 8d2b8beb9a58f..3c7358d8cd53e 100644
|
||
|
--- a/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h
|
||
|
+++ b/src/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.h
|
||
|
@@ -59,6 +59,10 @@ class ARMFrameLowering : public TargetFrameLowering {
|
||
|
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
|
||
|
RegScavenger *RS) const override;
|
||
|
|
||
|
+ /// Update the IsRestored flag on LR if it is spilled, based on the return
|
||
|
+ /// instructions.
|
||
|
+ static void updateLRRestored(MachineFunction &MF);
|
||
|
+
|
||
|
void processFunctionBeforeFrameFinalized(
|
||
|
MachineFunction &MF, RegScavenger *RS = nullptr) const override;
|
||
|
|
||
|
diff --git a/src/llvm-project/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/src/llvm-project/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
|
||
|
index ed9d30c3c3ab9..6121055eb0217 100644
|
||
|
--- a/src/llvm-project/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
|
||
|
+++ b/src/llvm-project/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
|
||
|
@@ -2062,17 +2062,6 @@ bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
|
||
|
MO.setReg(ARM::PC);
|
||
|
PrevMI.copyImplicitOps(*MBB.getParent(), *MBBI);
|
||
|
MBB.erase(MBBI);
|
||
|
- // We now restore LR into PC so it is not live-out of the return block
|
||
|
- // anymore: Clear the CSI Restored bit.
|
||
|
- MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
|
||
|
- // CSI should be fixed after PrologEpilog Insertion
|
||
|
- assert(MFI.isCalleeSavedInfoValid() && "CSI should be valid");
|
||
|
- for (CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
|
||
|
- if (Info.getReg() == ARM::LR) {
|
||
|
- Info.setRestored(false);
|
||
|
- break;
|
||
|
- }
|
||
|
- }
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
@@ -2120,14 +2109,22 @@ bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
|
||
|
isThumb2 = AFI->isThumb2Function();
|
||
|
isThumb1 = AFI->isThumbFunction() && !isThumb2;
|
||
|
|
||
|
- bool Modified = false;
|
||
|
+ bool Modified = false, ModifiedLDMReturn = false;
|
||
|
for (MachineBasicBlock &MBB : Fn) {
|
||
|
Modified |= LoadStoreMultipleOpti(MBB);
|
||
|
if (STI->hasV5TOps() && !AFI->shouldSignReturnAddress())
|
||
|
- Modified |= MergeReturnIntoLDM(MBB);
|
||
|
+ ModifiedLDMReturn |= MergeReturnIntoLDM(MBB);
|
||
|
if (isThumb1)
|
||
|
Modified |= CombineMovBx(MBB);
|
||
|
}
|
||
|
+ Modified |= ModifiedLDMReturn;
|
||
|
+
|
||
|
+ // If we merged a BX instruction into an LDM, we need to re-calculate whether
|
||
|
+ // LR is restored. This check needs to consider the whole function, not just
|
||
|
+ // the instruction(s) we changed, because there may be other BX returns which
|
||
|
+ // still need LR to be restored.
|
||
|
+ if (ModifiedLDMReturn)
|
||
|
+ ARMFrameLowering::updateLRRestored(Fn);
|
||
|
|
||
|
Allocator.DestroyAll();
|
||
|
return Modified;
|