return true;
}
-// Build an instruction sequence to load an immediate that is too large to fit
-// in 16-bit and add the result to Reg.
-static void expandLargeImm(unsigned Reg, int64_t Imm, bool IsN64,
- const MipsInstrInfo &TII, MachineBasicBlock& MBB,
- MachineBasicBlock::iterator II, DebugLoc DL) {
- unsigned LUi = IsN64 ? Mips::LUi64 : Mips::LUi;
- unsigned ADDu = IsN64 ? Mips::DADDu : Mips::ADDu;
- unsigned ZEROReg = IsN64 ? Mips::ZERO_64 : Mips::ZERO;
- unsigned ATReg = IsN64 ? Mips::AT_64 : Mips::AT;
- MipsAnalyzeImmediate AnalyzeImm;
- const MipsAnalyzeImmediate::InstSeq &Seq =
- AnalyzeImm.Analyze(Imm, IsN64 ? 64 : 32, false /* LastInstrIsADDiu */);
- MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin();
-
- // FIXME: change this when mips goes MC".
- BuildMI(MBB, II, DL, TII.get(Mips::NOAT));
-
- // The first instruction can be a LUi, which is different from other
- // instructions (ADDiu, ORI and SLL) in that it does not have a register
- // operand.
- if (Inst->Opc == LUi)
- BuildMI(MBB, II, DL, TII.get(LUi), ATReg)
- .addImm(SignExtend64<16>(Inst->ImmOpnd));
- else
- BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg)
- .addImm(SignExtend64<16>(Inst->ImmOpnd));
-
- // Build the remaining instructions in Seq.
- for (++Inst; Inst != Seq.end(); ++Inst)
- BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg)
- .addImm(SignExtend64<16>(Inst->ImmOpnd));
-
- BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(Reg).addReg(ATReg);
- BuildMI(MBB, II, DL, TII.get(Mips::ATMACRO));
-}
-
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front();
MachineFrameInfo *MFI = MF.getFrameInfo();
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
MachineBasicBlock::iterator MBBI = MBB.begin();
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
- bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_);
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 ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
// First, compute final stack size.
- unsigned RegSize = STI.isGP32bit() ? 4 : 8;
unsigned StackAlign = getStackAlignment();
- unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ?
- (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) :
- MipsFI->getMaxCallFrameSize();
- uint64_t StackSize = RoundUpToAlignment(LocalVarAreaOffset, StackAlign) +
- RoundUpToAlignment(MFI->getStackSize(), StackAlign);
+ uint64_t StackSize = RoundUpToAlignment(MFI->getStackSize(), StackAlign);
+
+ if (MipsFI->globalBaseRegSet())
+ StackSize += MFI->getObjectOffset(MipsFI->getGlobalRegFI()) + StackAlign;
+ else
+ StackSize += RoundUpToAlignment(MipsFI->getMaxCallFrameSize(), StackAlign);
// Update stack size
MFI->setStackSize(StackSize);
- BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER));
- BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
-
- // Emit instructions that set the global base register if the target ABI is
- // O32.
- if (isPIC && MipsFI->globalBaseRegSet() && STI.isABI_O32()) {
- if (MipsFI->globalBaseRegFixed())
- BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::CPLOAD))
- .addReg(RegInfo->getPICCallReg());
- else
- // See MipsInstrInfo.td for explanation.
- BuildMI(MBB, MBBI, dl, TII.get(Mips:: SETGP01), Mips::V0);
- }
-
// No need to allocate space on the stack.
if (StackSize == 0 && !MFI->adjustsStack()) 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.
- expandLargeImm(SP, -StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl);
+ 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);
+ }
// emit ".cfi_def_cfa_offset StackSize"
MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
// If Reg is a double precision register, emit two cfa_offsets,
// one for each of the paired single precision registers.
- if (Mips::AFGR64RegisterClass->contains(Reg)) {
- const uint16_t *SubRegs = RegInfo->getSubRegisters(Reg);
+ if (Mips::AFGR64RegClass.contains(Reg)) {
MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
- MachineLocation SrcML0(*SubRegs);
- MachineLocation SrcML1(*(SubRegs + 1));
+ MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven));
+ MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd));
if (!STI.isLittle())
std::swap(SrcML0, SrcML1);
Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
- }
- else {
+ } else {
// Reg is either in CPURegs or FGR32.
DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
SrcML = MachineLocation(Reg);
SrcML = MachineLocation(MachineLocation::VirtualFP);
Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
}
-
- // Restore GP from the saved stack location
- if (MipsFI->needGPSaveRestore()) {
- unsigned Offset = MFI->getObjectOffset(MipsFI->getGPFI());
- BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)).addImm(Offset);
-
- if (Offset >= 0x8000) {
- BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::MACRO));
- BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
- }
- }
}
void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
// 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.
- expandLargeImm(SP, StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl);
+ 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::
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS) const {
- MachineRegisterInfo& MRI = MF.getRegInfo();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
// FIXME: remove this code if register allocator can correctly mark
// Mark $fp and $ra as used or unused.
if (hasFP(MF))
MRI.setPhysRegUsed(FP);
+}
- // The register allocator might determine $ra is used after seeing
- // instruction "jr $ra", but we do not want PrologEpilogInserter to insert
- // instructions to save/restore $ra unless there is a function call.
- // To correct this, $ra is explicitly marked unused if there is no
- // function call.
- if (MF.getFrameInfo()->hasCalls())
- MRI.setPhysRegUsed(Mips::RA);
- else {
- MRI.setPhysRegUnused(Mips::RA);
- MRI.setPhysRegUnused(Mips::RA_64);
+bool MipsFrameLowering::
+spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const {
+ MachineFunction *MF = MBB.getParent();
+ MachineBasicBlock *EntryBlock = MF->begin();
+ const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
+
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ // Add the callee-saved register as live-in. Do not add if the register is
+ // RA and return address is taken, because it has already been added in
+ // method MipsTargetLowering::LowerRETURNADDR.
+ // It's killed at the spill, unless the register is RA and return address
+ // is taken.
+ unsigned Reg = CSI[i].getReg();
+ bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
+ && MF->getFrameInfo()->isReturnAddressTaken();
+ if (!IsRAAndRetAddrIsTaken)
+ EntryBlock->addLiveIn(Reg);
+
+ // Insert the spill to the stack frame.
+ bool IsKill = !IsRAAndRetAddrIsTaken;
+ const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
+ TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
+ CSI[i].getFrameIdx(), RC, TRI);
}
+
+ return true;
}