static void analyzeFrameIndexes(MachineFunction &MF) { if (MBDisableStackAdjust) return; MachineFrameInfo *MFI = MF.getFrameInfo(); MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); const MachineRegisterInfo &MRI = MF.getRegInfo(); MachineRegisterInfo::livein_iterator LII = MRI.livein_begin(); MachineRegisterInfo::livein_iterator LIE = MRI.livein_end(); const SmallVector<int, 16> &LiveInFI = MBlazeFI->getLiveIn(); SmallVector<MachineInstr*, 16> EraseInstr; SmallVector<std::pair<int,int64_t>, 16> FrameRelocate; MachineBasicBlock *MBB = MF.getBlockNumbered(0); MachineBasicBlock::iterator MIB = MBB->begin(); MachineBasicBlock::iterator MIE = MBB->end(); int StackAdjust = 0; int StackOffset = -28; // In this loop we are searching frame indexes that corrospond to incoming // arguments that are already in the stack. We look for instruction sequences // like the following: // // LWI REG, FI1, 0 // ... // SWI REG, FI2, 0 // // As long as there are no defs of REG in the ... part, we can eliminate // the SWI instruction because the value has already been stored to the // stack by the caller. All we need to do is locate FI at the correct // stack location according to the calling convensions. // // Additionally, if the SWI operation kills the def of REG then we don't // need the LWI operation so we can erase it as well. for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) { for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 || !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || I->getOperand(1).getIndex() != LiveInFI[i]) continue; unsigned FIReg = I->getOperand(0).getReg(); MachineBasicBlock::iterator SI = I; for (SI++; SI != MIE; ++SI) { if (!SI->getOperand(0).isReg() || !SI->getOperand(1).isFI() || SI->getOpcode() != MBlaze::SWI) continue; int FI = SI->getOperand(1).getIndex(); if (SI->getOperand(0).getReg() != FIReg || MFI->isFixedObjectIndex(FI) || MFI->getObjectSize(FI) != 4) continue; if (SI->getOperand(0).isDef()) break; if (SI->getOperand(0).isKill()) { DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex() << " removed\n"); EraseInstr.push_back(I); } EraseInstr.push_back(SI); DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n"); FrameRelocate.push_back(std::make_pair(FI,StackOffset)); DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n"); StackOffset -= 4; StackAdjust += 4; break; } } } // In this loop we are searching for frame indexes that corrospond to // incoming arguments that are in registers. We look for instruction // sequences like the following: // // ... SWI REG, FI, 0 // // As long as the ... part does not define REG and if REG is an incoming // parameter register then we know that, according to ABI convensions, the // caller has allocated stack space for it already. Instead of allocating // stack space on our frame, we record the correct location in the callers // frame. for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) { for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { if (I->definesRegister(LI->first)) break; if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 || !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || I->getOperand(1).getIndex() < 0) continue; if (I->getOperand(0).getReg() == LI->first) { int FI = I->getOperand(1).getIndex(); MBlazeFI->recordLiveIn(FI); int FILoc = 0; switch (LI->first) { default: llvm_unreachable("invalid incoming parameter!"); case MBlaze::R5: FILoc = -4; break; case MBlaze::R6: FILoc = -8; break; case MBlaze::R7: FILoc = -12; break; case MBlaze::R8: FILoc = -16; break; case MBlaze::R9: FILoc = -20; break; case MBlaze::R10: FILoc = -24; break; } StackAdjust += 4; FrameRelocate.push_back(std::make_pair(FI,FILoc)); DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n"); break; } } } // Go ahead and erase all of the instructions that we determined were // no longer needed. for (int i = 0, e = EraseInstr.size(); i < e; ++i) MBB->erase(EraseInstr[i]); // Replace all of the frame indexes that we have relocated with new // fixed object frame indexes. replaceFrameIndexes(MF, FrameRelocate); }
void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, int FrameIndex, uint64_t StackSize, int64_t SPOffset) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); MipsABIInfo ABI = static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo()); 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(); } bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex); // The following stack frame objects are always referenced relative to $sp: // 1. Outgoing arguments. // 2. Pointer to dynamically allocated stack space. // 3. Locations for callee-saved registers. // 4. Locations for eh data registers. // Everything else is referenced relative to whatever register // getFrameRegister() returns. unsigned FrameReg; if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI) FrameReg = ABI.GetStackPtr(); else if (RegInfo->needsStackRealignment(MF)) { if (MFI->hasVarSizedObjects() && !MFI->isFixedObjectIndex(FrameIndex)) FrameReg = ABI.GetBasePtr(); else if (MFI->isFixedObjectIndex(FrameIndex)) FrameReg = getFrameRegister(MF); else FrameReg = ABI.GetStackPtr(); } else FrameReg = getFrameRegister(MF); // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated // stack space or a $gp restore location, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: // incoming argument, callee-saved register location or local variable. bool IsKill = false; int64_t Offset; Offset = SPOffset + (int64_t)StackSize; Offset += MI.getOperand(OpNo + 1).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); if (!MI.isDebugValue()) { // Make sure Offset fits within the field available. // For MSA instructions, this is a 10-bit signed immediate (scaled by // element size), otherwise it is a 16-bit signed immediate. unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits(MI.getOpcode()); unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode()); if (OffsetBitSize < 16 && isInt<16>(Offset) && (!isIntN(OffsetBitSize, Offset) || OffsetToAlignment(Offset, OffsetAlign) != 0)) { // If we have an offset that needs to fit into a signed n-bit immediate // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); const TargetRegisterClass *PtrRC = ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); unsigned Reg = RegInfo.createVirtualRegister(PtrRC); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( MBB.getParent()->getSubtarget().getInstrInfo()); BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiuOp()), Reg) .addReg(FrameReg) .addImm(Offset); FrameReg = Reg; Offset = 0; IsKill = true; } else if (!isInt<16>(Offset)) { // Otherwise split the offset into 16-bit pieces and add it in multiple // instructions. MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); unsigned NewImm = 0; const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( MBB.getParent()->getSubtarget().getInstrInfo()); unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, OffsetBitSize == 16 ? &NewImm : nullptr); BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAdduOp()), Reg).addReg(FrameReg) .addReg(Reg, RegState::Kill); FrameReg = Reg; Offset = SignExtend64<16>(NewImm); IsKill = true; } } MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill); MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); }