Index: lib/Target/ARM/ARMBaseRegisterInfo.h =================================================================== --- lib/Target/ARM/ARMBaseRegisterInfo.h +++ lib/Target/ARM/ARMBaseRegisterInfo.h @@ -39,17 +39,71 @@ } // end namespace ARMRI +struct SpillAreaProperty { + bool AllowDiscreteRegs; + unsigned PushMultiThumb; + unsigned PushMultiARM; + unsigned PushOneThumb; + unsigned PushOneARM; + unsigned PopMultiThumb; + unsigned PopMultiARM; + unsigned PopOneThumb; + unsigned PopOneARM; +}; + +#define DEF_PROPERTIES \ + /* General purpose registers spilled/restored alongside LR/PC */ \ + DEF_PROPERTY( \ + /*enumerator*/ GPRCS1Area, /*AllowDiscreteRegs=*/true, \ + /*PushMultiThumb=*/ARM::t2STMDB_UPD, /*PushMultiARM=*/ARM::STMDB_UPD, \ + /*PushOneThumb*/ ARM::t2STR_PRE, /*PushOneARM=*/ARM::STR_PRE_IMM, \ + /*PopMultiThumb=*/ARM::t2LDMIA_UPD, /*PopMultiARM=*/ARM::LDMIA_UPD, \ + /*PopOneThumb=*/ARM::t2LDR_POST, /*PopOneARM=*/ARM::LDR_POST_IMM), \ + \ + /* General purpose registers spilled/restored separately from LR/PC */ \ + DEF_PROPERTY( \ + /*enumerator*/ GPRCS2Area, /*AllowDiscreteRegs=*/true, \ + /*PushMultiThumb=*/ARM::t2STMDB_UPD, /*PushMultiARM=*/ARM::STMDB_UPD, \ + /*PushOneThumb*/ ARM::t2STR_PRE, /*PushOneARM=*/ARM::STR_PRE_IMM, \ + /*PopMultiThumb=*/ARM::t2LDMIA_UPD, /*PopMultiARM=*/ARM::LDMIA_UPD, \ + /*PopOneThumb=*/ARM::t2LDR_POST, /*PopOneARM=*/ARM::LDR_POST_IMM), \ + \ + /* VFP registers without extra SP alignment requirement */ \ + DEF_PROPERTY( \ + /*enumerator*/ DPRCS1Area, /*AllowDiscreteRegs=*/false, \ + /*PushMultiThumb=*/ARM::VSTMDDB_UPD, /*PushMultiARM=*/ARM::VSTMDDB_UPD, \ + /*PushOneThumb*/ 0, /*PushOneARM=*/0, \ + /*PopMultiThumb=*/ARM::VLDMDIA_UPD, /*PopMultiARM=*/ARM::VLDMDIA_UPD, \ + /*PopOneThumb=*/0, /*PopOneARM=*/0), \ + \ + /* VFP registers requiring 16-byte SP alignment (see -align-neon-spills) */ \ + DEF_PROPERTY( \ + /*enumerator*/ DPRCS2Area, /*AllowDiscreteRegs=*/false, \ + /*PushMultiThumb=*/0, /*PushMultiARM=*/0, \ + /*PushOneThumb*/ 0, /*PushOneARM=*/0, \ + /*PopMultiThumb=*/0, /*PopMultiARM=*/0, \ + /*PopOneThumb=*/0, /*PopOneARM=*/0) + /// Sets of register to be pushed/poped together when spilling/restoring /// callee-saved registers. +#define DEF_PROPERTY(enumerator, AllowDiscreteRegs, PushMultiThumb, \ + PushMultiARM, PushOneThumb, PushOneARM, PopMultiThumb, \ + PopMultiARM, PopOneThumb, PopOneARM) \ + enumerator enum SpillArea { - GPRCS1Area, // GP registers spilled/restored alongside LR/PC - GPRCS2Area, // GP registers spilled/restored separately from LR/PC - DPRCS1Area, // VFP registers without extra SP alignment requirement - DPRCS2Area, // VFP registers requiring 16-byte SP alignment (see - // -align-neon-spills) + DEF_PROPERTIES, UnknownCSArea, // Unexpected callee-saved registers CSMaxArea = UnknownCSArea }; +#undef DEF_PROPERTY + +#define DEF_PROPERTY(enumerator, AllowDiscreteRegs, PushMultiThumb, \ + PushMultiARM, PushOneThumb, PushOneARM, PopMultiThumb, \ + PopMultiARM, PopOneThumb, PopOneARM) \ + {AllowDiscreteRegs, PushMultiThumb, PushMultiARM, PushOneThumb, PushOneARM, \ + PopMultiThumb, PopMultiARM, PopOneThumb, PopOneARM} +const std::array SpillAreaProperties = { + {DEF_PROPERTIES}}; /// getRegSpillArea - Returns which sets of registers Reg should be /// pushed/poped with, as a SpillArea enumerator. SplitGPRSpillArea Index: lib/Target/ARM/ARMFrameLowering.h =================================================================== --- lib/Target/ARM/ARMFrameLowering.h +++ lib/Target/ARM/ARMFrameLowering.h @@ -66,12 +66,10 @@ private: void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const std::vector &CSI, unsigned StmOpc, - unsigned StrOpc, bool NoGap, enum SpillArea SpillArea, - unsigned MIFlags = 0) const; + const std::vector &CSI, + enum SpillArea SpillArea, unsigned MIFlags = 0) const; void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - std::vector &CSI, unsigned LdmOpc, - unsigned LdrOpc, bool isVarArg, bool NoGap, + std::vector &CSI, bool isVarArg, enum SpillArea SpillArea) const; MachineBasicBlock::iterator Index: lib/Target/ARM/ARMFrameLowering.cpp =================================================================== --- lib/Target/ARM/ARMFrameLowering.cpp +++ lib/Target/ARM/ARMFrameLowering.cpp @@ -911,8 +911,7 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI, - unsigned StmOpc, unsigned StrOpc, - bool NoGap, enum SpillArea SpillArea, + enum SpillArea SpillArea, unsigned MIFlags) const { MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo(); @@ -920,6 +919,12 @@ const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); bool SplitFramePushPop = STI.splitFramePushPop(MF); unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs(); + const struct SpillAreaProperty SpillAreaProperty = + SpillAreaProperties.at(SpillArea); + unsigned StmOpc = AFI->isThumbFunction() ? SpillAreaProperty.PushMultiThumb + : SpillAreaProperty.PushMultiARM; + unsigned StrOpc = AFI->isThumbFunction() ? SpillAreaProperty.PushOneThumb + : SpillAreaProperty.PushOneARM; DebugLoc DL; @@ -939,10 +944,10 @@ bool isLiveIn = MRI.isLiveIn(Reg); if (!isLiveIn && !MRI.isReserved(Reg)) MBB.addLiveIn(Reg); - // If NoGap is true, push consecutive registers and then leave the rest - // for other instructions. e.g. + // If spill area only support consecutive registers, push consecutive + // registers and then leave the rest for other instructions. e.g. // vpush {d8, d10, d11} -> vpush {d8}, vpush {d10, d11} - if (NoGap && LastReg && LastReg != Reg-1) + if (!SpillAreaProperty.AllowDiscreteRegs && LastReg && LastReg != Reg - 1) break; LastReg = Reg; // Do not set a kill flag on values that are also marked as live-in. This @@ -989,8 +994,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, std::vector &CSI, - unsigned LdmOpc, unsigned LdrOpc, - bool isVarArg, bool NoGap, + bool isVarArg, enum SpillArea SpillArea) const { MachineFunction &MF = *MBB.getParent(); const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); @@ -998,6 +1002,12 @@ ARMFunctionInfo *AFI = MF.getInfo(); bool SplitFramePushPop = STI.splitFramePushPop(MF); unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs(); + const struct SpillAreaProperty SpillAreaProperty = + SpillAreaProperties.at(SpillArea); + unsigned LdmOpc = AFI->isThumbFunction() ? SpillAreaProperty.PopMultiThumb + : SpillAreaProperty.PopMultiARM; + unsigned LdrOpc = AFI->isThumbFunction() ? SpillAreaProperty.PopOneThumb + : SpillAreaProperty.PopOneARM; DebugLoc DL; bool isTailCall = false; bool isInterrupt = false; @@ -1039,10 +1049,10 @@ // Fold the return instruction into the LDM. } - // If NoGap is true, pop consecutive registers and then leave the rest - // for other instructions. e.g. + // If spill area only support consecutive registers, pop consecutive + // registers and then leave the rest for other instructions. e.g. // vpop {d8, d10, d11} -> vpop {d8}, vpop {d10, d11} - if (NoGap && LastReg && LastReg != Reg-1) + if (!SpillAreaProperty.AllowDiscreteRegs && LastReg && LastReg != Reg - 1) break; LastReg = Reg; @@ -1372,17 +1382,10 @@ MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo(); - unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD; - unsigned PushOneOpc = AFI->isThumbFunction() ? - ARM::t2STR_PRE : ARM::STR_PRE_IMM; - unsigned FltOpc = ARM::VSTMDDB_UPD; unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs(); - emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, GPRCS1Area, - MachineInstr::FrameSetup); - emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, GPRCS2Area, - MachineInstr::FrameSetup); - emitPushInst(MBB, MI, CSI, FltOpc, 0, true, DPRCS1Area, - MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, GPRCS1Area, MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, GPRCS2Area, MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, DPRCS1Area, MachineInstr::FrameSetup); // The code above does not insert spill code for the aligned DPRCS2 registers. // The stack realignment code will be inserted between the push instructions @@ -1410,12 +1413,9 @@ if (NumAlignedDPRCS2Regs) emitAlignedDPRCS2Restores(MBB, MI, NumAlignedDPRCS2Regs, CSI, TRI); - unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD; - unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST :ARM::LDR_POST_IMM; - unsigned FltOpc = ARM::VLDMDIA_UPD; - emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, DPRCS1Area); - emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, GPRCS2Area); - emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, GPRCS1Area); + emitPopInst(MBB, MI, CSI, isVarArg, DPRCS1Area); + emitPopInst(MBB, MI, CSI, isVarArg, GPRCS2Area); + emitPopInst(MBB, MI, CSI, isVarArg, GPRCS1Area); return true; }