Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -486,7 +486,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; @@ -494,7 +494,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,47 @@ 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(); + 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); + MachineInstrBuilder MIB = + BuildMI(*(MI->getParent()), 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: @@ -573,28 +614,125 @@ MachineBasicBlock *EntryBlock = MF->begin(); const TargetInstrInfo &TII = *STI.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 sregs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, + Mips::S5, Mips::S6, Mips::S7, Mips::FP}; + unsigned Size = CSI.size(); + int FirstIndx = -1; + bool Multi = false; + + for (int i = Size - 1; i >= 0; --i) { + 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; + Multi = true; + } else if (Reg != sregs[FirstIndx - i] && Reg != Mips::RA) + Multi = false; + + if (FirstIndx >= 0 && (Multi == false || i == 0)) { + // Emit SWM instruction. + int Count = FirstIndx - i; + BuildMultipleMemAccess(MBB, MI, CSI, FirstIndx, + Multi ? Count + 1 : Count, Mips::SWM32_MM); + FirstIndx = -1; + } + + if (Multi == false || FirstIndx == 0) { + // 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()) { + unsigned sregs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, + Mips::S5, Mips::S6, Mips::S7, Mips::FP}; + MachineFunction *MF = MBB.getParent(); + const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); + bool AtStart = MI == MBB.begin(); + MachineBasicBlock::iterator BeforeI = MI; + unsigned Size = CSI.size(); + int FirstIndx = 0; + bool Multi = false; + + if (!AtStart) + --BeforeI; + + for (int i = Size - 1; i >= 0; --i) { + unsigned Reg = CSI[i].getReg(); + + if (Reg == Mips::S0) { + FirstIndx = i; + Multi = true; + } else if (Reg != sregs[FirstIndx - i] && Reg != Mips::RA) + Multi = false; + + if (FirstIndx >= 0 && (Multi == false || i == 0)) { + // Emit SWM instruction. + int Count = FirstIndx - i; + BuildMultipleMemAccess(MBB, MI, CSI, FirstIndx, + Multi ? Count + 1 : Count, Mips::LWM32_MM); + FirstIndx = -1; + } + + if (Multi == false || FirstIndx == 0) { + 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,31 @@ +; 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 + %add3 = add nsw i32 %add2, %0 + %1 = load i32* @g2, align 4 + %add4 = add nsw i32 %add3, %1 + %2 = load i32* @g3, align 4 + %add5 = add nsw i32 %add4, %2 + %3 = load i32* @g4, align 4 + %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 + +; CHECK: swm32 +; CHECK: lwm32 +