43
43
#include < iterator>
44
44
#include < vector>
45
45
46
+ #define DEBUG_TYPE " arm-frame-lowering"
47
+
46
48
using namespace llvm ;
47
49
48
50
Thumb1FrameLowering::Thumb1FrameLowering (const ARMSubtarget &sti)
@@ -277,6 +279,20 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF,
277
279
}
278
280
}
279
281
282
+ // Skip past this code sequence, which is emitted to restore the LR if it is
283
+ // live-in and clobbered by the frame record setup code:
284
+ // ldr rX, [sp, #Y]
285
+ // mov lr, rX
286
+ if (MBBI != MBB.end () && MBBI->getOpcode () == ARM::tLDRspi &&
287
+ MBBI->getFlag (MachineInstr::FrameSetup)) {
288
+ ++MBBI;
289
+ if (MBBI != MBB.end () && MBBI->getOpcode () == ARM::tMOVr &&
290
+ MBBI->getOperand (0 ).getReg () == ARM::LR &&
291
+ MBBI->getFlag (MachineInstr::FrameSetup)) {
292
+ ++MBBI;
293
+ }
294
+ }
295
+
280
296
// Determine starting offsets of spill areas.
281
297
unsigned DPRCSOffset = NumBytes - ArgRegsSaveSize -
282
298
(FRSize + GPRCS1Size + GPRCS2Size + DPRCSSize);
@@ -857,7 +873,8 @@ static void pushRegsToStack(MachineBasicBlock &MBB,
857
873
MachineBasicBlock::iterator MI,
858
874
const TargetInstrInfo &TII,
859
875
const std::set<Register> &RegsToSave,
860
- const std::set<Register> &CopyRegs) {
876
+ const std::set<Register> &CopyRegs,
877
+ bool &UsedLRAsTemp) {
861
878
MachineFunction &MF = *MBB.getParent ();
862
879
const MachineRegisterInfo &MRI = MF.getRegInfo ();
863
880
DebugLoc DL;
@@ -914,6 +931,8 @@ static void pushRegsToStack(MachineBasicBlock &MBB,
914
931
bool isKill = !MRI.isLiveIn (*HiRegToSave);
915
932
if (isKill && !MRI.isReserved (*HiRegToSave))
916
933
MBB.addLiveIn (*HiRegToSave);
934
+ if (*CopyRegIt == ARM::LR)
935
+ UsedLRAsTemp = true ;
917
936
918
937
// Emit a MOV from the high reg to the low reg.
919
938
BuildMI (MBB, MI, DL, TII.get (ARM::tMOVr))
@@ -1093,6 +1112,8 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
1093
1112
// In case FP is a high reg, we need a separate push sequence to generate
1094
1113
// a correct Frame Record
1095
1114
bool NeedsFrameRecordPush = hasFP (MF) && ARM::hGPRRegClass.contains (FPReg);
1115
+ bool LRLiveIn = MF.getRegInfo ().isLiveIn (ARM::LR);
1116
+ bool UsedLRAsTemp = false ;
1096
1117
1097
1118
std::set<Register> FrameRecord;
1098
1119
std::set<Register> SpilledGPRs;
@@ -1104,7 +1125,22 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
1104
1125
SpilledGPRs.insert (Reg);
1105
1126
}
1106
1127
1107
- pushRegsToStack (MBB, MI, TII, FrameRecord, {ARM::LR});
1128
+ // Determine intermediate registers which can be used for pushing the frame
1129
+ // record:
1130
+ // - Unused argument registers
1131
+ // - LR: This is possible because the first PUSH will save it on the stack,
1132
+ // so it is free to be used as a temporary for the second. However, it
1133
+ // is possible for LR to be live-in to the function, in which case we
1134
+ // will need to restore it later in the prologue, so we only use this
1135
+ // if there are no free argument registers.
1136
+ std::set<Register> FrameRecordCopyRegs;
1137
+ for (unsigned ArgReg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3})
1138
+ if (!MF.getRegInfo ().isLiveIn (ArgReg))
1139
+ FrameRecordCopyRegs.insert (ArgReg);
1140
+ if (FrameRecordCopyRegs.empty ())
1141
+ FrameRecordCopyRegs.insert (ARM::LR);
1142
+
1143
+ pushRegsToStack (MBB, MI, TII, FrameRecord, FrameRecordCopyRegs, UsedLRAsTemp);
1108
1144
1109
1145
// Determine intermediate registers which can be used for pushing high regs:
1110
1146
// - Spilled low regs
@@ -1118,7 +1154,33 @@ bool Thumb1FrameLowering::spillCalleeSavedRegisters(
1118
1154
if (!MF.getRegInfo ().isLiveIn (ArgReg))
1119
1155
CopyRegs.insert (ArgReg);
1120
1156
1121
- pushRegsToStack (MBB, MI, TII, SpilledGPRs, CopyRegs);
1157
+ pushRegsToStack (MBB, MI, TII, SpilledGPRs, CopyRegs, UsedLRAsTemp);
1158
+
1159
+ // If the push sequence used LR as a temporary, and LR is live-in (for
1160
+ // example because it is used by the llvm.returnaddress intrinsic), then we
1161
+ // need to reload it from the stack. Thumb1 does not have a load instruction
1162
+ // which can use LR, so we need to load into a temporary low register and
1163
+ // copy to LR.
1164
+ if (LRLiveIn && UsedLRAsTemp) {
1165
+ auto CopyRegIt = getNextOrderedReg (OrderedCopyRegs.rbegin (),
1166
+ OrderedCopyRegs.rend (), CopyRegs);
1167
+ assert (CopyRegIt != OrderedCopyRegs.rend ());
1168
+ unsigned NumRegsPushed = FrameRecord.size () + SpilledGPRs.size ();
1169
+ LLVM_DEBUG (
1170
+ dbgs () << " LR is live-in but clobbered in prologue, restoring via "
1171
+ << RegInfo->getName (*CopyRegIt) << " \n " );
1172
+
1173
+ BuildMI (MBB, MI, DebugLoc (), TII.get (ARM::tLDRspi), *CopyRegIt)
1174
+ .addReg (ARM::SP)
1175
+ .addImm (NumRegsPushed - 1 )
1176
+ .add (predOps (ARMCC::AL))
1177
+ .setMIFlags (MachineInstr::FrameSetup);
1178
+
1179
+ BuildMI (MBB, MI, DebugLoc (), TII.get (ARM::tMOVr), ARM::LR)
1180
+ .addReg (*CopyRegIt)
1181
+ .add (predOps (ARMCC::AL))
1182
+ .setMIFlags (MachineInstr::FrameSetup);
1183
+ }
1122
1184
1123
1185
return true ;
1124
1186
}
0 commit comments