Index: lib/Target/PowerPC/PPCInstrInfo.h =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.h +++ lib/Target/PowerPC/PPCInstrInfo.h @@ -114,11 +114,9 @@ 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; + 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, @@ -128,6 +126,7 @@ unsigned ConstantOpNo, int64_t Imm) const; MachineInstr *getConstantDefMI(MachineInstr &MI, unsigned &ConstOp, bool &SeenIntermediateUse) const; + const unsigned *getOpcodesForSpillArray(bool ArchPower9) const; virtual void anchor(); protected: @@ -251,6 +250,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,26 @@ 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, + PPC_LAST_OPCODE_SPILL // This must be last on the enum +}; + // Pin the vtable to this file. void PPCInstrInfo::anchor() {} @@ -329,31 +349,20 @@ 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(); + unsigned Opcode = MI.getOpcode(); + const unsigned *OpcodesForSpill = + getOpcodesForSpillArray(Subtarget.hasP9Vector()); + + for (unsigned i = 0; i < PPC_LAST_OPCODE_SPILL; i++) { + if (OpcodesForSpill[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 +1009,125 @@ 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 { + const unsigned *OpcodesForSpill = + getOpcodesForSpillArray(Subtarget.hasP9Vector()); + 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[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 +1137,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]); @@ -2313,6 +2309,21 @@ return ConstOp == ~0U ? nullptr : DefMI; } + +const unsigned *PPCInstrInfo::getOpcodesForSpillArray(bool ArchPower9) const { + static const unsigned OpcodesForSpill[2][PPC_LAST_OPCODE_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}}; + + return OpcodesForSpill[ArchPower9]; +} + // If this instruction has an immediate form and one of its operands is a // result of a load-immediate, convert it to the immediate form if the constant // is in range.