summaryrefslogtreecommitdiff
path: root/0015-Backport-ARM-Check-all-terms-in-emitPopInst-when-clearing-Res.patch
diff options
context:
space:
mode:
Diffstat (limited to '0015-Backport-ARM-Check-all-terms-in-emitPopInst-when-clearing-Res.patch')
-rw-r--r--0015-Backport-ARM-Check-all-terms-in-emitPopInst-when-clearing-Res.patch87
1 files changed, 87 insertions, 0 deletions
diff --git a/0015-Backport-ARM-Check-all-terms-in-emitPopInst-when-clearing-Res.patch b/0015-Backport-ARM-Check-all-terms-in-emitPopInst-when-clearing-Res.patch
new file mode 100644
index 0000000..4528f50
--- /dev/null
+++ b/0015-Backport-ARM-Check-all-terms-in-emitPopInst-when-clearing-Res.patch
@@ -0,0 +1,87 @@
+From 4aec2da60ce3f639e31d81406c09d5c88b3b8f53 Mon Sep 17 00:00:00 2001
+From: Florian Hahn <flo@fhahn.com>
+Date: Wed, 20 Dec 2023 16:56:15 +0100
+Subject: [PATCH 2/3] [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
+---
+ llvm/lib/Target/ARM/ARMFrameLowering.cpp | 30 +++++++++++++++++++++---
+ llvm/lib/Target/ARM/ARMFrameLowering.h | 3 +++
+ 2 files changed, 30 insertions(+), 3 deletions(-)
+
+diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
+index 4496d4928ebe..650f4650eef0 100644
+--- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp
++++ b/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
+@@ -2769,6 +2766,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/llvm/lib/Target/ARM/ARMFrameLowering.h b/llvm/lib/Target/ARM/ARMFrameLowering.h
+index 16f2ce6bea6f..8d2b8beb9a58 100644
+--- a/llvm/lib/Target/ARM/ARMFrameLowering.h
++++ b/llvm/lib/Target/ARM/ARMFrameLowering.h
+@@ -59,6 +59,9 @@ public:
+ 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;
+
+--
+2.33.0
+