10b57cec5SDimitry Andric //===- Thumb1FrameLowering.cpp - Thumb1 Frame Information -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the Thumb1 implementation of TargetFrameLowering class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "Thumb1FrameLowering.h" 140b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h" 150b57cec5SDimitry Andric #include "ARMBaseRegisterInfo.h" 160b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h" 170b57cec5SDimitry Andric #include "ARMSubtarget.h" 180b57cec5SDimitry Andric #include "Thumb1InstrInfo.h" 190b57cec5SDimitry Andric #include "ThumbRegisterInfo.h" 200b57cec5SDimitry Andric #include "Utils/ARMBaseInfo.h" 210b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 220b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 230b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 360b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 370b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 380b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h" 390b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 400b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 410b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 420b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 430b57cec5SDimitry Andric #include <bitset> 440b57cec5SDimitry Andric #include <cassert> 450b57cec5SDimitry Andric #include <iterator> 460b57cec5SDimitry Andric #include <vector> 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric using namespace llvm; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric Thumb1FrameLowering::Thumb1FrameLowering(const ARMSubtarget &sti) 510b57cec5SDimitry Andric : ARMFrameLowering(sti) {} 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric bool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const{ 540b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 550b57cec5SDimitry Andric unsigned CFSize = MFI.getMaxCallFrameSize(); 560b57cec5SDimitry Andric // It's not always a good idea to include the call frame as part of the 570b57cec5SDimitry Andric // stack frame. ARM (especially Thumb) has small immediate offset to 580b57cec5SDimitry Andric // address the stack frame. So a large call frame can cause poor codegen 590b57cec5SDimitry Andric // and may even makes it impossible to scavenge a register. 600b57cec5SDimitry Andric if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 610b57cec5SDimitry Andric return false; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric return !MFI.hasVarSizedObjects(); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static void 670b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MachineBasicBlock &MBB, 680b57cec5SDimitry Andric MachineBasicBlock::iterator &MBBI, 690b57cec5SDimitry Andric const TargetInstrInfo &TII, const DebugLoc &dl, 700b57cec5SDimitry Andric const ThumbRegisterInfo &MRI, int NumBytes, 710b57cec5SDimitry Andric unsigned ScratchReg, unsigned MIFlags) { 720b57cec5SDimitry Andric // If it would take more than three instructions to adjust the stack pointer 730b57cec5SDimitry Andric // using tADDspi/tSUBspi, load an immediate instead. 740b57cec5SDimitry Andric if (std::abs(NumBytes) > 508 * 3) { 750b57cec5SDimitry Andric // We use a different codepath here from the normal 760b57cec5SDimitry Andric // emitThumbRegPlusImmediate so we don't have to deal with register 770b57cec5SDimitry Andric // scavenging. (Scavenging could try to use the emergency spill slot 780b57cec5SDimitry Andric // before we've actually finished setting up the stack.) 790b57cec5SDimitry Andric if (ScratchReg == ARM::NoRegister) 800b57cec5SDimitry Andric report_fatal_error("Failed to emit Thumb1 stack adjustment"); 810b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 820b57cec5SDimitry Andric const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>(); 830b57cec5SDimitry Andric if (ST.genExecuteOnly()) { 840b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ScratchReg) 850b57cec5SDimitry Andric .addImm(NumBytes).setMIFlags(MIFlags); 860b57cec5SDimitry Andric } else { 870b57cec5SDimitry Andric MRI.emitLoadConstPool(MBB, MBBI, dl, ScratchReg, 0, NumBytes, ARMCC::AL, 880b57cec5SDimitry Andric 0, MIFlags); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDhirr), ARM::SP) 915ffd83dbSDimitry Andric .addReg(ARM::SP) 925ffd83dbSDimitry Andric .addReg(ScratchReg, RegState::Kill) 935ffd83dbSDimitry Andric .add(predOps(ARMCC::AL)) 945ffd83dbSDimitry Andric .setMIFlags(MIFlags); 950b57cec5SDimitry Andric return; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric // FIXME: This is assuming the heuristics in emitThumbRegPlusImmediate 980b57cec5SDimitry Andric // won't change. 990b57cec5SDimitry Andric emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, 1000b57cec5SDimitry Andric MRI, MIFlags); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric static void emitCallSPUpdate(MachineBasicBlock &MBB, 1050b57cec5SDimitry Andric MachineBasicBlock::iterator &MBBI, 1060b57cec5SDimitry Andric const TargetInstrInfo &TII, const DebugLoc &dl, 1070b57cec5SDimitry Andric const ThumbRegisterInfo &MRI, int NumBytes, 1080b57cec5SDimitry Andric unsigned MIFlags = MachineInstr::NoFlags) { 1090b57cec5SDimitry Andric emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, 1100b57cec5SDimitry Andric MRI, MIFlags); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric MachineBasicBlock::iterator Thumb1FrameLowering:: 1150b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 1160b57cec5SDimitry Andric MachineBasicBlock::iterator I) const { 1170b57cec5SDimitry Andric const Thumb1InstrInfo &TII = 1180b57cec5SDimitry Andric *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); 1190b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 1200b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 1210b57cec5SDimitry Andric if (!hasReservedCallFrame(MF)) { 1220b57cec5SDimitry Andric // If we have alloca, convert as follows: 1230b57cec5SDimitry Andric // ADJCALLSTACKDOWN -> sub, sp, sp, amount 1240b57cec5SDimitry Andric // ADJCALLSTACKUP -> add, sp, sp, amount 1250b57cec5SDimitry Andric MachineInstr &Old = *I; 1260b57cec5SDimitry Andric DebugLoc dl = Old.getDebugLoc(); 1270b57cec5SDimitry Andric unsigned Amount = TII.getFrameSize(Old); 1280b57cec5SDimitry Andric if (Amount != 0) { 1290b57cec5SDimitry Andric // We need to keep the stack aligned properly. To do this, we round the 1300b57cec5SDimitry Andric // amount of space needed for the outgoing arguments up to the next 1310b57cec5SDimitry Andric // alignment boundary. 1325ffd83dbSDimitry Andric Amount = alignTo(Amount, getStackAlign()); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric // Replace the pseudo instruction with a new instruction... 1350b57cec5SDimitry Andric unsigned Opc = Old.getOpcode(); 1360b57cec5SDimitry Andric if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { 1370b57cec5SDimitry Andric emitCallSPUpdate(MBB, I, TII, dl, *RegInfo, -Amount); 1380b57cec5SDimitry Andric } else { 1390b57cec5SDimitry Andric assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); 1400b57cec5SDimitry Andric emitCallSPUpdate(MBB, I, TII, dl, *RegInfo, Amount); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric return MBB.erase(I); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, 1480b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 1490b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 1500b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 1510b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 1520b57cec5SDimitry Andric MachineModuleInfo &MMI = MF.getMMI(); 1530b57cec5SDimitry Andric const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 1540b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 1550b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 1560b57cec5SDimitry Andric const Thumb1InstrInfo &TII = 1570b57cec5SDimitry Andric *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); 1600b57cec5SDimitry Andric unsigned NumBytes = MFI.getStackSize(); 1610b57cec5SDimitry Andric assert(NumBytes >= ArgRegsSaveSize && 1620b57cec5SDimitry Andric "ArgRegsSaveSize is included in NumBytes"); 1630b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 1660b57cec5SDimitry Andric // to determine the end of the prologue. 1670b57cec5SDimitry Andric DebugLoc dl; 1680b57cec5SDimitry Andric 1698bcb0991SDimitry Andric Register FramePtr = RegInfo->getFrameRegister(MF); 17004eeddc0SDimitry Andric Register BasePtr = RegInfo->getBaseRegister(); 1710b57cec5SDimitry Andric int CFAOffset = 0; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. 1740b57cec5SDimitry Andric NumBytes = (NumBytes + 3) & ~3; 1750b57cec5SDimitry Andric MFI.setStackSize(NumBytes); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric // Determine the sizes of each callee-save spill areas and record which frame 1780b57cec5SDimitry Andric // belongs to which callee-save spill areas. 179*81ad6265SDimitry Andric unsigned FRSize = 0, GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; 1800b57cec5SDimitry Andric int FramePtrSpillFI = 0; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric if (ArgRegsSaveSize) { 1830b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -ArgRegsSaveSize, 1840b57cec5SDimitry Andric ARM::NoRegister, MachineInstr::FrameSetup); 1855ffd83dbSDimitry Andric CFAOffset += ArgRegsSaveSize; 1865ffd83dbSDimitry Andric unsigned CFIIndex = 1875ffd83dbSDimitry Andric MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset)); 1880b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 1890b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 1900b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric if (!AFI->hasStackFrame()) { 1940b57cec5SDimitry Andric if (NumBytes - ArgRegsSaveSize != 0) { 1950b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, 1960b57cec5SDimitry Andric -(NumBytes - ArgRegsSaveSize), 1970b57cec5SDimitry Andric ARM::NoRegister, MachineInstr::FrameSetup); 1985ffd83dbSDimitry Andric CFAOffset += NumBytes - ArgRegsSaveSize; 1990b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 2005ffd83dbSDimitry Andric MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset)); 2010b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 2020b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 2030b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric return; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 208*81ad6265SDimitry Andric bool HasFrameRecordArea = hasFP(MF) && ARM::hGPRRegClass.contains(FramePtr); 209*81ad6265SDimitry Andric 2104824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 21104eeddc0SDimitry Andric Register Reg = I.getReg(); 2124824e7fdSDimitry Andric int FI = I.getFrameIdx(); 213*81ad6265SDimitry Andric if (Reg == FramePtr) 214*81ad6265SDimitry Andric FramePtrSpillFI = FI; 2150b57cec5SDimitry Andric switch (Reg) { 216*81ad6265SDimitry Andric case ARM::R11: 217*81ad6265SDimitry Andric if (HasFrameRecordArea) { 218*81ad6265SDimitry Andric FRSize += 4; 219*81ad6265SDimitry Andric break; 220*81ad6265SDimitry Andric } 221*81ad6265SDimitry Andric LLVM_FALLTHROUGH; 2220b57cec5SDimitry Andric case ARM::R8: 2230b57cec5SDimitry Andric case ARM::R9: 2240b57cec5SDimitry Andric case ARM::R10: 2250b57cec5SDimitry Andric if (STI.splitFramePushPop(MF)) { 2260b57cec5SDimitry Andric GPRCS2Size += 4; 2270b57cec5SDimitry Andric break; 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric LLVM_FALLTHROUGH; 230*81ad6265SDimitry Andric case ARM::LR: 231*81ad6265SDimitry Andric if (HasFrameRecordArea) { 232*81ad6265SDimitry Andric FRSize += 4; 233*81ad6265SDimitry Andric break; 234*81ad6265SDimitry Andric } 235*81ad6265SDimitry Andric LLVM_FALLTHROUGH; 2360b57cec5SDimitry Andric case ARM::R4: 2370b57cec5SDimitry Andric case ARM::R5: 2380b57cec5SDimitry Andric case ARM::R6: 2390b57cec5SDimitry Andric case ARM::R7: 2400b57cec5SDimitry Andric GPRCS1Size += 4; 2410b57cec5SDimitry Andric break; 2420b57cec5SDimitry Andric default: 2430b57cec5SDimitry Andric DPRCSSize += 8; 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 247*81ad6265SDimitry Andric MachineBasicBlock::iterator FRPush, GPRCS1Push, GPRCS2Push; 248*81ad6265SDimitry Andric if (HasFrameRecordArea) { 249*81ad6265SDimitry Andric // Skip Frame Record setup: 250*81ad6265SDimitry Andric // push {lr} 251*81ad6265SDimitry Andric // mov lr, r11 252*81ad6265SDimitry Andric // push {lr} 253*81ad6265SDimitry Andric std::advance(MBBI, 2); 254*81ad6265SDimitry Andric FRPush = MBBI++; 255*81ad6265SDimitry Andric } 256*81ad6265SDimitry Andric 2570b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { 258*81ad6265SDimitry Andric GPRCS1Push = MBBI; 2590b57cec5SDimitry Andric ++MBBI; 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric 262*81ad6265SDimitry Andric // Find last push instruction for GPRCS2 - spilling of high registers 263*81ad6265SDimitry Andric // (r8-r11) could consist of multiple tPUSH and tMOVr instructions. 264*81ad6265SDimitry Andric while (true) { 265*81ad6265SDimitry Andric MachineBasicBlock::iterator OldMBBI = MBBI; 266*81ad6265SDimitry Andric // Skip a run of tMOVr instructions 267*81ad6265SDimitry Andric while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tMOVr && 268*81ad6265SDimitry Andric MBBI->getFlag(MachineInstr::FrameSetup)) 269*81ad6265SDimitry Andric MBBI++; 270*81ad6265SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH && 271*81ad6265SDimitry Andric MBBI->getFlag(MachineInstr::FrameSetup)) { 272*81ad6265SDimitry Andric GPRCS2Push = MBBI; 273*81ad6265SDimitry Andric MBBI++; 274*81ad6265SDimitry Andric } else { 275*81ad6265SDimitry Andric // We have reached an instruction which is not a push, so the previous 276*81ad6265SDimitry Andric // run of tMOVr instructions (which may have been empty) was not part of 277*81ad6265SDimitry Andric // the prologue. Reset MBBI back to the last PUSH of the prologue. 278*81ad6265SDimitry Andric MBBI = OldMBBI; 279*81ad6265SDimitry Andric break; 280*81ad6265SDimitry Andric } 281*81ad6265SDimitry Andric } 282*81ad6265SDimitry Andric 2830b57cec5SDimitry Andric // Determine starting offsets of spill areas. 284*81ad6265SDimitry Andric unsigned DPRCSOffset = NumBytes - ArgRegsSaveSize - 285*81ad6265SDimitry Andric (FRSize + GPRCS1Size + GPRCS2Size + DPRCSSize); 2860b57cec5SDimitry Andric unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; 2870b57cec5SDimitry Andric unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; 2880b57cec5SDimitry Andric bool HasFP = hasFP(MF); 2890b57cec5SDimitry Andric if (HasFP) 2900b57cec5SDimitry Andric AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) + 2910b57cec5SDimitry Andric NumBytes); 292*81ad6265SDimitry Andric if (HasFrameRecordArea) 293*81ad6265SDimitry Andric AFI->setFrameRecordSavedAreaSize(FRSize); 2940b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); 2950b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); 2960b57cec5SDimitry Andric AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); 2970b57cec5SDimitry Andric NumBytes = DPRCSOffset; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric int FramePtrOffsetInBlock = 0; 3000b57cec5SDimitry Andric unsigned adjustedGPRCS1Size = GPRCS1Size; 3010b57cec5SDimitry Andric if (GPRCS1Size > 0 && GPRCS2Size == 0 && 302*81ad6265SDimitry Andric tryFoldSPUpdateIntoPushPop(STI, MF, &*(GPRCS1Push), NumBytes)) { 3030b57cec5SDimitry Andric FramePtrOffsetInBlock = NumBytes; 3040b57cec5SDimitry Andric adjustedGPRCS1Size += NumBytes; 3050b57cec5SDimitry Andric NumBytes = 0; 3060b57cec5SDimitry Andric } 3075ffd83dbSDimitry Andric CFAOffset += adjustedGPRCS1Size; 308*81ad6265SDimitry Andric 309*81ad6265SDimitry Andric // Adjust FP so it point to the stack slot that contains the previous FP. 310*81ad6265SDimitry Andric if (HasFP) { 311*81ad6265SDimitry Andric MachineBasicBlock::iterator AfterPush = 312*81ad6265SDimitry Andric HasFrameRecordArea ? std::next(FRPush) : std::next(GPRCS1Push); 313*81ad6265SDimitry Andric if (HasFrameRecordArea) { 314*81ad6265SDimitry Andric // We have just finished pushing the previous FP into the stack, 315*81ad6265SDimitry Andric // so simply capture the SP value as the new Frame Pointer. 316*81ad6265SDimitry Andric BuildMI(MBB, AfterPush, dl, TII.get(ARM::tMOVr), FramePtr) 317*81ad6265SDimitry Andric .addReg(ARM::SP) 318*81ad6265SDimitry Andric .setMIFlags(MachineInstr::FrameSetup) 319*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)); 320*81ad6265SDimitry Andric } else { 321*81ad6265SDimitry Andric FramePtrOffsetInBlock += 322*81ad6265SDimitry Andric MFI.getObjectOffset(FramePtrSpillFI) + GPRCS1Size + ArgRegsSaveSize; 323*81ad6265SDimitry Andric BuildMI(MBB, AfterPush, dl, TII.get(ARM::tADDrSPi), FramePtr) 324*81ad6265SDimitry Andric .addReg(ARM::SP) 325*81ad6265SDimitry Andric .addImm(FramePtrOffsetInBlock / 4) 326*81ad6265SDimitry Andric .setMIFlags(MachineInstr::FrameSetup) 327*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)); 328*81ad6265SDimitry Andric } 329*81ad6265SDimitry Andric 330*81ad6265SDimitry Andric if(FramePtrOffsetInBlock) { 331*81ad6265SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa( 332*81ad6265SDimitry Andric nullptr, MRI->getDwarfRegNum(FramePtr, true), (CFAOffset - FramePtrOffsetInBlock))); 333*81ad6265SDimitry Andric BuildMI(MBB, AfterPush, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 334*81ad6265SDimitry Andric .addCFIIndex(CFIIndex) 335*81ad6265SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 336*81ad6265SDimitry Andric } else { 337*81ad6265SDimitry Andric unsigned CFIIndex = 338*81ad6265SDimitry Andric MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( 339*81ad6265SDimitry Andric nullptr, MRI->getDwarfRegNum(FramePtr, true))); 340*81ad6265SDimitry Andric BuildMI(MBB, AfterPush, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 341*81ad6265SDimitry Andric .addCFIIndex(CFIIndex) 342*81ad6265SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 343*81ad6265SDimitry Andric } 344*81ad6265SDimitry Andric if (NumBytes > 508) 345*81ad6265SDimitry Andric // If offset is > 508 then sp cannot be adjusted in a single instruction, 346*81ad6265SDimitry Andric // try restoring from fp instead. 347*81ad6265SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 348*81ad6265SDimitry Andric } 349*81ad6265SDimitry Andric 350*81ad6265SDimitry Andric // Emit call frame information for the callee-saved low registers. 351*81ad6265SDimitry Andric if (GPRCS1Size > 0) { 352*81ad6265SDimitry Andric MachineBasicBlock::iterator Pos = std::next(GPRCS1Push); 353*81ad6265SDimitry Andric if (adjustedGPRCS1Size) { 3545ffd83dbSDimitry Andric unsigned CFIIndex = 3555ffd83dbSDimitry Andric MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset)); 356*81ad6265SDimitry Andric BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 3570b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 3580b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 3590b57cec5SDimitry Andric } 3604824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 36104eeddc0SDimitry Andric Register Reg = I.getReg(); 3624824e7fdSDimitry Andric int FI = I.getFrameIdx(); 3630b57cec5SDimitry Andric switch (Reg) { 3640b57cec5SDimitry Andric case ARM::R8: 3650b57cec5SDimitry Andric case ARM::R9: 3660b57cec5SDimitry Andric case ARM::R10: 3670b57cec5SDimitry Andric case ARM::R11: 3680b57cec5SDimitry Andric case ARM::R12: 3690b57cec5SDimitry Andric if (STI.splitFramePushPop(MF)) 3700b57cec5SDimitry Andric break; 3710b57cec5SDimitry Andric LLVM_FALLTHROUGH; 3720b57cec5SDimitry Andric case ARM::R0: 3730b57cec5SDimitry Andric case ARM::R1: 3740b57cec5SDimitry Andric case ARM::R2: 3750b57cec5SDimitry Andric case ARM::R3: 3760b57cec5SDimitry Andric case ARM::R4: 3770b57cec5SDimitry Andric case ARM::R5: 3780b57cec5SDimitry Andric case ARM::R6: 3790b57cec5SDimitry Andric case ARM::R7: 3800b57cec5SDimitry Andric case ARM::LR: 3810b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 3820b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); 383*81ad6265SDimitry Andric BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 3840b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 3850b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 3860b57cec5SDimitry Andric break; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric // Emit call frame information for the callee-saved high registers. 392*81ad6265SDimitry Andric if (GPRCS2Size > 0) { 393*81ad6265SDimitry Andric MachineBasicBlock::iterator Pos = std::next(GPRCS2Push); 3940b57cec5SDimitry Andric for (auto &I : CSI) { 39504eeddc0SDimitry Andric Register Reg = I.getReg(); 3960b57cec5SDimitry Andric int FI = I.getFrameIdx(); 3970b57cec5SDimitry Andric switch (Reg) { 3980b57cec5SDimitry Andric case ARM::R8: 3990b57cec5SDimitry Andric case ARM::R9: 4000b57cec5SDimitry Andric case ARM::R10: 4010b57cec5SDimitry Andric case ARM::R11: 4020b57cec5SDimitry Andric case ARM::R12: { 4030b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 4040b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); 405*81ad6265SDimitry Andric BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 4060b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 4070b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 4080b57cec5SDimitry Andric break; 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric default: 4110b57cec5SDimitry Andric break; 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric } 414*81ad6265SDimitry Andric } 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric if (NumBytes) { 4170b57cec5SDimitry Andric // Insert it after all the callee-save spills. 4180b57cec5SDimitry Andric // 4190b57cec5SDimitry Andric // For a large stack frame, we might need a scratch register to store 4200b57cec5SDimitry Andric // the size of the frame. We know all callee-save registers are free 4210b57cec5SDimitry Andric // at this point in the prologue, so pick one. 4220b57cec5SDimitry Andric unsigned ScratchRegister = ARM::NoRegister; 4230b57cec5SDimitry Andric for (auto &I : CSI) { 42404eeddc0SDimitry Andric Register Reg = I.getReg(); 4250b57cec5SDimitry Andric if (isARMLowRegister(Reg) && !(HasFP && Reg == FramePtr)) { 4260b57cec5SDimitry Andric ScratchRegister = Reg; 4270b57cec5SDimitry Andric break; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, 4310b57cec5SDimitry Andric ScratchRegister, MachineInstr::FrameSetup); 4320b57cec5SDimitry Andric if (!HasFP) { 4335ffd83dbSDimitry Andric CFAOffset += NumBytes; 4340b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 4355ffd83dbSDimitry Andric MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset)); 4360b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 4370b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 4380b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric if (STI.isTargetELF() && HasFP) 4430b57cec5SDimitry Andric MFI.setOffsetAdjustment(MFI.getOffsetAdjustment() - 4440b57cec5SDimitry Andric AFI->getFramePtrSpillOffset()); 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); 4470b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); 4480b57cec5SDimitry Andric AFI->setDPRCalleeSavedAreaSize(DPRCSSize); 4490b57cec5SDimitry Andric 450fe6060f1SDimitry Andric if (RegInfo->hasStackRealignment(MF)) { 4515ffd83dbSDimitry Andric const unsigned NrBitsToZero = Log2(MFI.getMaxAlign()); 4520b57cec5SDimitry Andric // Emit the following sequence, using R4 as a temporary, since we cannot use 4530b57cec5SDimitry Andric // SP as a source or destination register for the shifts: 4540b57cec5SDimitry Andric // mov r4, sp 4550b57cec5SDimitry Andric // lsrs r4, r4, #NrBitsToZero 4560b57cec5SDimitry Andric // lsls r4, r4, #NrBitsToZero 4570b57cec5SDimitry Andric // mov sp, r4 4580b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4) 4590b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Kill) 4600b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSRri), ARM::R4) 4630b57cec5SDimitry Andric .addDef(ARM::CPSR) 4640b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 4650b57cec5SDimitry Andric .addImm(NrBitsToZero) 4660b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSLri), ARM::R4) 4690b57cec5SDimitry Andric .addDef(ARM::CPSR) 4700b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 4710b57cec5SDimitry Andric .addImm(NrBitsToZero) 4720b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 4750b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 4760b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric // If we need a base pointer, set it up here. It's whatever the value 4820b57cec5SDimitry Andric // of the stack pointer is at this point. Any variable size objects 4830b57cec5SDimitry Andric // will be allocated after this, so we can still use the base pointer 4840b57cec5SDimitry Andric // to reference locals. 4850b57cec5SDimitry Andric if (RegInfo->hasBasePointer(MF)) 4860b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), BasePtr) 4870b57cec5SDimitry Andric .addReg(ARM::SP) 4880b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric // If the frame has variable sized objects then the epilogue must restore 4910b57cec5SDimitry Andric // the sp from fp. We can assume there's an FP here since hasFP already 4920b57cec5SDimitry Andric // checks for hasVarSizedObjects. 4930b57cec5SDimitry Andric if (MFI.hasVarSizedObjects()) 4940b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric // In some cases, virtual registers have been introduced, e.g. by uses of 4970b57cec5SDimitry Andric // emitThumbRegPlusImmInReg. 4980b57cec5SDimitry Andric MF.getProperties().reset(MachineFunctionProperties::Property::NoVRegs); 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, 5020b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 5030b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); 5040b57cec5SDimitry Andric DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 5050b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 5060b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 5070b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 5080b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 5090b57cec5SDimitry Andric const Thumb1InstrInfo &TII = 5100b57cec5SDimitry Andric *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); 5130b57cec5SDimitry Andric int NumBytes = (int)MFI.getStackSize(); 5140b57cec5SDimitry Andric assert((unsigned)NumBytes >= ArgRegsSaveSize && 5150b57cec5SDimitry Andric "ArgRegsSaveSize is included in NumBytes"); 5168bcb0991SDimitry Andric Register FramePtr = RegInfo->getFrameRegister(MF); 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric if (!AFI->hasStackFrame()) { 5190b57cec5SDimitry Andric if (NumBytes - ArgRegsSaveSize != 0) 5200b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, 5210b57cec5SDimitry Andric NumBytes - ArgRegsSaveSize, ARM::NoRegister, 522*81ad6265SDimitry Andric MachineInstr::FrameDestroy); 5230b57cec5SDimitry Andric } else { 5240b57cec5SDimitry Andric // Unwind MBBI to point to first LDR / VLDRD. 5250b57cec5SDimitry Andric if (MBBI != MBB.begin()) { 5260b57cec5SDimitry Andric do 5270b57cec5SDimitry Andric --MBBI; 528*81ad6265SDimitry Andric while (MBBI != MBB.begin() && MBBI->getFlag(MachineInstr::FrameDestroy)); 529*81ad6265SDimitry Andric if (!MBBI->getFlag(MachineInstr::FrameDestroy)) 5300b57cec5SDimitry Andric ++MBBI; 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // Move SP to start of FP callee save spill area. 534*81ad6265SDimitry Andric NumBytes -= (AFI->getFrameRecordSavedAreaSize() + 535*81ad6265SDimitry Andric AFI->getGPRCalleeSavedArea1Size() + 5360b57cec5SDimitry Andric AFI->getGPRCalleeSavedArea2Size() + 5370b57cec5SDimitry Andric AFI->getDPRCalleeSavedAreaSize() + 5380b57cec5SDimitry Andric ArgRegsSaveSize); 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric if (AFI->shouldRestoreSPFromFP()) { 5410b57cec5SDimitry Andric NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; 5420b57cec5SDimitry Andric // Reset SP based on frame pointer only if the stack frame extends beyond 5430b57cec5SDimitry Andric // frame pointer stack slot, the target is ELF and the function has FP, or 5440b57cec5SDimitry Andric // the target uses var sized objects. 5450b57cec5SDimitry Andric if (NumBytes) { 5460b57cec5SDimitry Andric assert(!MFI.getPristineRegs(MF).test(ARM::R4) && 5470b57cec5SDimitry Andric "No scratch register to restore SP from FP!"); 5480b57cec5SDimitry Andric emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, 549*81ad6265SDimitry Andric TII, *RegInfo, MachineInstr::FrameDestroy); 5500b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 5510b57cec5SDimitry Andric .addReg(ARM::R4) 552*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 553*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 5540b57cec5SDimitry Andric } else 5550b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 5560b57cec5SDimitry Andric .addReg(FramePtr) 557*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 558*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 5590b57cec5SDimitry Andric } else { 5600b57cec5SDimitry Andric // For a large stack frame, we might need a scratch register to store 5610b57cec5SDimitry Andric // the size of the frame. We know all callee-save registers are free 5620b57cec5SDimitry Andric // at this point in the epilogue, so pick one. 5630b57cec5SDimitry Andric unsigned ScratchRegister = ARM::NoRegister; 5640b57cec5SDimitry Andric bool HasFP = hasFP(MF); 5650b57cec5SDimitry Andric for (auto &I : MFI.getCalleeSavedInfo()) { 56604eeddc0SDimitry Andric Register Reg = I.getReg(); 5670b57cec5SDimitry Andric if (isARMLowRegister(Reg) && !(HasFP && Reg == FramePtr)) { 5680b57cec5SDimitry Andric ScratchRegister = Reg; 5690b57cec5SDimitry Andric break; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tBX_RET && 5730b57cec5SDimitry Andric &MBB.front() != &*MBBI && std::prev(MBBI)->getOpcode() == ARM::tPOP) { 5740b57cec5SDimitry Andric MachineBasicBlock::iterator PMBBI = std::prev(MBBI); 5750b57cec5SDimitry Andric if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*PMBBI, NumBytes)) 5760b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, PMBBI, TII, dl, *RegInfo, NumBytes, 577*81ad6265SDimitry Andric ScratchRegister, MachineInstr::FrameDestroy); 5780b57cec5SDimitry Andric } else if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*MBBI, NumBytes)) 5790b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes, 580*81ad6265SDimitry Andric ScratchRegister, MachineInstr::FrameDestroy); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric if (needPopSpecialFixUp(MF)) { 5850b57cec5SDimitry Andric bool Done = emitPopSpecialFixUp(MBB, /* DoIt */ true); 5860b57cec5SDimitry Andric (void)Done; 5870b57cec5SDimitry Andric assert(Done && "Emission of the special fixup failed!?"); 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric bool Thumb1FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const { 5920b57cec5SDimitry Andric if (!needPopSpecialFixUp(*MBB.getParent())) 5930b57cec5SDimitry Andric return true; 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric MachineBasicBlock *TmpMBB = const_cast<MachineBasicBlock *>(&MBB); 5960b57cec5SDimitry Andric return emitPopSpecialFixUp(*TmpMBB, /* DoIt */ false); 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric bool Thumb1FrameLowering::needPopSpecialFixUp(const MachineFunction &MF) const { 6000b57cec5SDimitry Andric ARMFunctionInfo *AFI = 6010b57cec5SDimitry Andric const_cast<MachineFunction *>(&MF)->getInfo<ARMFunctionInfo>(); 6020b57cec5SDimitry Andric if (AFI->getArgRegsSaveSize()) 6030b57cec5SDimitry Andric return true; 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric // LR cannot be encoded with Thumb1, i.e., it requires a special fix-up. 6060b57cec5SDimitry Andric for (const CalleeSavedInfo &CSI : MF.getFrameInfo().getCalleeSavedInfo()) 6070b57cec5SDimitry Andric if (CSI.getReg() == ARM::LR) 6080b57cec5SDimitry Andric return true; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric return false; 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric static void findTemporariesForLR(const BitVector &GPRsNoLRSP, 6140b57cec5SDimitry Andric const BitVector &PopFriendly, 6150b57cec5SDimitry Andric const LivePhysRegs &UsedRegs, unsigned &PopReg, 616349cc55cSDimitry Andric unsigned &TmpReg, MachineRegisterInfo &MRI) { 6170b57cec5SDimitry Andric PopReg = TmpReg = 0; 6180b57cec5SDimitry Andric for (auto Reg : GPRsNoLRSP.set_bits()) { 619349cc55cSDimitry Andric if (UsedRegs.available(MRI, Reg)) { 6200b57cec5SDimitry Andric // Remember the first pop-friendly register and exit. 6210b57cec5SDimitry Andric if (PopFriendly.test(Reg)) { 6220b57cec5SDimitry Andric PopReg = Reg; 6230b57cec5SDimitry Andric TmpReg = 0; 6240b57cec5SDimitry Andric break; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric // Otherwise, remember that the register will be available to 6270b57cec5SDimitry Andric // save a pop-friendly register. 6280b57cec5SDimitry Andric TmpReg = Reg; 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, 6340b57cec5SDimitry Andric bool DoIt) const { 6350b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 6360b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 6370b57cec5SDimitry Andric unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); 6380b57cec5SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 6390b57cec5SDimitry Andric const ThumbRegisterInfo *RegInfo = 6400b57cec5SDimitry Andric static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric // If MBBI is a return instruction, or is a tPOP followed by a return 6430b57cec5SDimitry Andric // instruction in the successor BB, we may be able to directly restore 6440b57cec5SDimitry Andric // LR in the PC. 6450b57cec5SDimitry Andric // This is only possible with v5T ops (v4T can't change the Thumb bit via 6460b57cec5SDimitry Andric // a POP PC instruction), and only if we do not need to emit any SP update. 6470b57cec5SDimitry Andric // Otherwise, we need a temporary register to pop the value 6480b57cec5SDimitry Andric // and copy that value into LR. 6490b57cec5SDimitry Andric auto MBBI = MBB.getFirstTerminator(); 6500b57cec5SDimitry Andric bool CanRestoreDirectly = STI.hasV5TOps() && !ArgRegsSaveSize; 6510b57cec5SDimitry Andric if (CanRestoreDirectly) { 6520b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() != ARM::tB) 6530b57cec5SDimitry Andric CanRestoreDirectly = (MBBI->getOpcode() == ARM::tBX_RET || 6540b57cec5SDimitry Andric MBBI->getOpcode() == ARM::tPOP_RET); 6550b57cec5SDimitry Andric else { 6560b57cec5SDimitry Andric auto MBBI_prev = MBBI; 6570b57cec5SDimitry Andric MBBI_prev--; 6580b57cec5SDimitry Andric assert(MBBI_prev->getOpcode() == ARM::tPOP); 6590b57cec5SDimitry Andric assert(MBB.succ_size() == 1); 6600b57cec5SDimitry Andric if ((*MBB.succ_begin())->begin()->getOpcode() == ARM::tBX_RET) 6610b57cec5SDimitry Andric MBBI = MBBI_prev; // Replace the final tPOP with a tPOP_RET. 6620b57cec5SDimitry Andric else 6630b57cec5SDimitry Andric CanRestoreDirectly = false; 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric if (CanRestoreDirectly) { 6680b57cec5SDimitry Andric if (!DoIt || MBBI->getOpcode() == ARM::tPOP_RET) 6690b57cec5SDimitry Andric return true; 6700b57cec5SDimitry Andric MachineInstrBuilder MIB = 6710b57cec5SDimitry Andric BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP_RET)) 672*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 673*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 6740b57cec5SDimitry Andric // Copy implicit ops and popped registers, if any. 6750b57cec5SDimitry Andric for (auto MO: MBBI->operands()) 6760b57cec5SDimitry Andric if (MO.isReg() && (MO.isImplicit() || MO.isDef())) 6770b57cec5SDimitry Andric MIB.add(MO); 6780b57cec5SDimitry Andric MIB.addReg(ARM::PC, RegState::Define); 6790b57cec5SDimitry Andric // Erase the old instruction (tBX_RET or tPOP). 6800b57cec5SDimitry Andric MBB.erase(MBBI); 6810b57cec5SDimitry Andric return true; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric // Look for a temporary register to use. 6850b57cec5SDimitry Andric // First, compute the liveness information. 6860b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 6870b57cec5SDimitry Andric LivePhysRegs UsedRegs(TRI); 6880b57cec5SDimitry Andric UsedRegs.addLiveOuts(MBB); 6890b57cec5SDimitry Andric // The semantic of pristines changed recently and now, 6900b57cec5SDimitry Andric // the callee-saved registers that are touched in the function 6910b57cec5SDimitry Andric // are not part of the pristines set anymore. 6920b57cec5SDimitry Andric // Add those callee-saved now. 6930b57cec5SDimitry Andric const MCPhysReg *CSRegs = TRI.getCalleeSavedRegs(&MF); 6940b57cec5SDimitry Andric for (unsigned i = 0; CSRegs[i]; ++i) 6950b57cec5SDimitry Andric UsedRegs.addReg(CSRegs[i]); 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric DebugLoc dl = DebugLoc(); 6980b57cec5SDimitry Andric if (MBBI != MBB.end()) { 6990b57cec5SDimitry Andric dl = MBBI->getDebugLoc(); 7000b57cec5SDimitry Andric auto InstUpToMBBI = MBB.end(); 7010b57cec5SDimitry Andric while (InstUpToMBBI != MBBI) 7020b57cec5SDimitry Andric // The pre-decrement is on purpose here. 7030b57cec5SDimitry Andric // We want to have the liveness right before MBBI. 7040b57cec5SDimitry Andric UsedRegs.stepBackward(*--InstUpToMBBI); 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric // Look for a register that can be directly use in the POP. 7080b57cec5SDimitry Andric unsigned PopReg = 0; 7090b57cec5SDimitry Andric // And some temporary register, just in case. 7100b57cec5SDimitry Andric unsigned TemporaryReg = 0; 7110b57cec5SDimitry Andric BitVector PopFriendly = 7120b57cec5SDimitry Andric TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::tGPRRegClassID)); 7130b57cec5SDimitry Andric // R7 may be used as a frame pointer, hence marked as not generally 7140b57cec5SDimitry Andric // allocatable, however there's no reason to not use it as a temporary for 7150b57cec5SDimitry Andric // restoring LR. 716fe6060f1SDimitry Andric if (STI.getFramePointerReg() == ARM::R7) 7170b57cec5SDimitry Andric PopFriendly.set(ARM::R7); 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric assert(PopFriendly.any() && "No allocatable pop-friendly register?!"); 7200b57cec5SDimitry Andric // Rebuild the GPRs from the high registers because they are removed 7210b57cec5SDimitry Andric // form the GPR reg class for thumb1. 7220b57cec5SDimitry Andric BitVector GPRsNoLRSP = 7230b57cec5SDimitry Andric TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::hGPRRegClassID)); 7240b57cec5SDimitry Andric GPRsNoLRSP |= PopFriendly; 7250b57cec5SDimitry Andric GPRsNoLRSP.reset(ARM::LR); 7260b57cec5SDimitry Andric GPRsNoLRSP.reset(ARM::SP); 7270b57cec5SDimitry Andric GPRsNoLRSP.reset(ARM::PC); 728349cc55cSDimitry Andric findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, TemporaryReg, 729349cc55cSDimitry Andric MF.getRegInfo()); 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric // If we couldn't find a pop-friendly register, try restoring LR before 7320b57cec5SDimitry Andric // popping the other callee-saved registers, so we could use one of them as a 7330b57cec5SDimitry Andric // temporary. 7340b57cec5SDimitry Andric bool UseLDRSP = false; 7350b57cec5SDimitry Andric if (!PopReg && MBBI != MBB.begin()) { 7360b57cec5SDimitry Andric auto PrevMBBI = MBBI; 7370b57cec5SDimitry Andric PrevMBBI--; 7380b57cec5SDimitry Andric if (PrevMBBI->getOpcode() == ARM::tPOP) { 7390b57cec5SDimitry Andric UsedRegs.stepBackward(*PrevMBBI); 740349cc55cSDimitry Andric findTemporariesForLR(GPRsNoLRSP, PopFriendly, UsedRegs, PopReg, 741349cc55cSDimitry Andric TemporaryReg, MF.getRegInfo()); 7420b57cec5SDimitry Andric if (PopReg) { 7430b57cec5SDimitry Andric MBBI = PrevMBBI; 7440b57cec5SDimitry Andric UseLDRSP = true; 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric if (!DoIt && !PopReg && !TemporaryReg) 7500b57cec5SDimitry Andric return false; 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric assert((PopReg || TemporaryReg) && "Cannot get LR"); 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric if (UseLDRSP) { 7550b57cec5SDimitry Andric assert(PopReg && "Do not know how to get LR"); 7560b57cec5SDimitry Andric // Load the LR via LDR tmp, [SP, #off] 7570b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRspi)) 7580b57cec5SDimitry Andric .addReg(PopReg, RegState::Define) 7590b57cec5SDimitry Andric .addReg(ARM::SP) 7600b57cec5SDimitry Andric .addImm(MBBI->getNumExplicitOperands() - 2) 761*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 762*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 7630b57cec5SDimitry Andric // Move from the temporary register to the LR. 7640b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 7650b57cec5SDimitry Andric .addReg(ARM::LR, RegState::Define) 7660b57cec5SDimitry Andric .addReg(PopReg, RegState::Kill) 767*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 768*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 7690b57cec5SDimitry Andric // Advance past the pop instruction. 7700b57cec5SDimitry Andric MBBI++; 7710b57cec5SDimitry Andric // Increment the SP. 7720b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, 7730b57cec5SDimitry Andric ArgRegsSaveSize + 4, ARM::NoRegister, 774*81ad6265SDimitry Andric MachineInstr::FrameDestroy); 7750b57cec5SDimitry Andric return true; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric if (TemporaryReg) { 7790b57cec5SDimitry Andric assert(!PopReg && "Unnecessary MOV is about to be inserted"); 7800b57cec5SDimitry Andric PopReg = PopFriendly.find_first(); 7810b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 7820b57cec5SDimitry Andric .addReg(TemporaryReg, RegState::Define) 7830b57cec5SDimitry Andric .addReg(PopReg, RegState::Kill) 784*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 785*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPOP_RET) { 7890b57cec5SDimitry Andric // We couldn't use the direct restoration above, so 7900b57cec5SDimitry Andric // perform the opposite conversion: tPOP_RET to tPOP. 7910b57cec5SDimitry Andric MachineInstrBuilder MIB = 7920b57cec5SDimitry Andric BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP)) 793*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 794*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 7950b57cec5SDimitry Andric bool Popped = false; 7960b57cec5SDimitry Andric for (auto MO: MBBI->operands()) 7970b57cec5SDimitry Andric if (MO.isReg() && (MO.isImplicit() || MO.isDef()) && 7980b57cec5SDimitry Andric MO.getReg() != ARM::PC) { 7990b57cec5SDimitry Andric MIB.add(MO); 8000b57cec5SDimitry Andric if (!MO.isImplicit()) 8010b57cec5SDimitry Andric Popped = true; 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric // Is there anything left to pop? 8040b57cec5SDimitry Andric if (!Popped) 8050b57cec5SDimitry Andric MBB.erase(MIB.getInstr()); 8060b57cec5SDimitry Andric // Erase the old instruction. 8070b57cec5SDimitry Andric MBB.erase(MBBI); 8080b57cec5SDimitry Andric MBBI = BuildMI(MBB, MBB.end(), dl, TII.get(ARM::tBX_RET)) 809*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 810*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric assert(PopReg && "Do not know how to get LR"); 8140b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP)) 8150b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 816*81ad6265SDimitry Andric .addReg(PopReg, RegState::Define) 817*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric emitPrologueEpilogueSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize, 820*81ad6265SDimitry Andric ARM::NoRegister, MachineInstr::FrameDestroy); 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 8230b57cec5SDimitry Andric .addReg(ARM::LR, RegState::Define) 8240b57cec5SDimitry Andric .addReg(PopReg, RegState::Kill) 825*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 826*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric if (TemporaryReg) 8290b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) 8300b57cec5SDimitry Andric .addReg(PopReg, RegState::Define) 8310b57cec5SDimitry Andric .addReg(TemporaryReg, RegState::Kill) 832*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 833*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric return true; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 838*81ad6265SDimitry Andric static const SmallVector<Register> OrderedLowRegs = {ARM::R4, ARM::R5, ARM::R6, 839*81ad6265SDimitry Andric ARM::R7, ARM::LR}; 840*81ad6265SDimitry Andric static const SmallVector<Register> OrderedHighRegs = {ARM::R8, ARM::R9, 841*81ad6265SDimitry Andric ARM::R10, ARM::R11}; 842*81ad6265SDimitry Andric static const SmallVector<Register> OrderedCopyRegs = { 843*81ad6265SDimitry Andric ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R4, 844*81ad6265SDimitry Andric ARM::R5, ARM::R6, ARM::R7, ARM::LR}; 8450b57cec5SDimitry Andric 846*81ad6265SDimitry Andric static void splitLowAndHighRegs(const std::set<Register> &Regs, 847*81ad6265SDimitry Andric std::set<Register> &LowRegs, 848*81ad6265SDimitry Andric std::set<Register> &HighRegs) { 849*81ad6265SDimitry Andric for (Register Reg : Regs) { 8500b57cec5SDimitry Andric if (ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) { 851*81ad6265SDimitry Andric LowRegs.insert(Reg); 8520b57cec5SDimitry Andric } else if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::LR) { 853*81ad6265SDimitry Andric HighRegs.insert(Reg); 8540b57cec5SDimitry Andric } else { 8550b57cec5SDimitry Andric llvm_unreachable("callee-saved register of unexpected class"); 8560b57cec5SDimitry Andric } 857*81ad6265SDimitry Andric } 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 860*81ad6265SDimitry Andric template <typename It> 861*81ad6265SDimitry Andric It getNextOrderedReg(It OrderedStartIt, It OrderedEndIt, 862*81ad6265SDimitry Andric const std::set<Register> &RegSet) { 863*81ad6265SDimitry Andric return std::find_if(OrderedStartIt, OrderedEndIt, 864*81ad6265SDimitry Andric [&](Register Reg) { return RegSet.count(Reg); }); 865*81ad6265SDimitry Andric } 8660b57cec5SDimitry Andric 867*81ad6265SDimitry Andric static void pushRegsToStack(MachineBasicBlock &MBB, 868*81ad6265SDimitry Andric MachineBasicBlock::iterator MI, 869*81ad6265SDimitry Andric const TargetInstrInfo &TII, 870*81ad6265SDimitry Andric const std::set<Register> &RegsToSave, 871*81ad6265SDimitry Andric const std::set<Register> &CopyRegs) { 872*81ad6265SDimitry Andric MachineFunction &MF = *MBB.getParent(); 8730b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 874*81ad6265SDimitry Andric DebugLoc DL; 875*81ad6265SDimitry Andric 876*81ad6265SDimitry Andric std::set<Register> LowRegs, HighRegs; 877*81ad6265SDimitry Andric splitLowAndHighRegs(RegsToSave, LowRegs, HighRegs); 878*81ad6265SDimitry Andric 879*81ad6265SDimitry Andric // Push low regs first 880*81ad6265SDimitry Andric if (!LowRegs.empty()) { 8810b57cec5SDimitry Andric MachineInstrBuilder MIB = 8820b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL)); 883*81ad6265SDimitry Andric for (unsigned Reg : OrderedLowRegs) { 884*81ad6265SDimitry Andric if (LowRegs.count(Reg)) { 8850b57cec5SDimitry Andric bool isKill = !MRI.isLiveIn(Reg); 8860b57cec5SDimitry Andric if (isKill && !MRI.isReserved(Reg)) 8870b57cec5SDimitry Andric MBB.addLiveIn(Reg); 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric MIB.addReg(Reg, getKillRegState(isKill)); 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric MIB.setMIFlags(MachineInstr::FrameSetup); 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 895*81ad6265SDimitry Andric // Now push the high registers 896*81ad6265SDimitry Andric // There are no store instructions that can access high registers directly, 897*81ad6265SDimitry Andric // so we have to move them to low registers, and push them. 898*81ad6265SDimitry Andric // This might take multiple pushes, as it is possible for there to 8990b57cec5SDimitry Andric // be fewer low registers available than high registers which need saving. 9000b57cec5SDimitry Andric 901*81ad6265SDimitry Andric // Find the first register to save. 902*81ad6265SDimitry Andric // Registers must be processed in reverse order so that in case we need to use 9030b57cec5SDimitry Andric // multiple PUSH instructions, the order of the registers on the stack still 9040b57cec5SDimitry Andric // matches the unwind info. They need to be swicthed back to ascending order 9050b57cec5SDimitry Andric // before adding to the PUSH instruction. 906*81ad6265SDimitry Andric auto HiRegToSave = getNextOrderedReg(OrderedHighRegs.rbegin(), 907*81ad6265SDimitry Andric OrderedHighRegs.rend(), 908*81ad6265SDimitry Andric HighRegs); 9090b57cec5SDimitry Andric 910*81ad6265SDimitry Andric while (HiRegToSave != OrderedHighRegs.rend()) { 9110b57cec5SDimitry Andric // Find the first low register to use. 912*81ad6265SDimitry Andric auto CopyRegIt = getNextOrderedReg(OrderedCopyRegs.rbegin(), 913*81ad6265SDimitry Andric OrderedCopyRegs.rend(), 914*81ad6265SDimitry Andric CopyRegs); 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric // Create the PUSH, but don't insert it yet (the MOVs need to come first). 9170b57cec5SDimitry Andric MachineInstrBuilder PushMIB = BuildMI(MF, DL, TII.get(ARM::tPUSH)) 9180b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 9190b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric SmallVector<unsigned, 4> RegsToPush; 922*81ad6265SDimitry Andric while (HiRegToSave != OrderedHighRegs.rend() && 923*81ad6265SDimitry Andric CopyRegIt != OrderedCopyRegs.rend()) { 924*81ad6265SDimitry Andric if (HighRegs.count(*HiRegToSave)) { 9250b57cec5SDimitry Andric bool isKill = !MRI.isLiveIn(*HiRegToSave); 9260b57cec5SDimitry Andric if (isKill && !MRI.isReserved(*HiRegToSave)) 9270b57cec5SDimitry Andric MBB.addLiveIn(*HiRegToSave); 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric // Emit a MOV from the high reg to the low reg. 9300b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)) 931*81ad6265SDimitry Andric .addReg(*CopyRegIt, RegState::Define) 9320b57cec5SDimitry Andric .addReg(*HiRegToSave, getKillRegState(isKill)) 9330b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 9340b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric // Record the register that must be added to the PUSH. 937*81ad6265SDimitry Andric RegsToPush.push_back(*CopyRegIt); 9380b57cec5SDimitry Andric 939*81ad6265SDimitry Andric CopyRegIt = getNextOrderedReg(std::next(CopyRegIt), 940*81ad6265SDimitry Andric OrderedCopyRegs.rend(), 941*81ad6265SDimitry Andric CopyRegs); 942*81ad6265SDimitry Andric HiRegToSave = getNextOrderedReg(std::next(HiRegToSave), 943*81ad6265SDimitry Andric OrderedHighRegs.rend(), 944*81ad6265SDimitry Andric HighRegs); 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric // Add the low registers to the PUSH, in ascending order. 9490b57cec5SDimitry Andric for (unsigned Reg : llvm::reverse(RegsToPush)) 9500b57cec5SDimitry Andric PushMIB.addReg(Reg, RegState::Kill); 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric // Insert the PUSH instruction after the MOVs. 9530b57cec5SDimitry Andric MBB.insert(MI, PushMIB); 9540b57cec5SDimitry Andric } 9550b57cec5SDimitry Andric } 9560b57cec5SDimitry Andric 957*81ad6265SDimitry Andric static void popRegsFromStack(MachineBasicBlock &MBB, 958*81ad6265SDimitry Andric MachineBasicBlock::iterator &MI, 959*81ad6265SDimitry Andric const TargetInstrInfo &TII, 960*81ad6265SDimitry Andric const std::set<Register> &RegsToRestore, 961*81ad6265SDimitry Andric const std::set<Register> &AvailableCopyRegs, 962*81ad6265SDimitry Andric bool IsVarArg, bool HasV5Ops) { 963*81ad6265SDimitry Andric if (RegsToRestore.empty()) 964*81ad6265SDimitry Andric return; 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 9670b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 9680b57cec5SDimitry Andric DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); 9690b57cec5SDimitry Andric 970*81ad6265SDimitry Andric std::set<Register> LowRegs, HighRegs; 971*81ad6265SDimitry Andric splitLowAndHighRegs(RegsToRestore, LowRegs, HighRegs); 9720b57cec5SDimitry Andric 973*81ad6265SDimitry Andric // Pop the high registers first 974*81ad6265SDimitry Andric // There are no store instructions that can access high registers directly, 975*81ad6265SDimitry Andric // so we have to pop into low registers and them move to the high registers. 976*81ad6265SDimitry Andric // This might take multiple pops, as it is possible for there to 977*81ad6265SDimitry Andric // be fewer low registers available than high registers which need restoring. 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric // Find the first register to restore. 980*81ad6265SDimitry Andric auto HiRegToRestore = getNextOrderedReg(OrderedHighRegs.begin(), 981*81ad6265SDimitry Andric OrderedHighRegs.end(), 982*81ad6265SDimitry Andric HighRegs); 9830b57cec5SDimitry Andric 984*81ad6265SDimitry Andric std::set<Register> CopyRegs = AvailableCopyRegs; 985*81ad6265SDimitry Andric Register LowScratchReg; 986*81ad6265SDimitry Andric if (!HighRegs.empty() && CopyRegs.empty()) { 987*81ad6265SDimitry Andric // No copy regs are available to pop high regs. Let's make use of a return 988*81ad6265SDimitry Andric // register and the scratch register (IP/R12) to copy things around. 989*81ad6265SDimitry Andric LowScratchReg = ARM::R0; 990*81ad6265SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)) 991*81ad6265SDimitry Andric .addReg(ARM::R12, RegState::Define) 992*81ad6265SDimitry Andric .addReg(LowScratchReg, RegState::Kill) 993*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 994*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 995*81ad6265SDimitry Andric CopyRegs.insert(LowScratchReg); 996*81ad6265SDimitry Andric } 997*81ad6265SDimitry Andric 998*81ad6265SDimitry Andric while (HiRegToRestore != OrderedHighRegs.end()) { 999*81ad6265SDimitry Andric assert(!CopyRegs.empty()); 10000b57cec5SDimitry Andric // Find the first low register to use. 1001*81ad6265SDimitry Andric auto CopyReg = getNextOrderedReg(OrderedCopyRegs.begin(), 1002*81ad6265SDimitry Andric OrderedCopyRegs.end(), 1003*81ad6265SDimitry Andric CopyRegs); 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric // Create the POP instruction. 1006*81ad6265SDimitry Andric MachineInstrBuilder PopMIB = BuildMI(MBB, MI, DL, TII.get(ARM::tPOP)) 1007*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 1008*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 10090b57cec5SDimitry Andric 1010*81ad6265SDimitry Andric while (HiRegToRestore != OrderedHighRegs.end() && 1011*81ad6265SDimitry Andric CopyReg != OrderedCopyRegs.end()) { 10120b57cec5SDimitry Andric // Add the low register to the POP. 10130b57cec5SDimitry Andric PopMIB.addReg(*CopyReg, RegState::Define); 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric // Create the MOV from low to high register. 10160b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)) 10170b57cec5SDimitry Andric .addReg(*HiRegToRestore, RegState::Define) 10180b57cec5SDimitry Andric .addReg(*CopyReg, RegState::Kill) 1019*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 1020*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 10210b57cec5SDimitry Andric 1022*81ad6265SDimitry Andric CopyReg = getNextOrderedReg(std::next(CopyReg), 1023*81ad6265SDimitry Andric OrderedCopyRegs.end(), 1024*81ad6265SDimitry Andric CopyRegs); 1025*81ad6265SDimitry Andric HiRegToRestore = getNextOrderedReg(std::next(HiRegToRestore), 1026*81ad6265SDimitry Andric OrderedHighRegs.end(), 1027*81ad6265SDimitry Andric HighRegs); 10280b57cec5SDimitry Andric } 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric 1031*81ad6265SDimitry Andric // Restore low register used as scratch if necessary 1032*81ad6265SDimitry Andric if (LowScratchReg.isValid()) { 1033*81ad6265SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::tMOVr)) 1034*81ad6265SDimitry Andric .addReg(LowScratchReg, RegState::Define) 1035*81ad6265SDimitry Andric .addReg(ARM::R12, RegState::Kill) 1036*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 1037*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 1038*81ad6265SDimitry Andric } 1039*81ad6265SDimitry Andric 1040*81ad6265SDimitry Andric // Now pop the low registers 1041*81ad6265SDimitry Andric if (!LowRegs.empty()) { 1042*81ad6265SDimitry Andric MachineInstrBuilder MIB = BuildMI(MF, DL, TII.get(ARM::tPOP)) 1043*81ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 1044*81ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric bool NeedsPop = false; 1047*81ad6265SDimitry Andric for (Register Reg : OrderedLowRegs) { 1048*81ad6265SDimitry Andric if (!LowRegs.count(Reg)) 10490b57cec5SDimitry Andric continue; 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric if (Reg == ARM::LR) { 10520b57cec5SDimitry Andric if (!MBB.succ_empty() || 10530b57cec5SDimitry Andric MI->getOpcode() == ARM::TCRETURNdi || 10540b57cec5SDimitry Andric MI->getOpcode() == ARM::TCRETURNri) 10550b57cec5SDimitry Andric // LR may only be popped into PC, as part of return sequence. 10560b57cec5SDimitry Andric // If this isn't the return sequence, we'll need emitPopSpecialFixUp 10570b57cec5SDimitry Andric // to restore LR the hard way. 10580b57cec5SDimitry Andric // FIXME: if we don't pass any stack arguments it would be actually 10590b57cec5SDimitry Andric // advantageous *and* correct to do the conversion to an ordinary call 10600b57cec5SDimitry Andric // instruction here. 10610b57cec5SDimitry Andric continue; 10620b57cec5SDimitry Andric // Special epilogue for vararg functions. See emitEpilogue 1063*81ad6265SDimitry Andric if (IsVarArg) 10640b57cec5SDimitry Andric continue; 10650b57cec5SDimitry Andric // ARMv4T requires BX, see emitEpilogue 1066*81ad6265SDimitry Andric if (!HasV5Ops) 10670b57cec5SDimitry Andric continue; 10680b57cec5SDimitry Andric 10695ffd83dbSDimitry Andric // CMSE entry functions must return via BXNS, see emitEpilogue. 10705ffd83dbSDimitry Andric if (AFI->isCmseNSEntryFunction()) 10715ffd83dbSDimitry Andric continue; 10725ffd83dbSDimitry Andric 10730b57cec5SDimitry Andric // Pop LR into PC. 10740b57cec5SDimitry Andric Reg = ARM::PC; 10750b57cec5SDimitry Andric (*MIB).setDesc(TII.get(ARM::tPOP_RET)); 10760b57cec5SDimitry Andric if (MI != MBB.end()) 10770b57cec5SDimitry Andric MIB.copyImplicitOps(*MI); 10780b57cec5SDimitry Andric MI = MBB.erase(MI); 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric MIB.addReg(Reg, getDefRegState(true)); 10810b57cec5SDimitry Andric NeedsPop = true; 10820b57cec5SDimitry Andric } 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric // It's illegal to emit pop instruction without operands. 10850b57cec5SDimitry Andric if (NeedsPop) 10860b57cec5SDimitry Andric MBB.insert(MI, &*MIB); 10870b57cec5SDimitry Andric else 10880eae32dcSDimitry Andric MF.deleteMachineInstr(MIB); 1089*81ad6265SDimitry Andric } 1090*81ad6265SDimitry Andric } 1091*81ad6265SDimitry Andric 1092*81ad6265SDimitry Andric bool Thumb1FrameLowering::spillCalleeSavedRegisters( 1093*81ad6265SDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 1094*81ad6265SDimitry Andric ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 1095*81ad6265SDimitry Andric if (CSI.empty()) 1096*81ad6265SDimitry Andric return false; 1097*81ad6265SDimitry Andric 1098*81ad6265SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 1099*81ad6265SDimitry Andric MachineFunction &MF = *MBB.getParent(); 1100*81ad6265SDimitry Andric const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( 1101*81ad6265SDimitry Andric MF.getSubtarget().getRegisterInfo()); 1102*81ad6265SDimitry Andric Register FPReg = RegInfo->getFrameRegister(MF); 1103*81ad6265SDimitry Andric 1104*81ad6265SDimitry Andric // In case FP is a high reg, we need a separate push sequence to generate 1105*81ad6265SDimitry Andric // a correct Frame Record 1106*81ad6265SDimitry Andric bool NeedsFrameRecordPush = hasFP(MF) && ARM::hGPRRegClass.contains(FPReg); 1107*81ad6265SDimitry Andric 1108*81ad6265SDimitry Andric std::set<Register> FrameRecord; 1109*81ad6265SDimitry Andric std::set<Register> SpilledGPRs; 1110*81ad6265SDimitry Andric for (const CalleeSavedInfo &I : CSI) { 1111*81ad6265SDimitry Andric Register Reg = I.getReg(); 1112*81ad6265SDimitry Andric if (NeedsFrameRecordPush && (Reg == FPReg || Reg == ARM::LR)) 1113*81ad6265SDimitry Andric FrameRecord.insert(Reg); 1114*81ad6265SDimitry Andric else 1115*81ad6265SDimitry Andric SpilledGPRs.insert(Reg); 1116*81ad6265SDimitry Andric } 1117*81ad6265SDimitry Andric 1118*81ad6265SDimitry Andric pushRegsToStack(MBB, MI, TII, FrameRecord, {ARM::LR}); 1119*81ad6265SDimitry Andric 1120*81ad6265SDimitry Andric // Determine intermediate registers which can be used for pushing high regs: 1121*81ad6265SDimitry Andric // - Spilled low regs 1122*81ad6265SDimitry Andric // - Unused argument registers 1123*81ad6265SDimitry Andric std::set<Register> CopyRegs; 1124*81ad6265SDimitry Andric for (Register Reg : SpilledGPRs) 1125*81ad6265SDimitry Andric if ((ARM::tGPRRegClass.contains(Reg) || Reg == ARM::LR) && 1126*81ad6265SDimitry Andric !MF.getRegInfo().isLiveIn(Reg) && !(hasFP(MF) && Reg == FPReg)) 1127*81ad6265SDimitry Andric CopyRegs.insert(Reg); 1128*81ad6265SDimitry Andric for (unsigned ArgReg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) 1129*81ad6265SDimitry Andric if (!MF.getRegInfo().isLiveIn(ArgReg)) 1130*81ad6265SDimitry Andric CopyRegs.insert(ArgReg); 1131*81ad6265SDimitry Andric 1132*81ad6265SDimitry Andric pushRegsToStack(MBB, MI, TII, SpilledGPRs, CopyRegs); 1133*81ad6265SDimitry Andric 1134*81ad6265SDimitry Andric return true; 1135*81ad6265SDimitry Andric } 1136*81ad6265SDimitry Andric 1137*81ad6265SDimitry Andric bool Thumb1FrameLowering::restoreCalleeSavedRegisters( 1138*81ad6265SDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 1139*81ad6265SDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 1140*81ad6265SDimitry Andric if (CSI.empty()) 1141*81ad6265SDimitry Andric return false; 1142*81ad6265SDimitry Andric 1143*81ad6265SDimitry Andric MachineFunction &MF = *MBB.getParent(); 1144*81ad6265SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 1145*81ad6265SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 1146*81ad6265SDimitry Andric const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( 1147*81ad6265SDimitry Andric MF.getSubtarget().getRegisterInfo()); 1148*81ad6265SDimitry Andric bool IsVarArg = AFI->getArgRegsSaveSize() > 0; 1149*81ad6265SDimitry Andric Register FPReg = RegInfo->getFrameRegister(MF); 1150*81ad6265SDimitry Andric 1151*81ad6265SDimitry Andric // In case FP is a high reg, we need a separate pop sequence to generate 1152*81ad6265SDimitry Andric // a correct Frame Record 1153*81ad6265SDimitry Andric bool NeedsFrameRecordPop = hasFP(MF) && ARM::hGPRRegClass.contains(FPReg); 1154*81ad6265SDimitry Andric 1155*81ad6265SDimitry Andric std::set<Register> FrameRecord; 1156*81ad6265SDimitry Andric std::set<Register> SpilledGPRs; 1157*81ad6265SDimitry Andric for (CalleeSavedInfo &I : CSI) { 1158*81ad6265SDimitry Andric Register Reg = I.getReg(); 1159*81ad6265SDimitry Andric if (NeedsFrameRecordPop && (Reg == FPReg || Reg == ARM::LR)) 1160*81ad6265SDimitry Andric FrameRecord.insert(Reg); 1161*81ad6265SDimitry Andric else 1162*81ad6265SDimitry Andric SpilledGPRs.insert(Reg); 1163*81ad6265SDimitry Andric 1164*81ad6265SDimitry Andric if (Reg == ARM::LR) 1165*81ad6265SDimitry Andric I.setRestored(false); 1166*81ad6265SDimitry Andric } 1167*81ad6265SDimitry Andric 1168*81ad6265SDimitry Andric // Determine intermidiate registers which can be used for popping high regs: 1169*81ad6265SDimitry Andric // - Spilled low regs 1170*81ad6265SDimitry Andric // - Unused return registers 1171*81ad6265SDimitry Andric std::set<Register> CopyRegs; 1172*81ad6265SDimitry Andric std::set<Register> UnusedReturnRegs; 1173*81ad6265SDimitry Andric for (Register Reg : SpilledGPRs) 1174*81ad6265SDimitry Andric if ((ARM::tGPRRegClass.contains(Reg)) && !(hasFP(MF) && Reg == FPReg)) 1175*81ad6265SDimitry Andric CopyRegs.insert(Reg); 1176*81ad6265SDimitry Andric auto Terminator = MBB.getFirstTerminator(); 1177*81ad6265SDimitry Andric if (Terminator != MBB.end() && Terminator->getOpcode() == ARM::tBX_RET) { 1178*81ad6265SDimitry Andric UnusedReturnRegs.insert(ARM::R0); 1179*81ad6265SDimitry Andric UnusedReturnRegs.insert(ARM::R1); 1180*81ad6265SDimitry Andric UnusedReturnRegs.insert(ARM::R2); 1181*81ad6265SDimitry Andric UnusedReturnRegs.insert(ARM::R3); 1182*81ad6265SDimitry Andric for (auto Op : Terminator->implicit_operands()) { 1183*81ad6265SDimitry Andric if (Op.isReg()) 1184*81ad6265SDimitry Andric UnusedReturnRegs.erase(Op.getReg()); 1185*81ad6265SDimitry Andric } 1186*81ad6265SDimitry Andric } 1187*81ad6265SDimitry Andric CopyRegs.insert(UnusedReturnRegs.begin(), UnusedReturnRegs.end()); 1188*81ad6265SDimitry Andric 1189*81ad6265SDimitry Andric // First pop regular spilled regs. 1190*81ad6265SDimitry Andric popRegsFromStack(MBB, MI, TII, SpilledGPRs, CopyRegs, IsVarArg, 1191*81ad6265SDimitry Andric STI.hasV5TOps()); 1192*81ad6265SDimitry Andric 1193*81ad6265SDimitry Andric // LR may only be popped into pc, as part of a return sequence. 1194*81ad6265SDimitry Andric // Check that no other pop instructions are inserted after that. 1195*81ad6265SDimitry Andric assert((!SpilledGPRs.count(ARM::LR) || FrameRecord.empty()) && 1196*81ad6265SDimitry Andric "Can't insert pop after return sequence"); 1197*81ad6265SDimitry Andric 1198*81ad6265SDimitry Andric // Now pop Frame Record regs. 1199*81ad6265SDimitry Andric // Only unused return registers can be used as copy regs at this point. 1200*81ad6265SDimitry Andric popRegsFromStack(MBB, MI, TII, FrameRecord, UnusedReturnRegs, IsVarArg, 1201*81ad6265SDimitry Andric STI.hasV5TOps()); 12020b57cec5SDimitry Andric 12030b57cec5SDimitry Andric return true; 12040b57cec5SDimitry Andric } 1205