diff options
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.patch | 87 |
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 + |