1*0b57cec5SDimitry Andric //===- Thumb1FrameLowering.cpp - Thumb1 Frame Information -----------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains the Thumb1 implementation of TargetFrameLowering class. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "Thumb1FrameLowering.h" 14*0b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h" 15*0b57cec5SDimitry Andric #include "ARMBaseRegisterInfo.h" 16*0b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h" 17*0b57cec5SDimitry Andric #include "ARMSubtarget.h" 18*0b57cec5SDimitry Andric #include "Thumb1InstrInfo.h" 19*0b57cec5SDimitry Andric #include "ThumbRegisterInfo.h" 20*0b57cec5SDimitry Andric #include "Utils/ARMBaseInfo.h" 21*0b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 22*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 23*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 24*0b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 26*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 27*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 28*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 29*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 30*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 31*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 32*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 33*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 34*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 35*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 36*0b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 37*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 38*0b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h" 39*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 40*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 41*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 42*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 43*0b57cec5SDimitry Andric #include <bitset> 44*0b57cec5SDimitry Andric #include <cassert> 45*0b57cec5SDimitry Andric #include <iterator> 46*0b57cec5SDimitry Andric #include <vector> 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric using namespace llvm; 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric Thumb1FrameLowering::Thumb1FrameLowering(const ARMSubtarget &sti) 51*0b57cec5SDimitry Andric : ARMFrameLowering(sti) {} 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric bool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const{ 54*0b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 55*0b57cec5SDimitry Andric unsigned CFSize = MFI.getMaxCallFrameSize(); 56*0b57cec5SDimitry Andric // It's not always a good idea to include the call frame as part of the 57*0b57cec5SDimitry Andric // stack frame. ARM (especially Thumb) has small immediate offset to 58*0b57cec5SDimitry Andric // address the stack frame. So a large call frame can cause poor codegen 59*0b57cec5SDimitry Andric // and may even makes it impossible to scavenge a register. 60*0b57cec5SDimitry Andric if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 61*0b57cec5SDimitry Andric return false; 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric return !MFI.hasVarSizedObjects(); 64*0b57cec5SDimitry Andric } 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric static void 67*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MachineBasicBlock &MBB, 68*0b57cec5SDimitry Andric MachineBasicBlock::iterator &MBBI, 69*0b57cec5SDimitry Andric const TargetInstrInfo &TII, const DebugLoc &dl, 70*0b57cec5SDimitry Andric const ThumbRegisterInfo &MRI, int NumBytes, 71*0b57cec5SDimitry Andric unsigned ScratchReg, unsigned MIFlags) { 72*0b57cec5SDimitry Andric // If it would take more than three instructions to adjust the stack pointer 73*0b57cec5SDimitry Andric // using tADDspi/tSUBspi, load an immediate instead. 74*0b57cec5SDimitry Andric if (std::abs(NumBytes) > 508 * 3) { 75*0b57cec5SDimitry Andric // We use a different codepath here from the normal 76*0b57cec5SDimitry Andric // emitThumbRegPlusImmediate so we don't have to deal with register 77*0b57cec5SDimitry Andric // scavenging. (Scavenging could try to use the emergency spill slot 78*0b57cec5SDimitry Andric // before we've actually finished setting up the stack.) 79*0b57cec5SDimitry Andric if (ScratchReg == ARM::NoRegister) 80*0b57cec5SDimitry Andric report_fatal_error("Failed to emit Thumb1 stack adjustment"); 81*0b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 82*0b57cec5SDimitry Andric const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>(); 83*0b57cec5SDimitry Andric if (ST.genExecuteOnly()) { 84*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ScratchReg) 85*0b57cec5SDimitry Andric .addImm(NumBytes).setMIFlags(MIFlags); 86*0b57cec5SDimitry Andric } else { 87*0b57cec5SDimitry Andric MRI.emitLoadConstPool(MBB, MBBI, dl, ScratchReg, 0, NumBytes, ARMCC::AL, 88*0b57cec5SDimitry Andric 0, MIFlags); 89*0b57cec5SDimitry Andric } 90*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDhirr), ARM::SP) 91*0b57cec5SDimitry Andric .addReg(ARM::SP).addReg(ScratchReg, RegState::Kill) 92*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 93*0b57cec5SDimitry Andric return; 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric // FIXME: This is assuming the heuristics in emitThumbRegPlusImmediate 96*0b57cec5SDimitry Andric // won't change. 97*0b57cec5SDimitry Andric emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, 98*0b57cec5SDimitry Andric MRI, MIFlags); 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric } 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric static void emitCallSPUpdate(MachineBasicBlock &MBB, 103*0b57cec5SDimitry Andric MachineBasicBlock::iterator &MBBI, 104*0b57cec5SDimitry Andric const TargetInstrInfo &TII, const DebugLoc &dl, 105*0b57cec5SDimitry Andric const ThumbRegisterInfo &MRI, int NumBytes, 106*0b57cec5SDimitry Andric unsigned MIFlags = MachineInstr::NoFlags) { 107*0b57cec5SDimitry Andric emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, 108*0b57cec5SDimitry Andric MRI, MIFlags); 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric MachineBasicBlock::iterator Thumb1FrameLowering:: 113*0b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 114*0b57cec5SDimitry Andric MachineBasicBlock::iterator I) const { 115*0b57cec5SDimitry Andric const Thumb1InstrInfo &TII = 116*0b57cec5SDimitry Andric *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); 117*0b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 118*0b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 119*0b57cec5SDimitry Andric if (!hasReservedCallFrame(MF)) { 120*0b57cec5SDimitry Andric // If we have alloca, convert as follows: 121*0b57cec5SDimitry Andric // ADJCALLSTACKDOWN -> sub, sp, sp, amount 122*0b57cec5SDimitry Andric // ADJCALLSTACKUP -> add, sp, sp, amount 123*0b57cec5SDimitry Andric MachineInstr &Old = *I; 124*0b57cec5SDimitry Andric DebugLoc dl = Old.getDebugLoc(); 125*0b57cec5SDimitry Andric unsigned Amount = TII.getFrameSize(Old); 126*0b57cec5SDimitry Andric if (Amount != 0) { 127*0b57cec5SDimitry Andric // We need to keep the stack aligned properly. To do this, we round the 128*0b57cec5SDimitry Andric // amount of space needed for the outgoing arguments up to the next 129*0b57cec5SDimitry Andric // alignment boundary. 130*0b57cec5SDimitry Andric Amount = alignTo(Amount, getStackAlignment()); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric // Replace the pseudo instruction with a new instruction... 133*0b57cec5SDimitry Andric unsigned Opc = Old.getOpcode(); 134*0b57cec5SDimitry Andric if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { 135*0b57cec5SDimitry Andric emitCallSPUpdate(MBB, I, TII, dl, *RegInfo, -Amount); 136*0b57cec5SDimitry Andric } else { 137*0b57cec5SDimitry Andric assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); 138*0b57cec5SDimitry Andric emitCallSPUpdate(MBB, I, TII, dl, *RegInfo, Amount); 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric return MBB.erase(I); 143*0b57cec5SDimitry Andric } 144*0b57cec5SDimitry Andric 145*0b57cec5SDimitry Andric void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, 146*0b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 147*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 148*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 149*0b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 150*0b57cec5SDimitry Andric MachineModuleInfo &MMI = MF.getMMI(); 151*0b57cec5SDimitry Andric const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 152*0b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 153*0b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 154*0b57cec5SDimitry Andric const Thumb1InstrInfo &TII = 155*0b57cec5SDimitry Andric *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); 158*0b57cec5SDimitry Andric unsigned NumBytes = MFI.getStackSize(); 159*0b57cec5SDimitry Andric assert(NumBytes >= ArgRegsSaveSize && 160*0b57cec5SDimitry Andric "ArgRegsSaveSize is included in NumBytes"); 161*0b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 164*0b57cec5SDimitry Andric // to determine the end of the prologue. 165*0b57cec5SDimitry Andric DebugLoc dl; 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric unsigned FramePtr = RegInfo->getFrameRegister(MF); 168*0b57cec5SDimitry Andric unsigned BasePtr = RegInfo->getBaseRegister(); 169*0b57cec5SDimitry Andric int CFAOffset = 0; 170*0b57cec5SDimitry Andric 171*0b57cec5SDimitry Andric // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. 172*0b57cec5SDimitry Andric NumBytes = (NumBytes + 3) & ~3; 173*0b57cec5SDimitry Andric MFI.setStackSize(NumBytes); 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric // Determine the sizes of each callee-save spill areas and record which frame 176*0b57cec5SDimitry Andric // belongs to which callee-save spill areas. 177*0b57cec5SDimitry Andric unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; 178*0b57cec5SDimitry Andric int FramePtrSpillFI = 0; 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric if (ArgRegsSaveSize) { 181*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -ArgRegsSaveSize, 182*0b57cec5SDimitry Andric ARM::NoRegister, MachineInstr::FrameSetup); 183*0b57cec5SDimitry Andric CFAOffset -= ArgRegsSaveSize; 184*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 185*0b57cec5SDimitry Andric MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); 186*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 187*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 188*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 189*0b57cec5SDimitry Andric } 190*0b57cec5SDimitry Andric 191*0b57cec5SDimitry Andric if (!AFI->hasStackFrame()) { 192*0b57cec5SDimitry Andric if (NumBytes - ArgRegsSaveSize != 0) { 193*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, 194*0b57cec5SDimitry Andric -(NumBytes - ArgRegsSaveSize), 195*0b57cec5SDimitry Andric ARM::NoRegister, MachineInstr::FrameSetup); 196*0b57cec5SDimitry Andric CFAOffset -= NumBytes - ArgRegsSaveSize; 197*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 198*0b57cec5SDimitry Andric MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); 199*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 200*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 201*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 202*0b57cec5SDimitry Andric } 203*0b57cec5SDimitry Andric return; 204*0b57cec5SDimitry Andric } 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 207*0b57cec5SDimitry Andric unsigned Reg = CSI[i].getReg(); 208*0b57cec5SDimitry Andric int FI = CSI[i].getFrameIdx(); 209*0b57cec5SDimitry Andric switch (Reg) { 210*0b57cec5SDimitry Andric case ARM::R8: 211*0b57cec5SDimitry Andric case ARM::R9: 212*0b57cec5SDimitry Andric case ARM::R10: 213*0b57cec5SDimitry Andric case ARM::R11: 214*0b57cec5SDimitry Andric if (STI.splitFramePushPop(MF)) { 215*0b57cec5SDimitry Andric GPRCS2Size += 4; 216*0b57cec5SDimitry Andric break; 217*0b57cec5SDimitry Andric } 218*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 219*0b57cec5SDimitry Andric case ARM::R4: 220*0b57cec5SDimitry Andric case ARM::R5: 221*0b57cec5SDimitry Andric case ARM::R6: 222*0b57cec5SDimitry Andric case ARM::R7: 223*0b57cec5SDimitry Andric case ARM::LR: 224*0b57cec5SDimitry Andric if (Reg == FramePtr) 225*0b57cec5SDimitry Andric FramePtrSpillFI = FI; 226*0b57cec5SDimitry Andric GPRCS1Size += 4; 227*0b57cec5SDimitry Andric break; 228*0b57cec5SDimitry Andric default: 229*0b57cec5SDimitry Andric DPRCSSize += 8; 230*0b57cec5SDimitry Andric } 231*0b57cec5SDimitry Andric } 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { 234*0b57cec5SDimitry Andric ++MBBI; 235*0b57cec5SDimitry Andric } 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric // Determine starting offsets of spill areas. 238*0b57cec5SDimitry Andric unsigned DPRCSOffset = NumBytes - ArgRegsSaveSize - (GPRCS1Size + GPRCS2Size + DPRCSSize); 239*0b57cec5SDimitry Andric unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; 240*0b57cec5SDimitry Andric unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; 241*0b57cec5SDimitry Andric bool HasFP = hasFP(MF); 242*0b57cec5SDimitry Andric if (HasFP) 243*0b57cec5SDimitry Andric AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) + 244*0b57cec5SDimitry Andric NumBytes); 245*0b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); 246*0b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); 247*0b57cec5SDimitry Andric AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); 248*0b57cec5SDimitry Andric NumBytes = DPRCSOffset; 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric int FramePtrOffsetInBlock = 0; 251*0b57cec5SDimitry Andric unsigned adjustedGPRCS1Size = GPRCS1Size; 252*0b57cec5SDimitry Andric if (GPRCS1Size > 0 && GPRCS2Size == 0 && 253*0b57cec5SDimitry Andric tryFoldSPUpdateIntoPushPop(STI, MF, &*std::prev(MBBI), NumBytes)) { 254*0b57cec5SDimitry Andric FramePtrOffsetInBlock = NumBytes; 255*0b57cec5SDimitry Andric adjustedGPRCS1Size += NumBytes; 256*0b57cec5SDimitry Andric NumBytes = 0; 257*0b57cec5SDimitry Andric } 258*0b57cec5SDimitry Andric 259*0b57cec5SDimitry Andric if (adjustedGPRCS1Size) { 260*0b57cec5SDimitry Andric CFAOffset -= adjustedGPRCS1Size; 261*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 262*0b57cec5SDimitry Andric MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); 263*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 264*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 265*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 266*0b57cec5SDimitry Andric } 267*0b57cec5SDimitry Andric for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), 268*0b57cec5SDimitry Andric E = CSI.end(); I != E; ++I) { 269*0b57cec5SDimitry Andric unsigned Reg = I->getReg(); 270*0b57cec5SDimitry Andric int FI = I->getFrameIdx(); 271*0b57cec5SDimitry Andric switch (Reg) { 272*0b57cec5SDimitry Andric case ARM::R8: 273*0b57cec5SDimitry Andric case ARM::R9: 274*0b57cec5SDimitry Andric case ARM::R10: 275*0b57cec5SDimitry Andric case ARM::R11: 276*0b57cec5SDimitry Andric case ARM::R12: 277*0b57cec5SDimitry Andric if (STI.splitFramePushPop(MF)) 278*0b57cec5SDimitry Andric break; 279*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 280*0b57cec5SDimitry Andric case ARM::R0: 281*0b57cec5SDimitry Andric case ARM::R1: 282*0b57cec5SDimitry Andric case ARM::R2: 283*0b57cec5SDimitry Andric case ARM::R3: 284*0b57cec5SDimitry Andric case ARM::R4: 285*0b57cec5SDimitry Andric case ARM::R5: 286*0b57cec5SDimitry Andric case ARM::R6: 287*0b57cec5SDimitry Andric case ARM::R7: 288*0b57cec5SDimitry Andric case ARM::LR: 289*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 290*0b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); 291*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 292*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 293*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 294*0b57cec5SDimitry Andric break; 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric } 297*0b57cec5SDimitry Andric 298*0b57cec5SDimitry Andric // Adjust FP so it point to the stack slot that contains the previous FP. 299*0b57cec5SDimitry Andric if (HasFP) { 300*0b57cec5SDimitry Andric FramePtrOffsetInBlock += 301*0b57cec5SDimitry Andric MFI.getObjectOffset(FramePtrSpillFI) + GPRCS1Size + ArgRegsSaveSize; 302*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) 303*0b57cec5SDimitry Andric .addReg(ARM::SP) 304*0b57cec5SDimitry Andric .addImm(FramePtrOffsetInBlock / 4) 305*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup) 306*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 307*0b57cec5SDimitry Andric if(FramePtrOffsetInBlock) { 308*0b57cec5SDimitry Andric CFAOffset += FramePtrOffsetInBlock; 309*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa( 310*0b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(FramePtr, true), CFAOffset)); 311*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 312*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 313*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 314*0b57cec5SDimitry Andric } else { 315*0b57cec5SDimitry Andric unsigned CFIIndex = 316*0b57cec5SDimitry Andric MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( 317*0b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(FramePtr, true))); 318*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 319*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 320*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 321*0b57cec5SDimitry Andric } 322*0b57cec5SDimitry Andric if (NumBytes > 508) 323*0b57cec5SDimitry Andric // If offset is > 508 then sp cannot be adjusted in a single instruction, 324*0b57cec5SDimitry Andric // try restoring from fp instead. 325*0b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric // Skip past the spilling of r8-r11, which could consist of multiple tPUSH 329*0b57cec5SDimitry Andric // and tMOVr instructions. We don't need to add any call frame information 330*0b57cec5SDimitry Andric // in-between these instructions, because they do not modify the high 331*0b57cec5SDimitry Andric // registers. 332*0b57cec5SDimitry Andric while (true) { 333*0b57cec5SDimitry Andric MachineBasicBlock::iterator OldMBBI = MBBI; 334*0b57cec5SDimitry Andric // Skip a run of tMOVr instructions 335*0b57cec5SDimitry Andric while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tMOVr) 336*0b57cec5SDimitry Andric MBBI++; 337*0b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { 338*0b57cec5SDimitry Andric MBBI++; 339*0b57cec5SDimitry Andric } else { 340*0b57cec5SDimitry Andric // We have reached an instruction which is not a push, so the previous 341*0b57cec5SDimitry Andric // run of tMOVr instructions (which may have been empty) was not part of 342*0b57cec5SDimitry Andric // the prologue. Reset MBBI back to the last PUSH of the prologue. 343*0b57cec5SDimitry Andric MBBI = OldMBBI; 344*0b57cec5SDimitry Andric break; 345*0b57cec5SDimitry Andric } 346*0b57cec5SDimitry Andric } 347*0b57cec5SDimitry Andric 348*0b57cec5SDimitry Andric // Emit call frame information for the callee-saved high registers. 349*0b57cec5SDimitry Andric for (auto &I : CSI) { 350*0b57cec5SDimitry Andric unsigned Reg = I.getReg(); 351*0b57cec5SDimitry Andric int FI = I.getFrameIdx(); 352*0b57cec5SDimitry Andric switch (Reg) { 353*0b57cec5SDimitry Andric case ARM::R8: 354*0b57cec5SDimitry Andric case ARM::R9: 355*0b57cec5SDimitry Andric case ARM::R10: 356*0b57cec5SDimitry Andric case ARM::R11: 357*0b57cec5SDimitry Andric case ARM::R12: { 358*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 359*0b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); 360*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 361*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 362*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 363*0b57cec5SDimitry Andric break; 364*0b57cec5SDimitry Andric } 365*0b57cec5SDimitry Andric default: 366*0b57cec5SDimitry Andric break; 367*0b57cec5SDimitry Andric } 368*0b57cec5SDimitry Andric } 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric if (NumBytes) { 371*0b57cec5SDimitry Andric // Insert it after all the callee-save spills. 372*0b57cec5SDimitry Andric // 373*0b57cec5SDimitry Andric // For a large stack frame, we might need a scratch register to store 374*0b57cec5SDimitry Andric // the size of the frame. We know all callee-save registers are free 375*0b57cec5SDimitry Andric // at this point in the prologue, so pick one. 376*0b57cec5SDimitry Andric unsigned ScratchRegister = ARM::NoRegister; 377*0b57cec5SDimitry Andric for (auto &I : CSI) { 378*0b57cec5SDimitry Andric unsigned Reg = I.getReg(); 379*0b57cec5SDimitry Andric if (isARMLowRegister(Reg) && !(HasFP && Reg == FramePtr)) { 380*0b57cec5SDimitry Andric ScratchRegister = Reg; 381*0b57cec5SDimitry Andric break; 382*0b57cec5SDimitry Andric } 383*0b57cec5SDimitry Andric } 384*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, 385*0b57cec5SDimitry Andric ScratchRegister, MachineInstr::FrameSetup); 386*0b57cec5SDimitry Andric if (!HasFP) { 387*0b57cec5SDimitry Andric CFAOffset -= NumBytes; 388*0b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 389*0b57cec5SDimitry Andric MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); 390*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 391*0b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 392*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 393*0b57cec5SDimitry Andric } 394*0b57cec5SDimitry Andric } 395*0b57cec5SDimitry Andric 396*0b57cec5SDimitry Andric if (STI.isTargetELF() && HasFP) 397*0b57cec5SDimitry Andric MFI.setOffsetAdjustment(MFI.getOffsetAdjustment() - 398*0b57cec5SDimitry Andric AFI->getFramePtrSpillOffset()); 399*0b57cec5SDimitry Andric 400*0b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); 401*0b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); 402*0b57cec5SDimitry Andric AFI->setDPRCalleeSavedAreaSize(DPRCSSize); 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric if (RegInfo->needsStackRealignment(MF)) { 405*0b57cec5SDimitry Andric const unsigned NrBitsToZero = countTrailingZeros(MFI.getMaxAlignment()); 406*0b57cec5SDimitry Andric // Emit the following sequence, using R4 as a temporary, since we cannot use 407*0b57cec5SDimitry Andric // SP as a source or destination register for the shifts: 408*0b57cec5SDimitry Andric // mov r4, sp 409*0b57cec5SDimitry Andric // lsrs r4, r4, #NrBitsToZero 410*0b57cec5SDimitry Andric // lsls r4, r4, #NrBitsToZero 411*0b57cec5SDimitry Andric // mov sp, r4 412*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4) 413*0b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Kill) 414*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 415*0b57cec5SDimitry Andric 416*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSRri), ARM::R4) 417*0b57cec5SDimitry Andric .addDef(ARM::CPSR) 418*0b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 419*0b57cec5SDimitry Andric .addImm(NrBitsToZero) 420*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 421*0b57cec5SDimitry Andric 422*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSLri), ARM::R4) 423*0b57cec5SDimitry Andric .addDef(ARM::CPSR) 424*0b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 425*0b57cec5SDimitry Andric .addImm(NrBitsToZero) 426*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 427*0b57cec5SDimitry Andric 428*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 429*0b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 430*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 431*0b57cec5SDimitry Andric 432*0b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 433*0b57cec5SDimitry Andric } 434*0b57cec5SDimitry Andric 435*0b57cec5SDimitry Andric // If we need a base pointer, set it up here. It's whatever the value 436*0b57cec5SDimitry Andric // of the stack pointer is at this point. Any variable size objects 437*0b57cec5SDimitry Andric // will be allocated after this, so we can still use the base pointer 438*0b57cec5SDimitry Andric // to reference locals. 439*0b57cec5SDimitry Andric if (RegInfo->hasBasePointer(MF)) 440*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), BasePtr) 441*0b57cec5SDimitry Andric .addReg(ARM::SP) 442*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric // If the frame has variable sized objects then the epilogue must restore 445*0b57cec5SDimitry Andric // the sp from fp. We can assume there's an FP here since hasFP already 446*0b57cec5SDimitry Andric // checks for hasVarSizedObjects. 447*0b57cec5SDimitry Andric if (MFI.hasVarSizedObjects()) 448*0b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 449*0b57cec5SDimitry Andric 450*0b57cec5SDimitry Andric // In some cases, virtual registers have been introduced, e.g. by uses of 451*0b57cec5SDimitry Andric // emitThumbRegPlusImmInReg. 452*0b57cec5SDimitry Andric MF.getProperties().reset(MachineFunctionProperties::Property::NoVRegs); 453*0b57cec5SDimitry Andric } 454*0b57cec5SDimitry Andric 455*0b57cec5SDimitry Andric static bool isCSRestore(MachineInstr &MI, const MCPhysReg *CSRegs) { 456*0b57cec5SDimitry Andric if (MI.getOpcode() == ARM::tLDRspi && MI.getOperand(1).isFI() && 457*0b57cec5SDimitry Andric isCalleeSavedRegister(MI.getOperand(0).getReg(), CSRegs)) 458*0b57cec5SDimitry Andric return true; 459*0b57cec5SDimitry Andric else if (MI.getOpcode() == ARM::tPOP) { 460*0b57cec5SDimitry Andric return true; 461*0b57cec5SDimitry Andric } else if (MI.getOpcode() == ARM::tMOVr) { 462*0b57cec5SDimitry Andric unsigned Dst = MI.getOperand(0).getReg(); 463*0b57cec5SDimitry Andric unsigned Src = MI.getOperand(1).getReg(); 464*0b57cec5SDimitry Andric return ((ARM::tGPRRegClass.contains(Src) || Src == ARM::LR) && 465*0b57cec5SDimitry Andric ARM::hGPRRegClass.contains(Dst)); 466*0b57cec5SDimitry Andric } 467*0b57cec5SDimitry Andric return false; 468*0b57cec5SDimitry Andric } 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, 471*0b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 472*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); 473*0b57cec5SDimitry Andric DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 474*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 475*0b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 476*0b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 477*0b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 478*0b57cec5SDimitry Andric const Thumb1InstrInfo &TII = 479*0b57cec5SDimitry Andric *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); 482*0b57cec5SDimitry Andric int NumBytes = (int)MFI.getStackSize(); 483*0b57cec5SDimitry Andric assert((unsigned)NumBytes >= ArgRegsSaveSize && 484*0b57cec5SDimitry Andric "ArgRegsSaveSize is included in NumBytes"); 485*0b57cec5SDimitry Andric const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF); 486*0b57cec5SDimitry Andric unsigned FramePtr = RegInfo->getFrameRegister(MF); 487*0b57cec5SDimitry Andric 488*0b57cec5SDimitry Andric if (!AFI->hasStackFrame()) { 489*0b57cec5SDimitry Andric if (NumBytes - ArgRegsSaveSize != 0) 490*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, 491*0b57cec5SDimitry Andric NumBytes - ArgRegsSaveSize, ARM::NoRegister, 492*0b57cec5SDimitry Andric MachineInstr::NoFlags); 493*0b57cec5SDimitry Andric } else { 494*0b57cec5SDimitry Andric // Unwind MBBI to point to first LDR / VLDRD. 495*0b57cec5SDimitry Andric if (MBBI != MBB.begin()) { 496*0b57cec5SDimitry Andric do 497*0b57cec5SDimitry Andric --MBBI; 498*0b57cec5SDimitry Andric while (MBBI != MBB.begin() && isCSRestore(*MBBI, CSRegs)); 499*0b57cec5SDimitry Andric if (!isCSRestore(*MBBI, CSRegs)) 500*0b57cec5SDimitry Andric ++MBBI; 501*0b57cec5SDimitry Andric } 502*0b57cec5SDimitry Andric 503*0b57cec5SDimitry Andric // Move SP to start of FP callee save spill area. 504*0b57cec5SDimitry Andric NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + 505*0b57cec5SDimitry Andric AFI->getGPRCalleeSavedArea2Size() + 506*0b57cec5SDimitry Andric AFI->getDPRCalleeSavedAreaSize() + 507*0b57cec5SDimitry Andric ArgRegsSaveSize); 508*0b57cec5SDimitry Andric 509*0b57cec5SDimitry Andric if (AFI->shouldRestoreSPFromFP()) { 510*0b57cec5SDimitry Andric NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; 511*0b57cec5SDimitry Andric // Reset SP based on frame pointer only if the stack frame extends beyond 512*0b57cec5SDimitry Andric // frame pointer stack slot, the target is ELF and the function has FP, or 513*0b57cec5SDimitry Andric // the target uses var sized objects. 514*0b57cec5SDimitry Andric if (NumBytes) { 515*0b57cec5SDimitry Andric assert(!MFI.getPristineRegs(MF).test(ARM::R4) && 516*0b57cec5SDimitry Andric "No scratch register to restore SP from FP!"); 517*0b57cec5SDimitry Andric emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, 518*0b57cec5SDimitry Andric TII, *RegInfo); 519*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 520*0b57cec5SDimitry Andric .addReg(ARM::R4) 521*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 522*0b57cec5SDimitry Andric } else 523*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 524*0b57cec5SDimitry Andric .addReg(FramePtr) 525*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 526*0b57cec5SDimitry Andric } else { 527*0b57cec5SDimitry Andric // For a large stack frame, we might need a scratch register to store 528*0b57cec5SDimitry Andric // the size of the frame. We know all callee-save registers are free 529*0b57cec5SDimitry Andric // at this point in the epilogue, so pick one. 530*0b57cec5SDimitry Andric unsigned ScratchRegister = ARM::NoRegister; 531*0b57cec5SDimitry Andric bool HasFP = hasFP(MF); 532*0b57cec5SDimitry Andric for (auto &I : MFI.getCalleeSavedInfo()) { 533*0b57cec5SDimitry Andric unsigned Reg = I.getReg(); 534*0b57cec5SDimitry Andric if (isARMLowRegister(Reg) && !(HasFP && Reg == FramePtr)) { 535*0b57cec5SDimitry Andric ScratchRegister = Reg; 536*0b57cec5SDimitry Andric break; 537*0b57cec5SDimitry Andric } 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tBX_RET && 540*0b57cec5SDimitry Andric &MBB.front() != &*MBBI && std::prev(MBBI)->getOpcode() == ARM::tPOP) { 541*0b57cec5SDimitry Andric MachineBasicBlock::iterator PMBBI = std::prev(MBBI); 542*0b57cec5SDimitry Andric if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*PMBBI, NumBytes)) 543*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, PMBBI, TII, dl, *RegInfo, NumBytes, 544*0b57cec5SDimitry Andric ScratchRegister, MachineInstr::NoFlags); 545*0b57cec5SDimitry Andric } else if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*MBBI, NumBytes)) 546*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes, 547*0b57cec5SDimitry Andric ScratchRegister, MachineInstr::NoFlags); 548*0b57cec5SDimitry Andric } 549*0b57cec5SDimitry Andric } 550*0b57cec5SDimitry Andric 551*0b57cec5SDimitry Andric if (needPopSpecialFixUp(MF)) { 552*0b57cec5SDimitry Andric bool Done = emitPopSpecialFixUp(MBB, /* DoIt */ true); 553*0b57cec5SDimitry Andric (void)Done; 554*0b57cec5SDimitry Andric assert(Done && "Emission of the special fixup failed!?"); 555*0b57cec5SDimitry Andric } 556*0b57cec5SDimitry Andric } 557*0b57cec5SDimitry Andric 558*0b57cec5SDimitry Andric bool Thumb1FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const { 559*0b57cec5SDimitry Andric if (!needPopSpecialFixUp(*MBB.getParent())) 560*0b57cec5SDimitry Andric return true; 561*0b57cec5SDimitry Andric 562*0b57cec5SDimitry Andric MachineBasicBlock *TmpMBB = const_cast<MachineBasicBlock *>(&MBB); 563*0b57cec5SDimitry Andric return emitPopSpecialFixUp(*TmpMBB, /* DoIt */ false); 564*0b57cec5SDimitry Andric } 565*0b57cec5SDimitry Andric 566*0b57cec5SDimitry Andric bool Thumb1FrameLowering::needPopSpecialFixUp(const MachineFunction &MF) const { 567*0b57cec5SDimitry Andric ARMFunctionInfo *AFI = 568*0b57cec5SDimitry Andric const_cast<MachineFunction *>(&MF)->getInfo<ARMFunctionInfo>(); 569*0b57cec5SDimitry Andric if (AFI->getArgRegsSaveSize()) 570*0b57cec5SDimitry Andric return true; 571*0b57cec5SDimitry Andric 572*0b57cec5SDimitry Andric // LR cannot be encoded with Thumb1, i.e., it requires a special fix-up. 573*0b57cec5SDimitry Andric for (const CalleeSavedInfo &CSI : MF.getFrameInfo().getCalleeSavedInfo()) 574*0b57cec5SDimitry Andric if (CSI.getReg() == ARM::LR) 575*0b57cec5SDimitry Andric return true; 576*0b57cec5SDimitry Andric 577*0b57cec5SDimitry Andric return false; 578*0b57cec5SDimitry Andric } 579*0b57cec5SDimitry Andric 580*0b57cec5SDimitry Andric static void findTemporariesForLR(const BitVector &GPRsNoLRSP, 581*0b57cec5SDimitry Andric const BitVector &PopFriendly, 582*0b57cec5SDimitry Andric const LivePhysRegs &UsedRegs, unsigned &PopReg, 583*0b57cec5SDimitry Andric unsigned &TmpReg) { 584*0b57cec5SDimitry Andric PopReg = TmpReg = 0; 585*0b57cec5SDimitry Andric for (auto Reg : GPRsNoLRSP.set_bits()) { 586*0b57cec5SDimitry Andric if (!UsedRegs.contains(Reg)) { 587*0b57cec5SDimitry Andric // Remember the first pop-friendly register and exit. 588*0b57cec5SDimitry Andric if (PopFriendly.test(Reg)) { 589*0b57cec5SDimitry Andric PopReg = Reg; 590*0b57cec5SDimitry Andric TmpReg = 0; 591*0b57cec5SDimitry Andric break; 592*0b57cec5SDimitry Andric } 593*0b57cec5SDimitry Andric // Otherwise, remember that the register will be available to 594*0b57cec5SDimitry Andric // save a pop-friendly register. 595*0b57cec5SDimitry Andric TmpReg = Reg; 596*0b57cec5SDimitry Andric } 597*0b57cec5SDimitry Andric } 598*0b57cec5SDimitry Andric } 599*0b57cec5SDimitry Andric 600*0b57cec5SDimitry Andric bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, 601*0b57cec5SDimitry Andric bool DoIt) const { 602*0b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 603*0b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 604*0b57cec5SDimitry Andric unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); 605*0b57cec5SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 606*0b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 607*0b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 608*0b57cec5SDimitry Andric 609*0b57cec5SDimitry Andric // If MBBI is a return instruction, or is a tPOP followed by a return 610*0b57cec5SDimitry Andric // instruction in the successor BB, we may be able to directly restore 611*0b57cec5SDimitry Andric // LR in the PC. 612*0b57cec5SDimitry Andric // This is only possible with v5T ops (v4T can't change the Thumb bit via 613*0b57cec5SDimitry Andric // a POP PC instruction), and only if we do not need to emit any SP update. 614*0b57cec5SDimitry Andric // Otherwise, we need a temporary register to pop the value 615*0b57cec5SDimitry Andric // and copy that value into LR. 616*0b57cec5SDimitry Andric auto MBBI = MBB.getFirstTerminator(); 617*0b57cec5SDimitry Andric bool CanRestoreDirectly = STI.hasV5TOps() && !ArgRegsSaveSize; 618*0b57cec5SDimitry Andric if (CanRestoreDirectly) { 619*0b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() != ARM::tB) 620*0b57cec5SDimitry Andric CanRestoreDirectly = (MBBI->getOpcode() == ARM::tBX_RET || 621*0b57cec5SDimitry Andric MBBI->getOpcode() == ARM::tPOP_RET); 622*0b57cec5SDimitry Andric else { 623*0b57cec5SDimitry Andric auto MBBI_prev = MBBI; 624*0b57cec5SDimitry Andric MBBI_prev--; 625*0b57cec5SDimitry Andric assert(MBBI_prev->getOpcode() == ARM::tPOP); 626*0b57cec5SDimitry Andric assert(MBB.succ_size() == 1); 627*0b57cec5SDimitry Andric if ((*MBB.succ_begin())->begin()->getOpcode() == ARM::tBX_RET) 628*0b57cec5SDimitry Andric MBBI = MBBI_prev; // Replace the final tPOP with a tPOP_RET. 629*0b57cec5SDimitry Andric else 630*0b57cec5SDimitry Andric CanRestoreDirectly = false; 631*0b57cec5SDimitry Andric } 632*0b57cec5SDimitry Andric } 633*0b57cec5SDimitry Andric 634*0b57cec5SDimitry Andric if (CanRestoreDirectly) { 635*0b57cec5SDimitry Andric if (!DoIt || MBBI->getOpcode() == ARM::tPOP_RET) 636*0b57cec5SDimitry Andric return true; 637*0b57cec5SDimitry Andric MachineInstrBuilder MIB = 638*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP_RET)) 639*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 640*0b57cec5SDimitry Andric // Copy implicit ops and popped registers, if any. 641*0b57cec5SDimitry Andric for (auto MO: MBBI->operands()) 642*0b57cec5SDimitry Andric if (MO.isReg() && (MO.isImplicit() || MO.isDef())) 643*0b57cec5SDimitry Andric MIB.add(MO); 644*0b57cec5SDimitry Andric MIB.addReg(ARM::PC, RegState::Define); 645*0b57cec5SDimitry Andric // Erase the old instruction (tBX_RET or tPOP). 646*0b57cec5SDimitry Andric MBB.erase(MBBI); 647*0b57cec5SDimitry Andric return true; 648*0b57cec5SDimitry Andric } 649*0b57cec5SDimitry Andric 650*0b57cec5SDimitry Andric // Look for a temporary register to use. 651*0b57cec5SDimitry Andric // First, compute the liveness information. 652*0b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 653*0b57cec5SDimitry Andric LivePhysRegs UsedRegs(TRI); 654*0b57cec5SDimitry Andric UsedRegs.addLiveOuts(MBB); 655*0b57cec5SDimitry Andric // The semantic of pristines changed recently and now, 656*0b57cec5SDimitry Andric // the callee-saved registers that are touched in the function 657*0b57cec5SDimitry Andric // are not part of the pristines set anymore. 658*0b57cec5SDimitry Andric // Add those callee-saved now. 659*0b57cec5SDimitry Andric const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF); 660*0b57cec5SDimitry Andric for (unsigned i = 0; CSRegs[i]; ++i) 661*0b57cec5SDimitry Andric UsedRegs.addReg(CSRegs[i]); 662*0b57cec5SDimitry Andric 663*0b57cec5SDimitry Andric DebugLoc dl = DebugLoc(); 664*0b57cec5SDimitry Andric if (MBBI != MBB.end()) { 665*0b57cec5SDimitry Andric dl = MBBI->getDebugLoc(); 666*0b57cec5SDimitry Andric auto InstUpToMBBI = MBB.end(); 667*0b57cec5SDimitry Andric while (InstUpToMBBI != MBBI) 668*0b57cec5SDimitry Andric // The pre-decrement is on purpose here. 669*0b57cec5SDimitry Andric // We want to have the liveness right before MBBI. 670*0b57cec5SDimitry Andric UsedRegs.stepBackward(*--InstUpToMBBI); 671*0b57cec5SDimitry Andric } 672*0b57cec5SDimitry Andric 673*0b57cec5SDimitry Andric // Look for a register that can be directly use in the POP. 674*0b57cec5SDimitry Andric unsigned PopReg = 0; 675*0b57cec5SDimitry Andric // And some temporary register, just in case. 676*0b57cec5SDimitry Andric unsigned TemporaryReg = 0; 677*0b57cec5SDimitry Andric BitVector PopFriendly = 678*0b57cec5SDimitry Andric TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::tGPRRegClassID)); 679*0b57cec5SDimitry Andric // R7 may be used as a frame pointer, hence marked as not generally 680*0b57cec5SDimitry Andric // allocatable, however there's no reason to not use it as a temporary for 681*0b57cec5SDimitry Andric // restoring LR. 682*0b57cec5SDimitry Andric if (STI.useR7AsFramePointer()) 683*0b57cec5SDimitry Andric PopFriendly.set(ARM::R7); 684*0b57cec5SDimitry Andric 685*0b57cec5SDimitry Andric assert(PopFriendly.any() && "No allocatable pop-friendly register?!"); 686*0b57cec5SDimitry Andric // Rebuild the GPRs from the high registers because they are removed 687*0b57cec5SDimitry Andric // form the GPR reg class for thumb1. 688*0b57cec5SDimitry Andric BitVector GPRsNoLRSP = 689*0b57cec5SDimitry Andric TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::hGPRRegClassID)); 690*0b57cec5SDimitry Andric GPRsNoLRSP |= PopFriendly; 691*0b57cec5SDimitry Andric GPRsNoLRSP.reset(ARM::LR); 692*0b57cec5SDimitry Andric GPRsNoLRSP.reset(ARM::SP); 693*0b57cec5SDimitry Andric GPRsNoLRSP.reset(ARM::PC); 694*0b57cec5SDimitry Andric findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, TemporaryReg); 695*0b57cec5SDimitry Andric 696*0b57cec5SDimitry Andric // If we couldn't find a pop-friendly register, try restoring LR before 697*0b57cec5SDimitry Andric // popping the other callee-saved registers, so we could use one of them as a 698*0b57cec5SDimitry Andric // temporary. 699*0b57cec5SDimitry Andric bool UseLDRSP = false; 700*0b57cec5SDimitry Andric if (!PopReg && MBBI != MBB.begin()) { 701*0b57cec5SDimitry Andric auto PrevMBBI = MBBI; 702*0b57cec5SDimitry Andric PrevMBBI--; 703*0b57cec5SDimitry Andric if (PrevMBBI->getOpcode() == ARM::tPOP) { 704*0b57cec5SDimitry Andric UsedRegs.stepBackward(*PrevMBBI); 705*0b57cec5SDimitry Andric findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, TemporaryReg); 706*0b57cec5SDimitry Andric if (PopReg) { 707*0b57cec5SDimitry Andric MBBI = PrevMBBI; 708*0b57cec5SDimitry Andric UseLDRSP = true; 709*0b57cec5SDimitry Andric } 710*0b57cec5SDimitry Andric } 711*0b57cec5SDimitry Andric } 712*0b57cec5SDimitry Andric 713*0b57cec5SDimitry Andric if (!DoIt && !PopReg && !TemporaryReg) 714*0b57cec5SDimitry Andric return false; 715*0b57cec5SDimitry Andric 716*0b57cec5SDimitry Andric assert((PopReg || TemporaryReg) && "Cannot get LR"); 717*0b57cec5SDimitry Andric 718*0b57cec5SDimitry Andric if (UseLDRSP) { 719*0b57cec5SDimitry Andric assert(PopReg && "Do not know how to get LR"); 720*0b57cec5SDimitry Andric // Load the LR via LDR tmp, [SP, #off] 721*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRspi)) 722*0b57cec5SDimitry Andric .addReg(PopReg, RegState::Define) 723*0b57cec5SDimitry Andric .addReg(ARM::SP) 724*0b57cec5SDimitry Andric .addImm(MBBI->getNumExplicitOperands() - 2) 725*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 726*0b57cec5SDimitry Andric // Move from the temporary register to the LR. 727*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 728*0b57cec5SDimitry Andric .addReg(ARM::LR, RegState::Define) 729*0b57cec5SDimitry Andric .addReg(PopReg, RegState::Kill) 730*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 731*0b57cec5SDimitry Andric // Advance past the pop instruction. 732*0b57cec5SDimitry Andric MBBI++; 733*0b57cec5SDimitry Andric // Increment the SP. 734*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, 735*0b57cec5SDimitry Andric ArgRegsSaveSize + 4, ARM::NoRegister, 736*0b57cec5SDimitry Andric MachineInstr::NoFlags); 737*0b57cec5SDimitry Andric return true; 738*0b57cec5SDimitry Andric } 739*0b57cec5SDimitry Andric 740*0b57cec5SDimitry Andric if (TemporaryReg) { 741*0b57cec5SDimitry Andric assert(!PopReg && "Unnecessary MOV is about to be inserted"); 742*0b57cec5SDimitry Andric PopReg = PopFriendly.find_first(); 743*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 744*0b57cec5SDimitry Andric .addReg(TemporaryReg, RegState::Define) 745*0b57cec5SDimitry Andric .addReg(PopReg, RegState::Kill) 746*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 747*0b57cec5SDimitry Andric } 748*0b57cec5SDimitry Andric 749*0b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPOP_RET) { 750*0b57cec5SDimitry Andric // We couldn't use the direct restoration above, so 751*0b57cec5SDimitry Andric // perform the opposite conversion: tPOP_RET to tPOP. 752*0b57cec5SDimitry Andric MachineInstrBuilder MIB = 753*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP)) 754*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 755*0b57cec5SDimitry Andric bool Popped = false; 756*0b57cec5SDimitry Andric for (auto MO: MBBI->operands()) 757*0b57cec5SDimitry Andric if (MO.isReg() && (MO.isImplicit() || MO.isDef()) && 758*0b57cec5SDimitry Andric MO.getReg() != ARM::PC) { 759*0b57cec5SDimitry Andric MIB.add(MO); 760*0b57cec5SDimitry Andric if (!MO.isImplicit()) 761*0b57cec5SDimitry Andric Popped = true; 762*0b57cec5SDimitry Andric } 763*0b57cec5SDimitry Andric // Is there anything left to pop? 764*0b57cec5SDimitry Andric if (!Popped) 765*0b57cec5SDimitry Andric MBB.erase(MIB.getInstr()); 766*0b57cec5SDimitry Andric // Erase the old instruction. 767*0b57cec5SDimitry Andric MBB.erase(MBBI); 768*0b57cec5SDimitry Andric MBBI = BuildMI(MBB, MBB.end(), dl, TII.get(ARM::tBX_RET)) 769*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 770*0b57cec5SDimitry Andric } 771*0b57cec5SDimitry Andric 772*0b57cec5SDimitry Andric assert(PopReg && "Do not know how to get LR"); 773*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP)) 774*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 775*0b57cec5SDimitry Andric .addReg(PopReg, RegState::Define); 776*0b57cec5SDimitry Andric 777*0b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize, 778*0b57cec5SDimitry Andric ARM::NoRegister, MachineInstr::NoFlags); 779*0b57cec5SDimitry Andric 780*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 781*0b57cec5SDimitry Andric .addReg(ARM::LR, RegState::Define) 782*0b57cec5SDimitry Andric .addReg(PopReg, RegState::Kill) 783*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 784*0b57cec5SDimitry Andric 785*0b57cec5SDimitry Andric if (TemporaryReg) 786*0b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 787*0b57cec5SDimitry Andric .addReg(PopReg, RegState::Define) 788*0b57cec5SDimitry Andric .addReg(TemporaryReg, RegState::Kill) 789*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 790*0b57cec5SDimitry Andric 791*0b57cec5SDimitry Andric return true; 792*0b57cec5SDimitry Andric } 793*0b57cec5SDimitry Andric 794*0b57cec5SDimitry Andric using ARMRegSet = std::bitset<ARM::NUM_TARGET_REGS>; 795*0b57cec5SDimitry Andric 796*0b57cec5SDimitry Andric // Return the first iteraror after CurrentReg which is present in EnabledRegs, 797*0b57cec5SDimitry Andric // or OrderEnd if no further registers are in that set. This does not advance 798*0b57cec5SDimitry Andric // the iterator fiorst, so returns CurrentReg if it is in EnabledRegs. 799*0b57cec5SDimitry Andric static const unsigned *findNextOrderedReg(const unsigned *CurrentReg, 800*0b57cec5SDimitry Andric const ARMRegSet &EnabledRegs, 801*0b57cec5SDimitry Andric const unsigned *OrderEnd) { 802*0b57cec5SDimitry Andric while (CurrentReg != OrderEnd && !EnabledRegs[*CurrentReg]) 803*0b57cec5SDimitry Andric ++CurrentReg; 804*0b57cec5SDimitry Andric return CurrentReg; 805*0b57cec5SDimitry Andric } 806*0b57cec5SDimitry Andric 807*0b57cec5SDimitry Andric bool Thumb1FrameLowering:: 808*0b57cec5SDimitry Andric spillCalleeSavedRegisters(MachineBasicBlock &MBB, 809*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 810*0b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI, 811*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 812*0b57cec5SDimitry Andric if (CSI.empty()) 813*0b57cec5SDimitry Andric return false; 814*0b57cec5SDimitry Andric 815*0b57cec5SDimitry Andric DebugLoc DL; 816*0b57cec5SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 817*0b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 818*0b57cec5SDimitry Andric const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( 819*0b57cec5SDimitry Andric MF.getSubtarget().getRegisterInfo()); 820*0b57cec5SDimitry Andric 821*0b57cec5SDimitry Andric ARMRegSet LoRegsToSave; // r0-r7, lr 822*0b57cec5SDimitry Andric ARMRegSet HiRegsToSave; // r8-r11 823*0b57cec5SDimitry Andric ARMRegSet CopyRegs; // Registers which can be used after pushing 824*0b57cec5SDimitry Andric // LoRegs for saving HiRegs. 825*0b57cec5SDimitry Andric 826*0b57cec5SDimitry Andric for (unsigned i = CSI.size(); i != 0; --i) { 827*0b57cec5SDimitry Andric unsigned Reg = CSI[i-1].getReg(); 828*0b57cec5SDimitry Andric 829*0b57cec5SDimitry Andric if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) { 830*0b57cec5SDimitry Andric LoRegsToSave[Reg] = true; 831*0b57cec5SDimitry Andric } else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) { 832*0b57cec5SDimitry Andric HiRegsToSave[Reg] = true; 833*0b57cec5SDimitry Andric } else { 834*0b57cec5SDimitry Andric llvm_unreachable("callee-saved register of unexpected class"); 835*0b57cec5SDimitry Andric } 836*0b57cec5SDimitry Andric 837*0b57cec5SDimitry Andric if ((ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) && 838*0b57cec5SDimitry Andric !MF.getRegInfo().isLiveIn(Reg) && 839*0b57cec5SDimitry Andric !(hasFP(MF) && Reg == RegInfo->getFrameRegister(MF))) 840*0b57cec5SDimitry Andric CopyRegs[Reg] = true; 841*0b57cec5SDimitry Andric } 842*0b57cec5SDimitry Andric 843*0b57cec5SDimitry Andric // Unused argument registers can be used for the high register saving. 844*0b57cec5SDimitry Andric for (unsigned ArgReg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) 845*0b57cec5SDimitry Andric if (!MF.getRegInfo().isLiveIn(ArgReg)) 846*0b57cec5SDimitry Andric CopyRegs[ArgReg] = true; 847*0b57cec5SDimitry Andric 848*0b57cec5SDimitry Andric // Push the low registers and lr 849*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 850*0b57cec5SDimitry Andric if (!LoRegsToSave.none()) { 851*0b57cec5SDimitry Andric MachineInstrBuilder MIB = 852*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL)); 853*0b57cec5SDimitry Andric for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6, ARM::R7, ARM::LR}) { 854*0b57cec5SDimitry Andric if (LoRegsToSave[Reg]) { 855*0b57cec5SDimitry Andric bool isKill = !MRI.isLiveIn(Reg); 856*0b57cec5SDimitry Andric if (isKill && !MRI.isReserved(Reg)) 857*0b57cec5SDimitry Andric MBB.addLiveIn(Reg); 858*0b57cec5SDimitry Andric 859*0b57cec5SDimitry Andric MIB.addReg(Reg, getKillRegState(isKill)); 860*0b57cec5SDimitry Andric } 861*0b57cec5SDimitry Andric } 862*0b57cec5SDimitry Andric MIB.setMIFlags(MachineInstr::FrameSetup); 863*0b57cec5SDimitry Andric } 864*0b57cec5SDimitry Andric 865*0b57cec5SDimitry Andric // Push the high registers. There are no store instructions that can access 866*0b57cec5SDimitry Andric // these registers directly, so we have to move them to low registers, and 867*0b57cec5SDimitry Andric // push them. This might take multiple pushes, as it is possible for there to 868*0b57cec5SDimitry Andric // be fewer low registers available than high registers which need saving. 869*0b57cec5SDimitry Andric 870*0b57cec5SDimitry Andric // These are in reverse order so that in the case where we need to use 871*0b57cec5SDimitry Andric // multiple PUSH instructions, the order of the registers on the stack still 872*0b57cec5SDimitry Andric // matches the unwind info. They need to be swicthed back to ascending order 873*0b57cec5SDimitry Andric // before adding to the PUSH instruction. 874*0b57cec5SDimitry Andric static const unsigned AllCopyRegs[] = {ARM::LR, ARM::R7, ARM::R6, 875*0b57cec5SDimitry Andric ARM::R5, ARM::R4, ARM::R3, 876*0b57cec5SDimitry Andric ARM::R2, ARM::R1, ARM::R0}; 877*0b57cec5SDimitry Andric static const unsigned AllHighRegs[] = {ARM::R11, ARM::R10, ARM::R9, ARM::R8}; 878*0b57cec5SDimitry Andric 879*0b57cec5SDimitry Andric const unsigned *AllCopyRegsEnd = std::end(AllCopyRegs); 880*0b57cec5SDimitry Andric const unsigned *AllHighRegsEnd = std::end(AllHighRegs); 881*0b57cec5SDimitry Andric 882*0b57cec5SDimitry Andric // Find the first register to save. 883*0b57cec5SDimitry Andric const unsigned *HiRegToSave = findNextOrderedReg( 884*0b57cec5SDimitry Andric std::begin(AllHighRegs), HiRegsToSave, AllHighRegsEnd); 885*0b57cec5SDimitry Andric 886*0b57cec5SDimitry Andric while (HiRegToSave != AllHighRegsEnd) { 887*0b57cec5SDimitry Andric // Find the first low register to use. 888*0b57cec5SDimitry Andric const unsigned *CopyReg = 889*0b57cec5SDimitry Andric findNextOrderedReg(std::begin(AllCopyRegs), CopyRegs, AllCopyRegsEnd); 890*0b57cec5SDimitry Andric 891*0b57cec5SDimitry Andric // Create the PUSH, but don't insert it yet (the MOVs need to come first). 892*0b57cec5SDimitry Andric MachineInstrBuilder PushMIB = BuildMI(MF, DL, TII.get(ARM::tPUSH)) 893*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 894*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 895*0b57cec5SDimitry Andric 896*0b57cec5SDimitry Andric SmallVector<unsigned, 4> RegsToPush; 897*0b57cec5SDimitry Andric while (HiRegToSave != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) { 898*0b57cec5SDimitry Andric if (HiRegsToSave[*HiRegToSave]) { 899*0b57cec5SDimitry Andric bool isKill = !MRI.isLiveIn(*HiRegToSave); 900*0b57cec5SDimitry Andric if (isKill && !MRI.isReserved(*HiRegToSave)) 901*0b57cec5SDimitry Andric MBB.addLiveIn(*HiRegToSave); 902*0b57cec5SDimitry Andric 903*0b57cec5SDimitry Andric // Emit a MOV from the high reg to the low reg. 904*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)) 905*0b57cec5SDimitry Andric .addReg(*CopyReg, RegState::Define) 906*0b57cec5SDimitry Andric .addReg(*HiRegToSave, getKillRegState(isKill)) 907*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 908*0b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 909*0b57cec5SDimitry Andric 910*0b57cec5SDimitry Andric // Record the register that must be added to the PUSH. 911*0b57cec5SDimitry Andric RegsToPush.push_back(*CopyReg); 912*0b57cec5SDimitry Andric 913*0b57cec5SDimitry Andric CopyReg = findNextOrderedReg(++CopyReg, CopyRegs, AllCopyRegsEnd); 914*0b57cec5SDimitry Andric HiRegToSave = 915*0b57cec5SDimitry Andric findNextOrderedReg(++HiRegToSave, HiRegsToSave, AllHighRegsEnd); 916*0b57cec5SDimitry Andric } 917*0b57cec5SDimitry Andric } 918*0b57cec5SDimitry Andric 919*0b57cec5SDimitry Andric // Add the low registers to the PUSH, in ascending order. 920*0b57cec5SDimitry Andric for (unsigned Reg : llvm::reverse(RegsToPush)) 921*0b57cec5SDimitry Andric PushMIB.addReg(Reg, RegState::Kill); 922*0b57cec5SDimitry Andric 923*0b57cec5SDimitry Andric // Insert the PUSH instruction after the MOVs. 924*0b57cec5SDimitry Andric MBB.insert(MI, PushMIB); 925*0b57cec5SDimitry Andric } 926*0b57cec5SDimitry Andric 927*0b57cec5SDimitry Andric return true; 928*0b57cec5SDimitry Andric } 929*0b57cec5SDimitry Andric 930*0b57cec5SDimitry Andric bool Thumb1FrameLowering:: 931*0b57cec5SDimitry Andric restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 932*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 933*0b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSI, 934*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 935*0b57cec5SDimitry Andric if (CSI.empty()) 936*0b57cec5SDimitry Andric return false; 937*0b57cec5SDimitry Andric 938*0b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 939*0b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 940*0b57cec5SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 941*0b57cec5SDimitry Andric const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( 942*0b57cec5SDimitry Andric MF.getSubtarget().getRegisterInfo()); 943*0b57cec5SDimitry Andric 944*0b57cec5SDimitry Andric bool isVarArg = AFI->getArgRegsSaveSize() > 0; 945*0b57cec5SDimitry Andric DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); 946*0b57cec5SDimitry Andric 947*0b57cec5SDimitry Andric ARMRegSet LoRegsToRestore; 948*0b57cec5SDimitry Andric ARMRegSet HiRegsToRestore; 949*0b57cec5SDimitry Andric // Low registers (r0-r7) which can be used to restore the high registers. 950*0b57cec5SDimitry Andric ARMRegSet CopyRegs; 951*0b57cec5SDimitry Andric 952*0b57cec5SDimitry Andric for (CalleeSavedInfo I : CSI) { 953*0b57cec5SDimitry Andric unsigned Reg = I.getReg(); 954*0b57cec5SDimitry Andric 955*0b57cec5SDimitry Andric if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) { 956*0b57cec5SDimitry Andric LoRegsToRestore[Reg] = true; 957*0b57cec5SDimitry Andric } else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) { 958*0b57cec5SDimitry Andric HiRegsToRestore[Reg] = true; 959*0b57cec5SDimitry Andric } else { 960*0b57cec5SDimitry Andric llvm_unreachable("callee-saved register of unexpected class"); 961*0b57cec5SDimitry Andric } 962*0b57cec5SDimitry Andric 963*0b57cec5SDimitry Andric // If this is a low register not used as the frame pointer, we may want to 964*0b57cec5SDimitry Andric // use it for restoring the high registers. 965*0b57cec5SDimitry Andric if ((ARM::tGPRRegClass.contains(Reg)) && 966*0b57cec5SDimitry Andric !(hasFP(MF) && Reg == RegInfo->getFrameRegister(MF))) 967*0b57cec5SDimitry Andric CopyRegs[Reg] = true; 968*0b57cec5SDimitry Andric } 969*0b57cec5SDimitry Andric 970*0b57cec5SDimitry Andric // If this is a return block, we may be able to use some unused return value 971*0b57cec5SDimitry Andric // registers for restoring the high regs. 972*0b57cec5SDimitry Andric auto Terminator = MBB.getFirstTerminator(); 973*0b57cec5SDimitry Andric if (Terminator != MBB.end() && Terminator->getOpcode() == ARM::tBX_RET) { 974*0b57cec5SDimitry Andric CopyRegs[ARM::R0] = true; 975*0b57cec5SDimitry Andric CopyRegs[ARM::R1] = true; 976*0b57cec5SDimitry Andric CopyRegs[ARM::R2] = true; 977*0b57cec5SDimitry Andric CopyRegs[ARM::R3] = true; 978*0b57cec5SDimitry Andric for (auto Op : Terminator->implicit_operands()) { 979*0b57cec5SDimitry Andric if (Op.isReg()) 980*0b57cec5SDimitry Andric CopyRegs[Op.getReg()] = false; 981*0b57cec5SDimitry Andric } 982*0b57cec5SDimitry Andric } 983*0b57cec5SDimitry Andric 984*0b57cec5SDimitry Andric static const unsigned AllCopyRegs[] = {ARM::R0, ARM::R1, ARM::R2, ARM::R3, 985*0b57cec5SDimitry Andric ARM::R4, ARM::R5, ARM::R6, ARM::R7}; 986*0b57cec5SDimitry Andric static const unsigned AllHighRegs[] = {ARM::R8, ARM::R9, ARM::R10, ARM::R11}; 987*0b57cec5SDimitry Andric 988*0b57cec5SDimitry Andric const unsigned *AllCopyRegsEnd = std::end(AllCopyRegs); 989*0b57cec5SDimitry Andric const unsigned *AllHighRegsEnd = std::end(AllHighRegs); 990*0b57cec5SDimitry Andric 991*0b57cec5SDimitry Andric // Find the first register to restore. 992*0b57cec5SDimitry Andric auto HiRegToRestore = findNextOrderedReg(std::begin(AllHighRegs), 993*0b57cec5SDimitry Andric HiRegsToRestore, AllHighRegsEnd); 994*0b57cec5SDimitry Andric 995*0b57cec5SDimitry Andric while (HiRegToRestore != AllHighRegsEnd) { 996*0b57cec5SDimitry Andric assert(!CopyRegs.none()); 997*0b57cec5SDimitry Andric // Find the first low register to use. 998*0b57cec5SDimitry Andric auto CopyReg = 999*0b57cec5SDimitry Andric findNextOrderedReg(std::begin(AllCopyRegs), CopyRegs, AllCopyRegsEnd); 1000*0b57cec5SDimitry Andric 1001*0b57cec5SDimitry Andric // Create the POP instruction. 1002*0b57cec5SDimitry Andric MachineInstrBuilder PopMIB = 1003*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL)); 1004*0b57cec5SDimitry Andric 1005*0b57cec5SDimitry Andric while (HiRegToRestore != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) { 1006*0b57cec5SDimitry Andric // Add the low register to the POP. 1007*0b57cec5SDimitry Andric PopMIB.addReg(*CopyReg, RegState::Define); 1008*0b57cec5SDimitry Andric 1009*0b57cec5SDimitry Andric // Create the MOV from low to high register. 1010*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)) 1011*0b57cec5SDimitry Andric .addReg(*HiRegToRestore, RegState::Define) 1012*0b57cec5SDimitry Andric .addReg(*CopyReg, RegState::Kill) 1013*0b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 1014*0b57cec5SDimitry Andric 1015*0b57cec5SDimitry Andric CopyReg = findNextOrderedReg(++CopyReg, CopyRegs, AllCopyRegsEnd); 1016*0b57cec5SDimitry Andric HiRegToRestore = 1017*0b57cec5SDimitry Andric findNextOrderedReg(++HiRegToRestore, HiRegsToRestore, AllHighRegsEnd); 1018*0b57cec5SDimitry Andric } 1019*0b57cec5SDimitry Andric } 1020*0b57cec5SDimitry Andric 1021*0b57cec5SDimitry Andric MachineInstrBuilder MIB = 1022*0b57cec5SDimitry Andric BuildMI(MF, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL)); 1023*0b57cec5SDimitry Andric 1024*0b57cec5SDimitry Andric bool NeedsPop = false; 1025*0b57cec5SDimitry Andric for (unsigned i = CSI.size(); i != 0; --i) { 1026*0b57cec5SDimitry Andric CalleeSavedInfo &Info = CSI[i-1]; 1027*0b57cec5SDimitry Andric unsigned Reg = Info.getReg(); 1028*0b57cec5SDimitry Andric 1029*0b57cec5SDimitry Andric // High registers (excluding lr) have already been dealt with 1030*0b57cec5SDimitry Andric if (!(ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR)) 1031*0b57cec5SDimitry Andric continue; 1032*0b57cec5SDimitry Andric 1033*0b57cec5SDimitry Andric if (Reg == ARM::LR) { 1034*0b57cec5SDimitry Andric Info.setRestored(false); 1035*0b57cec5SDimitry Andric if (!MBB.succ_empty() || 1036*0b57cec5SDimitry Andric MI->getOpcode() == ARM::TCRETURNdi || 1037*0b57cec5SDimitry Andric MI->getOpcode() == ARM::TCRETURNri) 1038*0b57cec5SDimitry Andric // LR may only be popped into PC, as part of return sequence. 1039*0b57cec5SDimitry Andric // If this isn't the return sequence, we'll need emitPopSpecialFixUp 1040*0b57cec5SDimitry Andric // to restore LR the hard way. 1041*0b57cec5SDimitry Andric // FIXME: if we don't pass any stack arguments it would be actually 1042*0b57cec5SDimitry Andric // advantageous *and* correct to do the conversion to an ordinary call 1043*0b57cec5SDimitry Andric // instruction here. 1044*0b57cec5SDimitry Andric continue; 1045*0b57cec5SDimitry Andric // Special epilogue for vararg functions. See emitEpilogue 1046*0b57cec5SDimitry Andric if (isVarArg) 1047*0b57cec5SDimitry Andric continue; 1048*0b57cec5SDimitry Andric // ARMv4T requires BX, see emitEpilogue 1049*0b57cec5SDimitry Andric if (!STI.hasV5TOps()) 1050*0b57cec5SDimitry Andric continue; 1051*0b57cec5SDimitry Andric 1052*0b57cec5SDimitry Andric // Pop LR into PC. 1053*0b57cec5SDimitry Andric Reg = ARM::PC; 1054*0b57cec5SDimitry Andric (*MIB).setDesc(TII.get(ARM::tPOP_RET)); 1055*0b57cec5SDimitry Andric if (MI != MBB.end()) 1056*0b57cec5SDimitry Andric MIB.copyImplicitOps(*MI); 1057*0b57cec5SDimitry Andric MI = MBB.erase(MI); 1058*0b57cec5SDimitry Andric } 1059*0b57cec5SDimitry Andric MIB.addReg(Reg, getDefRegState(true)); 1060*0b57cec5SDimitry Andric NeedsPop = true; 1061*0b57cec5SDimitry Andric } 1062*0b57cec5SDimitry Andric 1063*0b57cec5SDimitry Andric // It's illegal to emit pop instruction without operands. 1064*0b57cec5SDimitry Andric if (NeedsPop) 1065*0b57cec5SDimitry Andric MBB.insert(MI, &*MIB); 1066*0b57cec5SDimitry Andric else 1067*0b57cec5SDimitry Andric MF.DeleteMachineInstr(MIB); 1068*0b57cec5SDimitry Andric 1069*0b57cec5SDimitry Andric return true; 1070*0b57cec5SDimitry Andric } 1071