123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605 |
- //===-- ARMFrameLowering.cpp - ARM Frame Information ----------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file contains the ARM implementation of TargetFrameLowering class.
- //
- //===----------------------------------------------------------------------===//
- #include "ARMFrameLowering.h"
- #include "ARMBaseInstrInfo.h"
- #include "ARMBaseRegisterInfo.h"
- #include "ARMMachineFunctionInfo.h"
- #include "MCTargetDesc/ARMAddressingModes.h"
- #include "llvm/CodeGen/MachineFrameInfo.h"
- #include "llvm/CodeGen/MachineFunction.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- #include "llvm/CodeGen/MachineModuleInfo.h"
- #include "llvm/CodeGen/MachineRegisterInfo.h"
- #include "llvm/CodeGen/RegisterScavenging.h"
- #include "llvm/IR/CallingConv.h"
- #include "llvm/IR/Function.h"
- #include "llvm/MC/MCContext.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Target/TargetOptions.h"
- using namespace llvm;
- static cl::opt<bool>
- SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true),
- cl::desc("Align ARM NEON spills in prolog and epilog"));
- static MachineBasicBlock::iterator
- skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI,
- unsigned NumAlignedDPRCS2Regs);
- /// hasFP - Return true if the specified function should have a dedicated frame
- /// pointer register. This is true if the function has variable sized allocas
- /// or if frame pointer elimination is disabled.
- bool ARMFrameLowering::hasFP(const MachineFunction &MF) const {
- const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
- // iOS requires FP not to be clobbered for backtracing purpose.
- if (STI.isTargetIOS())
- return true;
- const MachineFrameInfo *MFI = MF.getFrameInfo();
- // Always eliminate non-leaf frame pointers.
- return ((MF.getTarget().Options.DisableFramePointerElim(MF) &&
- MFI->hasCalls()) ||
- RegInfo->needsStackRealignment(MF) ||
- MFI->hasVarSizedObjects() ||
- MFI->isFrameAddressTaken());
- }
- /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is
- /// not required, we reserve argument space for call sites in the function
- /// immediately on entry to the current function. This eliminates the need for
- /// add/sub sp brackets around call sites. Returns true if the call frame is
- /// included as part of the stack frame.
- bool ARMFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
- const MachineFrameInfo *FFI = MF.getFrameInfo();
- unsigned CFSize = FFI->getMaxCallFrameSize();
- // It's not always a good idea to include the call frame as part of the
- // stack frame. ARM (especially Thumb) has small immediate offset to
- // address the stack frame. So a large call frame can cause poor codegen
- // and may even makes it impossible to scavenge a register.
- if (CFSize >= ((1 << 12) - 1) / 2) // Half of imm12
- return false;
- return !MF.getFrameInfo()->hasVarSizedObjects();
- }
- /// canSimplifyCallFramePseudos - If there is a reserved call frame, the
- /// call frame pseudos can be simplified. Unlike most targets, having a FP
- /// is not sufficient here since we still may reference some objects via SP
- /// even when FP is available in Thumb2 mode.
- bool
- ARMFrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const {
- return hasReservedCallFrame(MF) || MF.getFrameInfo()->hasVarSizedObjects();
- }
- static bool isCSRestore(MachineInstr *MI,
- const ARMBaseInstrInfo &TII,
- const uint16_t *CSRegs) {
- // Integer spill area is handled with "pop".
- if (isPopOpcode(MI->getOpcode())) {
- // The first two operands are predicates. The last two are
- // imp-def and imp-use of SP. Check everything in between.
- for (int i = 5, e = MI->getNumOperands(); i != e; ++i)
- if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs))
- return false;
- return true;
- }
- if ((MI->getOpcode() == ARM::LDR_POST_IMM ||
- MI->getOpcode() == ARM::LDR_POST_REG ||
- MI->getOpcode() == ARM::t2LDR_POST) &&
- isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs) &&
- MI->getOperand(1).getReg() == ARM::SP)
- return true;
- return false;
- }
- static void emitRegPlusImmediate(bool isARM, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &MBBI, DebugLoc dl,
- const ARMBaseInstrInfo &TII, unsigned DestReg,
- unsigned SrcReg, int NumBytes,
- unsigned MIFlags = MachineInstr::NoFlags,
- ARMCC::CondCodes Pred = ARMCC::AL,
- unsigned PredReg = 0) {
- if (isARM)
- emitARMRegPlusImmediate(MBB, MBBI, dl, DestReg, SrcReg, NumBytes,
- Pred, PredReg, TII, MIFlags);
- else
- emitT2RegPlusImmediate(MBB, MBBI, dl, DestReg, SrcReg, NumBytes,
- Pred, PredReg, TII, MIFlags);
- }
- static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &MBBI, DebugLoc dl,
- const ARMBaseInstrInfo &TII, int NumBytes,
- unsigned MIFlags = MachineInstr::NoFlags,
- ARMCC::CondCodes Pred = ARMCC::AL,
- unsigned PredReg = 0) {
- emitRegPlusImmediate(isARM, MBB, MBBI, dl, TII, ARM::SP, ARM::SP, NumBytes,
- MIFlags, Pred, PredReg);
- }
- static int sizeOfSPAdjustment(const MachineInstr *MI) {
- assert(MI->getOpcode() == ARM::VSTMDDB_UPD);
- int count = 0;
- // ARM and Thumb2 push/pop insts have explicit "sp, sp" operands (+
- // pred) so the list starts at 4.
- for (int i = MI->getNumOperands() - 1; i >= 4; --i)
- count += 8;
- return count;
- }
- void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
- MachineBasicBlock &MBB = MF.front();
- MachineBasicBlock::iterator MBBI = MBB.begin();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- MachineModuleInfo &MMI = MF.getMMI();
- MCContext &Context = MMI.getContext();
- const MCRegisterInfo *MRI = Context.getRegisterInfo();
- const ARMBaseRegisterInfo *RegInfo =
- static_cast<const ARMBaseRegisterInfo*>(MF.getTarget().getRegisterInfo());
- const ARMBaseInstrInfo &TII =
- *static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
- assert(!AFI->isThumb1OnlyFunction() &&
- "This emitPrologue does not support Thumb1!");
- bool isARM = !AFI->isThumbFunction();
- unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment();
- unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(Align);
- unsigned NumBytes = MFI->getStackSize();
- const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
- DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
- unsigned FramePtr = RegInfo->getFrameRegister(MF);
- int CFAOffset = 0;
- // Determine the sizes of each callee-save spill areas and record which frame
- // belongs to which callee-save spill areas.
- unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
- int FramePtrSpillFI = 0;
- int D8SpillFI = 0;
- // All calls are tail calls in GHC calling conv, and functions have no
- // prologue/epilogue.
- if (MF.getFunction()->getCallingConv() == CallingConv::GHC)
- return;
- // Allocate the vararg register save area. This is not counted in NumBytes.
- if (ArgRegsSaveSize) {
- emitSPUpdate(isARM, MBB, MBBI, dl, TII, -ArgRegsSaveSize,
- MachineInstr::FrameSetup);
- MCSymbol *SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- CFAOffset -= ArgRegsSaveSize;
- MMI.addFrameInst(
- MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset));
- }
- if (!AFI->hasStackFrame()) {
- if (NumBytes != 0) {
- emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes,
- MachineInstr::FrameSetup);
- MCSymbol *SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- CFAOffset -= NumBytes;
- MMI.addFrameInst(MCCFIInstruction::createDefCfaOffset(SPLabel,
- CFAOffset));
- }
- return;
- }
- // Determine spill area sizes.
- for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
- unsigned Reg = CSI[i].getReg();
- int FI = CSI[i].getFrameIdx();
- switch (Reg) {
- case ARM::R8:
- case ARM::R9:
- case ARM::R10:
- case ARM::R11:
- case ARM::R12:
- if (STI.isTargetMachO()) {
- GPRCS2Size += 4;
- break;
- }
- // fallthrough
- case ARM::R0:
- case ARM::R1:
- case ARM::R2:
- case ARM::R3:
- case ARM::R4:
- case ARM::R5:
- case ARM::R6:
- case ARM::R7:
- case ARM::LR:
- if (Reg == FramePtr)
- FramePtrSpillFI = FI;
- GPRCS1Size += 4;
- break;
- default:
- // This is a DPR. Exclude the aligned DPRCS2 spills.
- if (Reg == ARM::D8)
- D8SpillFI = FI;
- if (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())
- DPRCSSize += 8;
- }
- }
- // Move past area 1.
- MachineBasicBlock::iterator LastPush = MBB.end(), GPRCS1Push, GPRCS2Push,
- DPRCSPush;
- if (GPRCS1Size > 0)
- GPRCS1Push = LastPush = MBBI++;
- // Determine starting offsets of spill areas.
- bool HasFP = hasFP(MF);
- unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
- unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
- unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
- int FramePtrOffsetInPush = 0;
- if (HasFP) {
- FramePtrOffsetInPush = MFI->getObjectOffset(FramePtrSpillFI) + GPRCS1Size;
- AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) +
- NumBytes);
- }
- AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
- AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
- AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
- // Move past area 2.
- if (GPRCS2Size > 0)
- GPRCS2Push = LastPush = MBBI++;
- // Move past area 3.
- if (DPRCSSize > 0) {
- DPRCSPush = MBBI;
- // Since vpush register list cannot have gaps, there may be multiple vpush
- // instructions in the prologue.
- while (MBBI->getOpcode() == ARM::VSTMDDB_UPD)
- LastPush = MBBI++;
- }
- // Move past the aligned DPRCS2 area.
- if (AFI->getNumAlignedDPRCS2Regs() > 0) {
- MBBI = skipAlignedDPRCS2Spills(MBBI, AFI->getNumAlignedDPRCS2Regs());
- // The code inserted by emitAlignedDPRCS2Spills realigns the stack, and
- // leaves the stack pointer pointing to the DPRCS2 area.
- //
- // Adjust NumBytes to represent the stack slots below the DPRCS2 area.
- NumBytes += MFI->getObjectOffset(D8SpillFI);
- } else
- NumBytes = DPRCSOffset;
- unsigned adjustedGPRCS1Size = GPRCS1Size;
- if (NumBytes) {
- // Adjust SP after all the callee-save spills.
- if (tryFoldSPUpdateIntoPushPop(STI, MF, LastPush, NumBytes)) {
- if (LastPush == GPRCS1Push) {
- FramePtrOffsetInPush += NumBytes;
- adjustedGPRCS1Size += NumBytes;
- NumBytes = 0;
- }
- } else
- emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes,
- MachineInstr::FrameSetup);
- if (HasFP && isARM)
- // Restore from fp only in ARM mode: e.g. sub sp, r7, #24
- // Note it's not safe to do this in Thumb2 mode because it would have
- // taken two instructions:
- // mov sp, r7
- // sub sp, #24
- // If an interrupt is taken between the two instructions, then sp is in
- // an inconsistent state (pointing to the middle of callee-saved area).
- // The interrupt handler can end up clobbering the registers.
- AFI->setShouldRestoreSPFromFP(true);
- }
- if (adjustedGPRCS1Size > 0) {
- MCSymbol *SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, ++GPRCS1Push, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- CFAOffset -= adjustedGPRCS1Size;
- MMI.addFrameInst(
- MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset));
- for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
- E = CSI.end(); I != E; ++I) {
- unsigned Reg = I->getReg();
- int FI = I->getFrameIdx();
- switch (Reg) {
- case ARM::R8:
- case ARM::R9:
- case ARM::R10:
- case ARM::R11:
- case ARM::R12:
- if (STI.isTargetMachO())
- break;
- // fallthrough
- case ARM::R0:
- case ARM::R1:
- case ARM::R2:
- case ARM::R3:
- case ARM::R4:
- case ARM::R5:
- case ARM::R6:
- case ARM::R7:
- case ARM::LR:
- MMI.addFrameInst(MCCFIInstruction::createOffset(SPLabel,
- MRI->getDwarfRegNum(Reg, true),
- MFI->getObjectOffset(FI) - ArgRegsSaveSize));
- break;
- }
- }
- }
- // Set FP to point to the stack slot that contains the previous FP.
- // For iOS, FP is R7, which has now been stored in spill area 1.
- // Otherwise, if this is not iOS, all the callee-saved registers go
- // into spill area 1, including the FP in R11. In either case, it
- // is in area one and the adjustment needs to take place just after
- // that push.
- if (HasFP) {
- emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, GPRCS1Push, dl, TII,
- FramePtr, ARM::SP, FramePtrOffsetInPush,
- MachineInstr::FrameSetup);
- MCSymbol *SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, GPRCS1Push, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- if (FramePtrOffsetInPush) {
- CFAOffset += FramePtrOffsetInPush;
- MMI.addFrameInst(
- MCCFIInstruction::createDefCfa(SPLabel,
- MRI->getDwarfRegNum(FramePtr, true), CFAOffset));
- } else
- MMI.addFrameInst(
- MCCFIInstruction::createDefCfaRegister(SPLabel,
- MRI->getDwarfRegNum(FramePtr, true)));
- }
- if (GPRCS2Size > 0) {
- MCSymbol *SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, ++GPRCS2Push, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- if (!HasFP) {
- CFAOffset -= GPRCS2Size;
- MMI.addFrameInst(
- MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset));
- }
- for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
- E = CSI.end(); I != E; ++I) {
- unsigned Reg = I->getReg();
- int FI = I->getFrameIdx();
- switch (Reg) {
- case ARM::R8:
- case ARM::R9:
- case ARM::R10:
- case ARM::R11:
- case ARM::R12:
- if (STI.isTargetMachO()) {
- unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
- unsigned Offset = MFI->getObjectOffset(FI) - ArgRegsSaveSize;
- MMI.addFrameInst(
- MCCFIInstruction::createOffset(SPLabel, DwarfReg, Offset));
- }
- break;
- }
- }
- }
- if (DPRCSSize > 0) {
- // Since vpush register list cannot have gaps, there may be multiple vpush
- // instructions in the prologue.
- MCSymbol *SPLabel = NULL;
- do {
- MachineBasicBlock::iterator Push = DPRCSPush++;
- if (!HasFP) {
- SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, DPRCSPush, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- CFAOffset -= sizeOfSPAdjustment(Push);;
- MMI.addFrameInst(
- MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset));
- }
- } while (DPRCSPush->getOpcode() == ARM::VSTMDDB_UPD);
- if (!SPLabel) {
- SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, DPRCSPush, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- }
- for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
- E = CSI.end(); I != E; ++I) {
- unsigned Reg = I->getReg();
- int FI = I->getFrameIdx();
- if ((Reg >= ARM::D0 && Reg <= ARM::D31) &&
- (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())) {
- unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
- unsigned Offset = MFI->getObjectOffset(FI);
- MMI.addFrameInst(MCCFIInstruction::createOffset(SPLabel, DwarfReg,
- Offset));
- }
- }
- }
- if (NumBytes) {
- if (!HasFP) {
- MCSymbol *SPLabel = Context.CreateTempSymbol();
- BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL))
- .addSym(SPLabel);
- CFAOffset -= NumBytes;
- MMI.addFrameInst(
- MCCFIInstruction::createDefCfaOffset(SPLabel, CFAOffset));
- }
- }
- if (STI.isTargetELF() && hasFP(MF))
- MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
- AFI->getFramePtrSpillOffset());
- AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
- AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
- AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
- // If we need dynamic stack realignment, do it here. Be paranoid and make
- // sure if we also have VLAs, we have a base pointer for frame access.
- // If aligned NEON registers were spilled, the stack has already been
- // realigned.
- if (!AFI->getNumAlignedDPRCS2Regs() && RegInfo->needsStackRealignment(MF)) {
- unsigned MaxAlign = MFI->getMaxAlignment();
- assert (!AFI->isThumb1OnlyFunction());
- if (!AFI->isThumbFunction()) {
- // Emit bic sp, sp, MaxAlign
- AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl,
- TII.get(ARM::BICri), ARM::SP)
- .addReg(ARM::SP, RegState::Kill)
- .addImm(MaxAlign-1)));
- } else {
- // We cannot use sp as source/dest register here, thus we're emitting the
- // following sequence:
- // mov r4, sp
- // bic r4, r4, MaxAlign
- // mov sp, r4
- // FIXME: It will be better just to find spare register here.
- AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4)
- .addReg(ARM::SP, RegState::Kill));
- AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl,
- TII.get(ARM::t2BICri), ARM::R4)
- .addReg(ARM::R4, RegState::Kill)
- .addImm(MaxAlign-1)));
- AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
- .addReg(ARM::R4, RegState::Kill));
- }
- AFI->setShouldRestoreSPFromFP(true);
- }
- // If we need a base pointer, set it up here. It's whatever the value
- // of the stack pointer is at this point. Any variable size objects
- // will be allocated after this, so we can still use the base pointer
- // to reference locals.
- // FIXME: Clarify FrameSetup flags here.
- if (RegInfo->hasBasePointer(MF)) {
- if (isARM)
- BuildMI(MBB, MBBI, dl,
- TII.get(ARM::MOVr), RegInfo->getBaseRegister())
- .addReg(ARM::SP)
- .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
- else
- AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr),
- RegInfo->getBaseRegister())
- .addReg(ARM::SP));
- }
- // If the frame has variable sized objects then the epilogue must restore
- // the sp from fp. We can assume there's an FP here since hasFP already
- // checks for hasVarSizedObjects.
- if (MFI->hasVarSizedObjects())
- AFI->setShouldRestoreSPFromFP(true);
- }
- void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {
- MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
- assert(MBBI->isReturn() && "Can only insert epilog into returning blocks");
- unsigned RetOpcode = MBBI->getOpcode();
- DebugLoc dl = MBBI->getDebugLoc();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
- const ARMBaseInstrInfo &TII =
- *static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
- assert(!AFI->isThumb1OnlyFunction() &&
- "This emitEpilogue does not support Thumb1!");
- bool isARM = !AFI->isThumbFunction();
- unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment();
- unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(Align);
- int NumBytes = (int)MFI->getStackSize();
- unsigned FramePtr = RegInfo->getFrameRegister(MF);
- // All calls are tail calls in GHC calling conv, and functions have no
- // prologue/epilogue.
- if (MF.getFunction()->getCallingConv() == CallingConv::GHC)
- return;
- if (!AFI->hasStackFrame()) {
- if (NumBytes != 0)
- emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
- } else {
- // Unwind MBBI to point to first LDR / VLDRD.
- const uint16_t *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
- if (MBBI != MBB.begin()) {
- do {
- --MBBI;
- } while (MBBI != MBB.begin() && isCSRestore(MBBI, TII, CSRegs));
- if (!isCSRestore(MBBI, TII, CSRegs))
- ++MBBI;
- }
- // Move SP to start of FP callee save spill area.
- NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
- AFI->getGPRCalleeSavedArea2Size() +
- AFI->getDPRCalleeSavedAreaSize());
- // Reset SP based on frame pointer only if the stack frame extends beyond
- // frame pointer stack slot or target is ELF and the function has FP.
- if (AFI->shouldRestoreSPFromFP()) {
- NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
- if (NumBytes) {
- if (isARM)
- emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
- ARMCC::AL, 0, TII);
- else {
- // It's not possible to restore SP from FP in a single instruction.
- // For iOS, this looks like:
- // mov sp, r7
- // sub sp, #24
- // This is bad, if an interrupt is taken after the mov, sp is in an
- // inconsistent state.
- // Use the first callee-saved register as a scratch register.
- assert(MF.getRegInfo().isPhysRegUsed(ARM::R4) &&
- "No scratch register to restore SP from FP!");
- emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes,
- ARMCC::AL, 0, TII);
- AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr),
- ARM::SP)
- .addReg(ARM::R4));
- }
- } else {
- // Thumb2 or ARM.
- if (isARM)
- BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
- .addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
- else
- AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr),
- ARM::SP)
- .addReg(FramePtr));
- }
- } else if (NumBytes &&
- !tryFoldSPUpdateIntoPushPop(STI, MF, MBBI, NumBytes))
- emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
- // Increment past our save areas.
- if (AFI->getDPRCalleeSavedAreaSize()) {
- MBBI++;
- // Since vpop register list cannot have gaps, there may be multiple vpop
- // instructions in the epilogue.
- while (MBBI->getOpcode() == ARM::VLDMDIA_UPD)
- MBBI++;
- }
- if (AFI->getGPRCalleeSavedArea2Size()) MBBI++;
- if (AFI->getGPRCalleeSavedArea1Size()) MBBI++;
- }
- if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri) {
- // Tail call return: adjust the stack pointer and jump to callee.
- MBBI = MBB.getLastNonDebugInstr();
- MachineOperand &JumpTarget = MBBI->getOperand(0);
- // Jump to label or value in register.
- if (RetOpcode == ARM::TCRETURNdi) {
- unsigned TCOpcode = STI.isThumb() ?
- (STI.isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND) :
- ARM::TAILJMPd;
- MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
- if (JumpTarget.isGlobal())
- MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
- JumpTarget.getTargetFlags());
- else {
- assert(JumpTarget.isSymbol());
- MIB.addExternalSymbol(JumpTarget.getSymbolName(),
- JumpTarget.getTargetFlags());
- }
- // Add the default predicate in Thumb mode.
- if (STI.isThumb()) MIB.addImm(ARMCC::AL).addReg(0);
- } else if (RetOpcode == ARM::TCRETURNri) {
- BuildMI(MBB, MBBI, dl,
- TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)).
- addReg(JumpTarget.getReg(), RegState::Kill);
- }
- MachineInstr *NewMI = std::prev(MBBI);
- for (unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i)
- NewMI->addOperand(MBBI->getOperand(i));
- // Delete the pseudo instruction TCRETURN.
- MBB.erase(MBBI);
- MBBI = NewMI;
- }
- if (ArgRegsSaveSize)
- emitSPUpdate(isARM, MBB, MBBI, dl, TII, ArgRegsSaveSize);
- }
- /// getFrameIndexReference - Provide a base+offset reference to an FI slot for
- /// debug info. It's the same as what we use for resolving the code-gen
- /// references for now. FIXME: This can go wrong when references are
- /// SP-relative and simple call frames aren't used.
- int
- ARMFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
- unsigned &FrameReg) const {
- return ResolveFrameIndexReference(MF, FI, FrameReg, 0);
- }
- int
- ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF,
- int FI, unsigned &FrameReg,
- int SPAdj) const {
- const MachineFrameInfo *MFI = MF.getFrameInfo();
- const ARMBaseRegisterInfo *RegInfo =
- static_cast<const ARMBaseRegisterInfo*>(MF.getTarget().getRegisterInfo());
- const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- int Offset = MFI->getObjectOffset(FI) + MFI->getStackSize();
- int FPOffset = Offset - AFI->getFramePtrSpillOffset();
- bool isFixed = MFI->isFixedObjectIndex(FI);
- FrameReg = ARM::SP;
- Offset += SPAdj;
- // SP can move around if there are allocas. We may also lose track of SP
- // when emergency spilling inside a non-reserved call frame setup.
- bool hasMovingSP = !hasReservedCallFrame(MF);
- // When dynamically realigning the stack, use the frame pointer for
- // parameters, and the stack/base pointer for locals.
- if (RegInfo->needsStackRealignment(MF)) {
- assert (hasFP(MF) && "dynamic stack realignment without a FP!");
- if (isFixed) {
- FrameReg = RegInfo->getFrameRegister(MF);
- Offset = FPOffset;
- } else if (hasMovingSP) {
- assert(RegInfo->hasBasePointer(MF) &&
- "VLAs and dynamic stack alignment, but missing base pointer!");
- FrameReg = RegInfo->getBaseRegister();
- }
- return Offset;
- }
- // If there is a frame pointer, use it when we can.
- if (hasFP(MF) && AFI->hasStackFrame()) {
- // Use frame pointer to reference fixed objects. Use it for locals if
- // there are VLAs (and thus the SP isn't reliable as a base).
- if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
- FrameReg = RegInfo->getFrameRegister(MF);
- return FPOffset;
- } else if (hasMovingSP) {
- assert(RegInfo->hasBasePointer(MF) && "missing base pointer!");
- if (AFI->isThumb2Function()) {
- // Try to use the frame pointer if we can, else use the base pointer
- // since it's available. This is handy for the emergency spill slot, in
- // particular.
- if (FPOffset >= -255 && FPOffset < 0) {
- FrameReg = RegInfo->getFrameRegister(MF);
- return FPOffset;
- }
- }
- } else if (AFI->isThumb2Function()) {
- // Use add <rd>, sp, #<imm8>
- // ldr <rd>, [sp, #<imm8>]
- // if at all possible to save space.
- if (Offset >= 0 && (Offset & 3) == 0 && Offset <= 1020)
- return Offset;
- // In Thumb2 mode, the negative offset is very limited. Try to avoid
- // out of range references. ldr <rt>,[<rn>, #-<imm8>]
- if (FPOffset >= -255 && FPOffset < 0) {
- FrameReg = RegInfo->getFrameRegister(MF);
- return FPOffset;
- }
- } else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
- // Otherwise, use SP or FP, whichever is closer to the stack slot.
- FrameReg = RegInfo->getFrameRegister(MF);
- return FPOffset;
- }
- }
- // Use the base pointer if we have one.
- if (RegInfo->hasBasePointer(MF))
- FrameReg = RegInfo->getBaseRegister();
- return Offset;
- }
- int ARMFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
- int FI) const {
- unsigned FrameReg;
- return getFrameIndexReference(MF, FI, FrameReg);
- }
- void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- unsigned StmOpc, unsigned StrOpc,
- bool NoGap,
- bool(*Func)(unsigned, bool),
- unsigned NumAlignedDPRCS2Regs,
- unsigned MIFlags) const {
- MachineFunction &MF = *MBB.getParent();
- const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
- DebugLoc DL;
- if (MI != MBB.end()) DL = MI->getDebugLoc();
- SmallVector<std::pair<unsigned,bool>, 4> Regs;
- unsigned i = CSI.size();
- while (i != 0) {
- unsigned LastReg = 0;
- for (; i != 0; --i) {
- unsigned Reg = CSI[i-1].getReg();
- if (!(Func)(Reg, STI.isTargetMachO())) continue;
- // D-registers in the aligned area DPRCS2 are NOT spilled here.
- if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
- continue;
- // Add the callee-saved register as live-in unless it's LR and
- // @llvm.returnaddress is called. If LR is returned for
- // @llvm.returnaddress then it's already added to the function and
- // entry block live-in sets.
- bool isKill = true;
- if (Reg == ARM::LR) {
- if (MF.getFrameInfo()->isReturnAddressTaken() &&
- MF.getRegInfo().isLiveIn(Reg))
- isKill = false;
- }
- if (isKill)
- MBB.addLiveIn(Reg);
- // If NoGap is true, push consecutive registers and then leave the rest
- // for other instructions. e.g.
- // vpush {d8, d10, d11} -> vpush {d8}, vpush {d10, d11}
- if (NoGap && LastReg && LastReg != Reg-1)
- break;
- LastReg = Reg;
- Regs.push_back(std::make_pair(Reg, isKill));
- }
- if (Regs.empty())
- continue;
- if (Regs.size() > 1 || StrOpc== 0) {
- MachineInstrBuilder MIB =
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(StmOpc), ARM::SP)
- .addReg(ARM::SP).setMIFlags(MIFlags));
- for (unsigned i = 0, e = Regs.size(); i < e; ++i)
- MIB.addReg(Regs[i].first, getKillRegState(Regs[i].second));
- } else if (Regs.size() == 1) {
- MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc),
- ARM::SP)
- .addReg(Regs[0].first, getKillRegState(Regs[0].second))
- .addReg(ARM::SP).setMIFlags(MIFlags)
- .addImm(-4);
- AddDefaultPred(MIB);
- }
- Regs.clear();
- }
- }
- void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- unsigned LdmOpc, unsigned LdrOpc,
- bool isVarArg, bool NoGap,
- bool(*Func)(unsigned, bool),
- unsigned NumAlignedDPRCS2Regs) const {
- MachineFunction &MF = *MBB.getParent();
- const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- DebugLoc DL = MI->getDebugLoc();
- unsigned RetOpcode = MI->getOpcode();
- bool isTailCall = (RetOpcode == ARM::TCRETURNdi ||
- RetOpcode == ARM::TCRETURNri);
- bool isInterrupt =
- RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
- SmallVector<unsigned, 4> Regs;
- unsigned i = CSI.size();
- while (i != 0) {
- unsigned LastReg = 0;
- bool DeleteRet = false;
- for (; i != 0; --i) {
- unsigned Reg = CSI[i-1].getReg();
- if (!(Func)(Reg, STI.isTargetMachO())) continue;
- // The aligned reloads from area DPRCS2 are not inserted here.
- if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
- continue;
- if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
- STI.hasV5TOps()) {
- Reg = ARM::PC;
- LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
- // Fold the return instruction into the LDM.
- DeleteRet = true;
- }
- // If NoGap is true, pop consecutive registers and then leave the rest
- // for other instructions. e.g.
- // vpop {d8, d10, d11} -> vpop {d8}, vpop {d10, d11}
- if (NoGap && LastReg && LastReg != Reg-1)
- break;
- LastReg = Reg;
- Regs.push_back(Reg);
- }
- if (Regs.empty())
- continue;
- if (Regs.size() > 1 || LdrOpc == 0) {
- MachineInstrBuilder MIB =
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP)
- .addReg(ARM::SP));
- for (unsigned i = 0, e = Regs.size(); i < e; ++i)
- MIB.addReg(Regs[i], getDefRegState(true));
- if (DeleteRet) {
- MIB.copyImplicitOps(&*MI);
- MI->eraseFromParent();
- }
- MI = MIB;
- } else if (Regs.size() == 1) {
- // If we adjusted the reg to PC from LR above, switch it back here. We
- // only do that for LDM.
- if (Regs[0] == ARM::PC)
- Regs[0] = ARM::LR;
- MachineInstrBuilder MIB =
- BuildMI(MBB, MI, DL, TII.get(LdrOpc), Regs[0])
- .addReg(ARM::SP, RegState::Define)
- .addReg(ARM::SP);
- // ARM mode needs an extra reg0 here due to addrmode2. Will go away once
- // that refactoring is complete (eventually).
- if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
- MIB.addReg(0);
- MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift));
- } else
- MIB.addImm(4);
- AddDefaultPred(MIB);
- }
- Regs.clear();
- }
- }
- /// Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers
- /// starting from d8. Also insert stack realignment code and leave the stack
- /// pointer pointing to the d8 spill slot.
- static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned NumAlignedDPRCS2Regs,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- DebugLoc DL = MI->getDebugLoc();
- const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
- MachineFrameInfo &MFI = *MF.getFrameInfo();
- // Mark the D-register spill slots as properly aligned. Since MFI computes
- // stack slot layout backwards, this can actually mean that the d-reg stack
- // slot offsets can be wrong. The offset for d8 will always be correct.
- for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
- unsigned DNum = CSI[i].getReg() - ARM::D8;
- if (DNum >= 8)
- continue;
- int FI = CSI[i].getFrameIdx();
- // The even-numbered registers will be 16-byte aligned, the odd-numbered
- // registers will be 8-byte aligned.
- MFI.setObjectAlignment(FI, DNum % 2 ? 8 : 16);
- // The stack slot for D8 needs to be maximally aligned because this is
- // actually the point where we align the stack pointer. MachineFrameInfo
- // computes all offsets relative to the incoming stack pointer which is a
- // bit weird when realigning the stack. Any extra padding for this
- // over-alignment is not realized because the code inserted below adjusts
- // the stack pointer by numregs * 8 before aligning the stack pointer.
- if (DNum == 0)
- MFI.setObjectAlignment(FI, MFI.getMaxAlignment());
- }
- // Move the stack pointer to the d8 spill slot, and align it at the same
- // time. Leave the stack slot address in the scratch register r4.
- //
- // sub r4, sp, #numregs * 8
- // bic r4, r4, #align - 1
- // mov sp, r4
- //
- bool isThumb = AFI->isThumbFunction();
- assert(!AFI->isThumb1OnlyFunction() && "Can't realign stack for thumb1");
- AFI->setShouldRestoreSPFromFP(true);
- // sub r4, sp, #numregs * 8
- // The immediate is <= 64, so it doesn't need any special encoding.
- unsigned Opc = isThumb ? ARM::t2SUBri : ARM::SUBri;
- AddDefaultCC(AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(Opc), ARM::R4)
- .addReg(ARM::SP)
- .addImm(8 * NumAlignedDPRCS2Regs)));
- // bic r4, r4, #align-1
- Opc = isThumb ? ARM::t2BICri : ARM::BICri;
- unsigned MaxAlign = MF.getFrameInfo()->getMaxAlignment();
- AddDefaultCC(AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(Opc), ARM::R4)
- .addReg(ARM::R4, RegState::Kill)
- .addImm(MaxAlign - 1)));
- // mov sp, r4
- // The stack pointer must be adjusted before spilling anything, otherwise
- // the stack slots could be clobbered by an interrupt handler.
- // Leave r4 live, it is used below.
- Opc = isThumb ? ARM::tMOVr : ARM::MOVr;
- MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(Opc), ARM::SP)
- .addReg(ARM::R4);
- MIB = AddDefaultPred(MIB);
- if (!isThumb)
- AddDefaultCC(MIB);
- // Now spill NumAlignedDPRCS2Regs registers starting from d8.
- // r4 holds the stack slot address.
- unsigned NextReg = ARM::D8;
- // 16-byte aligned vst1.64 with 4 d-regs and address writeback.
- // The writeback is only needed when emitting two vst1.64 instructions.
- if (NumAlignedDPRCS2Regs >= 6) {
- unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
- &ARM::QQPRRegClass);
- MBB.addLiveIn(SupReg);
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VST1d64Qwb_fixed),
- ARM::R4)
- .addReg(ARM::R4, RegState::Kill).addImm(16)
- .addReg(NextReg)
- .addReg(SupReg, RegState::ImplicitKill));
- NextReg += 4;
- NumAlignedDPRCS2Regs -= 4;
- }
- // We won't modify r4 beyond this point. It currently points to the next
- // register to be spilled.
- unsigned R4BaseReg = NextReg;
- // 16-byte aligned vst1.64 with 4 d-regs, no writeback.
- if (NumAlignedDPRCS2Regs >= 4) {
- unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
- &ARM::QQPRRegClass);
- MBB.addLiveIn(SupReg);
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VST1d64Q))
- .addReg(ARM::R4).addImm(16).addReg(NextReg)
- .addReg(SupReg, RegState::ImplicitKill));
- NextReg += 4;
- NumAlignedDPRCS2Regs -= 4;
- }
- // 16-byte aligned vst1.64 with 2 d-regs.
- if (NumAlignedDPRCS2Regs >= 2) {
- unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
- &ARM::QPRRegClass);
- MBB.addLiveIn(SupReg);
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VST1q64))
- .addReg(ARM::R4).addImm(16).addReg(SupReg));
- NextReg += 2;
- NumAlignedDPRCS2Regs -= 2;
- }
- // Finally, use a vanilla vstr.64 for the odd last register.
- if (NumAlignedDPRCS2Regs) {
- MBB.addLiveIn(NextReg);
- // vstr.64 uses addrmode5 which has an offset scale of 4.
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VSTRD))
- .addReg(NextReg)
- .addReg(ARM::R4).addImm((NextReg-R4BaseReg)*2));
- }
- // The last spill instruction inserted should kill the scratch register r4.
- std::prev(MI)->addRegisterKilled(ARM::R4, TRI);
- }
- /// Skip past the code inserted by emitAlignedDPRCS2Spills, and return an
- /// iterator to the following instruction.
- static MachineBasicBlock::iterator
- skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI,
- unsigned NumAlignedDPRCS2Regs) {
- // sub r4, sp, #numregs * 8
- // bic r4, r4, #align - 1
- // mov sp, r4
- ++MI; ++MI; ++MI;
- assert(MI->mayStore() && "Expecting spill instruction");
- // These switches all fall through.
- switch(NumAlignedDPRCS2Regs) {
- case 7:
- ++MI;
- assert(MI->mayStore() && "Expecting spill instruction");
- default:
- ++MI;
- assert(MI->mayStore() && "Expecting spill instruction");
- case 1:
- case 2:
- case 4:
- assert(MI->killsRegister(ARM::R4) && "Missed kill flag");
- ++MI;
- }
- return MI;
- }
- /// Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers
- /// starting from d8. These instructions are assumed to execute while the
- /// stack is still aligned, unlike the code inserted by emitPopInst.
- static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned NumAlignedDPRCS2Regs,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) {
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- DebugLoc DL = MI->getDebugLoc();
- const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
- // Find the frame index assigned to d8.
- int D8SpillFI = 0;
- for (unsigned i = 0, e = CSI.size(); i != e; ++i)
- if (CSI[i].getReg() == ARM::D8) {
- D8SpillFI = CSI[i].getFrameIdx();
- break;
- }
- // Materialize the address of the d8 spill slot into the scratch register r4.
- // This can be fairly complicated if the stack frame is large, so just use
- // the normal frame index elimination mechanism to do it. This code runs as
- // the initial part of the epilog where the stack and base pointers haven't
- // been changed yet.
- bool isThumb = AFI->isThumbFunction();
- assert(!AFI->isThumb1OnlyFunction() && "Can't realign stack for thumb1");
- unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri;
- AddDefaultCC(AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(Opc), ARM::R4)
- .addFrameIndex(D8SpillFI).addImm(0)));
- // Now restore NumAlignedDPRCS2Regs registers starting from d8.
- unsigned NextReg = ARM::D8;
- // 16-byte aligned vld1.64 with 4 d-regs and writeback.
- if (NumAlignedDPRCS2Regs >= 6) {
- unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
- &ARM::QQPRRegClass);
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VLD1d64Qwb_fixed), NextReg)
- .addReg(ARM::R4, RegState::Define)
- .addReg(ARM::R4, RegState::Kill).addImm(16)
- .addReg(SupReg, RegState::ImplicitDefine));
- NextReg += 4;
- NumAlignedDPRCS2Regs -= 4;
- }
- // We won't modify r4 beyond this point. It currently points to the next
- // register to be spilled.
- unsigned R4BaseReg = NextReg;
- // 16-byte aligned vld1.64 with 4 d-regs, no writeback.
- if (NumAlignedDPRCS2Regs >= 4) {
- unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
- &ARM::QQPRRegClass);
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VLD1d64Q), NextReg)
- .addReg(ARM::R4).addImm(16)
- .addReg(SupReg, RegState::ImplicitDefine));
- NextReg += 4;
- NumAlignedDPRCS2Regs -= 4;
- }
- // 16-byte aligned vld1.64 with 2 d-regs.
- if (NumAlignedDPRCS2Regs >= 2) {
- unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
- &ARM::QPRRegClass);
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VLD1q64), SupReg)
- .addReg(ARM::R4).addImm(16));
- NextReg += 2;
- NumAlignedDPRCS2Regs -= 2;
- }
- // Finally, use a vanilla vldr.64 for the remaining odd register.
- if (NumAlignedDPRCS2Regs)
- AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(ARM::VLDRD), NextReg)
- .addReg(ARM::R4).addImm(2*(NextReg-R4BaseReg)));
- // Last store kills r4.
- std::prev(MI)->addRegisterKilled(ARM::R4, TRI);
- }
- bool ARMFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const {
- if (CSI.empty())
- return false;
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
- unsigned PushOneOpc = AFI->isThumbFunction() ?
- ARM::t2STR_PRE : ARM::STR_PRE_IMM;
- unsigned FltOpc = ARM::VSTMDDB_UPD;
- unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs();
- emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, 0,
- MachineInstr::FrameSetup);
- emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea2Register, 0,
- MachineInstr::FrameSetup);
- emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register,
- NumAlignedDPRCS2Regs, MachineInstr::FrameSetup);
- // The code above does not insert spill code for the aligned DPRCS2 registers.
- // The stack realignment code will be inserted between the push instructions
- // and these spills.
- if (NumAlignedDPRCS2Regs)
- emitAlignedDPRCS2Spills(MBB, MI, NumAlignedDPRCS2Regs, CSI, TRI);
- return true;
- }
- bool ARMFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const {
- if (CSI.empty())
- return false;
- MachineFunction &MF = *MBB.getParent();
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- bool isVarArg = AFI->getArgRegsSaveSize() > 0;
- unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs();
- // The emitPopInst calls below do not insert reloads for the aligned DPRCS2
- // registers. Do that here instead.
- if (NumAlignedDPRCS2Regs)
- emitAlignedDPRCS2Restores(MBB, MI, NumAlignedDPRCS2Regs, CSI, TRI);
- unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
- unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST :ARM::LDR_POST_IMM;
- unsigned FltOpc = ARM::VLDMDIA_UPD;
- emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register,
- NumAlignedDPRCS2Regs);
- emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
- &isARMArea2Register, 0);
- emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
- &isARMArea1Register, 0);
- return true;
- }
- // FIXME: Make generic?
- static unsigned GetFunctionSizeInBytes(const MachineFunction &MF,
- const ARMBaseInstrInfo &TII) {
- unsigned FnSize = 0;
- for (MachineFunction::const_iterator MBBI = MF.begin(), E = MF.end();
- MBBI != E; ++MBBI) {
- const MachineBasicBlock &MBB = *MBBI;
- for (MachineBasicBlock::const_iterator I = MBB.begin(),E = MBB.end();
- I != E; ++I)
- FnSize += TII.GetInstSizeInBytes(I);
- }
- return FnSize;
- }
- /// estimateRSStackSizeLimit - Look at each instruction that references stack
- /// frames and return the stack size limit beyond which some of these
- /// instructions will require a scratch register during their expansion later.
- // FIXME: Move to TII?
- static unsigned estimateRSStackSizeLimit(MachineFunction &MF,
- const TargetFrameLowering *TFI) {
- const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- unsigned Limit = (1 << 12) - 1;
- for (MachineFunction::iterator BB = MF.begin(),E = MF.end(); BB != E; ++BB) {
- for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end();
- I != E; ++I) {
- for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
- if (!I->getOperand(i).isFI()) continue;
- // When using ADDri to get the address of a stack object, 255 is the
- // largest offset guaranteed to fit in the immediate offset.
- if (I->getOpcode() == ARM::ADDri) {
- Limit = std::min(Limit, (1U << 8) - 1);
- break;
- }
- // Otherwise check the addressing mode.
- switch (I->getDesc().TSFlags & ARMII::AddrModeMask) {
- case ARMII::AddrMode3:
- case ARMII::AddrModeT2_i8:
- Limit = std::min(Limit, (1U << 8) - 1);
- break;
- case ARMII::AddrMode5:
- case ARMII::AddrModeT2_i8s4:
- Limit = std::min(Limit, ((1U << 8) - 1) * 4);
- break;
- case ARMII::AddrModeT2_i12:
- // i12 supports only positive offset so these will be converted to
- // i8 opcodes. See llvm::rewriteT2FrameIndex.
- if (TFI->hasFP(MF) && AFI->hasStackFrame())
- Limit = std::min(Limit, (1U << 8) - 1);
- break;
- case ARMII::AddrMode4:
- case ARMII::AddrMode6:
- // Addressing modes 4 & 6 (load/store) instructions can't encode an
- // immediate offset for stack references.
- return 0;
- default:
- break;
- }
- break; // At most one FI per instruction
- }
- }
- }
- return Limit;
- }
- // In functions that realign the stack, it can be an advantage to spill the
- // callee-saved vector registers after realigning the stack. The vst1 and vld1
- // instructions take alignment hints that can improve performance.
- //
- static void checkNumAlignedDPRCS2Regs(MachineFunction &MF) {
- MF.getInfo<ARMFunctionInfo>()->setNumAlignedDPRCS2Regs(0);
- if (!SpillAlignedNEONRegs)
- return;
- // Naked functions don't spill callee-saved registers.
- if (MF.getFunction()->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
- Attribute::Naked))
- return;
- // We are planning to use NEON instructions vst1 / vld1.
- if (!MF.getTarget().getSubtarget<ARMSubtarget>().hasNEON())
- return;
- // Don't bother if the default stack alignment is sufficiently high.
- if (MF.getTarget().getFrameLowering()->getStackAlignment() >= 8)
- return;
- // Aligned spills require stack realignment.
- const ARMBaseRegisterInfo *RegInfo =
- static_cast<const ARMBaseRegisterInfo*>(MF.getTarget().getRegisterInfo());
- if (!RegInfo->canRealignStack(MF))
- return;
- // We always spill contiguous d-registers starting from d8. Count how many
- // needs spilling. The register allocator will almost always use the
- // callee-saved registers in order, but it can happen that there are holes in
- // the range. Registers above the hole will be spilled to the standard DPRCS
- // area.
- MachineRegisterInfo &MRI = MF.getRegInfo();
- unsigned NumSpills = 0;
- for (; NumSpills < 8; ++NumSpills)
- if (!MRI.isPhysRegUsed(ARM::D8 + NumSpills))
- break;
- // Don't do this for just one d-register. It's not worth it.
- if (NumSpills < 2)
- return;
- // Spill the first NumSpills D-registers after realigning the stack.
- MF.getInfo<ARMFunctionInfo>()->setNumAlignedDPRCS2Regs(NumSpills);
- // A scratch register is required for the vst1 / vld1 instructions.
- MF.getRegInfo().setPhysRegUsed(ARM::R4);
- }
- void
- ARMFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
- RegScavenger *RS) const {
- // This tells PEI to spill the FP as if it is any other callee-save register
- // to take advantage the eliminateFrameIndex machinery. This also ensures it
- // is spilled in the order specified by getCalleeSavedRegs() to make it easier
- // to combine multiple loads / stores.
- bool CanEliminateFrame = true;
- bool CS1Spilled = false;
- bool LRSpilled = false;
- unsigned NumGPRSpills = 0;
- SmallVector<unsigned, 4> UnspilledCS1GPRs;
- SmallVector<unsigned, 4> UnspilledCS2GPRs;
- const ARMBaseRegisterInfo *RegInfo =
- static_cast<const ARMBaseRegisterInfo*>(MF.getTarget().getRegisterInfo());
- const ARMBaseInstrInfo &TII =
- *static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- MachineRegisterInfo &MRI = MF.getRegInfo();
- unsigned FramePtr = RegInfo->getFrameRegister(MF);
- // Spill R4 if Thumb2 function requires stack realignment - it will be used as
- // scratch register. Also spill R4 if Thumb2 function has varsized objects,
- // since it's not always possible to restore sp from fp in a single
- // instruction.
- // FIXME: It will be better just to find spare register here.
- if (AFI->isThumb2Function() &&
- (MFI->hasVarSizedObjects() || RegInfo->needsStackRealignment(MF)))
- MRI.setPhysRegUsed(ARM::R4);
- if (AFI->isThumb1OnlyFunction()) {
- // Spill LR if Thumb1 function uses variable length argument lists.
- if (AFI->getArgRegsSaveSize() > 0)
- MRI.setPhysRegUsed(ARM::LR);
- // Spill R4 if Thumb1 epilogue has to restore SP from FP. We don't know
- // for sure what the stack size will be, but for this, an estimate is good
- // enough. If there anything changes it, it'll be a spill, which implies
- // we've used all the registers and so R4 is already used, so not marking
- // it here will be OK.
- // FIXME: It will be better just to find spare register here.
- unsigned StackSize = MFI->estimateStackSize(MF);
- if (MFI->hasVarSizedObjects() || StackSize > 508)
- MRI.setPhysRegUsed(ARM::R4);
- }
- // See if we can spill vector registers to aligned stack.
- checkNumAlignedDPRCS2Regs(MF);
- // Spill the BasePtr if it's used.
- if (RegInfo->hasBasePointer(MF))
- MRI.setPhysRegUsed(RegInfo->getBaseRegister());
- // Don't spill FP if the frame can be eliminated. This is determined
- // by scanning the callee-save registers to see if any is used.
- const uint16_t *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
- for (unsigned i = 0; CSRegs[i]; ++i) {
- unsigned Reg = CSRegs[i];
- bool Spilled = false;
- if (MRI.isPhysRegUsed(Reg)) {
- Spilled = true;
- CanEliminateFrame = false;
- }
- if (!ARM::GPRRegClass.contains(Reg))
- continue;
- if (Spilled) {
- NumGPRSpills++;
- if (!STI.isTargetMachO()) {
- if (Reg == ARM::LR)
- LRSpilled = true;
- CS1Spilled = true;
- continue;
- }
- // Keep track if LR and any of R4, R5, R6, and R7 is spilled.
- switch (Reg) {
- case ARM::LR:
- LRSpilled = true;
- // Fallthrough
- case ARM::R0: case ARM::R1:
- case ARM::R2: case ARM::R3:
- case ARM::R4: case ARM::R5:
- case ARM::R6: case ARM::R7:
- CS1Spilled = true;
- break;
- default:
- break;
- }
- } else {
- if (!STI.isTargetMachO()) {
- UnspilledCS1GPRs.push_back(Reg);
- continue;
- }
- switch (Reg) {
- case ARM::R0: case ARM::R1:
- case ARM::R2: case ARM::R3:
- case ARM::R4: case ARM::R5:
- case ARM::R6: case ARM::R7:
- case ARM::LR:
- UnspilledCS1GPRs.push_back(Reg);
- break;
- default:
- UnspilledCS2GPRs.push_back(Reg);
- break;
- }
- }
- }
- bool ForceLRSpill = false;
- if (!LRSpilled && AFI->isThumb1OnlyFunction()) {
- unsigned FnSize = GetFunctionSizeInBytes(MF, TII);
- // Force LR to be spilled if the Thumb function size is > 2048. This enables
- // use of BL to implement far jump. If it turns out that it's not needed
- // then the branch fix up path will undo it.
- if (FnSize >= (1 << 11)) {
- CanEliminateFrame = false;
- ForceLRSpill = true;
- }
- }
- // If any of the stack slot references may be out of range of an immediate
- // offset, make sure a register (or a spill slot) is available for the
- // register scavenger. Note that if we're indexing off the frame pointer, the
- // effective stack size is 4 bytes larger since the FP points to the stack
- // slot of the previous FP. Also, if we have variable sized objects in the
- // function, stack slot references will often be negative, and some of
- // our instructions are positive-offset only, so conservatively consider
- // that case to want a spill slot (or register) as well. Similarly, if
- // the function adjusts the stack pointer during execution and the
- // adjustments aren't already part of our stack size estimate, our offset
- // calculations may be off, so be conservative.
- // FIXME: We could add logic to be more precise about negative offsets
- // and which instructions will need a scratch register for them. Is it
- // worth the effort and added fragility?
- bool BigStack =
- (RS &&
- (MFI->estimateStackSize(MF) +
- ((hasFP(MF) && AFI->hasStackFrame()) ? 4:0) >=
- estimateRSStackSizeLimit(MF, this)))
- || MFI->hasVarSizedObjects()
- || (MFI->adjustsStack() && !canSimplifyCallFramePseudos(MF));
- bool ExtraCSSpill = false;
- if (BigStack || !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
- AFI->setHasStackFrame(true);
- // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled.
- // Spill LR as well so we can fold BX_RET to the registers restore (LDM).
- if (!LRSpilled && CS1Spilled) {
- MRI.setPhysRegUsed(ARM::LR);
- NumGPRSpills++;
- SmallVectorImpl<unsigned>::iterator LRPos;
- LRPos = std::find(UnspilledCS1GPRs.begin(), UnspilledCS1GPRs.end(),
- (unsigned)ARM::LR);
- if (LRPos != UnspilledCS1GPRs.end())
- UnspilledCS1GPRs.erase(LRPos);
- ForceLRSpill = false;
- ExtraCSSpill = true;
- }
- if (hasFP(MF)) {
- MRI.setPhysRegUsed(FramePtr);
- NumGPRSpills++;
- }
- // If stack and double are 8-byte aligned and we are spilling an odd number
- // of GPRs, spill one extra callee save GPR so we won't have to pad between
- // the integer and double callee save areas.
- unsigned TargetAlign = getStackAlignment();
- if (TargetAlign == 8 && (NumGPRSpills & 1)) {
- if (CS1Spilled && !UnspilledCS1GPRs.empty()) {
- for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) {
- unsigned Reg = UnspilledCS1GPRs[i];
- // Don't spill high register if the function is thumb1
- if (!AFI->isThumb1OnlyFunction() ||
- isARMLowRegister(Reg) || Reg == ARM::LR) {
- MRI.setPhysRegUsed(Reg);
- if (!MRI.isReserved(Reg))
- ExtraCSSpill = true;
- break;
- }
- }
- } else if (!UnspilledCS2GPRs.empty() && !AFI->isThumb1OnlyFunction()) {
- unsigned Reg = UnspilledCS2GPRs.front();
- MRI.setPhysRegUsed(Reg);
- if (!MRI.isReserved(Reg))
- ExtraCSSpill = true;
- }
- }
- // Estimate if we might need to scavenge a register at some point in order
- // to materialize a stack offset. If so, either spill one additional
- // callee-saved register or reserve a special spill slot to facilitate
- // register scavenging. Thumb1 needs a spill slot for stack pointer
- // adjustments also, even when the frame itself is small.
- if (BigStack && !ExtraCSSpill) {
- // If any non-reserved CS register isn't spilled, just spill one or two
- // extra. That should take care of it!
- unsigned NumExtras = TargetAlign / 4;
- SmallVector<unsigned, 2> Extras;
- while (NumExtras && !UnspilledCS1GPRs.empty()) {
- unsigned Reg = UnspilledCS1GPRs.back();
- UnspilledCS1GPRs.pop_back();
- if (!MRI.isReserved(Reg) &&
- (!AFI->isThumb1OnlyFunction() || isARMLowRegister(Reg) ||
- Reg == ARM::LR)) {
- Extras.push_back(Reg);
- NumExtras--;
- }
- }
- // For non-Thumb1 functions, also check for hi-reg CS registers
- if (!AFI->isThumb1OnlyFunction()) {
- while (NumExtras && !UnspilledCS2GPRs.empty()) {
- unsigned Reg = UnspilledCS2GPRs.back();
- UnspilledCS2GPRs.pop_back();
- if (!MRI.isReserved(Reg)) {
- Extras.push_back(Reg);
- NumExtras--;
- }
- }
- }
- if (Extras.size() && NumExtras == 0) {
- for (unsigned i = 0, e = Extras.size(); i != e; ++i) {
- MRI.setPhysRegUsed(Extras[i]);
- }
- } else if (!AFI->isThumb1OnlyFunction()) {
- // note: Thumb1 functions spill to R12, not the stack. Reserve a slot
- // closest to SP or frame pointer.
- const TargetRegisterClass *RC = &ARM::GPRRegClass;
- RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
- RC->getAlignment(),
- false));
- }
- }
- }
- if (ForceLRSpill) {
- MRI.setPhysRegUsed(ARM::LR);
- AFI->setLRIsSpilledForFarJump(true);
- }
- }
- void ARMFrameLowering::
- eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) const {
- const ARMBaseInstrInfo &TII =
- *static_cast<const ARMBaseInstrInfo*>(MF.getTarget().getInstrInfo());
- if (!hasReservedCallFrame(MF)) {
- // If we have alloca, convert as follows:
- // ADJCALLSTACKDOWN -> sub, sp, sp, amount
- // ADJCALLSTACKUP -> add, sp, sp, amount
- MachineInstr *Old = I;
- DebugLoc dl = Old->getDebugLoc();
- unsigned Amount = Old->getOperand(0).getImm();
- if (Amount != 0) {
- // We need to keep the stack aligned properly. To do this, we round the
- // amount of space needed for the outgoing arguments up to the next
- // alignment boundary.
- unsigned Align = getStackAlignment();
- Amount = (Amount+Align-1)/Align*Align;
- ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
- assert(!AFI->isThumb1OnlyFunction() &&
- "This eliminateCallFramePseudoInstr does not support Thumb1!");
- bool isARM = !AFI->isThumbFunction();
- // Replace the pseudo instruction with a new instruction...
- unsigned Opc = Old->getOpcode();
- int PIdx = Old->findFirstPredOperandIdx();
- ARMCC::CondCodes Pred = (PIdx == -1)
- ? ARMCC::AL : (ARMCC::CondCodes)Old->getOperand(PIdx).getImm();
- if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
- // Note: PredReg is operand 2 for ADJCALLSTACKDOWN.
- unsigned PredReg = Old->getOperand(2).getReg();
- emitSPUpdate(isARM, MBB, I, dl, TII, -Amount, MachineInstr::NoFlags,
- Pred, PredReg);
- } else {
- // Note: PredReg is operand 3 for ADJCALLSTACKUP.
- unsigned PredReg = Old->getOperand(3).getReg();
- assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
- emitSPUpdate(isARM, MBB, I, dl, TII, Amount, MachineInstr::NoFlags,
- Pred, PredReg);
- }
- }
- }
- MBB.erase(I);
- }
|