diff options
Diffstat (limited to 'llvm/lib/Target/AVR/AVRFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/AVR/AVRFrameLowering.cpp | 119 |
1 files changed, 47 insertions, 72 deletions
diff --git a/llvm/lib/Target/AVR/AVRFrameLowering.cpp b/llvm/lib/Target/AVR/AVRFrameLowering.cpp index e6c48de5a782..c95a553b86ac 100644 --- a/llvm/lib/Target/AVR/AVRFrameLowering.cpp +++ b/llvm/lib/Target/AVR/AVRFrameLowering.cpp @@ -30,8 +30,7 @@ namespace llvm { AVRFrameLowering::AVRFrameLowering() - : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align::None(), - -2) {} + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(1), -2) {} bool AVRFrameLowering::canSimplifyCallFramePseudos( const MachineFunction &MF) const { @@ -53,30 +52,22 @@ bool AVRFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { void AVRFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.begin(); - CallingConv::ID CallConv = MF.getFunction().getCallingConv(); DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc(); const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>(); const AVRInstrInfo &TII = *STI.getInstrInfo(); + const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); bool HasFP = hasFP(MF); // Interrupt handlers re-enable interrupts in function entry. - if (CallConv == CallingConv::AVR_INTR) { + if (AFI->isInterruptHandler()) { BuildMI(MBB, MBBI, DL, TII.get(AVR::BSETs)) .addImm(0x07) .setMIFlag(MachineInstr::FrameSetup); } - // Save the frame pointer if we have one. - if (HasFP) { - BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr)) - .addReg(AVR::R29R28, RegState::Kill) - .setMIFlag(MachineInstr::FrameSetup); - } - // Emit special prologue code to save R1, R0 and SREG in interrupt/signal // handlers before saving any other registers. - if (CallConv == CallingConv::AVR_INTR || - CallConv == CallingConv::AVR_SIGNAL) { + if (AFI->isInterruptOrSignalHandler()) { BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr)) .addReg(AVR::R1R0, RegState::Kill) .setMIFlag(MachineInstr::FrameSetup); @@ -100,7 +91,6 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF, } const MachineFrameInfo &MFI = MF.getFrameInfo(); - const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize(); // Skip the callee-saved push instructions. @@ -143,13 +133,11 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF, void AVRFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { - CallingConv::ID CallConv = MF.getFunction().getCallingConv(); - bool isHandler = (CallConv == CallingConv::AVR_INTR || - CallConv == CallingConv::AVR_SIGNAL); + const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); // Early exit if the frame pointer is not needed in this function except for // signal/interrupt handlers where special code generation is required. - if (!hasFP(MF) && !isHandler) { + if (!hasFP(MF) && !AFI->isInterruptOrSignalHandler()) { return; } @@ -159,14 +147,13 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF, DebugLoc DL = MBBI->getDebugLoc(); const MachineFrameInfo &MFI = MF.getFrameInfo(); - const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize(); const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>(); const AVRInstrInfo &TII = *STI.getInstrInfo(); // Emit special epilogue code to restore R1, R0 and SREG in interrupt/signal // handlers at the very end of the function, just before reti. - if (isHandler) { + if (AFI->isInterruptOrSignalHandler()) { BuildMI(MBB, MBBI, DL, TII.get(AVR::POPRd), AVR::R0); BuildMI(MBB, MBBI, DL, TII.get(AVR::OUTARr)) .addImm(0x3f) @@ -174,9 +161,6 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R1R0); } - if (hasFP(MF)) - BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R29R28); - // Early exit if there is no need to restore the frame pointer. if (!FrameSize) { return; @@ -234,8 +218,7 @@ bool AVRFrameLowering::hasFP(const MachineFunction &MF) const { bool AVRFrameLowering::spillCalleeSavedRegisters( MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { + ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) { return false; } @@ -275,8 +258,7 @@ bool AVRFrameLowering::spillCalleeSavedRegisters( bool AVRFrameLowering::restoreCalleeSavedRegisters( MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { + MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) { return false; } @@ -299,15 +281,10 @@ bool AVRFrameLowering::restoreCalleeSavedRegisters( } /// Replace pseudo store instructions that pass arguments through the stack with -/// real instructions. If insertPushes is true then all instructions are -/// replaced with push instructions, otherwise regular std instructions are -/// inserted. +/// real instructions. static void fixStackStores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const TargetInstrInfo &TII, bool insertPushes) { - const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>(); - const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); - + const TargetInstrInfo &TII, Register FP) { // Iterate through the BB until we hit a call instruction or we reach the end. for (auto I = MI, E = MBB.end(); I != E && !I->isCall();) { MachineBasicBlock::iterator NextMI = std::next(I); @@ -322,29 +299,6 @@ static void fixStackStores(MachineBasicBlock &MBB, assert(MI.getOperand(0).getReg() == AVR::SP && "Invalid register, should be SP!"); - if (insertPushes) { - // Replace this instruction with a push. - Register SrcReg = MI.getOperand(2).getReg(); - bool SrcIsKill = MI.getOperand(2).isKill(); - - // We can't use PUSHWRr here because when expanded the order of the new - // instructions are reversed from what we need. Perform the expansion now. - if (Opcode == AVR::STDWSPQRr) { - BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr)) - .addReg(TRI.getSubReg(SrcReg, AVR::sub_hi), - getKillRegState(SrcIsKill)); - BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr)) - .addReg(TRI.getSubReg(SrcReg, AVR::sub_lo), - getKillRegState(SrcIsKill)); - } else { - BuildMI(MBB, I, MI.getDebugLoc(), TII.get(AVR::PUSHRr)) - .addReg(SrcReg, getKillRegState(SrcIsKill)); - } - - MI.eraseFromParent(); - I = NextMI; - continue; - } // Replace this instruction with a regular store. Use Y as the base // pointer since it is guaranteed to contain a copy of SP. @@ -352,7 +306,7 @@ static void fixStackStores(MachineBasicBlock &MBB, (Opcode == AVR::STDWSPQRr) ? AVR::STDWPtrQRr : AVR::STDPtrQRr; MI.setDesc(TII.get(STOpc)); - MI.getOperand(0).setReg(AVR::R29R28); + MI.getOperand(0).setReg(FP); I = NextMI; } @@ -368,7 +322,7 @@ MachineBasicBlock::iterator AVRFrameLowering::eliminateCallFramePseudoInstr( // function entry. Delete the call frame pseudo and replace all pseudo stores // with real store instructions. if (hasReservedCallFrame(MF)) { - fixStackStores(MBB, MI, TII, false); + fixStackStores(MBB, MI, TII, AVR::R29R28); return MBB.erase(MI); } @@ -376,18 +330,37 @@ MachineBasicBlock::iterator AVRFrameLowering::eliminateCallFramePseudoInstr( unsigned int Opcode = MI->getOpcode(); int Amount = TII.getFrameSize(*MI); - // Adjcallstackup does not need to allocate stack space for the call, instead - // we insert push instructions that will allocate the necessary stack. - // For adjcallstackdown we convert it into an 'adiw reg, <amt>' handling - // the read and write of SP in I/O space. + // ADJCALLSTACKUP and ADJCALLSTACKDOWN are converted to adiw/subi + // instructions to read and write the stack pointer in I/O space. if (Amount != 0) { - assert(getStackAlignment() == 1 && "Unsupported stack alignment"); + assert(getStackAlign() == Align(1) && "Unsupported stack alignment"); if (Opcode == TII.getCallFrameSetupOpcode()) { - fixStackStores(MBB, MI, TII, true); + // Update the stack pointer. + // In many cases this can be done far more efficiently by pushing the + // relevant values directly to the stack. However, doing that correctly + // (in the right order, possibly skipping some empty space for undef + // values, etc) is tricky and thus left to be optimized in the future. + BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP); + + MachineInstr *New = BuildMI(MBB, MI, DL, TII.get(AVR::SUBIWRdK), AVR::R31R30) + .addReg(AVR::R31R30, RegState::Kill) + .addImm(Amount); + New->getOperand(3).setIsDead(); + + BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP) + .addReg(AVR::R31R30, RegState::Kill); + + // Make sure the remaining stack stores are converted to real store + // instructions. + fixStackStores(MBB, MI, TII, AVR::R31R30); } else { assert(Opcode == TII.getCallFrameDestroyOpcode()); + // Note that small stack changes could be implemented more efficiently + // with a few pop instructions instead of the 8-9 instructions now + // required. + // Select the best opcode to adjust SP based on the offset size. unsigned addOpcode; if (isUInt<6>(Amount)) { @@ -419,8 +392,10 @@ void AVRFrameLowering::determineCalleeSaves(MachineFunction &MF, TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); // If we have a frame pointer, the Y register needs to be saved as well. - // We don't do that here however - the prologue and epilogue generation - // code will handle it specially. + if (hasFP(MF)) { + SavedRegs.set(AVR::R29); + SavedRegs.set(AVR::R28); + } } /// The frame analyzer pass. /// @@ -430,7 +405,7 @@ struct AVRFrameAnalyzer : public MachineFunctionPass { static char ID; AVRFrameAnalyzer() : MachineFunctionPass(ID) {} - bool runOnMachineFunction(MachineFunction &MF) { + bool runOnMachineFunction(MachineFunction &MF) override { const MachineFrameInfo &MFI = MF.getFrameInfo(); AVRMachineFunctionInfo *FuncInfo = MF.getInfo<AVRMachineFunctionInfo>(); @@ -482,7 +457,7 @@ struct AVRFrameAnalyzer : public MachineFunctionPass { return false; } - StringRef getPassName() const { return "AVR Frame Analyzer"; } + StringRef getPassName() const override { return "AVR Frame Analyzer"; } }; char AVRFrameAnalyzer::ID = 0; @@ -498,7 +473,7 @@ struct AVRDynAllocaSR : public MachineFunctionPass { static char ID; AVRDynAllocaSR() : MachineFunctionPass(ID) {} - bool runOnMachineFunction(MachineFunction &MF) { + bool runOnMachineFunction(MachineFunction &MF) override { // Early exit when there are no variable sized objects in the function. if (!MF.getFrameInfo().hasVarSizedObjects()) { return false; @@ -510,7 +485,7 @@ struct AVRDynAllocaSR : public MachineFunctionPass { MachineBasicBlock::iterator MBBI = EntryMBB.begin(); DebugLoc DL = EntryMBB.findDebugLoc(MBBI); - unsigned SPCopy = + Register SPCopy = MF.getRegInfo().createVirtualRegister(&AVR::DREGSRegClass); // Create a copy of SP in function entry before any dynallocas are @@ -531,7 +506,7 @@ struct AVRDynAllocaSR : public MachineFunctionPass { return true; } - StringRef getPassName() const { + StringRef getPassName() const override { return "AVR dynalloca stack pointer save/restore"; } }; |