void C65FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { const C65Subtarget &STI = MF.getSubtarget<C65Subtarget>(); const C65RegisterInfo &RegInfo = *STI.getRegisterInfo(); const TargetInstrInfo &TII = *STI.getInstrInfo(); const MachineFrameInfo &MFI = MF.getFrameInfo(); C65MachineFunctionInfo &FuncInfo = *MF.getInfo<C65MachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); int Size = (int)MFI.getStackSize() + (int)FuncInfo.getBytesToPopOnReturn(); bool Is16Bit = STI.has65802(); unsigned FramePtr = RegInfo.getFrameRegister(MF); assert((MBBI->getOpcode() == C65::RTS || MBBI->getOpcode() == C65::RTL) && "Can only put epilogue before 'RTS' or 'RTL' instruction!"); if (Size) emitSAdjustment(MF, MBB, MBBI, Size); if (hasFP(MF)) { // Restore the frame pointer. if (FramePtr == C65::X || FramePtr == C65::XL) BuildMI(MBB, MBBI, DL, TII.get(Is16Bit ? C65::PLX16 : C65::PLX8)); else llvm_unreachable("Only X may be a frame pointer."); } }
void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instruction "move $sp, $fp" at this location. BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO); } // Get the number of bytes from FrameInfo uint64_t StackSize = MFI->getStackSize(); if (!StackSize) return; // Adjust stack. TII.adjustStackPtr(SP, StackSize, MBB, MBBI); }
void NyuziFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const NyuziInstrInfo &TII = *static_cast<const NyuziInstrInfo *>(MF.getSubtarget().getInstrInfo()); DebugLoc DL = MBBI->getDebugLoc(); assert(MBBI->getOpcode() == Nyuzi::RET && "Can only put epilog before 'retl' instruction!"); // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; BuildMI(MBB, I, DL, TII.get(Nyuzi::MOVESS)) .addReg(Nyuzi::SP_REG) .addReg(Nyuzi::FP_REG); } uint64_t StackSize = RoundUpToAlignment(MFI->getStackSize(), getStackAlignment()); if (!StackSize) return; TII.adjustStackPointer(MBB, MBBI, StackSize); }
void MipsSEFrameLowering::emitInterruptEpilogueStub( MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Perform ISR handling like GCC const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; // Disable Interrupts. BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::DI), Mips::ZERO); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EHB)); // Restore EPC STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1, MipsFI->getISRRegFI(0), PtrRC, STI.getRegisterInfo()); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP014) .addReg(Mips::K1) .addImm(0); // Restore Status STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1, MipsFI->getISRRegFI(1), PtrRC, STI.getRegisterInfo()); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012) .addReg(Mips::K1) .addImm(0); }
void LEGFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { // Compute the stack size, to determine if we need an epilogue at all. const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); DebugLoc dl = MBBI->getDebugLoc(); uint64_t StackSize = computeStackSize(MF); if (!StackSize) { return; } // Restore the stack pointer to what it was at the beginning of the function. unsigned StackReg = LEG::SP; unsigned OffsetReg = materializeOffset(MF, MBB, MBBI, (unsigned)StackSize); if (OffsetReg) { BuildMI(MBB, MBBI, dl, TII.get(LEG::ADDrr), StackReg) .addReg(StackReg) .addReg(OffsetReg) .setMIFlag(MachineInstr::FrameSetup); } else { BuildMI(MBB, MBBI, dl, TII.get(LEG::ADDri), StackReg) .addReg(StackReg) .addImm(StackSize) .setMIFlag(MachineInstr::FrameSetup); } }
void VideoCore4FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineFrameInfo* MFI = MF.getFrameInfo(); const VideoCore4InstrInfo& TII = *static_cast<const VideoCore4InstrInfo*>( MF.getTarget().getInstrInfo()); const VideoCore4RegisterInfo& RI = *static_cast<const VideoCore4RegisterInfo*>( MF.getTarget().getRegisterInfo()); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); /* Check the return opcode. */ if (MBBI->getOpcode() != VideoCore4::RET) llvm_unreachable("can only insert epilog into returning blocks"); if (hasFP(MF)) { //BuildMI(MBB, MBBI, dl, TII.get(VideoCore4::MOV_R), VideoCore4::SP) // .addReg(VideoCore4::R6); } int stacksize = (int) MFI->getStackSize(); if (hasFP(MF)) stacksize += 4; TII.adjustStackPtr(stacksize, MBB, MBBI); }
unsigned ARCInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const { assert(!BytesRemoved && "Code size not handled"); MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); if (I == MBB.end()) return 0; if (!isUncondBranchOpcode(I->getOpcode()) && !isCondBranchOpcode(I->getOpcode())) return 0; // Remove the branch. I->eraseFromParent(); I = MBB.end(); if (I == MBB.begin()) return 1; --I; if (!isCondBranchOpcode(I->getOpcode())) return 1; // Remove the branch. I->eraseFromParent(); return 2; }
void Cpu0FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); const Cpu0InstrInfo &TII = *static_cast<const Cpu0InstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = Cpu0::SP; unsigned ADDiu = Cpu0::ADDiu; // Get the number of bytes from FrameInfo uint64_t StackSize = MFI->getStackSize(); if (!StackSize) return; // Adjust stack. if (isInt<16>(StackSize)) // addiu sp, sp, (stacksize) BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize); else { // Expand immediate that doesn't fit in 16-bit. Cpu0FI->setEmitNOAT(); expandLargeImm(SP, StackSize, TII, MBB, MBBI, dl); } }
void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const XCoreInstrInfo &TII = *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); bool FP = hasFP(MF); if (FP) { // Restore the stack pointer. unsigned FramePtr = XCore::R10; BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)) .addReg(FramePtr); } // Work out frame sizes. int FrameSize = MFI->getStackSize(); assert(FrameSize%4 == 0 && "Misaligned frame size"); FrameSize/=4; bool isU6 = isImmU6(FrameSize); if (!isU6 && !isImmU16(FrameSize)) { // FIXME could emit multiple instructions. report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize)); } if (FrameSize) { XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); if (FP) { // Restore R10 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot()); FPSpillOffset += FrameSize*4; loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII); } bool restoreLR = XFI->getUsesLR(); if (restoreLR && MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0) { int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot()); LRSpillOffset += FrameSize*4; loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII); restoreLR = false; } if (restoreLR) { // Fold prologue into return instruction assert(MBBI->getOpcode() == XCore::RETSP_u6 || MBBI->getOpcode() == XCore::RETSP_lu6); int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6; BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize); MBB.erase(MBBI); } else { int Opcode = (isU6) ? XCore::LDAWSP_ru6_RRegs : XCore::LDAWSP_lru6_RRegs; BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize); } } }
void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); DebugLoc DL = MBBI->getDebugLoc(); MipsABIInfo ABI = STI.getABI(); unsigned SP = ABI.GetStackPtr(); unsigned FP = ABI.GetFramePtr(); unsigned ZERO = ABI.GetNullPtr(); unsigned MOVE = ABI.GetGPRMoveOp(); // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instruction "move $sp, $fp" at this location. BuildMI(MBB, I, DL, TII.get(MOVE), SP).addReg(FP).addReg(ZERO); } if (MipsFI->callsEhReturn()) { const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; // Find first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instructions that restore eh data registers. for (int J = 0; J < 4; ++J) { TII.loadRegFromStackSlot(MBB, I, ABI.GetEhDataReg(J), MipsFI->getEhDataRegFI(J), RC, &RegInfo); } } if (MF.getFunction()->hasFnAttribute("interrupt")) emitInterruptEpilogueStub(MF, MBB); // Get the number of bytes from FrameInfo uint64_t StackSize = MFI->getStackSize(); if (!StackSize) return; // Adjust stack. TII.adjustStackPtr(SP, StackSize, MBB, MBBI); }
void SparcFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const SparcInstrInfo &TII = *static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); assert(MBBI->getOpcode() == SP::RETL && "Can only put epilog before 'retl' instruction!"); BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0) .addReg(SP::G0); }
void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instruction "move $sp, $fp" at this location. BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO); } if (MipsFI->callsEhReturn()) { const TargetRegisterClass *RC = STI.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; // Find first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instructions that restore eh data registers. for (int J = 0; J < 4; ++J) { TII.loadRegFromStackSlot(MBB, I, ehDataReg(J), MipsFI->getEhDataRegFI(J), RC, &RegInfo); } } // Get the number of bytes from FrameInfo uint64_t StackSize = MFI->getStackSize(); if (!StackSize) return; // Adjust stack. TII.adjustStackPtr(SP, StackSize, MBB, MBBI); }
void XTCFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); XTCFunctionInfo *XTCFI = MF.getInfo<XTCFunctionInfo>(); const XTCInstrInfo &TII = *static_cast<const XTCInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); // Get the FI's where RA and FP are saved. int FPOffset = XTCFI->getFPStackOffset(); int RAOffset = XTCFI->getRAStackOffset(); if (hasFP(MF)) { /* Save current FP into stack */ // BuildMI(MBB, MBBI, dl, TII.get(XTC::STWPREI)).addReg(XTC::r14, RegState::Kill).addReg(XTC::r15).addImm(-4); /* Copy from current SP */ BuildMI(MBB, MBBI, dl, TII.get(XTC::COPY), XTC::r15).addReg(XTC::r14); // Mark the FramePtr as live-in in every block except the entry. for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end(); I != E; ++I) I->addLiveIn(XTC::r14); } /* // lwi R15, R1, stack_loc if (MFI->adjustsStack() || requiresRA) { BuildMI(MBB, MBBI, dl, TII.get(XTC::LWI), XTC::R15) .addReg(XTC::R1).addImm(RAOffset); */ // Get the number of bytes from FrameInfo int StackSize = (int) MFI->getStackSize(); if (StackSize) { BuildMI(MBB, MBBI, dl, TII.get(XTC::ADDI), XTC::r15) .addReg(XTC::r15).addImm(StackSize); } }
// The function epilogue should not depend on the current stack pointer! // It should use the frame pointer only. This is mandatory because // of alloca; we also take advantage of it to omit stack adjustments // before returning. // // Note that when we go to restore the preserved register values we must // not try to address their slots by using offsets from the stack pointer. // That's because the stack pointer may have been moved during the function // execution due to a call to alloca(). Rather, we must restore all // preserved registers via offsets from the frame pointer value. // // Note also that when the current frame is being "popped" (by adjusting // the value of the stack pointer) on function exit, we must (for the // sake of alloca) set the new value of the stack pointer based upon // the current value of the frame pointer. We can't just add what we // believe to be the (static) frame size to the stack pointer because // if we did that, and alloca() had been called during this function, // we would end up returning *without* having fully deallocated all of // the space grabbed by alloca. If that happened, and a function // containing one or more alloca() calls was called over and over again, // then the stack would grow without limit! // // RET is lowered to // ld -4[%fp],%pc # modify %pc (two delay slots) // as the return address is in the stack frame and mov to pc is allowed. // emitEpilogue emits // mov %fp,%sp # restore the stack pointer // ld -8[%fp],%fp # restore the caller's frame pointer // before RET and the delay slot filler will move RET such that these // instructions execute in the delay slots of the load to PC. void LanaiFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const LanaiInstrInfo &LII = *static_cast<const LanaiInstrInfo *>(STI.getInstrInfo()); DebugLoc DL = MBBI->getDebugLoc(); // Restore the stack pointer using the callee's frame pointer value. BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP) .addReg(Lanai::FP) .addImm(0); // Restore the frame pointer from the stack. BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP) .addReg(Lanai::FP) .addImm(-8) .addImm(LPAC::ADD); }
void MipsFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instruction "move $sp, $fp" at this location. BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO); } // Get the number of bytes from FrameInfo uint64_t StackSize = MFI->getStackSize(); if (!StackSize) return; // Adjust stack. if (isInt<16>(StackSize)) // addi sp, sp, (-stacksize) BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize); else { // Expand immediate that doesn't fit in 16-bit. unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT; MF.getInfo<MipsFunctionInfo>()->setEmitNOAT(); Mips::loadImmediate(StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false, 0); BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg); } }
void MipsFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; // Get the number of bytes from FrameInfo unsigned StackSize = MFI->getStackSize(); unsigned NewReg = 0; int NewImm = 0; bool ATUsed = false; // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instruction "move $sp, $fp" at this location. BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO); } // adjust stack : insert addi sp, sp, (imm) if (StackSize) { ATUsed = expandRegLargeImmPair(SP, StackSize, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } }
void MBlazeFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); const MBlazeInstrInfo &TII = *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; // Get the FI's where RA and FP are saved. int FPOffset = MBlazeFI->getFPStackOffset(); int RAOffset = MBlazeFI->getRAStackOffset(); if (hasFP(MF)) { // add R1, R19, R0 BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1) .addReg(MBlaze::R19).addReg(MBlaze::R0); // lwi R19, R1, stack_loc BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19) .addReg(MBlaze::R1).addImm(FPOffset); } // lwi R15, R1, stack_loc if (MFI->adjustsStack() || requiresRA) { BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15) .addReg(MBlaze::R1).addImm(RAOffset); } // Get the number of bytes from FrameInfo int StackSize = (int) MFI->getStackSize(); // addi R1, R1, imm if (StackSize) { BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDIK), MBlaze::R1) .addReg(MBlaze::R1).addImm(StackSize); } }
void Cpu0FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); const Cpu0InstrInfo &TII = *static_cast<const Cpu0InstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); unsigned SP = Cpu0::SP; // lbd document - mark - emitEpilogue() Cpu0::SP unsigned FP = Cpu0::FP; unsigned ZERO = Cpu0::ZERO; unsigned ADDu = Cpu0::ADDu; // lbd document - mark - emitEpilogue() Cpu0::ADDu unsigned ADDiu = Cpu0::ADDiu; // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; // Insert instruction "move $sp, $fp" at this location. BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO); } // lbd document - mark - emitEpilogue() if (hasFP(MF)) // Get the number of bytes from FrameInfo uint64_t StackSize = MFI->getStackSize(); if (!StackSize) return; // Adjust stack. if (isInt<16>(StackSize)) // addiu sp, sp, (stacksize) BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize); else { // Expand immediate that doesn't fit in 16-bit. Cpu0FI->setEmitNOAT(); expandLargeImm(SP, StackSize, TII, MBB, MBBI, dl); } }
void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = *static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); uint64_t StackSize = MFI->getStackSize(); if (!StackSize) return; if (hasFP(MF)) BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP) .addReg(Mips::S0); // Adjust stack. // assumes stacksize multiple of 8 TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI); }
void llvm::guessSuccessors(const MachineBasicBlock &MBB, SmallVectorImpl<MachineBasicBlock*> &Result, bool &IsFallthrough) { SmallPtrSet<MachineBasicBlock*,8> Seen; for (const MachineInstr &MI : MBB) { if (MI.isPHI()) continue; for (const MachineOperand &MO : MI.operands()) { if (!MO.isMBB()) continue; MachineBasicBlock *Succ = MO.getMBB(); auto RP = Seen.insert(Succ); if (RP.second) Result.push_back(Succ); } } MachineBasicBlock::const_iterator I = MBB.getLastNonDebugInstr(); IsFallthrough = I == MBB.end() || !I->isBarrier(); }
void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const SystemZInstrInfo *ZII = static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); // Skip the return instruction. assert(MBBI->getOpcode() == SystemZ::RET && "Can only insert epilogue into returning blocks"); uint64_t StackSize = getAllocatedStackSize(MF); if (ZFI->getLowSavedGPR()) { --MBBI; unsigned Opcode = MBBI->getOpcode(); if (Opcode != SystemZ::LMG) llvm_unreachable("Expected to see callee-save register restore code"); unsigned AddrOpNo = 2; DebugLoc DL = MBBI->getDebugLoc(); uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm(); unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); // If the offset is too large, use the largest stack-aligned offset // and add the rest to the base register (the stack or frame pointer). if (!NewOpcode) { uint64_t NumBytes = Offset - 0x7fff8; emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(), NumBytes, ZII); Offset -= NumBytes; NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); assert(NewOpcode && "No restore instruction available"); } MBBI->setDesc(ZII->get(NewOpcode)); MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset); } else if (StackSize) { DebugLoc DL = MBBI->getDebugLoc(); emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII); } }
unsigned XCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); if (I == MBB.end()) return 0; if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode())) return 0; // Remove the branch. I->eraseFromParent(); I = MBB.end(); if (I == MBB.begin()) return 1; --I; if (!IsCondBranch(I->getOpcode())) return 1; // Remove the branch. I->eraseFromParent(); return 2; }
void SparcFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const SparcInstrInfo &TII = *static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); assert(MBBI->getOpcode() == SP::RETL && "Can only put epilog before 'retl' instruction!"); if (!FuncInfo->isLeafProc()) { BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0) .addReg(SP::G0); return; } MachineFrameInfo *MFI = MF.getFrameInfo(); int NumBytes = (int) MFI->getStackSize(); if (NumBytes == 0) return; NumBytes = SubTarget.getAdjustedFrameSize(NumBytes); emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri); }
void PatmosFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetInstrInfo *TII = TM.getInstrInfo(); DebugLoc dl = MBBI->getDebugLoc(); //---------------------------------------------------------------------------- // Handle Stack Cache // emit a free instruction MachineInstr *MI = emitSTC(MF, MBB, MBBI, Patmos::SFREEi); if (MI) MI->setFlag(MachineInstr::FrameSetup); //---------------------------------------------------------------------------- // Handle Shadow Stack // Get the number of bytes from FrameInfo unsigned stackSize = MFI->getStackSize(); // adjust stack : sp += stack size if (stackSize) { if (stackSize <= 0xFFF) { MachineInstr *MI = AddDefaultPred(BuildMI(MBB, MBBI, dl, TII->get(Patmos::ADDi), Patmos::RSP)) .addReg(Patmos::RSP).addImm(stackSize); MI->setFlag(MachineInstr::FrameSetup); } else { MachineInstr *MI = AddDefaultPred(BuildMI(MBB, MBBI, dl, TII->get(Patmos::ADDl), Patmos::RSP)) .addReg(Patmos::RSP).addImm(stackSize); MI->setFlag(MachineInstr::FrameSetup); } } }
/// fixupConditionalBranch - Fix up a conditional branch whose destination is /// too far away to fit in its displacement field. It is converted to an inverse /// conditional branch + an unconditional branch to the destination. bool AArch64BranchRelaxation::fixupConditionalBranch(MachineInstr *MI) { MachineBasicBlock *DestBB = getDestBlock(MI); // Add an unconditional branch to the destination and invert the branch // condition to jump over it: // tbz L1 // => // tbnz L2 // b L1 // L2: // If the branch is at the end of its MBB and that has a fall-through block, // direct the updated conditional branch to the fall-through block. Otherwise, // split the MBB before the next instruction. MachineBasicBlock *MBB = MI->getParent(); MachineInstr *BMI = &MBB->back(); bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB); if (BMI != MI) { if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->getLastNonDebugInstr()) && BMI->getOpcode() == AArch64::B) { // Last MI in the BB is an unconditional branch. Can we simply invert the // condition and swap destinations: // beq L1 // b L2 // => // bne L2 // b L1 MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB(); if (isBlockInRange(MI, NewDest, getBranchDisplacementBits(MI->getOpcode()))) { DEBUG(dbgs() << " Invert condition and swap its destination with " << *BMI); BMI->getOperand(0).setMBB(DestBB); unsigned OpNum = (MI->getOpcode() == AArch64::TBZW || MI->getOpcode() == AArch64::TBNZW || MI->getOpcode() == AArch64::TBZX || MI->getOpcode() == AArch64::TBNZX) ? 2 : 1; MI->getOperand(OpNum).setMBB(NewDest); MI->setDesc(TII->get(getOppositeConditionOpcode(MI->getOpcode()))); if (MI->getOpcode() == AArch64::Bcc) invertBccCondition(MI); return true; } } } if (NeedSplit) { // Analyze the branch so we know how to update the successor lists. MachineBasicBlock *TBB, *FBB; SmallVector<MachineOperand, 2> Cond; TII->AnalyzeBranch(*MBB, TBB, FBB, Cond, false); MachineBasicBlock *NewBB = splitBlockBeforeInstr(MI); // No need for the branch to the next block. We're adding an unconditional // branch to the destination. int delta = TII->GetInstSizeInBytes(&MBB->back()); BlockInfo[MBB->getNumber()].Size -= delta; MBB->back().eraseFromParent(); // BlockInfo[SplitBB].Offset is wrong temporarily, fixed below // Update the successor lists according to the transformation to follow. // Do it here since if there's no split, no update is needed. MBB->replaceSuccessor(FBB, NewBB); NewBB->addSuccessor(FBB); } MachineBasicBlock *NextBB = std::next(MachineFunction::iterator(MBB)); DEBUG(dbgs() << " Insert B to BB#" << DestBB->getNumber() << ", invert condition and change dest. to BB#" << NextBB->getNumber() << "\n"); // Insert a new conditional branch and a new unconditional branch. MachineInstrBuilder MIB = BuildMI( MBB, DebugLoc(), TII->get(getOppositeConditionOpcode(MI->getOpcode()))) .addOperand(MI->getOperand(0)); if (MI->getOpcode() == AArch64::TBZW || MI->getOpcode() == AArch64::TBNZW || MI->getOpcode() == AArch64::TBZX || MI->getOpcode() == AArch64::TBNZX) MIB.addOperand(MI->getOperand(1)); if (MI->getOpcode() == AArch64::Bcc) invertBccCondition(MIB); MIB.addMBB(NextBB); BlockInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back()); BuildMI(MBB, DebugLoc(), TII->get(AArch64::B)).addMBB(DestBB); BlockInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back()); // Remove the old conditional branch. It may or may not still be in MBB. BlockInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(MI); MI->eraseFromParent(); // Finally, keep the block offsets up to date. adjustBlockOffsets(*MBB); return true; }
void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { AArch64MachineFunctionInfo *FuncInfo = MF.getInfo<AArch64MachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); DebugLoc DL = MBBI->getDebugLoc(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); MachineFrameInfo &MFI = *MF.getFrameInfo(); unsigned RetOpcode = MBBI->getOpcode(); // Initial and residual are named for consitency with the prologue. Note that // in the epilogue, the residual adjustment is executed first. uint64_t NumInitialBytes = FuncInfo->getInitialStackAdjust(); uint64_t NumResidualBytes = MFI.getStackSize() - NumInitialBytes; uint64_t ArgumentPopSize = 0; if (RetOpcode == AArch64::TC_RETURNdi || RetOpcode == AArch64::TC_RETURNxi) { MachineOperand &JumpTarget = MBBI->getOperand(0); MachineOperand &StackAdjust = MBBI->getOperand(1); MachineInstrBuilder MIB; if (RetOpcode == AArch64::TC_RETURNdi) { MIB = BuildMI(MBB, MBBI, DL, TII.get(AArch64::TAIL_Bimm)); if (JumpTarget.isGlobal()) { MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(), JumpTarget.getTargetFlags()); } else { assert(JumpTarget.isSymbol() && "unexpected tail call destination"); MIB.addExternalSymbol(JumpTarget.getSymbolName(), JumpTarget.getTargetFlags()); } } else { assert(RetOpcode == AArch64::TC_RETURNxi && JumpTarget.isReg() && "Unexpected tail call"); MIB = BuildMI(MBB, MBBI, DL, TII.get(AArch64::TAIL_BRx)); MIB.addReg(JumpTarget.getReg(), RegState::Kill); } // Add the extra operands onto the new tail call instruction even though // they're not used directly (so that liveness is tracked properly etc). for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i) MIB->addOperand(MBBI->getOperand(i)); // Delete the pseudo instruction TC_RETURN. MachineInstr *NewMI = std::prev(MBBI); MBB.erase(MBBI); MBBI = NewMI; // For a tail-call in a callee-pops-arguments environment, some or all of // the stack may actually be in use for the call's arguments, this is // calculated during LowerCall and consumed here... ArgumentPopSize = StackAdjust.getImm(); } else { // ... otherwise the amount to pop is *all* of the argument space, // conveniently stored in the MachineFunctionInfo by // LowerFormalArguments. This will, of course, be zero for the C calling // convention. ArgumentPopSize = FuncInfo->getArgumentStackToRestore(); } assert(NumInitialBytes % 16 == 0 && NumResidualBytes % 16 == 0 && "refusing to adjust stack by misaligned amt"); // We may need to address callee-saved registers differently, so find out the // bound on the frame indices. const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; if (CSI.size()) { MinCSFI = CSI[0].getFrameIdx(); MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); } // The "residual" stack update comes first from this direction and guarantees // that SP is NumInitialBytes below its value on function entry, either by a // direct update or restoring it from the frame pointer. if (NumInitialBytes + ArgumentPopSize != 0) { emitSPUpdate(MBB, MBBI, DL, TII, AArch64::X16, NumInitialBytes + ArgumentPopSize); --MBBI; } // MBBI now points to the instruction just past the last callee-saved // restoration (either RET/B if NumInitialBytes == 0, or the "ADD sp, sp" // otherwise). // Now we need to find out where to put the bulk of the stack adjustment MachineBasicBlock::iterator FirstEpilogue = MBBI; while (MBBI != MBB.begin()) { --MBBI; unsigned FrameOp; for (FrameOp = 0; FrameOp < MBBI->getNumOperands(); ++FrameOp) { if (MBBI->getOperand(FrameOp).isFI()) break; } // If this instruction doesn't have a frame index we've reached the end of // the callee-save restoration. if (FrameOp == MBBI->getNumOperands()) break; // Likewise if it *is* a local reference, but not to a callee-saved object. int FrameIdx = MBBI->getOperand(FrameOp).getIndex(); if (FrameIdx < MinCSFI || FrameIdx > MaxCSFI) break; FirstEpilogue = MBBI; } if (MF.getFrameInfo()->hasVarSizedObjects()) { int64_t StaticFrameBase; StaticFrameBase = -(NumInitialBytes + FuncInfo->getFramePointerOffset()); emitRegUpdate(MBB, FirstEpilogue, DL, TII, AArch64::XSP, AArch64::X29, AArch64::NoRegister, StaticFrameBase); } else { emitSPUpdate(MBB, FirstEpilogue, DL,TII, AArch64::X16, NumResidualBytes); } }
void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>(); const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo(); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL; bool IsTailCallReturn = false; if (MBB.end() != MBBI) { DL = MBBI->getDebugLoc(); unsigned RetOpcode = MBBI->getOpcode(); IsTailCallReturn = RetOpcode == AArch64::TCRETURNdi || RetOpcode == AArch64::TCRETURNri; } int NumBytes = MFI->getStackSize(); const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>(); // All calls are tail calls in GHC calling conv, and functions have no // prologue/epilogue. if (MF.getFunction()->getCallingConv() == CallingConv::GHC) return; // Initial and residual are named for consistency with the prologue. Note that // in the epilogue, the residual adjustment is executed first. uint64_t ArgumentPopSize = 0; if (IsTailCallReturn) { MachineOperand &StackAdjust = MBBI->getOperand(1); // For a tail-call in a callee-pops-arguments environment, some or all of // the stack may actually be in use for the call's arguments, this is // calculated during LowerCall and consumed here... ArgumentPopSize = StackAdjust.getImm(); } else { // ... otherwise the amount to pop is *all* of the argument space, // conveniently stored in the MachineFunctionInfo by // LowerFormalArguments. This will, of course, be zero for the C calling // convention. ArgumentPopSize = AFI->getArgumentStackToRestore(); } // The stack frame should be like below, // // ---------------------- --- // | | | // | BytesInStackArgArea| CalleeArgStackSize // | (NumReusableBytes) | (of tail call) // | | --- // | | | // ---------------------| --- | // | | | | // | CalleeSavedReg | | | // | (NumRestores * 8) | | | // | | | | // ---------------------| | NumBytes // | | StackSize (StackAdjustUp) // | LocalStackSize | | | // | (covering callee | | | // | args) | | | // | | | | // ---------------------- --- --- // // So NumBytes = StackSize + BytesInStackArgArea - CalleeArgStackSize // = StackSize + ArgumentPopSize // // AArch64TargetLowering::LowerCall figures out ArgumentPopSize and keeps // it as the 2nd argument of AArch64ISD::TC_RETURN. NumBytes += ArgumentPopSize; unsigned NumRestores = 0; // Move past the restores of the callee-saved registers. MachineBasicBlock::iterator LastPopI = MBB.getFirstTerminator(); const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF); MachineBasicBlock::iterator Begin = MBB.begin(); while (LastPopI != Begin) { --LastPopI; unsigned Restores = getNumCSRestores(*LastPopI, CSRegs); NumRestores += Restores; if (Restores == 0) { ++LastPopI; break; } } NumBytes -= NumRestores * 8; assert(NumBytes >= 0 && "Negative stack allocation size!?"); if (!hasFP(MF)) { // If this was a redzone leaf function, we don't need to restore the // stack pointer. if (!canUseRedZone(MF)) emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP, NumBytes, TII); return; } // Restore the original stack pointer. // FIXME: Rather than doing the math here, we should instead just use // non-post-indexed loads for the restores if we aren't actually going to // be able to save any instructions. if (NumBytes || MFI->hasVarSizedObjects()) emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::FP, -(NumRestores - 2) * 8, TII, MachineInstr::NoFlags); }
// Returns true if MBB has a machine instructions that indicates a tail call // in the block. bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); unsigned RetOpcode = MBBI->getOpcode(); return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;}
void AVRFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); bool isHandler = (CallConv == CallingConv::AVR_INTR || CallConv == CallingConv::AVR_SIGNAL); // 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) { return; } MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); assert(MBBI->getDesc().isReturn() && "Can only insert epilog into returning blocks"); 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) { BuildMI(MBB, MBBI, DL, TII.get(AVR::POPRd), AVR::R0); BuildMI(MBB, MBBI, DL, TII.get(AVR::OUTARr)) .addImm(0x3f) .addReg(AVR::R0, RegState::Kill); 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; } // Skip the callee-saved pop instructions. while (MBBI != MBB.begin()) { MachineBasicBlock::iterator PI = std::prev(MBBI); int Opc = PI->getOpcode(); if (Opc != AVR::POPRd && Opc != AVR::POPWRd && !PI->isTerminator()) { break; } --MBBI; } unsigned Opcode; // Select the optimal opcode depending on how big it is. if (isUInt<6>(FrameSize)) { Opcode = AVR::ADIWRdK; } else { Opcode = AVR::SUBIWRdK; FrameSize = -FrameSize; } // Restore the frame pointer by doing FP += <size>. MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opcode), AVR::R29R28) .addReg(AVR::R29R28, RegState::Kill) .addImm(FrameSize); // The SREG implicit def is dead. MI->getOperand(3).setIsDead(); // Write back R29R28 to SP and temporarily disable interrupts. BuildMI(MBB, MBBI, DL, TII.get(AVR::SPWRITE), AVR::SP) .addReg(AVR::R29R28, RegState::Kill); }
bool AArch64RedundantCopyElimination::optimizeBlock(MachineBasicBlock *MBB) { // Check if the current basic block has a single predecessor. if (MBB->pred_size() != 1) return false; // Check if the predecessor has two successors, implying the block ends in a // conditional branch. MachineBasicBlock *PredMBB = *MBB->pred_begin(); if (PredMBB->succ_size() != 2) return false; MachineBasicBlock::iterator CondBr = PredMBB->getLastNonDebugInstr(); if (CondBr == PredMBB->end()) return false; // Keep track of the earliest point in the PredMBB block where kill markers // need to be removed if a COPY is removed. MachineBasicBlock::iterator FirstUse; // After calling knownRegValInBlock, FirstUse will either point to a CBZ/CBNZ // or a compare (i.e., SUBS). In the latter case, we must take care when // updating FirstUse when scanning for COPY instructions. In particular, if // there's a COPY in between the compare and branch the COPY should not // update FirstUse. bool SeenFirstUse = false; // Registers that contain a known value at the start of MBB. SmallVector<RegImm, 4> KnownRegs; MachineBasicBlock::iterator Itr = std::next(CondBr); do { --Itr; if (!knownRegValInBlock(*Itr, MBB, KnownRegs, FirstUse)) continue; // Reset the clobber list. OptBBClobberedRegs.reset(); // Look backward in PredMBB for COPYs from the known reg to find other // registers that are known to be a constant value. for (auto PredI = Itr;; --PredI) { if (FirstUse == PredI) SeenFirstUse = true; if (PredI->isCopy()) { MCPhysReg CopyDstReg = PredI->getOperand(0).getReg(); MCPhysReg CopySrcReg = PredI->getOperand(1).getReg(); for (auto &KnownReg : KnownRegs) { if (OptBBClobberedRegs[KnownReg.Reg]) continue; // If we have X = COPY Y, and Y is known to be zero, then now X is // known to be zero. if (CopySrcReg == KnownReg.Reg && !OptBBClobberedRegs[CopyDstReg]) { KnownRegs.push_back(RegImm(CopyDstReg, KnownReg.Imm)); if (SeenFirstUse) FirstUse = PredI; break; } // If we have X = COPY Y, and X is known to be zero, then now Y is // known to be zero. if (CopyDstReg == KnownReg.Reg && !OptBBClobberedRegs[CopySrcReg]) { KnownRegs.push_back(RegImm(CopySrcReg, KnownReg.Imm)); if (SeenFirstUse) FirstUse = PredI; break; } } } // Stop if we get to the beginning of PredMBB. if (PredI == PredMBB->begin()) break; trackRegDefs(*PredI, OptBBClobberedRegs, TRI); // Stop if all of the known-zero regs have been clobbered. if (all_of(KnownRegs, [&](RegImm KnownReg) { return OptBBClobberedRegs[KnownReg.Reg]; })) break; } break; } while (Itr != PredMBB->begin() && Itr->isTerminator()); // We've not found a registers with a known value, time to bail out. if (KnownRegs.empty()) return false; bool Changed = false; // UsedKnownRegs is the set of KnownRegs that have had uses added to MBB. SmallSetVector<unsigned, 4> UsedKnownRegs; MachineBasicBlock::iterator LastChange = MBB->begin(); // Remove redundant copy/move instructions unless KnownReg is modified. for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;) { MachineInstr *MI = &*I; ++I; bool RemovedMI = false; bool IsCopy = MI->isCopy(); bool IsMoveImm = MI->isMoveImmediate(); if (IsCopy || IsMoveImm) { MCPhysReg DefReg = MI->getOperand(0).getReg(); MCPhysReg SrcReg = IsCopy ? MI->getOperand(1).getReg() : 0; int64_t SrcImm = IsMoveImm ? MI->getOperand(1).getImm() : 0; if (!MRI->isReserved(DefReg) && ((IsCopy && (SrcReg == AArch64::XZR || SrcReg == AArch64::WZR)) || IsMoveImm)) { for (RegImm &KnownReg : KnownRegs) { if (KnownReg.Reg != DefReg && !TRI->isSuperRegister(DefReg, KnownReg.Reg)) continue; // For a copy, the known value must be a zero. if (IsCopy && KnownReg.Imm != 0) continue; if (IsMoveImm) { // For a move immediate, the known immediate must match the source // immediate. if (KnownReg.Imm != SrcImm) continue; // Don't remove a move immediate that implicitly defines the upper // bits when only the lower 32 bits are known. MCPhysReg CmpReg = KnownReg.Reg; if (any_of(MI->implicit_operands(), [CmpReg](MachineOperand &O) { return !O.isDead() && O.isReg() && O.isDef() && O.getReg() != CmpReg; })) continue; } if (IsCopy) DEBUG(dbgs() << "Remove redundant Copy : " << *MI); else DEBUG(dbgs() << "Remove redundant Move : " << *MI); MI->eraseFromParent(); Changed = true; LastChange = I; NumCopiesRemoved++; UsedKnownRegs.insert(KnownReg.Reg); RemovedMI = true; break; } } } // Skip to the next instruction if we removed the COPY/MovImm. if (RemovedMI) continue; // Remove any regs the MI clobbers from the KnownConstRegs set. for (unsigned RI = 0; RI < KnownRegs.size();) if (MI->modifiesRegister(KnownRegs[RI].Reg, TRI)) { std::swap(KnownRegs[RI], KnownRegs[KnownRegs.size() - 1]); KnownRegs.pop_back(); // Don't increment RI since we need to now check the swapped-in // KnownRegs[RI]. } else { ++RI; } // Continue until the KnownRegs set is empty. if (KnownRegs.empty()) break; } if (!Changed) return false; // Add newly used regs to the block's live-in list if they aren't there // already. for (MCPhysReg KnownReg : UsedKnownRegs) if (!MBB->isLiveIn(KnownReg)) MBB->addLiveIn(KnownReg); // Clear kills in the range where changes were made. This is conservative, // but should be okay since kill markers are being phased out. DEBUG(dbgs() << "Clearing kill flags.\n\tFirstUse: " << *FirstUse << "\tLastChange: " << *LastChange); for (MachineInstr &MMI : make_range(FirstUse, PredMBB->end())) MMI.clearKillInfo(); for (MachineInstr &MMI : make_range(MBB->begin(), LastChange)) MMI.clearKillInfo(); return true; }