Skip to content

Commit f03a987

Browse files
fhahnMingcongBai
authored andcommitted
[ARM] Check all terms in emitPopInst when clearing Restored for LR. (llvm#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 llvm#73553 (cherry picked from commit b1a5ee1)
1 parent 58fbea2 commit f03a987

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

llvm/lib/Target/ARM/ARMFrameLowering.cpp

+27-3
Original file line numberDiff line numberDiff line change
@@ -1645,9 +1645,6 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
16451645
// Fold the return instruction into the LDM.
16461646
DeleteRet = true;
16471647
LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
1648-
// We 'restore' LR into PC so it is not live out of the return block:
1649-
// Clear Restored bit.
1650-
Info.setRestored(false);
16511648
}
16521649

16531650
// If NoGap is true, pop consecutive registers and then leave the rest
@@ -2769,6 +2766,33 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
27692766
AFI->setLRIsSpilled(SavedRegs.test(ARM::LR));
27702767
}
27712768

2769+
void ARMFrameLowering::processFunctionBeforeFrameFinalized(
2770+
MachineFunction &MF, RegScavenger *RS) const {
2771+
TargetFrameLowering::processFunctionBeforeFrameFinalized(MF, RS);
2772+
2773+
MachineFrameInfo &MFI = MF.getFrameInfo();
2774+
if (!MFI.isCalleeSavedInfoValid())
2775+
return;
2776+
2777+
// Check if all terminators do not implicitly use LR. Then we can 'restore' LR
2778+
// into PC so it is not live out of the return block: Clear the Restored bit
2779+
// in that case.
2780+
for (CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
2781+
if (Info.getReg() != ARM::LR)
2782+
continue;
2783+
if (all_of(MF, [](const MachineBasicBlock &MBB) {
2784+
return all_of(MBB.terminators(), [](const MachineInstr &Term) {
2785+
return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
2786+
Term.getOpcode() == ARM::t2LDMIA_RET ||
2787+
Term.getOpcode() == ARM::tPOP_RET;
2788+
});
2789+
})) {
2790+
Info.setRestored(false);
2791+
break;
2792+
}
2793+
}
2794+
}
2795+
27722796
void ARMFrameLowering::getCalleeSaves(const MachineFunction &MF,
27732797
BitVector &SavedRegs) const {
27742798
TargetFrameLowering::getCalleeSaves(MF, SavedRegs);

llvm/lib/Target/ARM/ARMFrameLowering.h

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class ARMFrameLowering : public TargetFrameLowering {
5959
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
6060
RegScavenger *RS) const override;
6161

62+
void processFunctionBeforeFrameFinalized(
63+
MachineFunction &MF, RegScavenger *RS = nullptr) const override;
64+
6265
void adjustForSegmentedStacks(MachineFunction &MF,
6366
MachineBasicBlock &MBB) const override;
6467

llvm/test/CodeGen/Thumb2/outlined-fn-may-clobber-lr-in-caller.ll

+10-4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ target datalayout = "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
1111

1212
; Test case to make sure calling an outlined function does not clobber LR used
1313
; by a tail call in caller.
14-
; FIXME: Currently bl OUTLINED_FUNCTION_0 clobbers LR, which in turn is used
15-
; by the later call to memcpy to return to the caller.
1614
define void @test(ptr nocapture noundef writeonly %arg, i32 noundef %arg1, i8 noundef zeroext %arg2) unnamed_addr #0 {
1715
; CHECK-LABEL: test:
1816
; CHECK: @ %bb.0: @ %bb
@@ -22,11 +20,19 @@ define void @test(ptr nocapture noundef writeonly %arg, i32 noundef %arg1, i8 no
2220
; CHECK-NEXT: cmp r1, #1
2321
; CHECK-NEXT: bne .LBB0_5
2422
; CHECK-NEXT: @ %bb.2: @ %bb4
25-
; CHECK-NEXT: bl OUTLINED_FUNCTION_0
23+
; CHECK-NEXT: movs r1, #1
24+
; CHECK-NEXT: strb.w r1, [r0, #36]
25+
; CHECK-NEXT: movs r1, #30
26+
; CHECK-NEXT: strb.w r1, [r0, #34]
27+
; CHECK-NEXT: add.w r1, r2, r2, lsl #3
2628
; CHECK-NEXT: ldr r2, .LCPI0_1
2729
; CHECK-NEXT: b .LBB0_4
2830
; CHECK-NEXT: .LBB0_3: @ %bb14
29-
; CHECK-NEXT: bl OUTLINED_FUNCTION_0
31+
; CHECK-NEXT: movs r1, #1
32+
; CHECK-NEXT: strb.w r1, [r0, #36]
33+
; CHECK-NEXT: movs r1, #30
34+
; CHECK-NEXT: strb.w r1, [r0, #34]
35+
; CHECK-NEXT: add.w r1, r2, r2, lsl #3
3036
; CHECK-NEXT: ldr r2, .LCPI0_0
3137
; CHECK-NEXT: .LBB0_4: @ %bb4
3238
; CHECK-NEXT: add.w r1, r2, r1, lsl #2

0 commit comments

Comments
 (0)