Index: lib/Target/PowerPC/PPCInstrInfo.h =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.h +++ lib/Target/PowerPC/PPCInstrInfo.h @@ -109,16 +109,18 @@ unsigned SetCR : 1; }; +#define NUM_OPCODES_FOR_SPILL 15 + class PPCSubtarget; class PPCInstrInfo : public PPCGenInstrInfo { PPCSubtarget &Subtarget; const PPCRegisterInfo RI; - bool StoreRegToStackSlot(MachineFunction &MF, - unsigned SrcReg, bool isKill, int FrameIdx, - const TargetRegisterClass *RC, - SmallVectorImpl &NewMIs, - bool &NonRI, bool &SpillsVRS) const; + static const unsigned OpcodesForSpill[2][NUM_OPCODES_FOR_SPILL]; + + void StoreRegToStackSlot(MachineFunction &MF, unsigned SrcReg, bool isKill, + int FrameIdx, const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs) const; bool LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL, unsigned DestReg, int FrameIdx, const TargetRegisterClass *RC, @@ -251,6 +253,9 @@ const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override; + unsigned getOpcodeForSpill(unsigned Reg, + const TargetRegisterClass *RC = nullptr) const; + bool reverseBranchCondition(SmallVectorImpl &Cond) const override; Index: lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.cpp +++ lib/Target/PowerPC/PPCInstrInfo.cpp @@ -71,6 +71,35 @@ UseOldLatencyCalc("ppc-old-latency-calc", cl::Hidden, cl::desc("Use the old (incorrect) instruction latency calculation")); +// Index into the OpcodesForSpill array +enum OpcodesForSpillKey { + PPC_STW, + PPC_STD, + PPC_STFD, + PPC_STFS, + PPC_SPILL_CR, + PPC_SPILL_CRBIT, + PPC_STVX, + PPC_STXVD2X, + PPC_STXSDX, + PPC_STXSSPX, + PPC_SPILL_VRSAVE, + PPC_QVSTFDX, + PPC_QVSTFSXs, + PPC_QVSTFDXb, + PPC_SPILLTOVSR_ST +}; + +const unsigned PPCInstrInfo::OpcodesForSpill[2][NUM_OPCODES_FOR_SPILL] = { + // Power 8 + {PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, + PPC::STVX, PPC::STXVD2X, PPC::STXSDX, PPC::STXSSPX, PPC::SPILL_VRSAVE, + PPC::QVSTFDX, PPC::QVSTFSXs, PPC::QVSTFDXb, PPC::SPILLTOVSR_ST}, + // Power 9 + {PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, + PPC::STVX, PPC::STXV, PPC::DFSTOREf64, PPC::DFSTOREf32, PPC::SPILL_VRSAVE, + PPC::QVSTFDX, PPC::QVSTFSXs, PPC::QVSTFDXb, PPC::SPILLTOVSR_ST}}; + // Pin the vtable to this file. void PPCInstrInfo::anchor() {} @@ -329,31 +358,19 @@ unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const { - // Note: This list must be kept consistent with StoreRegToStackSlot. - switch (MI.getOpcode()) { - default: break; - case PPC::STD: - case PPC::STW: - case PPC::STFS: - case PPC::STFD: - case PPC::SPILL_CR: - case PPC::SPILL_CRBIT: - case PPC::STVX: - case PPC::STXVD2X: - case PPC::STXV: - case PPC::QVSTFDX: - case PPC::QVSTFSXs: - case PPC::QVSTFDXb: - case PPC::SPILL_VRSAVE: - case PPC::SPILLTOVSR_ST: - // Check for the operands added by addFrameReference (the immediate is the - // offset which defaults to 0). - if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() && - MI.getOperand(2).isFI()) { - FrameIndex = MI.getOperand(2).getIndex(); - return MI.getOperand(0).getReg(); + int ArchIndex = Subtarget.hasP9Vector() ? 1 : 0; + unsigned Opcode = MI.getOpcode(); + + for (unsigned i = 0; i < NUM_OPCODES_FOR_SPILL; i++) { + if (OpcodesForSpill[ArchIndex][i] == Opcode) { + // Check for the operands added by addFrameReference (the immediate is the + // offset which defaults to 0). + if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() && + MI.getOperand(2).isFI()) { + FrameIndex = MI.getOperand(2).getIndex(); + return MI.getOperand(0).getReg(); + } } - break; } return 0; } @@ -1000,129 +1017,124 @@ BuildMI(MBB, I, DL, MCID, DestReg).addReg(SrcReg, getKillRegState(KillSrc)); } -// This function returns true if a CR spill is necessary and false otherwise. -bool -PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF, - unsigned SrcReg, bool isKill, - int FrameIdx, - const TargetRegisterClass *RC, - SmallVectorImpl &NewMIs, - bool &NonRI, bool &SpillsVRS) const{ - // Note: If additional store instructions are added here, - // update isStoreToStackSlot. - - DebugLoc DL; - if (PPC::GPRCRegClass.hasSubClassEq(RC) || - PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::G8RCRegClass.hasSubClassEq(RC) || - PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::F8RCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFD)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::F4RCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFS)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::CRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CR)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - return true; - } else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CRBIT)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - return true; - } else if (PPC::VRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STVX)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) { - unsigned Op = Subtarget.hasP9Vector() ? PPC::STXV : PPC::STXVD2X; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Op)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) { - unsigned Opc = Subtarget.hasP9Vector() ? PPC::DFSTOREf64 : PPC::STXSDX; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opc)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) { - unsigned Opc = Subtarget.hasP9Vector() ? PPC::DFSTOREf32 : PPC::STXSSPX; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opc)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) { - assert(Subtarget.isDarwin() && - "VRSAVE only needs spill/restore on Darwin"); - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_VRSAVE)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - SpillsVRS = true; - } else if (PPC::QFRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVSTFDX)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::QSRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVSTFSXs)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::QBRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVSTFDXb)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILLTOVSR_ST)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); +unsigned PPCInstrInfo::getOpcodeForSpill(unsigned Reg, + const TargetRegisterClass *RC) const { + int ArchIndex = Subtarget.hasP9Vector() ? 1 : 0; + int OpcodeIndex = 0; + + if (RC != nullptr) { + if (PPC::GPRCRegClass.hasSubClassEq(RC) || + PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STW; + } else if (PPC::G8RCRegClass.hasSubClassEq(RC) || + PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STD; + } else if (PPC::F8RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STFD; + } else if (PPC::F4RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STFS; + } else if (PPC::CRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_SPILL_CR; + } else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_SPILL_CRBIT; + } else if (PPC::VRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STVX; + } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STXVD2X; + } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STXSDX; + } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_STXSSPX; + } else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_SPILL_VRSAVE; + } else if (PPC::QFRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_QVSTFDX; + } else if (PPC::QSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_QVSTFSXs; + } else if (PPC::QBRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_QVSTFDXb; + } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = PPC_SPILLTOVSR_ST; + } else { + llvm_unreachable("Unknown regclass!"); + } } else { - llvm_unreachable("Unknown regclass!"); + if (PPC::GPRCRegClass.contains(Reg) || + PPC::GPRC_NOR0RegClass.contains(Reg)) { + OpcodeIndex = PPC_STW; + } else if (PPC::G8RCRegClass.contains(Reg) || + PPC::G8RC_NOX0RegClass.contains(Reg)) { + OpcodeIndex = PPC_STD; + } else if (PPC::F8RCRegClass.contains(Reg)) { + OpcodeIndex = PPC_STFD; + } else if (PPC::F4RCRegClass.contains(Reg)) { + OpcodeIndex = PPC_STFS; + } else if (PPC::CRRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_SPILL_CR; + } else if (PPC::CRBITRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_SPILL_CRBIT; + } else if (PPC::VRRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_STVX; + } else if (PPC::VSRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_STXVD2X; + } else if (PPC::VSFRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_STXSDX; + } else if (PPC::VSSRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_STXSSPX; + } else if (PPC::VRSAVERCRegClass.contains(Reg)) { + OpcodeIndex = PPC_SPILL_VRSAVE; + } else if (PPC::QFRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_QVSTFDX; + } else if (PPC::QSRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_QVSTFSXs; + } else if (PPC::QBRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_QVSTFDXb; + } else if (PPC::SPILLTOVSRRCRegClass.contains(Reg)) { + OpcodeIndex = PPC_SPILLTOVSR_ST; + } else { + llvm_unreachable("Unknown regclass!"); + } } - - return false; + return OpcodesForSpill[ArchIndex][OpcodeIndex]; } -void -PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned SrcReg, bool isKill, int FrameIdx, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { - MachineFunction &MF = *MBB.getParent(); - SmallVector NewMIs; +void PPCInstrInfo::StoreRegToStackSlot( + MachineFunction &MF, unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs) const { + unsigned Opcode = getOpcodeForSpill(0, RC); + DebugLoc DL; PPCFunctionInfo *FuncInfo = MF.getInfo(); FuncInfo->setHasSpills(); + NewMIs.push_back(addFrameReference( + BuildMI(MF, DL, get(Opcode)).addReg(SrcReg, getKillRegState(isKill)), + FrameIdx)); + + if (Opcode == PPC::SPILL_CR || Opcode == PPC::SPILL_CRBIT) + FuncInfo->setSpillsCR(); + + if (Opcode == PPC::SPILL_VRSAVE) + FuncInfo->setSpillsVRSAVE(); + + if (Opcode == PPC::STVX || Opcode == PPC::STXV || Opcode == PPC::STXVD2X || + Opcode == PPC::DFSTOREf64 || Opcode == PPC::STXSDX || + Opcode == PPC::DFSTOREf32 || Opcode == PPC::STXSSPX || + Opcode == PPC::QVSTFDX || Opcode == PPC::QVSTFSXs || + Opcode == PPC::QVSTFDXb) + FuncInfo->setHasNonRISpills(); +} + +void PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, + int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + MachineFunction &MF = *MBB.getParent(); + SmallVector NewMIs; + // We need to avoid a situation in which the value from a VRRC register is // spilled using an Altivec instruction and reloaded into a VSRC register // using a VSX instruction. The issue with this is that the VSX @@ -1132,16 +1144,7 @@ // VSX instruction. RC = updatedRC(RC); - bool NonRI = false, SpillsVRS = false; - if (StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs, - NonRI, SpillsVRS)) - FuncInfo->setSpillsCR(); - - if (SpillsVRS) - FuncInfo->setSpillsVRSAVE(); - - if (NonRI) - FuncInfo->setHasNonRISpills(); + StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs); for (unsigned i = 0, e = NewMIs.size(); i != e; ++i) MBB.insert(MI, NewMIs[i]); Index: lib/Target/PowerPC/PPCRegisterInfo.h =================================================================== --- lib/Target/PowerPC/PPCRegisterInfo.h +++ lib/Target/PowerPC/PPCRegisterInfo.h @@ -92,9 +92,7 @@ return true; } - bool requiresFrameIndexScavenging(const MachineFunction &MF) const override { - return true; - } + bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override { return true; Index: lib/Target/PowerPC/PPCRegisterInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCRegisterInfo.cpp +++ lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -301,6 +301,43 @@ return Reserved; } +bool PPCRegisterInfo::requiresFrameIndexScavenging( + const MachineFunction &MF) const { + const PPCSubtarget &Subtarget = MF.getSubtarget(); + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const std::vector &Info = MFI.getCalleeSavedInfo(); + // Get the instruction info. + const PPCInstrInfo &TII = *Subtarget.getInstrInfo(); + bool RequiresScavenging = false; + + // If the saved info is invalid we have to default to true for safety. + if (!MFI.isCalleeSavedInfoValid()) + return true; + + // The saved info is valid so it can be traversed. + // Checking for registers that need saving that do not have load or store + // forms where the address offset is an immediate. + for (unsigned i = 0; i < Info.size(); i++) { + int FrIdx = Info[i].getFrameIdx(); + unsigned Reg = Info[i].getReg(); + + // We only care about negative frame indexes. + if (FrIdx >= 0) + continue; + + unsigned Opcode = TII.getOpcodeForSpill(Reg); + + if (Opcode == PPC::STVX || Opcode == PPC::STXVD2X || + Opcode == PPC::STXSDX || Opcode == PPC::STXSSPX || + Opcode == PPC::SPILL_VRSAVE || Opcode == PPC::QVSTFDX || + Opcode == PPC::QVSTFSXs || Opcode == PPC::QVSTFDXb || + Opcode == PPC::SPILLTOVSR_ST) { + return true; + } + } + return false; +} + bool PPCRegisterInfo::isCallerPreservedPhysReg(unsigned PhysReg, const MachineFunction &MF) const { assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));