Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -275,7 +275,7 @@ class StoreMultMM : - InstSE<(outs), (ins reglist:$rt, mem_mm_12:$addr), + InstSE<(outs), (ins reglist:$rt, variable_ops, mem_mm_12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayStore = 1; @@ -283,7 +283,7 @@ class LoadMultMM : - InstSE<(outs reglist:$rt), (ins mem_mm_12:$addr), + InstSE<(outs reglist:$rt, variable_ops), (ins mem_mm_12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayLoad = 1; Index: lib/Target/Mips/MipsSEFrameLowering.h =================================================================== --- lib/Target/Mips/MipsSEFrameLowering.h +++ lib/Target/Mips/MipsSEFrameLowering.h @@ -36,6 +36,12 @@ const std::vector &CSI, const TargetRegisterInfo *TRI) const override; + bool + restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const override; + bool hasReservedCallFrame(const MachineFunction &MF) const override; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, Index: lib/Target/Mips/MipsSEFrameLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEFrameLowering.cpp +++ lib/Target/Mips/MipsSEFrameLowering.cpp @@ -48,6 +48,48 @@ return std::make_pair(0, 0); } +static void BuildMultipleMemAccess(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + int FirstIndx, int Counter, + unsigned Opcode) { + MachineFunction *MF = MBB.getParent(); + MachineBasicBlock *EntryBlock = MF->begin(); + int FI = CSI[FirstIndx].getFrameIdx(); + const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); + unsigned Flag = ((Opcode == Mips::SWM32_MM) ? MachineMemOperand::MOStore + : MachineMemOperand::MOLoad); + + // Insert swm instruction. + DebugLoc DL; + if (MI != MBB.end()) + DL = MI->getDebugLoc(); + + MachineFrameInfo &MFI = *MF->getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + + MachineMemOperand *MMO = + MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FI), Flag, + MFI.getObjectSize(FI), Align); + Counter++; + MachineInstrBuilder MIB = BuildMI(*EntryBlock, MI, DL, TII.get(Opcode)); + + // Insert all registers into instruction. + for (int j = FirstIndx; j > FirstIndx - Counter; j--) { + unsigned SReg = CSI[j].getReg(); + + bool IsRAAndRetAddrIsTaken = (SReg == Mips::RA || SReg == Mips::RA_64) && + MF->getFrameInfo()->isReturnAddressTaken(); + bool IsKill = !IsRAAndRetAddrIsTaken; + unsigned Flag = Opcode == Mips::SWM32_MM ? getKillRegState(IsKill) + : getDefRegState(true); + MIB.addReg(SReg, Flag); + } + MIB.addFrameIndex(FI); + MIB.addImm(0); + MIB.addMemOperand(MMO); +} + /// Helper class to expand pseudos. class ExpandPseudo { public: @@ -607,28 +649,121 @@ MachineBasicBlock *EntryBlock = MF->begin(); const TargetInstrInfo &TII = *MF->getSubtarget().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); + if (STI.inMicroMipsMode()) { + unsigned Size = CSI.size(); + unsigned Counter = 0; + int FirstIndx = 0; + for (int i = Size - 1; i >= 0; --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 NextReg = i ? CSI[i - 1].getReg() : 0; + unsigned Reg = CSI[i].getReg(); + bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64) + && MF->getFrameInfo()->isReturnAddressTaken(); + if (!IsRAAndRetAddrIsTaken) + EntryBlock->addLiveIn(Reg); + + if (Reg == Mips::S0) { + FirstIndx = i; + Counter++; + } else if (NextReg == Reg + 1 || NextReg == Mips::FP || + NextReg == Mips::RA) { + Counter++; + } else if (Counter) { + // Emit SWM instruction. + BuildMultipleMemAccess(MBB, MI, CSI, FirstIndx, Counter, + Mips::SWM32_MM); + Counter = 0; + } else { + // 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); + } + } + } else { + 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; } +bool MipsSEFrameLowering:: +restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + + if (STI.inMicroMipsMode()) { + MachineFunction *MF = MBB.getParent(); + const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); + bool AtStart = MI == MBB.begin(); + MachineBasicBlock::iterator BeforeI = MI; + unsigned Counter = 0; + unsigned Size = CSI.size(); + int FirstIndx = 0; + + if (!AtStart) + --BeforeI; + + for (int i = Size - 1; i >= 0; --i) { + unsigned Reg = CSI[i].getReg(); + unsigned NextReg = i ? CSI[i - 1].getReg() : 0; + + if (Reg == Mips::S0) { + FirstIndx = i; + Counter++; + } else if (NextReg == Reg + 1 || NextReg == Mips::FP || + NextReg == Mips::RA) { + Counter++; + } else if (Counter) { + // Emit SWM instruction. + BuildMultipleMemAccess(MBB, MI, CSI, FirstIndx, Counter, + Mips::LWM32_MM); + Counter = 0; + } else { + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); + } + + assert(MI != MBB.begin() && + "loadRegFromStackSlot didn't insert any code!"); + // Insert in reverse order. loadRegFromStackSlot can insert + // multiple instructions. + if (AtStart) + MI = MBB.begin(); + else { + MI = BeforeI; + ++MI; + } + } + return true; + } + + return false; +} + bool MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); Index: test/CodeGen/Mips/micromips-swm-lwm.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/micromips-swm-lwm.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ +; RUN: -relocation-model=pic -O3 < %s | FileCheck %s + +@g1 = global i32 0, align 4 +@g2 = global i32 0, align 4 +@g3 = global i32 0, align 4 +@g4 = global i32 0, align 4 + +define i32 @_Z3fooiiii(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) #0 { +entry: + %add = add nsw i32 %arg2, %arg1 + %add1 = add nsw i32 %add, %arg3 + %add2 = add nsw i32 %add1, %arg4 + %0 = load i32* @g1, align 4, !tbaa !1 + %add3 = add nsw i32 %add2, %0 + %1 = load i32* @g2, align 4, !tbaa !1 + %add4 = add nsw i32 %add3, %1 + %2 = load i32* @g3, align 4, !tbaa !1 + %add5 = add nsw i32 %add4, %2 + %3 = load i32* @g4, align 4, !tbaa !1 + %add6 = add nsw i32 %add5, %3 + %call = tail call i32 @_Z3bariiii(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) + %add7 = add nsw i32 %add6, %call + ret i32 %add7 +} + +declare i32 @_Z3bariiii(i32, i32, i32, i32) #0 + +!0 = metadata !{metadata !"clang version 3.4 (195122)"} +!1 = metadata !{metadata !2, metadata !2, i64 0} +!2 = metadata !{metadata !"int", metadata !3, i64 0} +!3 = metadata !{metadata !"omnipotent char", metadata !4, i64 0} +!4 = metadata !{metadata !"Simple C/C++ TBAA"} + +; CHECK: swm32 +; CHECK: lwm32 +