diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:11:55 +0000 |
| commit | 5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch) | |
| tree | 1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/llvm/lib/Target/PowerPC | |
| parent | 3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff) | |
| parent | 312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/PowerPC')
55 files changed, 2564 insertions, 1905 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 4f93cdaaa137..8108cfa521c8 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -105,10 +105,9 @@ class PPCAsmParser : public MCTargetAsmParser { bool MatchRegisterName(MCRegister &RegNo, int64_t &IntVal); - bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) override; - OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) override; + bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; + ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, + SMLoc &EndLoc) override; const MCExpr *ExtractModifierFromExpr(const MCExpr *E, PPCMCExpr::VariantKind &Variant); @@ -887,6 +886,26 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, Inst = TmpInst; break; } + case PPC::PLA8: + case PPC::PLA: { + MCInst TmpInst; + TmpInst.setOpcode(Opcode == PPC::PLA ? PPC::PADDI : PPC::PADDI8); + TmpInst.addOperand(Inst.getOperand(0)); + TmpInst.addOperand(Inst.getOperand(1)); + TmpInst.addOperand(Inst.getOperand(2)); + Inst = TmpInst; + break; + } + case PPC::PLA8pc: + case PPC::PLApc: { + MCInst TmpInst; + TmpInst.setOpcode(Opcode == PPC::PLApc ? PPC::PADDIpc : PPC::PADDI8pc); + TmpInst.addOperand(Inst.getOperand(0)); + TmpInst.addOperand(MCOperand::createImm(0)); + TmpInst.addOperand(Inst.getOperand(1)); + Inst = TmpInst; + break; + } case PPC::SUBI: { MCInst TmpInst; TmpInst.setOpcode(PPC::ADDI); @@ -896,6 +915,15 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, Inst = TmpInst; break; } + case PPC::PSUBI: { + MCInst TmpInst; + TmpInst.setOpcode(PPC::PADDI); + TmpInst.addOperand(Inst.getOperand(0)); + TmpInst.addOperand(Inst.getOperand(1)); + addNegOperand(TmpInst, Inst.getOperand(2), getContext()); + Inst = TmpInst; + break; + } case PPC::SUBIS: { MCInst TmpInst; TmpInst.setOpcode(PPC::ADDIS); @@ -1320,24 +1348,23 @@ bool PPCAsmParser::MatchRegisterName(MCRegister &RegNo, int64_t &IntVal) { return false; } -bool PPCAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, +bool PPCAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) { - if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) + if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess()) return TokError("invalid register name"); return false; } -OperandMatchResultTy PPCAsmParser::tryParseRegister(MCRegister &RegNo, - SMLoc &StartLoc, - SMLoc &EndLoc) { +ParseStatus PPCAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, + SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); - RegNo = 0; + Reg = PPC::NoRegister; int64_t IntVal; - if (MatchRegisterName(RegNo, IntVal)) - return MatchOperand_NoMatch; - return MatchOperand_Success; + if (MatchRegisterName(Reg, IntVal)) + return ParseStatus::NoMatch; + return ParseStatus::Success; } /// Extract \code @l/@ha \endcode modifier from expression. Recursively scan @@ -1717,7 +1744,7 @@ bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) { ParseDirectiveAbiVersion(DirectiveID.getLoc()); else if (IDVal == ".localentry") ParseDirectiveLocalEntry(DirectiveID.getLoc()); - else if (IDVal.startswith(".gnu_attribute")) + else if (IDVal.starts_with(".gnu_attribute")) ParseGNUAttribute(DirectiveID.getLoc()); else return true; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp index 3913ede3dc18..99ecc3fe360d 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.cpp @@ -36,9 +36,10 @@ struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler { : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {} void assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign VA) override; + const CCValAssign &VA) override; void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, - MachinePointerInfo &MPO, CCValAssign &VA) override; + const MachinePointerInfo &MPO, + const CCValAssign &VA) override; Register getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO, ISD::ArgFlagsTy Flags) override; @@ -48,7 +49,7 @@ struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler { } // namespace void OutgoingArgHandler::assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign VA) { + const CCValAssign &VA) { MIB.addUse(PhysReg, RegState::Implicit); Register ExtReg = extendRegister(ValVReg, VA); MIRBuilder.buildCopy(PhysReg, ExtReg); @@ -56,8 +57,8 @@ void OutgoingArgHandler::assignValueToReg(Register ValVReg, Register PhysReg, void OutgoingArgHandler::assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, - MachinePointerInfo &MPO, - CCValAssign &VA) { + const MachinePointerInfo &MPO, + const CCValAssign &VA) { llvm_unreachable("unimplemented"); } @@ -143,18 +144,18 @@ bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, void PPCIncomingValueHandler::assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign VA) { + const CCValAssign &VA) { markPhysRegUsed(PhysReg); IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); } -void PPCIncomingValueHandler::assignValueToAddress(Register ValVReg, - Register Addr, LLT MemTy, - MachinePointerInfo &MPO, - CCValAssign &VA) { +void PPCIncomingValueHandler::assignValueToAddress( + Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO, + const CCValAssign &VA) { // define a lambda expression to load value - auto BuildLoad = [](MachineIRBuilder &MIRBuilder, MachinePointerInfo &MPO, - LLT MemTy, const DstOp &Res, Register Addr) { + auto BuildLoad = [](MachineIRBuilder &MIRBuilder, + const MachinePointerInfo &MPO, LLT MemTy, + const DstOp &Res, Register Addr) { MachineFunction &MF = MIRBuilder.getMF(); auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, inferAlignFromPtrInfo(MF, MPO)); diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h index cc2cb7b26e84..17e8c57e563f 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCCallLowering.h @@ -46,10 +46,11 @@ public: private: void assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign VA) override; + const CCValAssign &VA) override; void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, - MachinePointerInfo &MPO, CCValAssign &VA) override; + const MachinePointerInfo &MPO, + const CCValAssign &VA) override; Register getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO, diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp index 25587b39b97f..6aeef145e307 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp @@ -12,6 +12,7 @@ #include "PPCRegisterBankInfo.h" #include "PPCRegisterInfo.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" @@ -289,8 +290,11 @@ bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI, const TargetRegisterInfo &TRI, unsigned Depth) const { unsigned Op = MI.getOpcode(); - if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MI.getIntrinsicID())) - return true; + + if (auto *GI = dyn_cast<GIntrinsic>(&MI)) { + if (isFPIntrinsic(GI->getIntrinsicID())) + return true; + } // Do we have an explicit floating point instruction? if (isPreISelGenericFloatingPointOpcode(Op)) diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h index c2a16c92ba85..1477fdca917d 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h @@ -37,9 +37,9 @@ protected: PMI_Min = PMI_GPR32, }; - static RegisterBankInfo::PartialMapping PartMappings[]; - static RegisterBankInfo::ValueMapping ValMappings[]; - static PartialMappingIdx BankIDToCopyMapIdx[]; + static const RegisterBankInfo::PartialMapping PartMappings[]; + static const RegisterBankInfo::ValueMapping ValMappings[]; + static const PartialMappingIdx BankIDToCopyMapIdx[]; /// Get the pointer to the ValueMapping representing the RegisterBank /// at \p RBIdx. diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index 89d04dbe378e..251737ed1275 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -87,7 +87,8 @@ protected: Triple TT; public: PPCAsmBackend(const Target &T, const Triple &TT) - : MCAsmBackend(TT.isLittleEndian() ? support::little : support::big), + : MCAsmBackend(TT.isLittleEndian() ? llvm::endianness::little + : llvm::endianness::big), TT(TT) {} unsigned getNumFixupKinds() const override { @@ -132,7 +133,7 @@ public: assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); - return (Endian == support::little + return (Endian == llvm::endianness::little ? InfosLE : InfosBE)[Kind - FirstTargetFixupKind]; } @@ -154,13 +155,15 @@ public: // from the fixup value. The Value has been "split up" into the appropriate // bitfields above. for (unsigned i = 0; i != NumBytes; ++i) { - unsigned Idx = Endian == support::little ? i : (NumBytes - 1 - i); + unsigned Idx = + Endian == llvm::endianness::little ? i : (NumBytes - 1 - i); Data[Offset + i] |= uint8_t((Value >> (Idx * 8)) & 0xff); } } bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target) override { + const MCValue &Target, + const MCSubtargetInfo *STI) override { MCFixupKind Kind = Fixup.getKind(); switch ((unsigned)Kind) { default: diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 1e58039582c2..6a72b7b9ad05 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -28,7 +28,7 @@ namespace { unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - bool needsRelocateWithSymbol(const MCSymbol &Sym, + bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, unsigned Type) const override; }; } @@ -456,7 +456,13 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, } break; case FK_Data_4: - Type = ELF::R_PPC_ADDR32; + switch (Modifier) { + case MCSymbolRefExpr::VK_DTPREL: + Type = ELF::R_PPC_DTPREL32; + break; + default: + Type = ELF::R_PPC_ADDR32; + } break; case FK_Data_2: Type = ELF::R_PPC_ADDR16; @@ -466,7 +472,8 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, return Type; } -bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, +bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &, + const MCSymbol &Sym, unsigned Type) const { switch (Type) { default: diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp index 2f03aa37745f..1eaa57e16260 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp @@ -17,11 +17,10 @@ // //===----------------------------------------------------------------------===// - #include "PPCELFStreamer.h" #include "PPCFixupKinds.h" -#include "PPCInstrInfo.h" #include "PPCMCCodeEmitter.h" +#include "PPCMCTargetDesc.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h index 7d786ac13bb9..10204b184a49 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.h @@ -13,7 +13,6 @@ #ifndef LLVM_LIB_TARGET_PPC_MCELFSTREAMER_PPCELFSTREAMER_H #define LLVM_LIB_TARGET_PPC_MCELFSTREAMER_PPCELFSTREAMER_H -#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCELFStreamer.h" #include <memory> diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp index 13480da4e731..9a4291c90408 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp @@ -13,14 +13,14 @@ #include "MCTargetDesc/PPCInstPrinter.h" #include "MCTargetDesc/PPCMCTargetDesc.h" #include "MCTargetDesc/PPCPredicates.h" -#include "PPCInstrInfo.h" -#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -484,7 +484,10 @@ void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo, if (!MI->getOperand(OpNo).isImm()) return printOperand(MI, OpNo, STI, O); - O << SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2); + uint64_t Imm = static_cast<uint64_t>(MI->getOperand(OpNo).getImm()) << 2; + if (!TT.isPPC64()) + Imm = static_cast<uint32_t>(Imm); + O << formatHex(Imm); } void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo, @@ -597,7 +600,8 @@ void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo, /// showRegistersWithPercentPrefix - Check if this register name should be /// printed with a percentage symbol as prefix. bool PPCInstPrinter::showRegistersWithPercentPrefix(const char *RegName) const { - if (!FullRegNamesWithPercent || TT.getOS() == Triple::AIX) + if ((!FullRegNamesWithPercent && !MAI.useFullRegisterNames()) || + TT.getOS() == Triple::AIX) return false; switch (RegName[0]) { @@ -614,10 +618,10 @@ bool PPCInstPrinter::showRegistersWithPercentPrefix(const char *RegName) const { /// getVerboseConditionalRegName - This method expands the condition register /// when requested explicitly or targetting Darwin. -const char *PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum, - unsigned RegEncoding) - const { - if (!FullRegNames) +const char * +PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum, + unsigned RegEncoding) const { + if (!FullRegNames && !MAI.useFullRegisterNames()) return nullptr; if (RegNum < PPC::CR0EQ || RegNum > PPC::CR7UN) return nullptr; @@ -637,7 +641,7 @@ const char *PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum, // showRegistersWithPrefix - This method determines whether registers // should be number-only or include the prefix. bool PPCInstPrinter::showRegistersWithPrefix() const { - return FullRegNamesWithPercent || FullRegNames; + return FullRegNamesWithPercent || FullRegNames || MAI.useFullRegisterNames(); } void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, @@ -646,8 +650,7 @@ void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, if (Op.isReg()) { unsigned Reg = Op.getReg(); if (!ShowVSRNumsAsVR) - Reg = PPCInstrInfo::getRegNumForOperand(MII.get(MI->getOpcode()), - Reg, OpNo); + Reg = PPC::getRegNumForOperand(MII.get(MI->getOpcode()), Reg, OpNo); const char *RegName; RegName = getVerboseConditionRegName(Reg, MRI.getEncodingValue(Reg)); @@ -656,7 +659,7 @@ void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, if (showRegistersWithPercentPrefix(RegName)) O << "%"; if (!showRegistersWithPrefix()) - RegName = PPCRegisterInfo::stripRegisterPrefix(RegName); + RegName = PPC::stripRegisterPrefix(RegName); O << RegName; return; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index a5dc0b45b13c..4716e37b3443 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -12,7 +12,6 @@ #include "PPCMCAsmInfo.h" #include "llvm/TargetParser/Triple.h" -#include <cassert> using namespace llvm; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp index da0174ce1982..910b5892d033 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -12,12 +12,14 @@ #include "PPCMCCodeEmitter.h" #include "MCTargetDesc/PPCFixupKinds.h" -#include "PPCInstrInfo.h" +#include "PPCMCTargetDesc.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorHandling.h" @@ -47,16 +49,108 @@ getDirectBrEncoding(const MCInst &MI, unsigned OpNo, if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); - const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo *>(&MCII); - unsigned Opcode = MI.getOpcode(); // Add a fixup for the branch target. Fixups.push_back(MCFixup::create(0, MO.getExpr(), - (InstrInfo->isNoTOCCallInstr(Opcode) + (isNoTOCCallInstr(MI) ? (MCFixupKind)PPC::fixup_ppc_br24_notoc : (MCFixupKind)PPC::fixup_ppc_br24))); return 0; } +/// Check if Opcode corresponds to a call instruction that should be marked +/// with the NOTOC relocation. +bool PPCMCCodeEmitter::isNoTOCCallInstr(const MCInst &MI) const { + unsigned Opcode = MI.getOpcode(); + if (!MCII.get(Opcode).isCall()) + return false; + + switch (Opcode) { + default: +#ifndef NDEBUG + llvm_unreachable("Unknown call opcode"); +#endif + return false; + case PPC::BL8_NOTOC: + case PPC::BL8_NOTOC_TLS: + case PPC::BL8_NOTOC_RM: + return true; +#ifndef NDEBUG + case PPC::BL8: + case PPC::BL: + case PPC::BL8_TLS: + case PPC::BL_TLS: + case PPC::BLA8: + case PPC::BLA: + case PPC::BCCL: + case PPC::BCCLA: + case PPC::BCL: + case PPC::BCLn: + case PPC::BL8_NOP: + case PPC::BL_NOP: + case PPC::BL8_NOP_TLS: + case PPC::BLA8_NOP: + case PPC::BCTRL8: + case PPC::BCTRL: + case PPC::BCCCTRL8: + case PPC::BCCCTRL: + case PPC::BCCTRL8: + case PPC::BCCTRL: + case PPC::BCCTRL8n: + case PPC::BCCTRLn: + case PPC::BL8_RM: + case PPC::BLA8_RM: + case PPC::BL8_NOP_RM: + case PPC::BLA8_NOP_RM: + case PPC::BCTRL8_RM: + case PPC::BCTRL8_LDinto_toc: + case PPC::BCTRL8_LDinto_toc_RM: + case PPC::BL8_TLS_: + case PPC::TCRETURNdi8: + case PPC::TCRETURNai8: + case PPC::TCRETURNri8: + case PPC::TAILBCTR8: + case PPC::TAILB8: + case PPC::TAILBA8: + case PPC::BCLalways: + case PPC::BLRL: + case PPC::BCCLRL: + case PPC::BCLRL: + case PPC::BCLRLn: + case PPC::BDZL: + case PPC::BDNZL: + case PPC::BDZLA: + case PPC::BDNZLA: + case PPC::BDZLp: + case PPC::BDNZLp: + case PPC::BDZLAp: + case PPC::BDNZLAp: + case PPC::BDZLm: + case PPC::BDNZLm: + case PPC::BDZLAm: + case PPC::BDNZLAm: + case PPC::BDZLRL: + case PPC::BDNZLRL: + case PPC::BDZLRLp: + case PPC::BDNZLRLp: + case PPC::BDZLRLm: + case PPC::BDNZLRLm: + case PPC::BL_RM: + case PPC::BLA_RM: + case PPC::BL_NOP_RM: + case PPC::BCTRL_RM: + case PPC::TCRETURNdi: + case PPC::TCRETURNai: + case PPC::TCRETURNri: + case PPC::BCTRL_LWZinto_toc: + case PPC::BCTRL_LWZinto_toc_RM: + case PPC::TAILBCTR: + case PPC::TAILB: + case PPC::TAILBA: + return false; +#endif + } +} + unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { @@ -372,7 +466,7 @@ get_crbitm_encoding(const MCInst &MI, unsigned OpNo, } // Get the index for this operand in this instruction. This is needed for -// computing the register number in PPCInstrInfo::getRegNumForOperand() for +// computing the register number in PPC::getRegNumForOperand() for // any instructions that use a different numbering scheme for registers in // different operands. static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) { @@ -397,8 +491,7 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); unsigned OpNo = getOpIdxForMO(MI, MO); unsigned Reg = - PPCInstrInfo::getRegNumForOperand(MCII.get(MI.getOpcode()), - MO.getReg(), OpNo); + PPC::getRegNumForOperand(MCII.get(MI.getOpcode()), MO.getReg(), OpNo); return CTX.getRegisterInfo()->getEncodingValue(Reg); } @@ -415,7 +508,8 @@ void PPCMCCodeEmitter::encodeInstruction(const MCInst &MI, // Output the constant in big/little endian byte order. unsigned Size = getInstSizeInBytes(MI); - support::endianness E = IsLittleEndian ? support::little : support::big; + llvm::endianness E = + IsLittleEndian ? llvm::endianness::little : llvm::endianness::big; switch (Size) { case 0: break; @@ -443,9 +537,7 @@ unsigned PPCMCCodeEmitter::getInstSizeInBytes(const MCInst &MI) const { } bool PPCMCCodeEmitter::isPrefixedInstruction(const MCInst &MI) const { - unsigned Opcode = MI.getOpcode(); - const PPCInstrInfo *InstrInfo = static_cast<const PPCInstrInfo*>(&MCII); - return InstrInfo->isPrefixed(Opcode); + return MCII.get(MI.getOpcode()).TSFlags & PPCII::Prefixed; } #include "PPCGenMCCodeEmitter.inc" diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h index 17a15ef18cb7..b57455718319 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h @@ -121,6 +121,10 @@ public: // Is this instruction a prefixed instruction. bool isPrefixedInstruction(const MCInst &MI) const; + + /// Check if Opcode corresponds to a call instruction that should be marked + /// with the NOTOC relocation. + bool isNoTOCCallInstr(const MCInst &MI) const; }; } // namespace llvm diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index 271f7ab757e1..a804dd823daa 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -57,6 +57,90 @@ using namespace llvm; #define GET_REGINFO_MC_DESC #include "PPCGenRegisterInfo.inc" +/// stripRegisterPrefix - This method strips the character prefix from a +/// register name so that only the number is left. Used by for linux asm. +const char *PPC::stripRegisterPrefix(const char *RegName) { + switch (RegName[0]) { + case 'a': + if (RegName[1] == 'c' && RegName[2] == 'c') + return RegName + 3; + break; + case 'f': + if (RegName[1] == 'p') + return RegName + 2; + [[fallthrough]]; + case 'r': + case 'v': + if (RegName[1] == 's') { + if (RegName[2] == 'p') + return RegName + 3; + return RegName + 2; + } + return RegName + 1; + case 'c': + if (RegName[1] == 'r') + return RegName + 2; + break; + case 'w': + // For wacc and wacc_hi + if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') { + if (RegName[4] == '_') + return RegName + 7; + else + return RegName + 4; + } + break; + case 'd': + // For dmr, dmrp, dmrrow, dmrrowp + if (RegName[1] == 'm' && RegName[2] == 'r') { + if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' && + RegName[6] == 'p') + return RegName + 7; + else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w') + return RegName + 6; + else if (RegName[3] == 'p') + return RegName + 4; + else + return RegName + 3; + } + break; + } + + return RegName; +} + +/// getRegNumForOperand - some operands use different numbering schemes +/// for the same registers. For example, a VSX instruction may have any of +/// vs0-vs63 allocated whereas an Altivec instruction could only have +/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual +/// register number needed for the opcode/operand number combination. +/// The operand number argument will be useful when we need to extend this +/// to instructions that use both Altivec and VSX numbering (for different +/// operands). +unsigned PPC::getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg, + unsigned OpNo) { + int16_t regClass = Desc.operands()[OpNo].RegClass; + switch (regClass) { + // We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31, + // VSX32-VSX63 during encoding/disassembling + case PPC::VSSRCRegClassID: + case PPC::VSFRCRegClassID: + if (PPC::isVFRegister(Reg)) + return PPC::VSX32 + (Reg - PPC::VF0); + break; + // We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31, + // VSX32-VSX63 during encoding/disassembling + case PPC::VSRCRegClassID: + if (PPC::isVRRegister(Reg)) + return PPC::VSX32 + (Reg - PPC::V0); + break; + // Other RegClass doesn't need mapping + default: + break; + } + return Reg; +} + PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} // Pin the vtable to this file. @@ -148,9 +232,10 @@ public: cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly()) ->getQualNameSymbol(); // On AIX, we have a region handle (symbol@m) and the variable offset - // (symbol@{gd|le}) for TLS variables, depending on the TLS model. + // (symbol@{gd|ie|le}) for TLS variables, depending on the TLS model. if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD || Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM || + Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE || Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE) OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@" << MCSymbolRefExpr::getVariantKindName(Kind) << '\n'; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h index 86ca1386fed9..16777725990a 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -26,6 +26,7 @@ namespace llvm { class MCAsmBackend; class MCCodeEmitter; class MCContext; +class MCInstrDesc; class MCInstrInfo; class MCObjectTargetWriter; class MCRegisterInfo; @@ -33,6 +34,24 @@ class MCSubtargetInfo; class MCTargetOptions; class Target; +namespace PPC { +/// stripRegisterPrefix - This method strips the character prefix from a +/// register name so that only the number is left. Used by for linux asm. +const char *stripRegisterPrefix(const char *RegName); + +/// getRegNumForOperand - some operands use different numbering schemes +/// for the same registers. For example, a VSX instruction may have any of +/// vs0-vs63 allocated whereas an Altivec instruction could only have +/// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual +/// register number needed for the opcode/operand number combination. +/// The operand number argument will be useful when we need to extend this +/// to instructions that use both Altivec and VSX numbering (for different +/// operands). +unsigned getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg, + unsigned OpNo); + +} // namespace PPC + MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx); @@ -102,11 +121,61 @@ static inline bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME) { return false; } -} // end namespace llvm +/// PPCII - This namespace holds all of the PowerPC target-specific +/// per-instruction flags. These must match the corresponding definitions in +/// PPC.td and PPCInstrFormats.td. +namespace PPCII { +enum { + // PPC970 Instruction Flags. These flags describe the characteristics of the + // PowerPC 970 (aka G5) dispatch groups and how they are formed out of + // raw machine instructions. -// Generated files will use "namespace PPC". To avoid symbol clash, -// undefine PPC here. PPC may be predefined on some hosts. -#undef PPC + /// PPC970_First - This instruction starts a new dispatch group, so it will + /// always be the first one in the group. + PPC970_First = 0x1, + + /// PPC970_Single - This instruction starts a new dispatch group and + /// terminates it, so it will be the sole instruction in the group. + PPC970_Single = 0x2, + + /// PPC970_Cracked - This instruction is cracked into two pieces, requiring + /// two dispatch pipes to be available to issue. + PPC970_Cracked = 0x4, + + /// PPC970_Mask/Shift - This is a bitmask that selects the pipeline type that + /// an instruction is issued to. + PPC970_Shift = 3, + PPC970_Mask = 0x07 << PPC970_Shift +}; +enum PPC970_Unit { + /// These are the various PPC970 execution unit pipelines. Each instruction + /// is one of these. + PPC970_Pseudo = 0 << PPC970_Shift, // Pseudo instruction + PPC970_FXU = 1 << PPC970_Shift, // Fixed Point (aka Integer/ALU) Unit + PPC970_LSU = 2 << PPC970_Shift, // Load Store Unit + PPC970_FPU = 3 << PPC970_Shift, // Floating Point Unit + PPC970_CRU = 4 << PPC970_Shift, // Control Register Unit + PPC970_VALU = 5 << PPC970_Shift, // Vector ALU + PPC970_VPERM = 6 << PPC970_Shift, // Vector Permute Unit + PPC970_BRU = 7 << PPC970_Shift // Branch Unit +}; + +enum { + /// Shift count to bypass PPC970 flags + NewDef_Shift = 6, + + /// This instruction is an X-Form memory operation. + XFormMemOp = 0x1 << NewDef_Shift, + /// This instruction is prefixed. + Prefixed = 0x1 << (NewDef_Shift + 1), + /// This instruction produced a sign extended result. + SExt32To64 = 0x1 << (NewDef_Shift + 2), + /// This instruction produced a zero extended result. + ZExt32To64 = 0x1 << (NewDef_Shift + 3) +}; +} // end namespace PPCII + +} // end namespace llvm // Defines symbolic names for PowerPC registers. This defines a mapping from // register name to register number. @@ -214,4 +283,16 @@ using llvm::MCPhysReg; static const MCPhysReg DMRRegs[8] = PPC_REGS0_7(PPC::DMR); \ static const MCPhysReg DMRpRegs[4] = PPC_REGS0_3(PPC::DMRp); +namespace llvm { +namespace PPC { +static inline bool isVFRegister(unsigned Reg) { + return Reg >= PPC::VF0 && Reg <= PPC::VF31; +} + +static inline bool isVRRegister(unsigned Reg) { + return Reg >= PPC::V0 && Reg <= PPC::V31; +} +} // namespace PPC +} // namespace llvm + #endif // LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCTARGETDESC_H diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp index 284e52c298a2..80c37f82bf29 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp @@ -12,7 +12,6 @@ #include "PPCPredicates.h" #include "llvm/Support/ErrorHandling.h" -#include <cassert> using namespace llvm; PPC::Predicate PPC::InvertPredicate(PPC::Predicate Opcode) { diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp index df671f53cbd8..065daf42fe6e 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp @@ -69,6 +69,8 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize( return {XCOFF::RelocationType::R_TOCU, SignAndSizeForHalf16}; case MCSymbolRefExpr::VK_PPC_L: return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16}; + case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: + return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForHalf16}; } } break; case PPC::fixup_ppc_half16ds: @@ -82,6 +84,8 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize( return {XCOFF::RelocationType::R_TOC, 15}; case MCSymbolRefExpr::VK_PPC_L: return {XCOFF::RelocationType::R_TOCL, 15}; + case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: + return {XCOFF::RelocationType::R_TLS_LE, 15}; } } break; case PPC::fixup_ppc_br24: @@ -108,6 +112,8 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize( return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData}; case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM: return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData}; + case MCSymbolRefExpr::VK_PPC_AIX_TLSIE: + return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData}; case MCSymbolRefExpr::VK_PPC_AIX_TLSLE: return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData}; case MCSymbolRefExpr::VK_None: diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td index 0827e528a80f..3bbc5a63ca7a 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/P10InstrResources.td @@ -825,9 +825,7 @@ def : InstRW<[P10W_F2_4C, P10W_DISP_ANY, P10F2_Read, P10F2_Read, P10F2_Read], def : InstRW<[P10W_F2_4C, P10W_DISP_EVEN, P10W_DISP_ANY, P10F2_Read], (instrs SRADI_rec, - SRAWI_rec, - TABORTDCI, - TABORTWCI + SRAWI_rec )>; // Single crack instructions @@ -835,9 +833,7 @@ def : InstRW<[P10W_F2_4C, P10W_DISP_EVEN, P10W_DISP_ANY, P10F2_Read], def : InstRW<[P10W_F2_4C, P10W_DISP_EVEN, P10W_DISP_ANY, P10F2_Read, P10F2_Read], (instrs SRAD_rec, - SRAW_rec, - TABORTDC, - TABORTWC + SRAW_rec )>; // 2-way crack instructions @@ -879,7 +875,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_ANY], MCRXRX, MFCTR, MFCTR8, MFLR, MFLR8, - WAIT + WAIT, WAITP10 )>; // 3 Cycles ALU operations, 1 input operands @@ -1130,10 +1126,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_EVEN, P10W_DISP_ANY], MFFSCRNI, MFFSL, MFVSCR, - MTFSB0, - TBEGIN, - TRECHKPT, - TSR + MTFSB0 )>; // Single crack instructions @@ -1153,9 +1146,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_EVEN, P10W_DISP_ANY, P10FX_Read], SUBFME8_rec, SUBFME_rec, SUBFME8O_rec, SUBFMEO_rec, SUBFZE8_rec, SUBFZE_rec, - SUBFZE8O_rec, SUBFZEO_rec, - TABORT, - TRECLAIM + SUBFZE8O_rec, SUBFZEO_rec )>; // Single crack instructions @@ -1862,8 +1853,6 @@ def : InstRW<[P10W_ST_3C, P10W_DISP_EVEN, P10W_DISP_ANY], EnforceIEIO, MSGSYNC, SLBSYNC, - TCHECK, - TEND, TLBSYNC )>; @@ -1895,6 +1884,7 @@ def : InstRW<[P10W_ST_3C, P10W_DISP_EVEN, P10W_DISP_ANY, P10ST_Read, P10ST_Read, def : InstRW<[P10W_ST_3C, P10W_DISP_EVEN, P10W_FX_3C, P10W_DISP_ANY], (instrs ISYNC, + SYNCP10, SYNC )>; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h index 0d3d71742bfb..3d9ea5608193 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.h @@ -46,13 +46,14 @@ class ModulePass; FunctionPass *createPPCMIPeepholePass(); FunctionPass *createPPCBranchSelectionPass(); FunctionPass *createPPCBranchCoalescingPass(); - FunctionPass *createPPCISelDag(PPCTargetMachine &TM, CodeGenOpt::Level OL); + FunctionPass *createPPCISelDag(PPCTargetMachine &TM, CodeGenOptLevel OL); FunctionPass *createPPCTLSDynamicCallPass(); FunctionPass *createPPCBoolRetToIntPass(); FunctionPass *createPPCExpandISELPass(); FunctionPass *createPPCPreEmitPeepholePass(); FunctionPass *createPPCExpandAtomicPseudoPass(); FunctionPass *createPPCCTRLoopsPass(); + ModulePass *createPPCMergeStringPoolPass(); void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP); bool LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, @@ -78,6 +79,7 @@ class ModulePass; void initializePPCExpandAtomicPseudoPass(PassRegistry &); void initializePPCCTRLoopsPass(PassRegistry &); void initializePPCDAGToDAGISelPass(PassRegistry &); + void initializePPCMergeStringPoolPass(PassRegistry &); extern char &PPCVSXFMAMutateID; @@ -100,79 +102,99 @@ class ModulePass; // PPC Specific MachineOperand flags. MO_NO_FLAG, + /// On PPC, the 12 bits are not enough for all target operand flags. + /// Treat all PPC target flags as direct flags. To define new flag that is + /// combination of other flags, add new enum entry instead of combining + /// existing flags. See example MO_GOT_TPREL_PCREL_FLAG. + /// On a symbol operand "FOO", this indicates that the reference is actually /// to "FOO@plt". This is used for calls and jumps to external functions /// and for PIC calls on 32-bit ELF systems. - MO_PLT = 1, + MO_PLT, /// MO_PIC_FLAG - If this bit is set, the symbol reference is relative to /// the function's picbase, e.g. lo16(symbol-picbase). - MO_PIC_FLAG = 2, + MO_PIC_FLAG, /// MO_PCREL_FLAG - If this bit is set, the symbol reference is relative to /// the current instruction address(pc), e.g., var@pcrel. Fixup is VK_PCREL. - MO_PCREL_FLAG = 4, + MO_PCREL_FLAG, /// MO_GOT_FLAG - If this bit is set the symbol reference is to be computed /// via the GOT. For example when combined with the MO_PCREL_FLAG it should /// produce the relocation @got@pcrel. Fixup is VK_PPC_GOT_PCREL. - MO_GOT_FLAG = 8, + MO_GOT_FLAG, - // MO_PCREL_OPT_FLAG - If this bit is set the operand is part of a - // PC Relative linker optimization. - MO_PCREL_OPT_FLAG = 16, + /// MO_PCREL_OPT_FLAG - If this bit is set the operand is part of a + /// PC Relative linker optimization. + MO_PCREL_OPT_FLAG, /// MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to /// TLS General Dynamic model for Linux and the variable offset of TLS /// General Dynamic model for AIX. - MO_TLSGD_FLAG = 32, + MO_TLSGD_FLAG, /// MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to /// the thread pointer and the symbol can be used for the TLS Initial Exec /// and Local Exec models. - MO_TPREL_FLAG = 64, + MO_TPREL_FLAG, /// MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to /// TLS Local Dynamic model. - MO_TLSLD_FLAG = 128, + MO_TLSLD_FLAG, /// MO_TLSGDM_FLAG - If this bit is set the symbol reference is relative /// to the region handle of TLS General Dynamic model for AIX. - MO_TLSGDM_FLAG = 256, + MO_TLSGDM_FLAG, /// MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set /// they should produce the relocation @got@tlsgd@pcrel. /// Fix up is VK_PPC_GOT_TLSGD_PCREL - MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG, + /// MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG, + MO_GOT_TLSGD_PCREL_FLAG, /// MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set /// they should produce the relocation @got@tlsld@pcrel. /// Fix up is VK_PPC_GOT_TLSLD_PCREL - MO_GOT_TLSLD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSLD_FLAG, + /// MO_GOT_TLSLD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSLD_FLAG, + MO_GOT_TLSLD_PCREL_FLAG, /// MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set /// they should produce the relocation @got@tprel@pcrel. /// Fix up is VK_PPC_GOT_TPREL_PCREL - MO_GOT_TPREL_PCREL_FLAG = MO_GOT_FLAG | MO_TPREL_FLAG | MO_PCREL_FLAG, - - /// The next are not flags but distinct values. - MO_ACCESS_MASK = 0xf00, + /// MO_GOT_TPREL_PCREL_FLAG = MO_GOT_FLAG | MO_TPREL_FLAG | MO_PCREL_FLAG, + MO_GOT_TPREL_PCREL_FLAG, /// MO_LO, MO_HA - lo16(symbol) and ha16(symbol) - MO_LO = 1 << 8, - MO_HA = 2 << 8, + MO_LO, + MO_HA, - MO_TPREL_LO = 4 << 8, - MO_TPREL_HA = 3 << 8, + MO_TPREL_LO, + MO_TPREL_HA, /// These values identify relocations on immediates folded /// into memory operations. - MO_DTPREL_LO = 5 << 8, - MO_TLSLD_LO = 6 << 8, - MO_TOC_LO = 7 << 8, + MO_DTPREL_LO, + MO_TLSLD_LO, + MO_TOC_LO, + + /// Symbol for VK_PPC_TLS fixup attached to an ADD instruction + MO_TLS, + + /// MO_PIC_HA_FLAG = MO_PIC_FLAG | MO_HA + MO_PIC_HA_FLAG, + + /// MO_PIC_LO_FLAG = MO_PIC_FLAG | MO_LO + MO_PIC_LO_FLAG, + + /// MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TPREL_FLAG + MO_TPREL_PCREL_FLAG, + + /// MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TLS + MO_TLS_PCREL_FLAG, - // Symbol for VK_PPC_TLS fixup attached to an ADD instruction - MO_TLS = 8 << 8 + /// MO_GOT_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG + MO_GOT_PCREL_FLAG, }; } // end namespace PPCII diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td index 3ba36f4f01e1..535616d33a80 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPC.td @@ -318,6 +318,17 @@ def FeaturePrivileged : SubtargetFeature<"privileged", "HasPrivileged", "true", "Add privileged instructions">; +// Specifies that local-exec TLS accesses in any function with this target +// attribute should use the optimized TOC-free sequence (where the offset is an +// immediate off of R13 for which the linker might add fix-up code if the +// immediate is too large). +// Clearly, this isn't really a feature of the subtarget, but is used as a +// convenient way to affect code generation for individual functions. +def FeatureAIXLocalExecTLS : + SubtargetFeature<"aix-small-local-exec-tls", "HasAIXSmallLocalExecTLS", "true", + "Produce a TOC-free local-exec TLS sequence for this function " + "for 64-bit AIX">; + def FeaturePredictableSelectIsExpensive : SubtargetFeature<"predictable-select-expensive", "PredictableSelectIsExpensive", diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 5c10d6307c76..780b22b4fbe6 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -68,6 +68,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Threading.h" #include "llvm/Target/TargetMachine.h" #include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -316,7 +317,7 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, // Linux assembler (Others?) does not take register mnemonics. // FIXME - What about special registers used in mfspr/mtspr? - O << PPCRegisterInfo::stripRegisterPrefix(RegName); + O << PPC::stripRegisterPrefix(RegName); return; } case MachineOperand::MO_Immediate: @@ -376,13 +377,13 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, // This operand uses VSX numbering. // If the operand is a VMX register, convert it to a VSX register. Register Reg = MI->getOperand(OpNo).getReg(); - if (PPCInstrInfo::isVRRegister(Reg)) + if (PPC::isVRRegister(Reg)) Reg = PPC::VSX32 + (Reg - PPC::V0); - else if (PPCInstrInfo::isVFRegister(Reg)) + else if (PPC::isVFRegister(Reg)) Reg = PPC::VSX32 + (Reg - PPC::VF0); const char *RegName; RegName = PPCInstPrinter::getRegisterName(Reg); - RegName = PPCRegisterInfo::stripRegisterPrefix(RegName); + RegName = PPC::stripRegisterPrefix(RegName); O << RegName; return false; } @@ -632,7 +633,6 @@ void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) { const MCExpr *TlsRef = MCSymbolRefExpr::create(TlsCall, MCSymbolRefExpr::VK_None, OutContext); EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef)); - return; } /// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a @@ -715,25 +715,11 @@ static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO, } } -static bool hasTLSFlag(const MachineOperand &MO) { - unsigned Flags = MO.getTargetFlags(); - if (Flags & PPCII::MO_TLSGD_FLAG || Flags & PPCII::MO_TPREL_FLAG || - Flags & PPCII::MO_TLSLD_FLAG || Flags & PPCII::MO_TLSGDM_FLAG) - return true; - - if (Flags == PPCII::MO_TPREL_LO || Flags == PPCII::MO_TPREL_HA || - Flags == PPCII::MO_DTPREL_LO || Flags == PPCII::MO_TLSLD_LO || - Flags == PPCII::MO_TLS) - return true; - - return false; -} - static PPCAsmPrinter::TOCEntryType getTOCEntryTypeForMO(const MachineOperand &MO) { // Use the target flags to determine if this MO is Thread Local. // If we don't do this it comes out as Global. - if (hasTLSFlag(MO)) + if (PPCInstrInfo::hasTLSFlag(MO.getTargetFlags())) return PPCAsmPrinter::TOCType_ThreadLocal; switch (MO.getType()) { @@ -827,24 +813,27 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { return Expr; }; auto GetVKForMO = [&](const MachineOperand &MO) { - // For TLS local-exec accesses on AIX, we have one TOC entry for the symbol - // (with the variable offset), which is differentiated by MO_TPREL_FLAG. - if (MO.getTargetFlags() & PPCII::MO_TPREL_FLAG) { - // TODO: Update the query and the comment above to add a check for initial - // exec when this TLS model is supported on AIX in the future, as both - // local-exec and initial-exec can use MO_TPREL_FLAG. + // For TLS initial-exec and local-exec accesses on AIX, we have one TOC + // entry for the symbol (with the variable offset), which is differentiated + // by MO_TPREL_FLAG. + unsigned Flag = MO.getTargetFlags(); + if (Flag == PPCII::MO_TPREL_FLAG || + Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG || + Flag == PPCII::MO_TPREL_PCREL_FLAG) { assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n"); TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); if (Model == TLSModel::LocalExec) return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE; - llvm_unreachable("Only expecting local-exec accesses!"); + if (Model == TLSModel::InitialExec) + return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE; + llvm_unreachable("Only expecting local-exec or initial-exec accesses!"); } // For GD TLS access on AIX, we have two TOC entries for the symbol (one for // the variable offset and the other for the region handle). They are // differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG. - if (MO.getTargetFlags() & PPCII::MO_TLSGDM_FLAG) + if (Flag == PPCII::MO_TLSGDM_FLAG) return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM; - if (MO.getTargetFlags() & PPCII::MO_TLSGD_FLAG) + if (Flag == PPCII::MO_TLSGD_FLAG || Flag == PPCII::MO_GOT_TLSGD_PCREL_FLAG) return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD; return MCSymbolRefExpr::VariantKind::VK_None; }; @@ -1534,6 +1523,24 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO)); return; } + case PPC::ADDI8: { + // The faster non-TOC-based local-exec sequence is represented by `addi` + // with an immediate operand having the MO_TPREL_FLAG. Such an instruction + // does not otherwise arise. + unsigned Flag = MI->getOperand(2).getTargetFlags(); + if (Flag == PPCII::MO_TPREL_FLAG || + Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG || + Flag == PPCII::MO_TPREL_PCREL_FLAG) { + assert( + Subtarget->hasAIXSmallLocalExecTLS() && + "addi with thread-pointer only expected with local-exec small TLS"); + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(PPC::LA8); + EmitToStreamer(*OutStreamer, TmpInst); + return; + } + break; + } } LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); @@ -2512,7 +2519,7 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { } void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) { - assert(!GV->getName().startswith("llvm.") && + assert(!GV->getName().starts_with("llvm.") && "Unhandled intrinsic global variable."); if (GV->hasComdat()) @@ -2759,14 +2766,18 @@ bool PPCAIXAsmPrinter::doInitialization(Module &M) { // and add a format indicator as a part of function name in case we // will support more than one format. FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1); - else - // Use the Pid and current time as the unique module id when we cannot - // generate one based on a module's strong external symbols. - // FIXME: Adjust the comment accordingly after we use source file full - // path instead. + else { + // Use threadId, Pid, and current time as the unique module id when we + // cannot generate one based on a module's strong external symbols. + auto CurTime = + std::chrono::duration_cast<std::chrono::nanoseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); FormatIndicatorAndUniqueModId = - "clangPidTime_" + llvm::itostr(sys::Process::getProcessId()) + - "_" + llvm::itostr(time(nullptr)); + "clangPidTidTime_" + llvm::itostr(sys::Process::getProcessId()) + + "_" + llvm::itostr(llvm::get_threadid()) + "_" + + llvm::itostr(CurTime); + } } emitSpecialLLVMGlobal(&G); @@ -2781,11 +2792,21 @@ bool PPCAIXAsmPrinter::doInitialization(Module &M) { // Construct an aliasing list for each GlobalObject. for (const auto &Alias : M.aliases()) { - const GlobalObject *Base = Alias.getAliaseeObject(); - if (!Base) + const GlobalObject *Aliasee = Alias.getAliaseeObject(); + if (!Aliasee) report_fatal_error( "alias without a base object is not yet supported on AIX"); - GOAliasMap[Base].push_back(&Alias); + + if (Aliasee->hasCommonLinkage()) { + report_fatal_error("Aliases to common variables are not allowed on AIX:" + "\n\tAlias attribute for " + + Alias.getGlobalIdentifier() + + " is invalid because " + Aliasee->getName() + + " is common.", + false); + } + + GOAliasMap[Aliasee].push_back(&Alias); } return Result; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def index 5d97d187b296..8bbe315a2bb9 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def @@ -958,6 +958,7 @@ FUSION_FEATURE(GeneralBack2Back, hasBack2BackFusion, -1, V_SET0B, V_SET0H, WAIT, + WAITP10, XOR, XOR8, XOR8_rec, diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp index 3c6b1f84b821..20f53bd4badf 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp @@ -45,6 +45,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/OperandTraits.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" @@ -95,8 +96,6 @@ class PPCBoolRetToInt : public FunctionPass { Type *IntTy = ST->isPPC64() ? Type::getInt64Ty(V->getContext()) : Type::getInt32Ty(V->getContext()); - if (auto *C = dyn_cast<Constant>(V)) - return ConstantExpr::getZExt(C, IntTy); if (auto *P = dyn_cast<PHINode>(V)) { // Temporarily set the operands to 0. We'll fix this later in // runOnUse. @@ -108,13 +107,12 @@ class PPCBoolRetToInt : public FunctionPass { return Q; } - auto *A = dyn_cast<Argument>(V); - auto *I = dyn_cast<Instruction>(V); - assert((A || I) && "Unknown value type"); - - auto InstPt = - A ? &*A->getParent()->getEntryBlock().begin() : I->getNextNode(); - return new ZExtInst(V, IntTy, "", InstPt); + IRBuilder IRB(V->getContext()); + if (auto *I = dyn_cast<Instruction>(V)) + IRB.SetInsertPoint(I->getNextNode()); + else + IRB.SetInsertPoint(&Func->getEntryBlock(), Func->getEntryBlock().begin()); + return IRB.CreateZExt(V, IntTy); } typedef SmallPtrSet<const PHINode *, 8> PHINodeSet; @@ -196,6 +194,7 @@ class PPCBoolRetToInt : public FunctionPass { auto &TM = TPC->getTM<PPCTargetMachine>(); ST = TM.getSubtargetImpl(F); + Func = &F; PHINodeSet PromotablePHINodes = getPromotablePHINodes(F); B2IMap Bool2IntMap; @@ -277,6 +276,7 @@ class PPCBoolRetToInt : public FunctionPass { private: const PPCSubtarget *ST; + Function *Func; }; } // end anonymous namespace diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp index 9d580ff57471..799890928577 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "PPC.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -702,6 +701,7 @@ bool PPCBranchCoalescing::mergeCandidates(CoalescingCandidateInfo &SourceRegion, TargetRegion.FallThroughBlock->transferSuccessorsAndUpdatePHIs( SourceRegion.FallThroughBlock); TargetRegion.FallThroughBlock->removeSuccessor(SourceRegion.BranchBlock); + TargetRegion.FallThroughBlock->normalizeSuccProbs(); // Remove the blocks from the function. assert(SourceRegion.BranchBlock->empty() && diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp index b1f5bdd885cd..1f9947f6f327 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCTRLoopsVerify.cpp @@ -16,8 +16,6 @@ // something that needs to be run (or even defined) for Release builds so the // entire file is guarded by NDEBUG. #ifndef NDEBUG -#include <vector> - #include "MCTargetDesc/PPCMCTargetDesc.h" #include "PPC.h" #include "llvm/ADT/SmallSet.h" diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp index a9794ddd0566..aee57a5075ff 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp @@ -239,23 +239,18 @@ bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128( // loop: // old = lqarx ptr // <compare old, cmp> - // bne 0, fail + // bne 0, exit // succ: // stqcx new ptr // bne 0, loop - // b exit - // fail: - // stqcx old ptr // exit: // .... MachineFunction::iterator MFI = ++MBB.getIterator(); MachineBasicBlock *LoopCmpMBB = MF->CreateMachineBasicBlock(BB); MachineBasicBlock *CmpSuccMBB = MF->CreateMachineBasicBlock(BB); - MachineBasicBlock *CmpFailMBB = MF->CreateMachineBasicBlock(BB); MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB); MF->insert(MFI, LoopCmpMBB); MF->insert(MFI, CmpSuccMBB); - MF->insert(MFI, CmpFailMBB); MF->insert(MFI, ExitMBB); ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()), MBB.end()); @@ -276,9 +271,9 @@ bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128( BuildMI(CurrentMBB, DL, TII->get(PPC::BCC)) .addImm(PPC::PRED_NE) .addReg(PPC::CR0) - .addMBB(CmpFailMBB); + .addMBB(ExitMBB); CurrentMBB->addSuccessor(CmpSuccMBB); - CurrentMBB->addSuccessor(CmpFailMBB); + CurrentMBB->addSuccessor(ExitMBB); // Build succ. CurrentMBB = CmpSuccMBB; PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo, @@ -288,16 +283,11 @@ bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128( .addImm(PPC::PRED_NE) .addReg(PPC::CR0) .addMBB(LoopCmpMBB); - BuildMI(CurrentMBB, DL, TII->get(PPC::B)).addMBB(ExitMBB); CurrentMBB->addSuccessor(LoopCmpMBB); CurrentMBB->addSuccessor(ExitMBB); - CurrentMBB = CmpFailMBB; - BuildMI(CurrentMBB, DL, SC).addReg(Old).addReg(RA).addReg(RB); - CurrentMBB->addSuccessor(ExitMBB); recomputeLiveIns(*LoopCmpMBB); recomputeLiveIns(*CmpSuccMBB); - recomputeLiveIns(*CmpFailMBB); recomputeLiveIns(*ExitMBB); NMBBI = MBB.end(); MI.eraseFromParent(); diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp index d5e4ae34dde7..245e78641ed6 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -466,7 +466,7 @@ PPCFrameLowering::findScratchRegister(MachineBasicBlock *MBB, RS.enterBasicBlock(*MBB); } else { RS.enterBasicBlockEnd(*MBB); - RS.backward(std::prev(MBBI)); + RS.backward(MBBI); } } else { // The scratch register will be used at the start of the block. @@ -2334,24 +2334,16 @@ bool PPCFrameLowering::assignCalleeSavedSpillSlots( // In case of SPE we only have SuperRegs and CRs // in our CalleSaveInfo vector. - unsigned Idx = 0; for (auto &CalleeSaveReg : CSI) { - const MCPhysReg &Reg = CalleeSaveReg.getReg(); - const MCPhysReg &Lower = RegInfo->getSubReg(Reg, 1); - const MCPhysReg &Higher = RegInfo->getSubReg(Reg, 2); + MCPhysReg Reg = CalleeSaveReg.getReg(); + MCPhysReg Lower = RegInfo->getSubReg(Reg, 1); + MCPhysReg Higher = RegInfo->getSubReg(Reg, 2); - // Check only for SuperRegs. - if (Lower) { - if (MRI.isPhysRegModified(Higher)) { - Idx++; - continue; - } else { + if ( // Check only for SuperRegs. + Lower && // Replace Reg if only lower-32 bits modified - CSI.erase(CSI.begin() + Idx); - CSI.insert(CSI.begin() + Idx, CalleeSavedInfo(Lower)); - } - } - Idx++; + !MRI.isPhysRegModified(Higher)) + CalleeSaveReg = CalleeSavedInfo(Lower); } } @@ -2740,3 +2732,17 @@ bool PPCFrameLowering::enableShrinkWrapping(const MachineFunction &MF) const { return false; return !MF.getSubtarget<PPCSubtarget>().is32BitELFABI(); } + +uint64_t PPCFrameLowering::getStackThreshold() const { + // On PPC64, we use `stux r1, r1, <scratch_reg>` to extend the stack; + // use `add r1, r1, <scratch_reg>` to release the stack frame. + // Scratch register contains a signed 64-bit number, which is negative + // when extending the stack and is positive when releasing the stack frame. + // To make `stux` and `add` paired, the absolute value of the number contained + // in the scratch register should be the same. Thus the maximum stack size + // is (2^63)-1, i.e., LONG_MAX. + if (Subtarget.isPPC64()) + return LONG_MAX; + + return TargetFrameLowering::getStackThreshold(); +} diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h index 21883b19a575..e19087ce0e18 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCFrameLowering.h @@ -173,6 +173,8 @@ public: /// function prologue/epilogue. bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override; + + uint64_t getStackThreshold() const override; }; } // End llvm namespace diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def index eff4432206e1..b42f9247f691 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// namespace llvm { -RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{ +const RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{ /* StartIdx, Length, RegBank */ // 0: GPR 32-bit value. {0, 32, PPC::GPRRegBank}, @@ -39,7 +39,7 @@ RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{ // 3-operands instructions. // - Last, mappings for cross-register bank moves follow. Since COPY has only // 2 operands, a mapping consists of 2 entries. -RegisterBankInfo::ValueMapping PPCGenRegisterBankInfo::ValMappings[]{ +const RegisterBankInfo::ValueMapping PPCGenRegisterBankInfo::ValMappings[]{ /* BreakDown, NumBreakDowns */ // 0: invalid {nullptr, 0}, @@ -77,7 +77,7 @@ PPCGenRegisterBankInfo::getValueMapping(PartialMappingIdx RBIdx) { return &ValMappings[1 + 3 * ValMappingIdx]; } -PPCGenRegisterBankInfo::PartialMappingIdx +const PPCGenRegisterBankInfo::PartialMappingIdx PPCGenRegisterBankInfo::BankIDToCopyMapIdx[]{ PMI_None, PMI_FPR64, // FPR diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 96fd83ab6a7b..b57d185bb638 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -151,7 +151,7 @@ namespace { PPCDAGToDAGISel() = delete; - explicit PPCDAGToDAGISel(PPCTargetMachine &tm, CodeGenOpt::Level OptLevel) + explicit PPCDAGToDAGISel(PPCTargetMachine &tm, CodeGenOptLevel OptLevel) : SelectionDAGISel(ID, tm, OptLevel), TM(tm) {} bool runOnMachineFunction(MachineFunction &MF) override { @@ -387,18 +387,19 @@ namespace { /// register can be improved, but it is wrong to substitute Reg+Reg for /// Reg in an asm, because the load or store opcode would have to change. bool SelectInlineAsmMemoryOperand(const SDValue &Op, - unsigned ConstraintID, + InlineAsm::ConstraintCode ConstraintID, std::vector<SDValue> &OutOps) override { switch(ConstraintID) { default: - errs() << "ConstraintID: " << ConstraintID << "\n"; + errs() << "ConstraintID: " + << InlineAsm::getMemConstraintName(ConstraintID) << "\n"; llvm_unreachable("Unexpected asm memory constraint"); - case InlineAsm::Constraint_es: - case InlineAsm::Constraint_m: - case InlineAsm::Constraint_o: - case InlineAsm::Constraint_Q: - case InlineAsm::Constraint_Z: - case InlineAsm::Constraint_Zy: + case InlineAsm::ConstraintCode::es: + case InlineAsm::ConstraintCode::m: + case InlineAsm::ConstraintCode::o: + case InlineAsm::ConstraintCode::Q: + case InlineAsm::ConstraintCode::Z: + case InlineAsm::ConstraintCode::Zy: // We need to make sure that this one operand does not end up in r0 // (because we might end up lowering this as 0(%op)). const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); @@ -424,6 +425,7 @@ private: bool tryFoldSWTestBRCC(SDNode *N); bool trySelectLoopCountIntrinsic(SDNode *N); bool tryAsSingleRLDICL(SDNode *N); + bool tryAsSingleRLDCL(SDNode *N); bool tryAsSingleRLDICR(SDNode *N); bool tryAsSingleRLWINM(SDNode *N); bool tryAsSingleRLWINM8(SDNode *N); @@ -754,8 +756,8 @@ static bool isThreadPointerAcquisitionNode(SDValue Base, SelectionDAG *CurDAG) { static bool canOptimizeTLSDFormToXForm(SelectionDAG *CurDAG, SDValue Base) { // Do not do this transformation at -O0. - if (CurDAG->getTarget().getOptLevel() == CodeGenOpt::None) - return false; + if (CurDAG->getTarget().getOptLevel() == CodeGenOptLevel::None) + return false; // In order to perform this optimization inside tryTLSXForm[Load|Store], // Base is expected to be an ADD_TLS node. @@ -1165,6 +1167,31 @@ static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl, return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0), getI32Imm(Shift), getI32Imm(0)); } + // 2-7) Patterns : High word == Low word + // This may require 2 to 3 instructions, depending on whether Lo32 can be + // materialized in 1 instruction. + if (Hi32 == Lo32) { + // Handle the first 32 bits. + uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff; + uint64_t ImmLo16 = Lo32 & 0xffff; + if (isInt<16>(Lo32)) + Result = + CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, getI32Imm(ImmLo16)); + else if (!ImmLo16) + Result = + CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(ImmHi16)); + else { + InstCnt = 3; + Result = + CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(ImmHi16)); + Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, + SDValue(Result, 0), getI32Imm(ImmLo16)); + } + // Use rldimi to insert the Low word into High word. + SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32), + getI32Imm(0)}; + return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops); + } // Following patterns use 3 instructions to materialize the Imm. InstCnt = 3; @@ -1215,20 +1242,7 @@ static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl, return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0), getI32Imm(TO), getI32Imm(LZ)); } - // 3-4) Patterns : High word == Low word - if (Hi32 == Lo32) { - // Handle the first 32 bits. - uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff; - unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; - Result = CurDAG->getMachineNode(Opcode, dl, MVT::i64, getI32Imm(ImmHi16)); - Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0), - getI32Imm(Lo32 & 0xffff)); - // Use rldimi to insert the Low word into High word. - SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32), - getI32Imm(0)}; - return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops); - } - // 3-5) Patterns : {******}{33 zeros}{******} + // 3-4) Patterns : {******}{33 zeros}{******} // {******}{33 ones}{******} // If the Imm contains 33 consecutive zeros/ones, it means that a total of 31 // bits remain on both sides. Rotate right the Imm to construct an int<32> @@ -4041,7 +4055,7 @@ bool PPCDAGToDAGISel::tryIntCompareInGPR(SDNode *N) { // This optimization will emit code that assumes 64-bit registers // so we don't want to run it in 32-bit mode. Also don't run it // on functions that are not to be optimized. - if (TM.getOptLevel() == CodeGenOpt::None || !TM.isPPC64()) + if (TM.getOptLevel() == CodeGenOptLevel::None || !TM.isPPC64()) return false; // For POWER10, it is more profitable to use the set boolean extension @@ -4835,8 +4849,7 @@ bool PPCDAGToDAGISel::tryFoldSWTestBRCC(SDNode *N) { return false; SDValue CmpRHS = N->getOperand(3); - if (!isa<ConstantSDNode>(CmpRHS) || - cast<ConstantSDNode>(CmpRHS)->getSExtValue() != 0) + if (!isNullConstant(CmpRHS)) return false; SDValue CmpLHS = N->getOperand(2); @@ -5085,6 +5098,35 @@ bool PPCDAGToDAGISel::tryAsSingleRLWIMI(SDNode *N) { return false; } +bool PPCDAGToDAGISel::tryAsSingleRLDCL(SDNode *N) { + assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected"); + + uint64_t Imm64; + if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) || !isMask_64(Imm64)) + return false; + + SDValue Val = N->getOperand(0); + + if (Val.getOpcode() != ISD::ROTL) + return false; + + // Looking to try to avoid a situation like this one: + // %2 = tail call i64 @llvm.fshl.i64(i64 %word, i64 %word, i64 23) + // %and1 = and i64 %2, 9223372036854775807 + // In this function we are looking to try to match RLDCL. However, the above + // DAG would better match RLDICL instead which is not what we are looking + // for here. + SDValue RotateAmt = Val.getOperand(1); + if (RotateAmt.getOpcode() == ISD::Constant) + return false; + + unsigned MB = 64 - llvm::countr_one(Imm64); + SDLoc dl(N); + SDValue Ops[] = {Val.getOperand(0), RotateAmt, getI32Imm(MB, dl)}; + CurDAG->SelectNodeTo(N, PPC::RLDCL, MVT::i64, Ops); + return true; +} + bool PPCDAGToDAGISel::tryAsSingleRLDICL(SDNode *N) { assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected"); uint64_t Imm64; @@ -5605,8 +5647,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) { case ISD::AND: // If this is an 'and' with a mask, try to emit rlwinm/rldicl/rldicr - if (tryAsSingleRLWINM(N) || tryAsSingleRLWIMI(N) || tryAsSingleRLDICL(N) || - tryAsSingleRLDICR(N) || tryAsSingleRLWINM8(N) || tryAsPairOfRLDICL(N)) + if (tryAsSingleRLWINM(N) || tryAsSingleRLWIMI(N) || tryAsSingleRLDCL(N) || + tryAsSingleRLDICL(N) || tryAsSingleRLDICR(N) || tryAsSingleRLWINM8(N) || + tryAsPairOfRLDICL(N)) return; // Other cases are autogenerated. @@ -6624,7 +6667,7 @@ void PPCDAGToDAGISel::PreprocessISelDAG() { /// on the DAG representation. void PPCDAGToDAGISel::PostprocessISelDAG() { // Skip peepholes at -O0. - if (TM.getOptLevel() == CodeGenOpt::None) + if (TM.getOptLevel() == CodeGenOptLevel::None) return; PeepholePPC64(); @@ -6659,11 +6702,7 @@ bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) { Op2->getMachineOpcode() != PPC::LI8) return false; - ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op2->getOperand(0)); - if (!C) - return false; - - if (!C->isZero()) + if (!isNullConstant(Op2->getOperand(0))) return false; } @@ -7616,13 +7655,6 @@ void PPCDAGToDAGISel::PeepholePPC64() { // is already in place on the operand, so copying the operand // is sufficient. ReplaceFlags = false; - // For these cases, the immediate may not be divisible by 4, in - // which case the fold is illegal for DS-form instructions. (The - // other cases provide aligned addresses and are always safe.) - if (RequiresMod4Offset && - (!isa<ConstantSDNode>(Base.getOperand(1)) || - Base.getConstantOperandVal(1) % 4 != 0)) - continue; break; case PPC::ADDIdtprelL: Flags = PPCII::MO_DTPREL_LO; @@ -7674,6 +7706,18 @@ void PPCDAGToDAGISel::PeepholePPC64() { UpdateHBase = true; } } else { + // Global addresses can be folded, but only if they are sufficiently + // aligned. + if (RequiresMod4Offset) { + if (GlobalAddressSDNode *GA = + dyn_cast<GlobalAddressSDNode>(ImmOpnd)) { + const GlobalValue *GV = GA->getGlobal(); + Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout()); + if (Alignment < 4) + continue; + } + } + // If we're directly folding the addend from an addi instruction, then: // 1. In general, the offset on the memory access must be zero. // 2. If the addend is a constant, then it can be combined with a @@ -7748,6 +7792,6 @@ void PPCDAGToDAGISel::PeepholePPC64() { /// PowerPC-specific DAG, ready for instruction scheduling. /// FunctionPass *llvm::createPPCISelDag(PPCTargetMachine &TM, - CodeGenOpt::Level OptLevel) { + CodeGenOptLevel OptLevel) { return new PPCDAGToDAGISel(TM, OptLevel); } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 547b71a6101a..22c662a79d87 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -132,6 +132,10 @@ cl::opt<bool> DisableAutoPairedVecSt( cl::desc("disable automatically generated 32byte paired vector stores"), cl::init(true), cl::Hidden); +static cl::opt<unsigned> PPCMinimumJumpTableEntries( + "ppc-min-jump-table-entries", cl::init(64), cl::Hidden, + cl::desc("Set minimum number of entries to use a jump table on PPC")); + STATISTIC(NumTailCalls, "Number of tail calls"); STATISTIC(NumSiblingCalls, "Number of sibling calls"); STATISTIC(ShufflesHandledWithVPERM, @@ -144,6 +148,12 @@ static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl); static const char AIXSSPCanaryWordName[] = "__ssp_canary_word"; +// A faster local-exec TLS access sequence (enabled with the +// -maix-small-local-exec-tls option) can be produced for TLS variables; +// consistent with the IBM XL compiler, we apply a max size of slightly under +// 32KB. +constexpr uint64_t AIXSmallTlsPolicySizeLimit = 32751; + // FIXME: Remove this once the bug has been fixed! extern cl::opt<bool> ANDIGlueBug; @@ -389,7 +399,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, // MASS transformation for LLVM intrinsics with replicating fast-math flag // to be consistent to PPCGenScalarMASSEntries pass - if (TM.getOptLevel() == CodeGenOpt::Aggressive) { + if (TM.getOptLevel() == CodeGenOptLevel::Aggressive) { setOperationAction(ISD::FSIN , MVT::f64, Custom); setOperationAction(ISD::FCOS , MVT::f64, Custom); setOperationAction(ISD::FPOW , MVT::f64, Custom); @@ -1419,6 +1429,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setLibcallName(RTLIB::LLRINT_F128, "llrintf128"); setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128"); setLibcallName(RTLIB::FMA_F128, "fmaf128"); + setLibcallName(RTLIB::FREXP_F128, "frexpf128"); if (Subtarget.isAIXABI()) { setLibcallName(RTLIB::MEMCPY, isPPC64 ? "___memmove64" : "___memmove"); @@ -1434,6 +1445,12 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setJumpIsExpensive(); } + // TODO: The default entry number is set to 64. This stops most jump table + // generation on PPC. But it is good for current PPC HWs because the indirect + // branch instruction mtctr to the jump table may lead to bad branch predict. + // Re-evaluate this value on future HWs that can do better with mtctr. + setMinimumJumpTableEntries(PPCMinimumJumpTableEntries); + setMinFunctionAlignment(Align(4)); switch (Subtarget.getCPUDirective()) { @@ -1627,6 +1644,27 @@ bool PPCTargetLowering::preferIncOfAddToSubOfNot(EVT VT) const { return VT.isScalarInteger(); } +bool PPCTargetLowering::shallExtractConstSplatVectorElementToStore( + Type *VectorTy, unsigned ElemSizeInBits, unsigned &Index) const { + if (!Subtarget.isPPC64() || !Subtarget.hasVSX()) + return false; + + if (auto *VTy = dyn_cast<VectorType>(VectorTy)) { + if (VTy->getScalarType()->isIntegerTy()) { + // ElemSizeInBits 8/16 can fit in immediate field, not needed here. + if (ElemSizeInBits == 32) { + Index = Subtarget.isLittleEndian() ? 2 : 1; + return true; + } + if (ElemSizeInBits == 64) { + Index = Subtarget.isLittleEndian() ? 1 : 0; + return true; + } + } + } + return false; +} + const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((PPCISD::NodeType)Opcode) { case PPCISD::FIRST_NUMBER: break; @@ -2936,7 +2974,7 @@ bool PPCTargetLowering::SelectAddressRegRegOnly(SDValue N, SDValue &Base, template <typename Ty> static bool isValidPCRelNode(SDValue N) { Ty *PCRelCand = dyn_cast<Ty>(N); - return PCRelCand && (PCRelCand->getTargetFlags() & PPCII::MO_PCREL_FLAG); + return PCRelCand && (PPCInstrInfo::hasPCRelFlag(PCRelCand->getTargetFlags())); } /// Returns true if this address is a PC Relative address. @@ -3097,8 +3135,8 @@ static void getLabelAccessInfo(bool IsPIC, const PPCSubtarget &Subtarget, // Don't use the pic base if not in PIC relocation model. if (IsPIC) { - HiOpFlags |= PPCII::MO_PIC_FLAG; - LoOpFlags |= PPCII::MO_PIC_FLAG; + HiOpFlags = PPCII::MO_PIC_HA_FLAG; + LoOpFlags = PPCII::MO_PIC_LO_FLAG; } } @@ -3326,36 +3364,60 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, const GlobalValue *GV = GA->getGlobal(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); bool Is64Bit = Subtarget.isPPC64(); + bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS(); TLSModel::Model Model = getTargetMachine().getTLSModel(GV); + bool IsTLSLocalExecModel = Model == TLSModel::LocalExec; - if (Model == TLSModel::LocalExec) { + if (IsTLSLocalExecModel || Model == TLSModel::InitialExec) { SDValue VariableOffsetTGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TPREL_FLAG); SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA); SDValue TLSReg; - if (Is64Bit) - // For local-exec on AIX (64-bit), the sequence that is generated involves - // a load of the variable offset (from the TOC), followed by an add of the - // loaded variable offset to R13 (the thread pointer). + if (Is64Bit) { + // For local-exec and initial-exec on AIX (64-bit), the sequence generated + // involves a load of the variable offset (from the TOC), followed by an + // add of the loaded variable offset to R13 (the thread pointer). // This code sequence looks like: // ld reg1,var[TC](2) // add reg2, reg1, r13 // r13 contains the thread pointer TLSReg = DAG.getRegister(PPC::X13, MVT::i64); - else - // For local-exec on AIX (32-bit), the sequence that is generated involves - // loading the variable offset from the TOC, generating a call to + + // With the -maix-small-local-exec-tls option, produce a faster access + // sequence for local-exec TLS variables where the offset from the TLS + // base is encoded as an immediate operand. + // + // We only utilize the faster local-exec access sequence when the TLS + // variable has a size within the policy limit. We treat types that are + // not sized or are empty as being over the policy size limit. + if (HasAIXSmallLocalExecTLS && IsTLSLocalExecModel) { + Type *GVType = GV->getValueType(); + if (GVType->isSized() && !GVType->isEmptyTy() && + GV->getParent()->getDataLayout().getTypeAllocSize(GVType) <= + AIXSmallTlsPolicySizeLimit) + return DAG.getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA, TLSReg); + } + } else { + // For local-exec and initial-exec on AIX (32-bit), the sequence generated + // involves loading the variable offset from the TOC, generating a call to // .__get_tpointer to get the thread pointer (which will be in R3), and // adding the two together: // lwz reg1,var[TC](2) // bla .__get_tpointer // add reg2, reg1, r3 TLSReg = DAG.getNode(PPCISD::GET_TPOINTER, dl, PtrVT); + + // We do not implement the 32-bit version of the faster access sequence + // for local-exec that is controlled by -maix-small-local-exec-tls. + if (HasAIXSmallLocalExecTLS) + report_fatal_error("The small-local-exec TLS access sequence is " + "currently only supported on AIX (64-bit mode)."); + } return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset); } - // The Local-Exec and General-Dynamic TLS models are currently the only - // supported access models. If Local-exec is not possible or specified, all - // GlobalTLSAddress nodes are lowered using the general-dynamic model. + // Only Local-Exec, Initial-Exec and General-Dynamic TLS models are currently + // supported models. If Local- or Initial-exec are not possible or specified, + // all GlobalTLSAddress nodes are lowered using the general-dynamic model. // We need to generate two TOC entries, one for the variable offset, one for // the region handle. The global address for the TOC entry of the region // handle is created with the MO_TLSGDM_FLAG flag and the global address @@ -3393,8 +3455,8 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressLinux(SDValue Op, if (Model == TLSModel::LocalExec) { if (Subtarget.isUsingPCRelativeCalls()) { SDValue TLSReg = DAG.getRegister(PPC::X13, MVT::i64); - SDValue TGA = DAG.getTargetGlobalAddress( - GV, dl, PtrVT, 0, (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG)); + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, + PPCII::MO_TPREL_PCREL_FLAG); SDValue MatAddr = DAG.getNode(PPCISD::TLS_LOCAL_EXEC_MAT_ADDR, dl, PtrVT, TGA); return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, MatAddr); @@ -3416,8 +3478,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressLinux(SDValue Op, SDValue TGA = DAG.getTargetGlobalAddress( GV, dl, PtrVT, 0, IsPCRel ? PPCII::MO_GOT_TPREL_PCREL_FLAG : 0); SDValue TGATLS = DAG.getTargetGlobalAddress( - GV, dl, PtrVT, 0, - IsPCRel ? (PPCII::MO_TLS | PPCII::MO_PCREL_FLAG) : PPCII::MO_TLS); + GV, dl, PtrVT, 0, IsPCRel ? PPCII::MO_TLS_PCREL_FLAG : PPCII::MO_TLS); SDValue TPOffset; if (IsPCRel) { SDValue MatPCRel = DAG.getNode(PPCISD::MAT_PCREL_ADDR, dl, PtrVT, TGA); @@ -3513,8 +3574,7 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, EVT Ty = getPointerTy(DAG.getDataLayout()); if (isAccessedAsGotIndirect(Op)) { SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty, GSDN->getOffset(), - PPCII::MO_PCREL_FLAG | - PPCII::MO_GOT_FLAG); + PPCII::MO_GOT_PCREL_FLAG); SDValue MatPCRel = DAG.getNode(PPCISD::MAT_PCREL_ADDR, DL, Ty, GA); SDValue Load = DAG.getLoad(MVT::i64, DL, DAG.getEntryNode(), MatPCRel, MachinePointerInfo()); @@ -3764,21 +3824,22 @@ SDValue PPCTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const { // Check all operands that may contain the LR. for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { - unsigned Flags = cast<ConstantSDNode>(Op.getOperand(i))->getZExtValue(); - unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + const InlineAsm::Flag Flags( + cast<ConstantSDNode>(Op.getOperand(i))->getZExtValue()); + unsigned NumVals = Flags.getNumOperandRegisters(); ++i; // Skip the ID value. - switch (InlineAsm::getKind(Flags)) { + switch (Flags.getKind()) { default: llvm_unreachable("Bad flags!"); - case InlineAsm::Kind_RegUse: - case InlineAsm::Kind_Imm: - case InlineAsm::Kind_Mem: + case InlineAsm::Kind::RegUse: + case InlineAsm::Kind::Imm: + case InlineAsm::Kind::Mem: i += NumVals; break; - case InlineAsm::Kind_Clobber: - case InlineAsm::Kind_RegDef: - case InlineAsm::Kind_RegDefEarlyClobber: { + case InlineAsm::Kind::Clobber: + case InlineAsm::Kind::RegDef: + case InlineAsm::Kind::RegDefEarlyClobber: { for (; NumVals; --NumVals, ++i) { Register Reg = cast<RegisterSDNode>(Op.getOperand(i))->getReg(); if (Reg != PPC::LR && Reg != PPC::LR8) @@ -5278,7 +5339,7 @@ static unsigned getCallOpcode(PPCTargetLowering::CallFlags CFlags, // inserted into the DAG as part of call lowering. The restore of the TOC // pointer is modeled by using a pseudo instruction for the call opcode that // represents the 2 instruction sequence of an indirect branch and link, - // immediately followed by a load of the TOC pointer from the the stack save + // immediately followed by a load of the TOC pointer from the stack save // slot into gpr2. For 64-bit ELFv2 ABI with PCRel, do not restore the TOC // as it is not saved or used. RetOpc = isTOCSaveRestoreRequired(Subtarget) ? PPCISD::BCTRL_LOAD_TOC @@ -7193,7 +7254,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX( // be future work. SDValue Store = DAG.getStore( CopyFrom.getValue(1), dl, CopyFrom, - DAG.getObjectPtrOffset(dl, FIN, TypeSize::Fixed(Offset)), + DAG.getObjectPtrOffset(dl, FIN, TypeSize::getFixed(Offset)), MachinePointerInfo::getFixedStack(MF, FI, Offset)); MemOps.push_back(Store); @@ -7373,12 +7434,12 @@ SDValue PPCTargetLowering::LowerCall_AIX( } auto GetLoad = [&](EVT VT, unsigned LoadOffset) { - return DAG.getExtLoad( - ISD::ZEXTLOAD, dl, PtrVT, Chain, - (LoadOffset != 0) - ? DAG.getObjectPtrOffset(dl, Arg, TypeSize::Fixed(LoadOffset)) - : Arg, - MachinePointerInfo(), VT); + return DAG.getExtLoad(ISD::ZEXTLOAD, dl, PtrVT, Chain, + (LoadOffset != 0) + ? DAG.getObjectPtrOffset( + dl, Arg, TypeSize::getFixed(LoadOffset)) + : Arg, + MachinePointerInfo(), VT); }; unsigned LoadOffset = 0; @@ -7408,11 +7469,11 @@ SDValue PPCTargetLowering::LowerCall_AIX( // Only memcpy the bytes that don't pass in register. MemcpyFlags.setByValSize(ByValSize - LoadOffset); Chain = CallSeqStart = createMemcpyOutsideCallSeq( - (LoadOffset != 0) - ? DAG.getObjectPtrOffset(dl, Arg, TypeSize::Fixed(LoadOffset)) - : Arg, - DAG.getObjectPtrOffset(dl, StackPtr, - TypeSize::Fixed(ByValVA.getLocMemOffset())), + (LoadOffset != 0) ? DAG.getObjectPtrOffset( + dl, Arg, TypeSize::getFixed(LoadOffset)) + : Arg, + DAG.getObjectPtrOffset( + dl, StackPtr, TypeSize::getFixed(ByValVA.getLocMemOffset())), CallSeqStart, MemcpyFlags, DAG, dl); continue; } @@ -8020,7 +8081,8 @@ SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { // For more information, see section F.3 of the 2.06 ISA specification. // With ISA 3.0 if ((!DAG.getTarget().Options.NoInfsFPMath && !Flags.hasNoInfs()) || - (!DAG.getTarget().Options.NoNaNsFPMath && !Flags.hasNoNaNs())) + (!DAG.getTarget().Options.NoNaNsFPMath && !Flags.hasNoNaNs()) || + ResVT == MVT::f128) return Op; // If the RHS of the comparison is a 0.0, we don't need to do the @@ -10254,11 +10316,6 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG, bool isLittleEndian = Subtarget.isLittleEndian(); bool isPPC64 = Subtarget.isPPC64(); - // Only need to place items backwards in LE, - // the mask will be properly calculated. - if (isLittleEndian) - std::swap(V1, V2); - if (Subtarget.hasVSX() && Subtarget.hasP9Vector() && (V1->hasOneUse() || V2->hasOneUse())) { LLVM_DEBUG(dbgs() << "At least one of two input vectors are dead - using " @@ -10268,7 +10325,8 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG, // The second input to XXPERM is also an output so if the second input has // multiple uses then copying is necessary, as a result we want the // single-use operand to be used as the second input to prevent copying. - if (!V2->hasOneUse() && V1->hasOneUse()) { + if ((!isLittleEndian && !V2->hasOneUse() && V1->hasOneUse()) || + (isLittleEndian && !V1->hasOneUse() && V2->hasOneUse())) { std::swap(V1, V2); NeedSwap = !NeedSwap; } @@ -10307,27 +10365,24 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG, for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; - if (Opcode == PPCISD::XXPERM) { - if (V1HasXXSWAPD) { - if (SrcElt < 8) - SrcElt += 8; - else if (SrcElt < 16) - SrcElt -= 8; - } - if (V2HasXXSWAPD) { - if (SrcElt > 23) - SrcElt -= 8; - else if (SrcElt > 15) - SrcElt += 8; - } - if (NeedSwap) { - if (SrcElt < 16) - SrcElt += 16; - else - SrcElt -= 16; - } + if (V1HasXXSWAPD) { + if (SrcElt < 8) + SrcElt += 8; + else if (SrcElt < 16) + SrcElt -= 8; + } + if (V2HasXXSWAPD) { + if (SrcElt > 23) + SrcElt -= 8; + else if (SrcElt > 15) + SrcElt += 8; + } + if (NeedSwap) { + if (SrcElt < 16) + SrcElt += 16; + else + SrcElt -= 16; } - for (unsigned j = 0; j != BytesPerElement; ++j) if (isLittleEndian) ResultMask.push_back( @@ -10337,18 +10392,19 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG, DAG.getConstant(SrcElt * BytesPerElement + j, dl, MVT::i32)); } - if (Opcode == PPCISD::XXPERM && (V1HasXXSWAPD || V2HasXXSWAPD)) { - if (V1HasXXSWAPD) { - dl = SDLoc(V1->getOperand(0)); - V1 = V1->getOperand(0)->getOperand(1); - } - if (V2HasXXSWAPD) { - dl = SDLoc(V2->getOperand(0)); - V2 = V2->getOperand(0)->getOperand(1); - } - if (isPPC64 && ValType != MVT::v2f64) + if (V1HasXXSWAPD) { + dl = SDLoc(V1->getOperand(0)); + V1 = V1->getOperand(0)->getOperand(1); + } + if (V2HasXXSWAPD) { + dl = SDLoc(V2->getOperand(0)); + V2 = V2->getOperand(0)->getOperand(1); + } + + if (isPPC64 && (V1HasXXSWAPD || V2HasXXSWAPD)) { + if (ValType != MVT::v2f64) V1 = DAG.getBitcast(MVT::v2f64, V1); - if (isPPC64 && V2.getValueType() != MVT::v2f64) + if (V2.getValueType() != MVT::v2f64) V2 = DAG.getBitcast(MVT::v2f64, V2); } @@ -10369,6 +10425,11 @@ SDValue PPCTargetLowering::LowerVPERM(SDValue Op, SelectionDAG &DAG, if (Opcode == PPCISD::XXPERM) VPermMask = DAG.getBitcast(MVT::v4i32, VPermMask); + // Only need to place items backwards in LE, + // the mask was properly calculated. + if (isLittleEndian) + std::swap(V1, V2); + SDValue VPERMNode = DAG.getNode(Opcode, dl, V1.getValueType(), V1, V2, VPermMask); @@ -11037,14 +11098,14 @@ SDValue PPCTargetLowering::LowerATOMIC_LOAD_STORE(SDValue Op, SmallVector<SDValue, 4> Ops{ N->getOperand(0), DAG.getConstant(Intrinsic::ppc_atomic_store_i128, dl, MVT::i32)}; - SDValue Val = N->getOperand(2); + SDValue Val = N->getOperand(1); SDValue ValLo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i64, Val); SDValue ValHi = DAG.getNode(ISD::SRL, dl, MVT::i128, Val, DAG.getConstant(64, dl, MVT::i32)); ValHi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i64, ValHi); Ops.push_back(ValLo); Ops.push_back(ValHi); - Ops.push_back(N->getOperand(1)); + Ops.push_back(N->getOperand(2)); return DAG.getMemIntrinsicNode(ISD::INTRINSIC_VOID, dl, Tys, Ops, MemVT, N->getMemOperand()); } @@ -16659,13 +16720,14 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector<SDValue>&Ops, + StringRef Constraint, + std::vector<SDValue> &Ops, SelectionDAG &DAG) const { SDValue Result; // Only support length 1 constraints. - if (Constraint.length() > 1) return; + if (Constraint.size() > 1) + return; char Letter = Constraint[0]; switch (Letter) { @@ -17075,13 +17137,23 @@ bool PPCTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, /// target-independent logic. EVT PPCTargetLowering::getOptimalMemOpType( const MemOp &Op, const AttributeList &FuncAttributes) const { - if (getTargetMachine().getOptLevel() != CodeGenOpt::None) { + if (getTargetMachine().getOptLevel() != CodeGenOptLevel::None) { // We should use Altivec/VSX loads and stores when available. For unaligned // addresses, unaligned VSX loads are only fast starting with the P8. - if (Subtarget.hasAltivec() && Op.size() >= 16 && - (Op.isAligned(Align(16)) || - ((Op.isMemset() && Subtarget.hasVSX()) || Subtarget.hasP8Vector()))) - return MVT::v4i32; + if (Subtarget.hasAltivec() && Op.size() >= 16) { + if (Op.isMemset() && Subtarget.hasVSX()) { + uint64_t TailSize = Op.size() % 16; + // For memset lowering, EXTRACT_VECTOR_ELT tries to return constant + // element if vector element type matches tail store. For tail size + // 3/4, the tail store is i32, v4i32 cannot be used, need a legal one. + if (TailSize > 2 && TailSize <= 4) { + return MVT::v8i16; + } + return MVT::v4i32; + } + if (Op.isAligned(Align(16)) || Subtarget.hasP8Vector()) + return MVT::v4i32; + } } if (Subtarget.isPPC64()) { @@ -17227,7 +17299,7 @@ bool PPCTargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, bool PPCTargetLowering::isFMAFasterThanFMulAndFAdd(const Function &F, Type *Ty) const { - if (Subtarget.hasSPE()) + if (Subtarget.hasSPE() || Subtarget.useSoftFloat()) return false; switch (Ty->getScalarType()->getTypeID()) { case Type::FloatTyID: @@ -17431,7 +17503,7 @@ bool PPCTargetLowering::useLoadStackGuardNode() const { void PPCTargetLowering::insertSSPDeclarations(Module &M) const { if (Subtarget.isAIXABI()) { M.getOrInsertGlobal(AIXSSPCanaryWordName, - Type::getInt8PtrTy(M.getContext())); + PointerType::getUnqual(M.getContext())); return; } if (!Subtarget.isTargetLinux()) @@ -18539,9 +18611,7 @@ Value *PPCTargetLowering::emitMaskedAtomicRMWIntrinsic( Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty, "incr_lo"); Value *IncrHi = Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty, "incr_hi"); - Value *Addr = - Builder.CreateBitCast(AlignedAddr, Type::getInt8PtrTy(M->getContext())); - Value *LoHi = Builder.CreateCall(RMW, {Addr, IncrLo, IncrHi}); + Value *LoHi = Builder.CreateCall(RMW, {AlignedAddr, IncrLo, IncrHi}); Value *Lo = Builder.CreateExtractValue(LoHi, 0, "lo"); Value *Hi = Builder.CreateExtractValue(LoHi, 1, "hi"); Lo = Builder.CreateZExt(Lo, ValTy, "lo64"); @@ -18566,11 +18636,9 @@ Value *PPCTargetLowering::emitMaskedAtomicCmpXchgIntrinsic( Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty, "new_lo"); Value *NewHi = Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty, "new_hi"); - Value *Addr = - Builder.CreateBitCast(AlignedAddr, Type::getInt8PtrTy(M->getContext())); emitLeadingFence(Builder, CI, Ord); Value *LoHi = - Builder.CreateCall(IntCmpXchg, {Addr, CmpLo, CmpHi, NewLo, NewHi}); + Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi}); emitTrailingFence(Builder, CI, Ord); Value *Lo = Builder.CreateExtractValue(LoHi, 0, "lo"); Value *Hi = Builder.CreateExtractValue(LoHi, 1, "hi"); diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h index e6ebc68008fb..d8679dcf4018 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -356,9 +356,9 @@ namespace llvm { /// ADDIS_TLSGD_L_ADDR until after register assignment. GET_TLS_ADDR, - /// %x3 = GET_TPOINTER - Used for the local-exec TLS model on 32-bit AIX, - /// produces a call to .__get_tpointer to retrieve the thread pointer - /// At the end of the call, the thread pointer is found in R3. + /// %x3 = GET_TPOINTER - Used for the local- and initial-exec TLS model on + /// 32-bit AIX, produces a call to .__get_tpointer to retrieve the thread + /// pointer. At the end of the call, the thread pointer is found in R3. GET_TPOINTER, /// G8RC = ADDI_TLSGD_L_ADDR G8RReg, Symbol, Symbol - Op that @@ -791,6 +791,11 @@ namespace llvm { return true; } + bool + shallExtractConstSplatVectorElementToStore(Type *VectorTy, + unsigned ElemSizeInBits, + unsigned &Index) const override; + bool isCtlzFast() const override { return true; } @@ -970,21 +975,20 @@ namespace llvm { /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops, SelectionDAG &DAG) const override; - unsigned + InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override { if (ConstraintCode == "es") - return InlineAsm::Constraint_es; + return InlineAsm::ConstraintCode::es; else if (ConstraintCode == "Q") - return InlineAsm::Constraint_Q; + return InlineAsm::ConstraintCode::Q; else if (ConstraintCode == "Z") - return InlineAsm::Constraint_Z; + return InlineAsm::ConstraintCode::Z; else if (ConstraintCode == "Zy") - return InlineAsm::Constraint_Zy; + return InlineAsm::ConstraintCode::Zy; return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index fd44efa1b3f4..0322bb37b1fd 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -380,7 +380,7 @@ let mayStore = 1, mayLoad = 1, Defs = [CR0], Constraints = "@earlyclobber $scratch,@earlyclobber $RTp" in { // Atomic pseudo instructions expanded post-ra. -def ATOMIC_SWAP_I128 : AtomicRMW128<"#ATOMIC_SWAP_I128">; +def ATOMIC_SWAP_I128 : AtomicRMW128<"#ATOMIC_SWAP_I128">; def ATOMIC_LOAD_ADD_I128 : AtomicRMW128<"#ATOMIC_LOAD_ADD_I128">; def ATOMIC_LOAD_SUB_I128 : AtomicRMW128<"#ATOMIC_LOAD_SUB_I128">; def ATOMIC_LOAD_AND_I128 : AtomicRMW128<"#ATOMIC_LOAD_AND_I128">; @@ -395,48 +395,21 @@ def ATOMIC_CMP_SWAP_I128 : PPCPostRAExpPseudo< "#ATOMIC_CMP_SWAP_I128", []>; } -def : Pat<(int_ppc_atomicrmw_add_i128 ForceXForm:$ptr, - i64:$incr_lo, - i64:$incr_hi), - (SPLIT_QUADWORD (ATOMIC_LOAD_ADD_I128 memrr:$ptr, - g8rc:$incr_lo, - g8rc:$incr_hi))>; -def : Pat<(int_ppc_atomicrmw_sub_i128 ForceXForm:$ptr, - i64:$incr_lo, - i64:$incr_hi), - (SPLIT_QUADWORD (ATOMIC_LOAD_SUB_I128 memrr:$ptr, - g8rc:$incr_lo, - g8rc:$incr_hi))>; -def : Pat<(int_ppc_atomicrmw_xor_i128 ForceXForm:$ptr, - i64:$incr_lo, - i64:$incr_hi), - (SPLIT_QUADWORD (ATOMIC_LOAD_XOR_I128 memrr:$ptr, - g8rc:$incr_lo, - g8rc:$incr_hi))>; -def : Pat<(int_ppc_atomicrmw_and_i128 ForceXForm:$ptr, - i64:$incr_lo, - i64:$incr_hi), - (SPLIT_QUADWORD (ATOMIC_LOAD_AND_I128 memrr:$ptr, - g8rc:$incr_lo, - g8rc:$incr_hi))>; -def : Pat<(int_ppc_atomicrmw_nand_i128 ForceXForm:$ptr, - i64:$incr_lo, - i64:$incr_hi), - (SPLIT_QUADWORD (ATOMIC_LOAD_NAND_I128 memrr:$ptr, - g8rc:$incr_lo, - g8rc:$incr_hi))>; -def : Pat<(int_ppc_atomicrmw_or_i128 ForceXForm:$ptr, - i64:$incr_lo, - i64:$incr_hi), - (SPLIT_QUADWORD (ATOMIC_LOAD_OR_I128 memrr:$ptr, - g8rc:$incr_lo, - g8rc:$incr_hi))>; -def : Pat<(int_ppc_atomicrmw_xchg_i128 ForceXForm:$ptr, - i64:$incr_lo, - i64:$incr_hi), - (SPLIT_QUADWORD (ATOMIC_SWAP_I128 memrr:$ptr, - g8rc:$incr_lo, - g8rc:$incr_hi))>; +class PatAtomicRMWI128<SDPatternOperator OpNode, AtomicRMW128 Inst> : + Pat<(OpNode ForceXForm:$ptr, + i64:$incr_lo, + i64:$incr_hi), + (SPLIT_QUADWORD (Inst memrr:$ptr, + g8rc:$incr_lo, + g8rc:$incr_hi))>; + +def : PatAtomicRMWI128<int_ppc_atomicrmw_add_i128, ATOMIC_LOAD_ADD_I128>; +def : PatAtomicRMWI128<int_ppc_atomicrmw_sub_i128, ATOMIC_LOAD_SUB_I128>; +def : PatAtomicRMWI128<int_ppc_atomicrmw_xor_i128, ATOMIC_LOAD_XOR_I128>; +def : PatAtomicRMWI128<int_ppc_atomicrmw_and_i128, ATOMIC_LOAD_AND_I128>; +def : PatAtomicRMWI128<int_ppc_atomicrmw_nand_i128, ATOMIC_LOAD_NAND_I128>; +def : PatAtomicRMWI128<int_ppc_atomicrmw_or_i128, ATOMIC_LOAD_OR_I128>; +def : PatAtomicRMWI128<int_ppc_atomicrmw_xchg_i128, ATOMIC_SWAP_I128>; def : Pat<(int_ppc_cmpxchg_i128 ForceXForm:$ptr, i64:$cmp_lo, i64:$cmp_hi, @@ -1958,8 +1931,8 @@ def : Pat<(add i64:$in, (PPChi tblockaddress:$g, 0)), def : Pat<(i64 (PPCtoc_entry tglobaltlsaddr:$disp, i64:$reg)), (i64 (LDtoc tglobaltlsaddr:$disp, i64:$reg))>; -// The following pattern matches 64-bit local-exec TLS accesses on AIX. -// PPCaddTls is used in local-exec accesses in order to: +// The following pattern matches 64-bit local- and initial-exec TLS accesses on AIX. +// PPCaddTls is used in local- and initial-exec accesses in order to: // - Get the address of a variable (adding the variable offset to the thread // pointer in r13). // - Create an opportunity to optimize the user of the loaded address. @@ -1970,8 +1943,8 @@ def : Pat<(PPCaddTls i64:$in, i64:$addr), def : Pat<(atomic_load_64 DSForm:$src), (LD memrix:$src)>; def : Pat<(atomic_load_64 XForm:$src), (LDX memrr:$src)>; -def : Pat<(atomic_store_64 DSForm:$ptr, i64:$val), (STD g8rc:$val, memrix:$ptr)>; -def : Pat<(atomic_store_64 XForm:$ptr, i64:$val), (STDX g8rc:$val, memrr:$ptr)>; +def : Pat<(atomic_store_64 i64:$val, DSForm:$ptr), (STD g8rc:$val, memrix:$ptr)>; +def : Pat<(atomic_store_64 i64:$val, XForm:$ptr), (STDX g8rc:$val, memrr:$ptr)>; let Predicates = [IsISA3_0, In64BitMode] in { def : Pat<(i64 (int_ppc_cmpeqb g8rc:$a, g8rc:$b)), diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td index 224c7b281ac4..5389f42a325c 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrFormats.td @@ -220,7 +220,7 @@ BForm_4<bits<6> opcode, bits<5> bo, bit aa, bit lk, } // 1.7.3 SC-Form -class SCForm<bits<6> opcode, bits<1> xo, +class SCForm<bits<6> opcode, bits<1> xo1, bits<1> xo2, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : I<opcode, OOL, IOL, asmstr, itin> { @@ -229,7 +229,8 @@ class SCForm<bits<6> opcode, bits<1> xo, let Pattern = pattern; let Inst{20-26} = LEV; - let Inst{30} = xo; + let Inst{30} = xo1; + let Inst{31} = xo2; } // 1.7.4 D-Form @@ -724,6 +725,38 @@ class XForm_24_sync<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, let Inst{31} = 0; } +class XForm_IMM2_IMM2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list<dag> pattern> + : I<opcode, OOL, IOL, asmstr, itin> { + bits<2> L; + bits<2> PL; + + let Pattern = pattern; + let Inst{6-8} = 0; + let Inst{9-10} = L; + let Inst{11-13} = 0; + let Inst{14-15} = PL; + let Inst{16-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class XForm_IMM3_IMM2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list<dag> pattern> + : I<opcode, OOL, IOL, asmstr, itin> { + bits<3> L; + bits<2> SC; + + let Pattern = pattern; + let Inst{6-7} = 0; + let Inst{8-10} = L; + let Inst{11-13} = 0; + let Inst{14-15} = SC; + let Inst{16-20} = 0; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + class XForm_24_eieio<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : XForm_24_sync<opcode, xo, OOL, IOL, asmstr, itin, pattern> { diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 784953dbc847..d0a6cced1b19 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -17,11 +17,11 @@ #include "PPCInstrBuilder.h" #include "PPCMachineFunctionInfo.h" #include "PPCTargetMachine.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/LiveIntervals.h" +#include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineCombinerPattern.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -155,22 +155,21 @@ unsigned PPCInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, if (!MO.isReg() || !MO.isDef() || MO.isImplicit()) continue; - int Cycle = ItinData->getOperandCycle(DefClass, i); - if (Cycle < 0) + std::optional<unsigned> Cycle = ItinData->getOperandCycle(DefClass, i); + if (!Cycle) continue; - Latency = std::max(Latency, (unsigned) Cycle); + Latency = std::max(Latency, *Cycle); } return Latency; } -int PPCInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, - const MachineInstr &DefMI, unsigned DefIdx, - const MachineInstr &UseMI, - unsigned UseIdx) const { - int Latency = PPCGenInstrInfo::getOperandLatency(ItinData, DefMI, DefIdx, - UseMI, UseIdx); +std::optional<unsigned> PPCInstrInfo::getOperandLatency( + const InstrItineraryData *ItinData, const MachineInstr &DefMI, + unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const { + std::optional<unsigned> Latency = PPCGenInstrInfo::getOperandLatency( + ItinData, DefMI, DefIdx, UseMI, UseIdx); if (!DefMI.getParent()) return Latency; @@ -190,7 +189,7 @@ int PPCInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } if (UseMI.isBranch() && IsRegCR) { - if (Latency < 0) + if (!Latency) Latency = getInstrLatency(ItinData, DefMI); // On some cores, there is an additional delay between writing to a condition @@ -210,34 +209,14 @@ int PPCInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case PPC::DIR_PWR7: case PPC::DIR_PWR8: // FIXME: Is this needed for POWER9? - Latency += 2; - break; + Latency = *Latency + 2; + break; } } return Latency; } -/// This is an architecture-specific helper function of reassociateOps. -/// Set special operand attributes for new instructions after reassociation. -void PPCInstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1, - MachineInstr &OldMI2, - MachineInstr &NewMI1, - MachineInstr &NewMI2) const { - // Propagate FP flags from the original instructions. - // But clear poison-generating flags because those may not be valid now. - uint32_t IntersectedFlags = OldMI1.getFlags() & OldMI2.getFlags(); - NewMI1.setFlags(IntersectedFlags); - NewMI1.clearFlag(MachineInstr::MIFlag::NoSWrap); - NewMI1.clearFlag(MachineInstr::MIFlag::NoUWrap); - NewMI1.clearFlag(MachineInstr::MIFlag::IsExact); - - NewMI2.setFlags(IntersectedFlags); - NewMI2.clearFlag(MachineInstr::MIFlag::NoSWrap); - NewMI2.clearFlag(MachineInstr::MIFlag::NoUWrap); - NewMI2.clearFlag(MachineInstr::MIFlag::IsExact); -} - void PPCInstrInfo::setSpecialOperandAttr(MachineInstr &MI, uint32_t Flags) const { MI.setFlags(Flags); @@ -763,7 +742,7 @@ bool PPCInstrInfo::getMachineCombinerPatterns( bool DoRegPressureReduce) const { // Using the machine combiner in this way is potentially expensive, so // restrict to when aggressive optimizations are desired. - if (Subtarget.getTargetMachine().getOptLevel() != CodeGenOpt::Aggressive) + if (Subtarget.getTargetMachine().getOptLevel() != CodeGenOptLevel::Aggressive) return false; if (getFMAPatterns(Root, Patterns, DoRegPressureReduce)) @@ -1121,7 +1100,7 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable( case PPC::XXSETACCZW: return true; } - return false; + return TargetInstrInfo::isReallyTriviallyReMaterializable(MI); } unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr &MI, @@ -1174,8 +1153,8 @@ MachineInstr *PPCInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, // If machine instrs are no longer in two-address forms, update // destination register as well. if (Reg0 == Reg1) { - // Must be two address instruction! - assert(MI.getDesc().getOperandConstraint(0, MCOI::TIED_TO) && + // Must be two address instruction (i.e. op1 is tied to op0). + assert(MI.getDesc().getOperandConstraint(1, MCOI::TIED_TO) == 0 && "Expecting a two-address instruction!"); assert(MI.getOperand(0).getSubReg() == SubReg1 && "Tied subreg mismatch"); Reg2IsKill = false; @@ -1530,6 +1509,9 @@ bool PPCInstrInfo::canInsertSelect(const MachineBasicBlock &MBB, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const { + if (!Subtarget.hasISEL()) + return false; + if (Cond.size() != 2) return false; @@ -2833,10 +2815,6 @@ bool PPCInstrInfo::optimizeCmpPostRA(MachineInstr &CmpMI) const { .addReg(CRReg, RegState::ImplicitDefine); SrcMI->clearRegisterDeads(CRReg); - // Fix up killed/dead flag for SrcReg after transformation. - if (SrcRegHasOtherUse || CmpMI.getOperand(1).isKill()) - fixupIsDeadOrKill(SrcMI, &CmpMI, SrcReg); - assert(SrcMI->definesRegister(PPC::CR0) && "Record-form instruction does not define cr0?"); @@ -2899,8 +2877,9 @@ static bool isClusterableLdStOpcPair(unsigned FirstOpc, unsigned SecondOpc, } bool PPCInstrInfo::shouldClusterMemOps( - ArrayRef<const MachineOperand *> BaseOps1, - ArrayRef<const MachineOperand *> BaseOps2, unsigned NumLoads, + ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1, + bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2, + int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const { assert(BaseOps1.size() == 1 && BaseOps2.size() == 1); @@ -2909,9 +2888,10 @@ bool PPCInstrInfo::shouldClusterMemOps( assert((BaseOp1.isReg() || BaseOp1.isFI()) && "Only base registers and frame indices are supported."); - // The NumLoads means the number of loads that has been clustered. + // ClusterSize means the number of memory operations that will have been + // clustered if this hook returns true. // Don't cluster memory op if there are already two ops clustered at least. - if (NumLoads > 2) + if (ClusterSize > 2) return false; // Cluster the load/store only when they have the same base @@ -2976,41 +2956,40 @@ unsigned PPCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { std::pair<unsigned, unsigned> PPCInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { - const unsigned Mask = PPCII::MO_ACCESS_MASK; - return std::make_pair(TF & Mask, TF & ~Mask); + // PPC always uses a direct mask. + return std::make_pair(TF, 0u); } ArrayRef<std::pair<unsigned, const char *>> PPCInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { using namespace PPCII; static const std::pair<unsigned, const char *> TargetFlags[] = { - {MO_LO, "ppc-lo"}, - {MO_HA, "ppc-ha"}, - {MO_TPREL_LO, "ppc-tprel-lo"}, - {MO_TPREL_HA, "ppc-tprel-ha"}, - {MO_DTPREL_LO, "ppc-dtprel-lo"}, - {MO_TLSLD_LO, "ppc-tlsld-lo"}, - {MO_TOC_LO, "ppc-toc-lo"}, - {MO_TLS, "ppc-tls"}}; - return ArrayRef(TargetFlags); -} - -ArrayRef<std::pair<unsigned, const char *>> -PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { - using namespace PPCII; - static const std::pair<unsigned, const char *> TargetFlags[] = { {MO_PLT, "ppc-plt"}, {MO_PIC_FLAG, "ppc-pic"}, {MO_PCREL_FLAG, "ppc-pcrel"}, {MO_GOT_FLAG, "ppc-got"}, {MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"}, {MO_TLSGD_FLAG, "ppc-tlsgd"}, - {MO_TLSLD_FLAG, "ppc-tlsld"}, {MO_TPREL_FLAG, "ppc-tprel"}, + {MO_TLSLD_FLAG, "ppc-tlsld"}, {MO_TLSGDM_FLAG, "ppc-tlsgdm"}, {MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"}, {MO_GOT_TLSLD_PCREL_FLAG, "ppc-got-tlsld-pcrel"}, - {MO_GOT_TPREL_PCREL_FLAG, "ppc-got-tprel-pcrel"}}; + {MO_GOT_TPREL_PCREL_FLAG, "ppc-got-tprel-pcrel"}, + {MO_LO, "ppc-lo"}, + {MO_HA, "ppc-ha"}, + {MO_TPREL_LO, "ppc-tprel-lo"}, + {MO_TPREL_HA, "ppc-tprel-ha"}, + {MO_DTPREL_LO, "ppc-dtprel-lo"}, + {MO_TLSLD_LO, "ppc-tlsld-lo"}, + {MO_TOC_LO, "ppc-toc-lo"}, + {MO_TLS, "ppc-tls"}, + {MO_PIC_HA_FLAG, "ppc-ha-pic"}, + {MO_PIC_LO_FLAG, "ppc-lo-pic"}, + {MO_TPREL_PCREL_FLAG, "ppc-tprel-pcrel"}, + {MO_TLS_PCREL_FLAG, "ppc-tls-pcrel"}, + {MO_GOT_PCREL_FLAG, "ppc-got-pcrel"}, + }; return ArrayRef(TargetFlags); } @@ -3412,7 +3391,7 @@ MachineInstr *PPCInstrInfo::getForwardingDefMI( Opc == PPC::RLWINM || Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8 || Opc == PPC::RLWINM8_rec; bool IsVFReg = (MI.getNumOperands() && MI.getOperand(0).isReg()) - ? isVFRegister(MI.getOperand(0).getReg()) + ? PPC::isVFRegister(MI.getOperand(0).getReg()) : false; if (!ConvertibleImmForm && !instrHasImmForm(Opc, IsVFReg, III, true)) return nullptr; @@ -3467,101 +3446,6 @@ ArrayRef<unsigned> PPCInstrInfo::getLoadOpcodesForSpillArray() const { return {LoadSpillOpcodesArray[getSpillTarget()], SOK_LastOpcodeSpill}; } -void PPCInstrInfo::fixupIsDeadOrKill(MachineInstr *StartMI, MachineInstr *EndMI, - unsigned RegNo) const { - // Conservatively clear kill flag for the register if the instructions are in - // different basic blocks and in SSA form, because the kill flag may no longer - // be right. There is no need to bother with dead flags since defs with no - // uses will be handled by DCE. - MachineRegisterInfo &MRI = StartMI->getParent()->getParent()->getRegInfo(); - if (MRI.isSSA() && (StartMI->getParent() != EndMI->getParent())) { - MRI.clearKillFlags(RegNo); - return; - } - - // Instructions between [StartMI, EndMI] should be in same basic block. - assert((StartMI->getParent() == EndMI->getParent()) && - "Instructions are not in same basic block"); - - // If before RA, StartMI may be def through COPY, we need to adjust it to the - // real def. See function getForwardingDefMI. - if (MRI.isSSA()) { - bool Reads, Writes; - std::tie(Reads, Writes) = StartMI->readsWritesVirtualRegister(RegNo); - if (!Reads && !Writes) { - assert(Register::isVirtualRegister(RegNo) && - "Must be a virtual register"); - // Get real def and ignore copies. - StartMI = MRI.getVRegDef(RegNo); - } - } - - bool IsKillSet = false; - - auto clearOperandKillInfo = [=] (MachineInstr &MI, unsigned Index) { - MachineOperand &MO = MI.getOperand(Index); - if (MO.isReg() && MO.isUse() && MO.isKill() && - getRegisterInfo().regsOverlap(MO.getReg(), RegNo)) - MO.setIsKill(false); - }; - - // Set killed flag for EndMI. - // No need to do anything if EndMI defines RegNo. - int UseIndex = - EndMI->findRegisterUseOperandIdx(RegNo, false, &getRegisterInfo()); - if (UseIndex != -1) { - EndMI->getOperand(UseIndex).setIsKill(true); - IsKillSet = true; - // Clear killed flag for other EndMI operands related to RegNo. In some - // upexpected cases, killed may be set multiple times for same register - // operand in same MI. - for (int i = 0, e = EndMI->getNumOperands(); i != e; ++i) - if (i != UseIndex) - clearOperandKillInfo(*EndMI, i); - } - - // Walking the inst in reverse order (EndMI -> StartMI]. - MachineBasicBlock::reverse_iterator It = *EndMI; - MachineBasicBlock::reverse_iterator E = EndMI->getParent()->rend(); - // EndMI has been handled above, skip it here. - It++; - MachineOperand *MO = nullptr; - for (; It != E; ++It) { - // Skip insturctions which could not be a def/use of RegNo. - if (It->isDebugInstr() || It->isPosition()) - continue; - - // Clear killed flag for all It operands related to RegNo. In some - // upexpected cases, killed may be set multiple times for same register - // operand in same MI. - for (int i = 0, e = It->getNumOperands(); i != e; ++i) - clearOperandKillInfo(*It, i); - - // If killed is not set, set killed for its last use or set dead for its def - // if no use found. - if (!IsKillSet) { - if ((MO = It->findRegisterUseOperand(RegNo, false, &getRegisterInfo()))) { - // Use found, set it killed. - IsKillSet = true; - MO->setIsKill(true); - continue; - } else if ((MO = It->findRegisterDefOperand(RegNo, false, true, - &getRegisterInfo()))) { - // No use found, set dead for its def. - assert(&*It == StartMI && "No new def between StartMI and EndMI."); - MO->setIsDead(true); - break; - } - } - - if ((&*It) == StartMI) - break; - } - // Ensure RegMo liveness is killed after EndMI. - assert((IsKillSet || (MO && MO->isDead())) && - "RegNo should be killed or dead"); -} - // This opt tries to convert the following imm form to an index form to save an // add for stack variables. // Return false if no such pattern found. @@ -3725,8 +3609,8 @@ bool PPCInstrInfo::isImmInstrEligibleForFolding(MachineInstr &MI, return false; // TODO: sync the logic between instrHasImmForm() and ImmToIdxMap. - if (!instrHasImmForm(XFormOpcode, isVFRegister(MI.getOperand(0).getReg()), - III, true)) + if (!instrHasImmForm(XFormOpcode, + PPC::isVFRegister(MI.getOperand(0).getReg()), III, true)) return false; if (!III.IsSummingOperands) @@ -3796,6 +3680,7 @@ bool PPCInstrInfo::isValidToBeChangedReg(MachineInstr *ADDMI, unsigned Index, // result of a load-immediate or an add-immediate, convert it to // the immediate form if the constant is in range. bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, + SmallSet<Register, 4> &RegsToUpdate, MachineInstr **KilledDef) const { MachineFunction *MF = MI.getParent()->getParent(); MachineRegisterInfo *MRI = &MF->getRegInfo(); @@ -3813,6 +3698,15 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, if (KilledDef && KillFwdDefMI) *KilledDef = DefMI; + // Conservatively add defs from DefMI and defs/uses from MI to the set of + // registers that need their kill flags updated. + for (const MachineOperand &MO : DefMI->operands()) + if (MO.isReg() && MO.isDef()) + RegsToUpdate.insert(MO.getReg()); + for (const MachineOperand &MO : MI.operands()) + if (MO.isReg()) + RegsToUpdate.insert(MO.getReg()); + // If this is a imm instruction and its register operands is produced by ADDI, // put the imm into imm inst directly. if (RI.getMappedIdxOpcForImmOpc(MI.getOpcode()) != @@ -3822,7 +3716,7 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, ImmInstrInfo III; bool IsVFReg = MI.getOperand(0).isReg() - ? isVFRegister(MI.getOperand(0).getReg()) + ? PPC::isVFRegister(MI.getOperand(0).getReg()) : false; bool HasImmForm = instrHasImmForm(MI.getOpcode(), IsVFReg, III, PostRA); // If this is a reg+reg instruction that has a reg+imm form, @@ -4615,9 +4509,6 @@ bool PPCInstrInfo::simplifyToLI(MachineInstr &MI, MachineInstr &DefMI, // Sign-extend to 64-bits. int64_t SExtImm = SignExtend64<16>(Immediate); - bool IsForwardingOperandKilled = MI.getOperand(OpNoForForwarding).isKill(); - Register ForwardingOperandReg = MI.getOperand(OpNoForForwarding).getReg(); - bool ReplaceWithLI = false; bool Is64BitLI = false; int64_t NewImm = 0; @@ -4829,12 +4720,8 @@ bool PPCInstrInfo::simplifyToLI(MachineInstr &MI, MachineInstr &DefMI, *KilledDef = nullptr; replaceInstrWithLI(MI, LII); - // Fixup killed/dead flag after transformation. - // Pattern: - // ForwardingOperandReg = LI imm1 - // y = op2 imm2, ForwardingOperandReg(killed) - if (IsForwardingOperandKilled) - fixupIsDeadOrKill(&DefMI, &MI, ForwardingOperandReg); + if (PostRA) + recomputeLivenessFlags(*MI.getParent()); LLVM_DEBUG(dbgs() << "With:\n"); LLVM_DEBUG(MI.dump()); @@ -4864,7 +4751,7 @@ bool PPCInstrInfo::transformToNewImmFormFedByAdd( // get Imm Form info. ImmInstrInfo III; bool IsVFReg = MI.getOperand(0).isReg() - ? isVFRegister(MI.getOperand(0).getReg()) + ? PPC::isVFRegister(MI.getOperand(0).getReg()) : false; if (!instrHasImmForm(XFormOpcode, IsVFReg, III, PostRA)) @@ -4895,11 +4782,6 @@ bool PPCInstrInfo::transformToNewImmFormFedByAdd( if (!isImmElgibleForForwarding(*ImmMO, DefMI, III, Imm, ImmBase)) return false; - // Get killed info in case fixup needed after transformation. - unsigned ForwardKilledOperandReg = ~0U; - if (MI.getOperand(III.OpNoForForwarding).isKill()) - ForwardKilledOperandReg = MI.getOperand(III.OpNoForForwarding).getReg(); - // Do the transform LLVM_DEBUG(dbgs() << "Replacing existing reg+imm instruction:\n"); LLVM_DEBUG(MI.dump()); @@ -4907,35 +4789,8 @@ bool PPCInstrInfo::transformToNewImmFormFedByAdd( LLVM_DEBUG(DefMI.dump()); MI.getOperand(III.OpNoForForwarding).setReg(RegMO->getReg()); - if (RegMO->isKill()) { - MI.getOperand(III.OpNoForForwarding).setIsKill(true); - // Clear the killed flag in RegMO. Doing this here can handle some cases - // that DefMI and MI are not in same basic block. - RegMO->setIsKill(false); - } MI.getOperand(III.ImmOpNo).setImm(Imm); - // FIXME: fix kill/dead flag if MI and DefMI are not in same basic block. - if (DefMI.getParent() == MI.getParent()) { - // Check if reg is killed between MI and DefMI. - auto IsKilledFor = [&](unsigned Reg) { - MachineBasicBlock::const_reverse_iterator It = MI; - MachineBasicBlock::const_reverse_iterator E = DefMI; - It++; - for (; It != E; ++It) { - if (It->killsRegister(Reg)) - return true; - } - return false; - }; - - // Update kill flag - if (RegMO->isKill() || IsKilledFor(RegMO->getReg())) - fixupIsDeadOrKill(&DefMI, &MI, RegMO->getReg()); - if (ForwardKilledOperandReg != ~0U) - fixupIsDeadOrKill(&DefMI, &MI, ForwardKilledOperandReg); - } - LLVM_DEBUG(dbgs() << "With:\n"); LLVM_DEBUG(MI.dump()); return true; @@ -4979,12 +4834,8 @@ bool PPCInstrInfo::transformToImmFormFedByAdd( IsFwdFeederRegKilled, SeenIntermediateUse)) return false; - // Get killed info in case fixup needed after transformation. - unsigned ForwardKilledOperandReg = ~0U; MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); bool PostRA = !MRI.isSSA(); - if (PostRA && MI.getOperand(OpNoForForwarding).isKill()) - ForwardKilledOperandReg = MI.getOperand(OpNoForForwarding).getReg(); // We know that, the MI and DefMI both meet the pattern, and // the Imm also meet the requirement with the new Imm-form. @@ -5036,22 +4887,8 @@ bool PPCInstrInfo::transformToImmFormFedByAdd( // Update the opcode. MI.setDesc(get(III.ImmOpcode)); - // Fix up killed/dead flag after transformation. - // Pattern 1: - // x = ADD KilledFwdFeederReg, imm - // n = opn KilledFwdFeederReg(killed), regn - // y = XOP 0, x - // Pattern 2: - // x = ADD reg(killed), imm - // y = XOP 0, x - if (IsFwdFeederRegKilled || RegMO->isKill()) - fixupIsDeadOrKill(&DefMI, &MI, RegMO->getReg()); - // Pattern 3: - // ForwardKilledOperandReg = ADD reg, imm - // y = XOP 0, ForwardKilledOperandReg(killed) - if (ForwardKilledOperandReg != ~0U) - fixupIsDeadOrKill(&DefMI, &MI, ForwardKilledOperandReg); - + if (PostRA) + recomputeLivenessFlags(*MI.getParent()); LLVM_DEBUG(dbgs() << "With:\n"); LLVM_DEBUG(MI.dump()); @@ -5107,11 +4944,6 @@ bool PPCInstrInfo::transformToImmFormFedByLI(MachineInstr &MI, return false; } - // Get killed info in case fixup needed after transformation. - unsigned ForwardKilledOperandReg = ~0U; - if (PostRA && MI.getOperand(ConstantOpNo).isKill()) - ForwardKilledOperandReg = MI.getOperand(ConstantOpNo).getReg(); - unsigned Opc = MI.getOpcode(); bool SpecialShift32 = Opc == PPC::SLW || Opc == PPC::SLW_rec || Opc == PPC::SRW || Opc == PPC::SRW_rec || @@ -5205,12 +5037,8 @@ bool PPCInstrInfo::transformToImmFormFedByLI(MachineInstr &MI, } } - // Fix up killed/dead flag after transformation. - // Pattern: - // ForwardKilledOperandReg = LI imm - // y = XOP reg, ForwardKilledOperandReg(killed) - if (ForwardKilledOperandReg != ~0U) - fixupIsDeadOrKill(&DefMI, &MI, ForwardKilledOperandReg); + if (PostRA) + recomputeLivenessFlags(*MI.getParent()); LLVM_DEBUG(dbgs() << "With: "); LLVM_DEBUG(MI.dump()); diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h index 3dc5e2680c61..75f9cd1c206d 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h @@ -13,7 +13,10 @@ #ifndef LLVM_LIB_TARGET_POWERPC_PPCINSTRINFO_H #define LLVM_LIB_TARGET_POWERPC_PPCINSTRINFO_H +#include "MCTargetDesc/PPCMCTargetDesc.h" +#include "PPC.h" #include "PPCRegisterInfo.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/TargetInstrInfo.h" #define GET_INSTRINFO_HEADER @@ -21,60 +24,6 @@ namespace llvm { -/// PPCII - This namespace holds all of the PowerPC target-specific -/// per-instruction flags. These must match the corresponding definitions in -/// PPC.td and PPCInstrFormats.td. -namespace PPCII { -enum { - // PPC970 Instruction Flags. These flags describe the characteristics of the - // PowerPC 970 (aka G5) dispatch groups and how they are formed out of - // raw machine instructions. - - /// PPC970_First - This instruction starts a new dispatch group, so it will - /// always be the first one in the group. - PPC970_First = 0x1, - - /// PPC970_Single - This instruction starts a new dispatch group and - /// terminates it, so it will be the sole instruction in the group. - PPC970_Single = 0x2, - - /// PPC970_Cracked - This instruction is cracked into two pieces, requiring - /// two dispatch pipes to be available to issue. - PPC970_Cracked = 0x4, - - /// PPC970_Mask/Shift - This is a bitmask that selects the pipeline type that - /// an instruction is issued to. - PPC970_Shift = 3, - PPC970_Mask = 0x07 << PPC970_Shift -}; -enum PPC970_Unit { - /// These are the various PPC970 execution unit pipelines. Each instruction - /// is one of these. - PPC970_Pseudo = 0 << PPC970_Shift, // Pseudo instruction - PPC970_FXU = 1 << PPC970_Shift, // Fixed Point (aka Integer/ALU) Unit - PPC970_LSU = 2 << PPC970_Shift, // Load Store Unit - PPC970_FPU = 3 << PPC970_Shift, // Floating Point Unit - PPC970_CRU = 4 << PPC970_Shift, // Control Register Unit - PPC970_VALU = 5 << PPC970_Shift, // Vector ALU - PPC970_VPERM = 6 << PPC970_Shift, // Vector Permute Unit - PPC970_BRU = 7 << PPC970_Shift // Branch Unit -}; - -enum { - /// Shift count to bypass PPC970 flags - NewDef_Shift = 6, - - /// This instruction is an X-Form memory operation. - XFormMemOp = 0x1 << NewDef_Shift, - /// This instruction is prefixed. - Prefixed = 0x1 << (NewDef_Shift + 1), - /// This instruction produced a sign extended result. - SExt32To64 = 0x1 << (NewDef_Shift + 2), - /// This instruction produced a zero extended result. - ZExt32To64 = 0x1 << (NewDef_Shift + 3) -}; -} // end namespace PPCII - // Instructions that have an immediate form might be convertible to that // form if the correct input is a result of a load immediate. In order to // know whether the transformation is special, we might need to know some @@ -324,99 +273,6 @@ public: return get(Opcode).TSFlags & PPCII::ZExt32To64; } - /// Check if Opcode corresponds to a call instruction that should be marked - /// with the NOTOC relocation. - bool isNoTOCCallInstr(unsigned Opcode) const { - if (!get(Opcode).isCall()) - return false; - - switch (Opcode) { - default: -#ifndef NDEBUG - llvm_unreachable("Unknown call opcode"); -#endif - return false; - case PPC::BL8_NOTOC: - case PPC::BL8_NOTOC_TLS: - case PPC::BL8_NOTOC_RM: - return true; -#ifndef NDEBUG - case PPC::BL8: - case PPC::BL: - case PPC::BL8_TLS: - case PPC::BL_TLS: - case PPC::BLA8: - case PPC::BLA: - case PPC::BCCL: - case PPC::BCCLA: - case PPC::BCL: - case PPC::BCLn: - case PPC::BL8_NOP: - case PPC::BL_NOP: - case PPC::BL8_NOP_TLS: - case PPC::BLA8_NOP: - case PPC::BCTRL8: - case PPC::BCTRL: - case PPC::BCCCTRL8: - case PPC::BCCCTRL: - case PPC::BCCTRL8: - case PPC::BCCTRL: - case PPC::BCCTRL8n: - case PPC::BCCTRLn: - case PPC::BL8_RM: - case PPC::BLA8_RM: - case PPC::BL8_NOP_RM: - case PPC::BLA8_NOP_RM: - case PPC::BCTRL8_RM: - case PPC::BCTRL8_LDinto_toc: - case PPC::BCTRL8_LDinto_toc_RM: - case PPC::BL8_TLS_: - case PPC::TCRETURNdi8: - case PPC::TCRETURNai8: - case PPC::TCRETURNri8: - case PPC::TAILBCTR8: - case PPC::TAILB8: - case PPC::TAILBA8: - case PPC::BCLalways: - case PPC::BLRL: - case PPC::BCCLRL: - case PPC::BCLRL: - case PPC::BCLRLn: - case PPC::BDZL: - case PPC::BDNZL: - case PPC::BDZLA: - case PPC::BDNZLA: - case PPC::BDZLp: - case PPC::BDNZLp: - case PPC::BDZLAp: - case PPC::BDNZLAp: - case PPC::BDZLm: - case PPC::BDNZLm: - case PPC::BDZLAm: - case PPC::BDNZLAm: - case PPC::BDZLRL: - case PPC::BDNZLRL: - case PPC::BDZLRLp: - case PPC::BDNZLRLp: - case PPC::BDZLRLm: - case PPC::BDNZLRLm: - case PPC::BL_RM: - case PPC::BLA_RM: - case PPC::BL_NOP_RM: - case PPC::BCTRL_RM: - case PPC::TCRETURNdi: - case PPC::TCRETURNai: - case PPC::TCRETURNri: - case PPC::BCTRL_LWZinto_toc: - case PPC::BCTRL_LWZinto_toc_RM: - case PPC::TAILBCTR: - case PPC::TAILB: - case PPC::TAILBA: - return false; -#endif - } - } - static bool isSameClassPhysRegCopy(unsigned Opcode) { unsigned CopyOpcodes[] = {PPC::OR, PPC::OR8, PPC::FMR, PPC::VOR, PPC::XXLOR, PPC::XXLORf, @@ -428,6 +284,32 @@ public: return false; } + static bool hasPCRelFlag(unsigned TF) { + return TF == PPCII::MO_PCREL_FLAG || TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG || + TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG || + TF == PPCII::MO_GOT_TPREL_PCREL_FLAG || + TF == PPCII::MO_TPREL_PCREL_FLAG || TF == PPCII::MO_TLS_PCREL_FLAG || + TF == PPCII::MO_GOT_PCREL_FLAG; + } + + static bool hasGOTFlag(unsigned TF) { + return TF == PPCII::MO_GOT_FLAG || TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG || + TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG || + TF == PPCII::MO_GOT_TPREL_PCREL_FLAG || + TF == PPCII::MO_GOT_PCREL_FLAG; + } + + static bool hasTLSFlag(unsigned TF) { + return TF == PPCII::MO_TLSGD_FLAG || TF == PPCII::MO_TPREL_FLAG || + TF == PPCII::MO_TLSLD_FLAG || TF == PPCII::MO_TLSGDM_FLAG || + TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG || + TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG || + TF == PPCII::MO_GOT_TPREL_PCREL_FLAG || TF == PPCII::MO_TPREL_LO || + TF == PPCII::MO_TPREL_HA || TF == PPCII::MO_DTPREL_LO || + TF == PPCII::MO_TLSLD_LO || TF == PPCII::MO_TLS || + TF == PPCII::MO_TPREL_PCREL_FLAG || TF == PPCII::MO_TLS_PCREL_FLAG; + } + ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const override; @@ -439,13 +321,15 @@ public: const MachineInstr &MI, unsigned *PredCost = nullptr) const override; - int getOperandLatency(const InstrItineraryData *ItinData, - const MachineInstr &DefMI, unsigned DefIdx, - const MachineInstr &UseMI, - unsigned UseIdx) const override; - int getOperandLatency(const InstrItineraryData *ItinData, - SDNode *DefNode, unsigned DefIdx, - SDNode *UseNode, unsigned UseIdx) const override { + std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr &DefMI, + unsigned DefIdx, + const MachineInstr &UseMI, + unsigned UseIdx) const override; + std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData, + SDNode *DefNode, unsigned DefIdx, + SDNode *UseNode, + unsigned UseIdx) const override { return PPCGenInstrInfo::getOperandLatency(ItinData, DefNode, DefIdx, UseNode, UseIdx); } @@ -512,12 +396,9 @@ public: /// perserved for more FMA chain reassociations on PowerPC. int getExtendResourceLenLimit() const override { return 1; } - void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2, - MachineInstr &NewMI1, - MachineInstr &NewMI2) const override; - // PowerPC specific version of setSpecialOperandAttr that copies Flags to MI // and clears nuw, nsw, and exact flags. + using TargetInstrInfo::setSpecialOperandAttr; void setSpecialOperandAttr(MachineInstr &MI, uint32_t Flags) const; bool isCoalescableExtInstr(const MachineInstr &MI, @@ -678,8 +559,11 @@ public: /// Returns true if the two given memory operations should be scheduled /// adjacent. bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1, + int64_t Offset1, bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2, - unsigned NumLoads, unsigned NumBytes) const override; + int64_t Offset2, bool OffsetIsScalable2, + unsigned ClusterSize, + unsigned NumBytes) const override; /// Return true if two MIs access different memory addresses and false /// otherwise @@ -700,21 +584,12 @@ public: ArrayRef<std::pair<unsigned, const char *>> getSerializableDirectMachineOperandTargetFlags() const override; - ArrayRef<std::pair<unsigned, const char *>> - getSerializableBitmaskMachineOperandTargetFlags() const override; - // Expand VSX Memory Pseudo instruction to either a VSX or a FP instruction. bool expandVSXMemPseudo(MachineInstr &MI) const; // Lower pseudo instructions after register allocation. bool expandPostRAPseudo(MachineInstr &MI) const override; - static bool isVFRegister(unsigned Reg) { - return Reg >= PPC::VF0 && Reg <= PPC::VF31; - } - static bool isVRRegister(unsigned Reg) { - return Reg >= PPC::V0 && Reg <= PPC::V31; - } const TargetRegisterClass *updatedRC(const TargetRegisterClass *RC) const; static int getRecordFormOpcode(unsigned Opcode); @@ -737,6 +612,7 @@ public: } bool convertToImmediateForm(MachineInstr &MI, + SmallSet<Register, 4> &RegsToUpdate, MachineInstr **KilledDef = nullptr) const; bool foldFrameOffset(MachineInstr &MI) const; bool combineRLWINM(MachineInstr &MI, MachineInstr **ToErase = nullptr) const; @@ -750,23 +626,6 @@ public: MachineInstr *&ADDIMI, int64_t &OffsetAddi, int64_t OffsetImm) const; - /// Fixup killed/dead flag for register \p RegNo between instructions [\p - /// StartMI, \p EndMI]. Some pre-RA or post-RA transformations may violate - /// register killed/dead flags semantics, this function can be called to fix - /// up. Before calling this function, - /// 1. Ensure that \p RegNo liveness is killed after instruction \p EndMI. - /// 2. Ensure that there is no new definition between (\p StartMI, \p EndMI) - /// and possible definition for \p RegNo is \p StartMI or \p EndMI. For - /// pre-RA cases, definition may be \p StartMI through COPY, \p StartMI - /// will be adjust to true definition. - /// 3. We can do accurate fixup for the case when all instructions between - /// [\p StartMI, \p EndMI] are in same basic block. - /// 4. For the case when \p StartMI and \p EndMI are not in same basic block, - /// we conservatively clear kill flag for all uses of \p RegNo for pre-RA - /// and for post-RA, we give an assertion as without reaching definition - /// analysis post-RA, \p StartMI and \p EndMI are hard to keep right. - void fixupIsDeadOrKill(MachineInstr *StartMI, MachineInstr *EndMI, - unsigned RegNo) const; void replaceInstrWithLI(MachineInstr &MI, const LoadImmediateInfo &LII) const; void replaceInstrOperandWithImm(MachineInstr &MI, unsigned OpNo, int64_t Imm) const; @@ -785,38 +644,6 @@ public: const DebugLoc &DL, Register Reg, int64_t Imm) const; - /// getRegNumForOperand - some operands use different numbering schemes - /// for the same registers. For example, a VSX instruction may have any of - /// vs0-vs63 allocated whereas an Altivec instruction could only have - /// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual - /// register number needed for the opcode/operand number combination. - /// The operand number argument will be useful when we need to extend this - /// to instructions that use both Altivec and VSX numbering (for different - /// operands). - static unsigned getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg, - unsigned OpNo) { - int16_t regClass = Desc.operands()[OpNo].RegClass; - switch (regClass) { - // We store F0-F31, VF0-VF31 in MCOperand and it should be F0-F31, - // VSX32-VSX63 during encoding/disassembling - case PPC::VSSRCRegClassID: - case PPC::VSFRCRegClassID: - if (isVFRegister(Reg)) - return PPC::VSX32 + (Reg - PPC::VF0); - break; - // We store VSL0-VSL31, V0-V31 in MCOperand and it should be VSL0-VSL31, - // VSX32-VSX63 during encoding/disassembling - case PPC::VSRCRegClassID: - if (isVRRegister(Reg)) - return PPC::VSX32 + (Reg - PPC::V0); - break; - // Other RegClass doesn't need mapping - default: - break; - } - return Reg; - } - /// Check \p Opcode is BDNZ (Decrement CTR and branch if it is still nonzero). bool isBDNZ(unsigned Opcode) const; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 2992f78aa38a..6199785206b2 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -1641,10 +1641,18 @@ let isBranch = 1, isTerminator = 1, Size = 0 in { // System call. let PPC970_Unit = 7 in { - def SC : SCForm<17, 1, (outs), (ins i32imm:$LEV), + def SC : SCForm<17, 1, 0, (outs), (ins i32imm:$LEV), "sc $LEV", IIC_BrB, [(PPCsc (i32 imm:$LEV))]>; } +// We mark SCV as having no scheduling model since it is only meant to be used +// as inline assembly. If we implement a builtin pattern for it we will need to +// add it to the P9 and P10 scheduling models. +let Predicates = [IsISA3_0], hasNoSchedulingInfo = 1 in { + def SCV : SCForm<17, 0, 1, (outs), (ins i32imm:$LEV), + "scv $LEV", IIC_BrB, []>; +} + // Branch history rolling buffer. def CLRBHRB : XForm_0<31, 430, (outs), (ins), "clrbhrb", IIC_BrB, [(PPCclrbhrb)]>, @@ -1713,11 +1721,11 @@ def : Pat<(int_ppc_dcbf xoaddr:$dst), def : Pat<(int_ppc_icbt xoaddr:$dst), (ICBT 0, xoaddr:$dst)>; -def : Pat<(prefetch xoaddr:$dst, (i32 0), imm, (i32 1)), +def : Pat<(prefetch xoaddr:$dst, (i32 0), timm, (i32 1)), (DCBT 0, xoaddr:$dst)>; // data prefetch for loads -def : Pat<(prefetch xoaddr:$dst, (i32 1), imm, (i32 1)), +def : Pat<(prefetch xoaddr:$dst, (i32 1), timm, (i32 1)), (DCBTST 0, xoaddr:$dst)>; // data prefetch for stores -def : Pat<(prefetch xoaddr:$dst, (i32 0), imm, (i32 0)), +def : Pat<(prefetch xoaddr:$dst, (i32 0), timm, (i32 0)), (ICBT 0, xoaddr:$dst)>, Requires<[HasICBT]>; // inst prefetch (for read) def : Pat<(int_ppc_dcbt_with_hint xoaddr:$dst, i32:$TH), @@ -3180,6 +3188,7 @@ def : Pat<(PPCtc_return CTRRC:$dst, imm:$imm), (TCRETURNri CTRRC:$dst, imm:$imm)>; def : Pat<(int_ppc_readflm), (MFFS)>; +def : Pat<(int_ppc_mffsl), (MFFSL)>; // Hi and Lo for Darwin Global Addresses. def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>; @@ -3251,8 +3260,8 @@ def GETtlsTpointer32AIX : PPCEmitTimePseudo<(outs gprc:$rD), (ins), "GETtlsTpointer32AIX", [(set i32:$rD, (PPCgetTpointer))]>; -// The following pattern matches local-exec TLS accesses on 32-bit AIX. -// PPCaddTls is used in local-exec accesses in order to: +// The following pattern matches local- and initial-exec TLS accesses on 32-bit AIX. +// PPCaddTls is used in local- and initial-exec accesses in order to: // - Get the address of a variable (add the variable offset to the thread // pointer, retrieved by calling .__get_tpointer). // - Create an opportunity to optimize the user of the loaded address. @@ -3428,6 +3437,23 @@ def crnot : OutPatFrag<(ops node:$in), def : Pat<(not i1:$in), (crnot $in)>; +// Pseudo-instructions for alternate assembly syntax (never used by codegen). +// These are aliases that require C++ handling to convert to the target +// instruction, while InstAliases can be handled directly by tblgen. +class PPCAsmPseudo<string asm, dag iops> + : Instruction { + let Namespace = "PPC"; + bit PPC64 = 0; // Default value, override with isPPC64 + + let OutOperandList = (outs); + let InOperandList = iops; + let Pattern = []; + let AsmString = asm; + let isAsmParserOnly = 1; + let isPseudo = 1; + let hasNoSchedulingInfo = 1; +} + // Prefixed instructions may require access to the above defs at a later // time so we include this after the def. include "PPCInstrP10.td" @@ -4449,23 +4475,6 @@ def ICBIEP : XForm_1a<31, 991, (outs), (ins (memrr $RA, $RB):$addr), "icbiep $a // PowerPC Assembler Instruction Aliases // -// Pseudo-instructions for alternate assembly syntax (never used by codegen). -// These are aliases that require C++ handling to convert to the target -// instruction, while InstAliases can be handled directly by tblgen. -class PPCAsmPseudo<string asm, dag iops> - : Instruction { - let Namespace = "PPC"; - bit PPC64 = 0; // Default value, override with isPPC64 - - let OutOperandList = (outs); - let InOperandList = iops; - let Pattern = []; - let AsmString = asm; - let isAsmParserOnly = 1; - let isPseudo = 1; - let hasNoSchedulingInfo = 1; -} - def : InstAlias<"sc", (SC 0)>; def : InstAlias<"sync", (SYNC 0)>, Requires<[HasSYNC]>; @@ -5027,12 +5036,12 @@ def : Pat<(atomic_load_16 XForm:$src), (LHZX memrr:$src)>; def : Pat<(atomic_load_32 XForm:$src), (LWZX memrr:$src)>; // Atomic stores -def : Pat<(atomic_store_8 DForm:$ptr, i32:$val), (STB gprc:$val, memri:$ptr)>; -def : Pat<(atomic_store_16 DForm:$ptr, i32:$val), (STH gprc:$val, memri:$ptr)>; -def : Pat<(atomic_store_32 DForm:$ptr, i32:$val), (STW gprc:$val, memri:$ptr)>; -def : Pat<(atomic_store_8 XForm:$ptr, i32:$val), (STBX gprc:$val, memrr:$ptr)>; -def : Pat<(atomic_store_16 XForm:$ptr, i32:$val), (STHX gprc:$val, memrr:$ptr)>; -def : Pat<(atomic_store_32 XForm:$ptr, i32:$val), (STWX gprc:$val, memrr:$ptr)>; +def : Pat<(atomic_store_8 i32:$val, DForm:$ptr), (STB gprc:$val, memri:$ptr)>; +def : Pat<(atomic_store_16 i32:$val, DForm:$ptr), (STH gprc:$val, memri:$ptr)>; +def : Pat<(atomic_store_32 i32:$val, DForm:$ptr), (STW gprc:$val, memri:$ptr)>; +def : Pat<(atomic_store_8 i32:$val, XForm:$ptr), (STBX gprc:$val, memrr:$ptr)>; +def : Pat<(atomic_store_16 i32:$val, XForm:$ptr), (STHX gprc:$val, memrr:$ptr)>; +def : Pat<(atomic_store_32 i32:$val, XForm:$ptr), (STWX gprc:$val, memrr:$ptr)>; let Predicates = [IsISA3_0] in { diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td index 8cb8e4d91db2..d5a372e4dc10 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrP10.td @@ -575,33 +575,54 @@ class XForm_XT5_BI5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, } multiclass MLS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL, - dag PCRel_IOL, string asmstr, + dag PCRel_IOL, dag PCRelOnly_IOL, + string asmstr, string asmstr_pcext, InstrItinClass itin> { def NAME : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, !strconcat(asmstr, ", 0"), itin, []>; def pc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRel_IOL, !strconcat(asmstr, ", 1"), itin, []>, isPCRel; + let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in { + def nopc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>; + let RA = 0 in + def onlypc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL, + asmstr_pcext, itin, []>, isPCRel; + } } multiclass 8LS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL, - dag PCRel_IOL, string asmstr, + dag PCRel_IOL, dag PCRelOnly_IOL, + string asmstr, string asmstr_pcext, InstrItinClass itin> { def NAME : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, !strconcat(asmstr, ", 0"), itin, []>; def pc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRel_IOL, !strconcat(asmstr, ", 1"), itin, []>, isPCRel; + let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in { + def nopc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>; + let RA = 0 in + def onlypc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL, + asmstr_pcext, itin, []>, isPCRel; + } } multiclass 8LS_DForm_R_SI34_XT6_RA5_MEM_p<bits<5> opcode, dag OOL, dag IOL, - dag PCRel_IOL, string asmstr, + dag PCRel_IOL, dag PCRelOnly_IOL, + string asmstr, string asmstr_pcext, InstrItinClass itin> { def NAME : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, !strconcat(asmstr, ", 0"), itin, []>; def pc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRel_IOL, !strconcat(asmstr, ", 1"), itin, []>, isPCRel; + let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in { + def nopc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, asmstr, itin, []>; + let RA = 0 in + def onlypc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRelOnly_IOL, + asmstr_pcext, itin, []>, isPCRel; + } } def PrefixInstrs : Predicate<"Subtarget->hasPrefixInstrs()">; @@ -615,7 +636,7 @@ def RCCp { let Predicates = [PrefixInstrs] in { let Interpretation64Bit = 1, isCodeGenOnly = 1 in { defm PADDI8 : - MLS_DForm_R_SI34_RTA5_p<14, (outs g8rc:$RT), (ins g8rc:$RA, s34imm:$SI), + MLS_DForm_R_SI34_RTA5_p<14, (outs g8rc:$RT), (ins g8rc_nox0:$RA, s34imm:$SI), (ins immZero:$RA, s34imm_pcrel:$SI), "paddi $RT, $RA, $SI", IIC_LdStLFD>; let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in { @@ -625,7 +646,7 @@ let Predicates = [PrefixInstrs] in { } } defm PADDI : - MLS_DForm_R_SI34_RTA5_p<14, (outs gprc:$RT), (ins gprc:$RA, s34imm:$SI), + MLS_DForm_R_SI34_RTA5_p<14, (outs gprc:$RT), (ins gprc_nor0:$RA, s34imm:$SI), (ins immZero:$RA, s34imm_pcrel:$SI), "paddi $RT, $RA, $SI", IIC_LdStLFD>; let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in { @@ -638,68 +659,88 @@ let Predicates = [PrefixInstrs] in { defm PLXV : 8LS_DForm_R_SI34_XT6_RA5_MEM_p<25, (outs vsrc:$XST), (ins (memri34 $D, $RA):$addr), (ins (memri34_pcrel $D, $RA):$addr), - "plxv $XST, $addr", IIC_LdStLFD>; + (ins s34imm_pcrel:$D), + "plxv $XST, $addr", "plxv $XST, $D", IIC_LdStLFD>; defm PLFS : MLS_DForm_R_SI34_RTA5_MEM_p<48, (outs f4rc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plfs $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plfs $RST, $addr", + "plfs $RST, $D", IIC_LdStLFD>; defm PLFD : MLS_DForm_R_SI34_RTA5_MEM_p<50, (outs f8rc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plfd $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plfd $RST, $addr", + "plfd $RST, $D", IIC_LdStLFD>; defm PLXSSP : 8LS_DForm_R_SI34_RTA5_MEM_p<43, (outs vfrc:$RST), (ins (memri34 $D, $RA):$addr), (ins (memri34_pcrel $D, $RA):$addr), - "plxssp $RST, $addr", IIC_LdStLFD>; + (ins s34imm_pcrel:$D), + "plxssp $RST, $addr", "plxssp $RST, $D", + IIC_LdStLFD>; defm PLXSD : 8LS_DForm_R_SI34_RTA5_MEM_p<42, (outs vfrc:$RST), (ins (memri34 $D, $RA):$addr), (ins (memri34_pcrel $D, $RA):$addr), - "plxsd $RST, $addr", IIC_LdStLFD>; + (ins s34imm_pcrel:$D), + "plxsd $RST, $addr", "plxsd $RST, $D", + IIC_LdStLFD>; let Interpretation64Bit = 1, isCodeGenOnly = 1 in { defm PLBZ8 : MLS_DForm_R_SI34_RTA5_MEM_p<34, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plbz $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plbz $RST, $addr", + "plbz $RST, $D", IIC_LdStLFD>; defm PLHZ8 : MLS_DForm_R_SI34_RTA5_MEM_p<40, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plhz $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plhz $RST, $addr", + "plhz $RST, $D", IIC_LdStLFD>; defm PLHA8 : MLS_DForm_R_SI34_RTA5_MEM_p<42, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plha $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plha $RST, $addr", + "plha $RST, $D", IIC_LdStLFD>; defm PLWA8 : 8LS_DForm_R_SI34_RTA5_MEM_p<41, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr), (ins (memri34_pcrel $D, $RA):$addr), - "plwa $RST, $addr", IIC_LdStLFD>; + (ins s34imm_pcrel:$D), + "plwa $RST, $addr", "plwa $RST, $D", IIC_LdStLFD>; defm PLWZ8 : MLS_DForm_R_SI34_RTA5_MEM_p<32, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plwz $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plwz $RST, $addr", + "plwz $RST, $D", IIC_LdStLFD>; } defm PLBZ : MLS_DForm_R_SI34_RTA5_MEM_p<34, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plbz $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plbz $RST, $addr", + "plbz $RST, $D", IIC_LdStLFD>; defm PLHZ : MLS_DForm_R_SI34_RTA5_MEM_p<40, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plhz $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plhz $RST, $addr", + "plhz $RST, $D", IIC_LdStLFD>; defm PLHA : MLS_DForm_R_SI34_RTA5_MEM_p<42, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plha $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plha $RST, $addr", + "plha $RST, $D", IIC_LdStLFD>; defm PLWZ : MLS_DForm_R_SI34_RTA5_MEM_p<32, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plwz $RST, $addr", - IIC_LdStLFD>; + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), "plwz $RST, $addr", + "plwz $RST, $D", IIC_LdStLFD>; defm PLWA : 8LS_DForm_R_SI34_RTA5_MEM_p<41, (outs gprc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plwa $RST, $addr", + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), + "plwa $RST, $addr", "plwa $RST, $D", IIC_LdStLFD>; defm PLD : 8LS_DForm_R_SI34_RTA5_MEM_p<57, (outs g8rc:$RST), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "pld $RST, $addr", + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), + "pld $RST, $addr", "pld $RST, $D", IIC_LdStLFD>; } @@ -707,53 +748,65 @@ let Predicates = [PrefixInstrs] in { defm PSTXV : 8LS_DForm_R_SI34_XT6_RA5_MEM_p<27, (outs), (ins vsrc:$XST, (memri34 $D, $RA):$addr), (ins vsrc:$XST, (memri34_pcrel $D, $RA):$addr), - "pstxv $XST, $addr", IIC_LdStLFD>; + (ins vsrc:$XST, s34imm_pcrel:$D), + "pstxv $XST, $addr", "pstxv $XST, $D", IIC_LdStLFD>; defm PSTFS : MLS_DForm_R_SI34_RTA5_MEM_p<52, (outs), (ins f4rc:$RST, (memri34 $D, $RA):$addr), (ins f4rc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstfs $RST, $addr", IIC_LdStLFD>; + (ins f4rc:$RST, s34imm_pcrel:$D), + "pstfs $RST, $addr", "pstfs $RST, $D", IIC_LdStLFD>; defm PSTFD : MLS_DForm_R_SI34_RTA5_MEM_p<54, (outs), (ins f8rc:$RST, (memri34 $D, $RA):$addr), (ins f8rc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstfd $RST, $addr", IIC_LdStLFD>; + (ins f8rc:$RST, s34imm_pcrel:$D), + "pstfd $RST, $addr", "pstfd $RST, $D", IIC_LdStLFD>; defm PSTXSSP : 8LS_DForm_R_SI34_RTA5_MEM_p<47, (outs), (ins vfrc:$RST, (memri34 $D, $RA):$addr), (ins vfrc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstxssp $RST, $addr", IIC_LdStLFD>; + (ins vfrc:$RST, s34imm_pcrel:$D), + "pstxssp $RST, $addr", "pstxssp $RST, $D", IIC_LdStLFD>; defm PSTXSD : 8LS_DForm_R_SI34_RTA5_MEM_p<46, (outs), (ins vfrc:$RST, (memri34 $D, $RA):$addr), (ins vfrc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstxsd $RST, $addr", IIC_LdStLFD>; + (ins vfrc:$RST, s34imm_pcrel:$D), + "pstxsd $RST, $addr", "pstxsd $RST, $D", IIC_LdStLFD>; let Interpretation64Bit = 1, isCodeGenOnly = 1 in { defm PSTB8 : MLS_DForm_R_SI34_RTA5_MEM_p<38, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr), (ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstb $RST, $addr", IIC_LdStLFD>; + (ins g8rc:$RST, s34imm_pcrel:$D), + "pstb $RST, $addr", "pstb $RST, $D", IIC_LdStLFD>; defm PSTH8 : MLS_DForm_R_SI34_RTA5_MEM_p<44, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr), (ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr), - "psth $RST, $addr", IIC_LdStLFD>; + (ins g8rc:$RST, s34imm_pcrel:$D), + "psth $RST, $addr", "psth $RST, $D", IIC_LdStLFD>; defm PSTW8 : MLS_DForm_R_SI34_RTA5_MEM_p<36, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr), (ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstw $RST, $addr", IIC_LdStLFD>; + (ins g8rc:$RST, s34imm_pcrel:$D), + "pstw $RST, $addr", "pstw $RST, $D", IIC_LdStLFD>; } defm PSTB : MLS_DForm_R_SI34_RTA5_MEM_p<38, (outs), (ins gprc:$RST, (memri34 $D, $RA):$addr), (ins gprc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstb $RST, $addr", IIC_LdStLFD>; + (ins gprc:$RST, s34imm_pcrel:$D), + "pstb $RST, $addr", "pstb $RST, $D", IIC_LdStLFD>; defm PSTH : MLS_DForm_R_SI34_RTA5_MEM_p<44, (outs), (ins gprc:$RST, (memri34 $D, $RA):$addr), (ins gprc:$RST, (memri34_pcrel $D, $RA):$addr), - "psth $RST, $addr", IIC_LdStLFD>; + (ins gprc:$RST, s34imm_pcrel:$D), + "psth $RST, $addr", "psth $RST, $D", IIC_LdStLFD>; defm PSTW : MLS_DForm_R_SI34_RTA5_MEM_p<36, (outs), (ins gprc:$RST, (memri34 $D, $RA):$addr), (ins gprc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstw $RST, $addr", IIC_LdStLFD>; + (ins gprc:$RST, s34imm_pcrel:$D), + "pstw $RST, $addr", "pstw $RST, $D", IIC_LdStLFD>; defm PSTD : 8LS_DForm_R_SI34_RTA5_MEM_p<61, (outs), (ins g8rc:$RST, (memri34 $D, $RA):$addr), (ins g8rc:$RST, (memri34_pcrel $D, $RA):$addr), - "pstd $RST, $addr", IIC_LdStLFD>; + (ins g8rc:$RST, s34imm_pcrel:$D), + "pstd $RST, $addr", "pstd $RST, $D", IIC_LdStLFD>; } } @@ -812,13 +865,20 @@ class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr, } multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL, - dag IOL, dag PCRel_IOL, - string asmstr, InstrItinClass itin> { + dag IOL, dag PCRel_IOL, dag PCRelOnly_IOL, + string asmstr, string asmstr_pcext, + InstrItinClass itin> { def NAME : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, !strconcat(asmstr, ", 0"), itin, []>; def pc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRel_IOL, !strconcat(asmstr, ", 1"), itin, []>, isPCRel; + let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in { + def nopc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, asmstr, itin, []>; + let RA = 0 in + def onlypc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRelOnly_IOL, + asmstr_pcext, itin, []>, isPCRel; + } } @@ -1079,7 +1139,9 @@ let mayLoad = 0, mayStore = 1, Predicates = [PairedVectorMemops] in { let mayLoad = 1, mayStore = 0, Predicates = [PairedVectorMemops, PrefixInstrs] in { defm PLXVP : 8LS_DForm_R_XTp5_SI34_MEM_p<58, (outs vsrprc:$XTp), (ins (memri34 $D, $RA):$addr), - (ins (memri34_pcrel $D, $RA):$addr), "plxvp $XTp, $addr", + (ins (memri34_pcrel $D, $RA):$addr), + (ins s34imm_pcrel:$D), + "plxvp $XTp, $addr", "plxvp $XTp, $D", IIC_LdStLFD>; } @@ -1087,7 +1149,8 @@ let mayLoad = 0, mayStore = 1, Predicates = [PairedVectorMemops, PrefixInstrs] i defm PSTXVP : 8LS_DForm_R_XTp5_SI34_MEM_p<62, (outs), (ins vsrprc:$XTp, (memri34 $D, $RA):$addr), (ins vsrprc:$XTp, (memri34_pcrel $D, $RA):$addr), - "pstxvp $XTp, $addr", IIC_LdStLFD>; + (ins vsrprc:$XTp, s34imm_pcrel:$D), + "pstxvp $XTp, $addr", "pstxvp $XTp, $D", IIC_LdStLFD>; } let Predicates = [PairedVectorMemops] in { @@ -1236,19 +1299,19 @@ let Predicates = [PCRelativeMemops] in { (PLDpc $ga, 0)>; // Atomic Store - def : Pat<(atomic_store_8 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS), + def : Pat<(atomic_store_8 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTBpc $RS, $ga, 0)>; - def : Pat<(atomic_store_16 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS), + def : Pat<(atomic_store_16 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTHpc $RS, $ga, 0)>; - def : Pat<(atomic_store_32 (PPCmatpcreladdr PCRelForm:$ga), i32:$RS), + def : Pat<(atomic_store_32 i32:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTWpc $RS, $ga, 0)>; - def : Pat<(atomic_store_8 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), + def : Pat<(atomic_store_8 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTB8pc $RS, $ga, 0)>; - def : Pat<(atomic_store_16 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), + def : Pat<(atomic_store_16 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTH8pc $RS, $ga, 0)>; - def : Pat<(atomic_store_32 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), + def : Pat<(atomic_store_32 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTW8pc $RS, $ga, 0)>; - def : Pat<(atomic_store_64 (PPCmatpcreladdr PCRelForm:$ga), i64:$RS), + def : Pat<(atomic_store_64 i64:$RS, (PPCmatpcreladdr PCRelForm:$ga)), (PSTDpc $RS, $ga, 0)>; // Special Cases For PPCstore_scal_int_from_vsr @@ -1855,6 +1918,13 @@ let Predicates = [IsISA3_1, HasVSX] in { [(set f128:$RST, (PPCxsminc f128:$RA, f128:$RB))]>; } +let Predicates = [IsISA3_1] in { + def WAITP10 : XForm_IMM2_IMM2<31, 30, (outs), (ins u2imm:$L, u2imm:$PL), + "wait $L $PL", IIC_LdStLoad, []>; + def SYNCP10 : XForm_IMM3_IMM2<31, 598, (outs), (ins u3imm:$L, u2imm:$SC), + "sync $L, $SC", IIC_LdStSync, []>; +} + // Multiclass defining patterns for Set Boolean Extension Reverse Instructions. // This is analogous to the CRNotPat multiclass but specifically for Power10 // and newer subtargets since the extended forms use Set Boolean instructions. @@ -2031,8 +2101,15 @@ let AddedComplexity = 400, Predicates = [IsISA3_1, IsLittleEndian] in { (v8i16 (COPY_TO_REGCLASS (LXVRHX ForceXForm:$src), VSRC))>; def : Pat<(v16i8 (scalar_to_vector (i32 (extloadi8 ForceXForm:$src)))), (v16i8 (COPY_TO_REGCLASS (LXVRBX ForceXForm:$src), VSRC))>; + def : Pat<(store (i64 (extractelt v2i64:$A, 1)), ForceXForm:$src), + (XFSTOREf64 (EXTRACT_SUBREG $A, sub_64), ForceXForm:$src)>; } +let Predicates = [IsISA3_1, IsBigEndian] in { + def : Pat<(store (i64 (extractelt v2i64:$A, 0)), ForceXForm:$src), + (XFSTOREf64 (EXTRACT_SUBREG $A, sub_64), ForceXForm:$src)>; +} + // FIXME: The swap is overkill when the shift amount is a constant. // We should just fix the constant in the DAG. let AddedComplexity = 400, Predicates = [IsISA3_1, HasVSX] in { @@ -2276,10 +2353,10 @@ let Predicates = [PrefixInstrs] in { def : Pat<(atomic_load_64 PDForm:$src), (PLD memri34:$src)>; // Atomic Store - def : Pat<(atomic_store_8 PDForm:$dst, i32:$RS), (PSTB $RS, memri34:$dst)>; - def : Pat<(atomic_store_16 PDForm:$dst, i32:$RS), (PSTH $RS, memri34:$dst)>; - def : Pat<(atomic_store_32 PDForm:$dst, i32:$RS), (PSTW $RS, memri34:$dst)>; - def : Pat<(atomic_store_64 PDForm:$dst, i64:$RS), (PSTD $RS, memri34:$dst)>; + def : Pat<(atomic_store_8 i32:$RS, PDForm:$dst), (PSTB $RS, memri34:$dst)>; + def : Pat<(atomic_store_16 i32:$RS, PDForm:$dst), (PSTH $RS, memri34:$dst)>; + def : Pat<(atomic_store_32 i32:$RS, PDForm:$dst), (PSTW $RS, memri34:$dst)>; + def : Pat<(atomic_store_64 i64:$RS, PDForm:$dst), (PSTD $RS, memri34:$dst)>; // Prefixed fpext to v2f64 def : Pat<(v4f32 (PPCldvsxlh PDForm:$src)), @@ -2379,3 +2456,50 @@ let AddedComplexity = 400, Predicates = [IsISA3_1, HasVSX, IsBigEndian] in { def : Pat<(v2i64 (insertelt v2i64:$vDi, i64:$rA, Idx)), (VINSD $vDi, !mul(Idx, 8), $rA)>; } + + +//===----------------------------------------------------------------------===// +// PowerPC ISA 3.1 Extended Mnemonics. +// + +let Predicates = [IsISA3_1] in { + def : InstAlias<"wait", (WAITP10 0, 0)>; + def : InstAlias<"wait 0", (WAITP10 0, 0), 0>; + def : InstAlias<"wait 1", (WAITP10 1, 0), 0>; + def : InstAlias<"waitrsv", (WAITP10 1, 0)>; + def : InstAlias<"pause_short", (WAITP10 2, 0), 0>; + + def : InstAlias<"sync", (SYNCP10 0, 0)>; + def : InstAlias<"hwsync", (SYNCP10 0, 0), 0>; + def : InstAlias<"wsync", (SYNCP10 1, 0), 0>; + def : InstAlias<"ptesync", (SYNCP10 2, 0)>; + def : InstAlias<"phwsync", (SYNCP10 4, 0)>; + def : InstAlias<"plwsync", (SYNCP10 5, 0)>; + def : InstAlias<"sync $L", (SYNCP10 u3imm:$L, 0)>; + def : InstAlias<"stncisync", (SYNCP10 1, 1)>; + def : InstAlias<"stcisync", (SYNCP10 0, 2)>; + def : InstAlias<"stsync", (SYNCP10 0, 3)>; + + def : InstAlias<"paddi $RT, $RA, $SI", (PADDI8 g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>; +} + +let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in { + let Interpretation64Bit = 1 in { + def PLA8 : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT), + (ins g8rc_nox0:$RA, s34imm:$SI), + "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>; + def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT), + (ins s34imm_pcrel:$SI), + "pla $RT, $SI", IIC_IntSimple, []>, isPCRel; + } + + def PSUBI : PPCAsmPseudo<"psubi $RT, $RA, $SI", + (ins g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>; + + def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT), + (ins gprc_nor0:$RA, s34imm:$SI), + "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>; + def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT), + (ins s34imm_pcrel:$SI), + "pla $RT, $SI", IIC_IntSimple, []>, isPCRel; +} diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp index f29a7af1bdf1..dc739a2c7a4d 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp @@ -660,8 +660,8 @@ PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV, Type *I8Ty = Type::getInt8Ty(BaseMemI->getParent()->getContext()); Type *I8PtrTy = - Type::getInt8PtrTy(BaseMemI->getParent()->getContext(), - BasePtr->getType()->getPointerAddressSpace()); + PointerType::get(BaseMemI->getParent()->getContext(), + BasePtr->getType()->getPointerAddressSpace()); bool IsConstantInc = false; const SCEV *BasePtrIncSCEV = BasePtrSCEV->getStepRecurrence(*SE); @@ -707,8 +707,8 @@ PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV, BasicBlock *LoopPredecessor = L->getLoopPredecessor(); PHINode *NewPHI = PHINode::Create(I8PtrTy, HeaderLoopPredCount, - getInstrName(BaseMemI, PHINodeNameSuffix), - Header->getFirstNonPHI()); + getInstrName(BaseMemI, PHINodeNameSuffix)); + NewPHI->insertBefore(Header->getFirstNonPHIIt()); Value *BasePtrStart = SCEVE.expandCodeFor(BasePtrStartSCEV, I8PtrTy, LoopPredecessor->getTerminator()); diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp index 976effb96adc..9a3ca5a78293 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -31,22 +31,21 @@ using namespace llvm; static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP) { - const TargetMachine &TM = AP.TM; - Mangler &Mang = TM.getObjFileLowering()->getMangler(); - const DataLayout &DL = AP.getDataLayout(); - MCContext &Ctx = AP.OutContext; - - SmallString<128> Name; - if (!MO.isGlobal()) { - assert(MO.isSymbol() && "Isn't a symbol reference"); - Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); - } else { + if (MO.isGlobal()) { + // Get the symbol from the global, accounting for XCOFF-specific + // intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol). const GlobalValue *GV = MO.getGlobal(); - TM.getNameWithPrefix(Name, GV, Mang); + return AP.getSymbol(GV); } - MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); + assert(MO.isSymbol() && "Isn't a symbol reference"); + + SmallString<128> Name; + const DataLayout &DL = AP.getDataLayout(); + Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); + MCContext &Ctx = AP.OutContext; + MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); return Sym; } @@ -55,7 +54,7 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, MCContext &Ctx = Printer.OutContext; MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; - unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; + unsigned access = MO.getTargetFlags(); switch (access) { case PPCII::MO_TPREL_LO: @@ -74,19 +73,22 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; break; case PPCII::MO_TLS: - bool IsPCRel = (MO.getTargetFlags() & ~access) == PPCII::MO_PCREL_FLAG; - RefKind = IsPCRel ? MCSymbolRefExpr::VK_PPC_TLS_PCREL - : MCSymbolRefExpr::VK_PPC_TLS; + RefKind = MCSymbolRefExpr::VK_PPC_TLS; + break; + case PPCII::MO_TLS_PCREL_FLAG: + RefKind = MCSymbolRefExpr::VK_PPC_TLS_PCREL; break; } + const TargetMachine &TM = Printer.TM; + if (MO.getTargetFlags() == PPCII::MO_PLT) RefKind = MCSymbolRefExpr::VK_PLT; else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_PCREL; - else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG)) + else if (MO.getTargetFlags() == PPCII::MO_GOT_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; - else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG)) + else if (MO.getTargetFlags() == PPCII::MO_TPREL_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_TPREL; else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; @@ -94,12 +96,21 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; + else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG) { + assert(MO.isGlobal() && "Only expecting a global MachineOperand here!"); + TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); + // For the local-exec TLS model, we may generate the offset from the TLS + // base as an immediate operand (instead of using a TOC entry). + // Set the relocation type in case the result is used for purposes other + // than a TOC reference. In TOC reference cases, this result is discarded. + if (Model == TLSModel::LocalExec) + RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE; + } const MachineInstr *MI = MO.getParent(); const MachineFunction *MF = MI->getMF(); const Module *M = MF->getFunction().getParent(); const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); - const TargetMachine &TM = Printer.TM; unsigned MIOpcode = MI->getOpcode(); assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && @@ -128,7 +139,9 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, Ctx); // Subtract off the PIC base if required. - if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) { + if (MO.getTargetFlags() == PPCII::MO_PIC_FLAG || + MO.getTargetFlags() == PPCII::MO_PIC_HA_FLAG || + MO.getTargetFlags() == PPCII::MO_PIC_LO_FLAG) { const MachineFunction *MF = MO.getParent()->getParent()->getParent(); const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx); @@ -138,9 +151,11 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, // Add ha16() / lo16() markers if required. switch (access) { case PPCII::MO_LO: + case PPCII::MO_PIC_LO_FLAG: Expr = PPCMCExpr::createLo(Expr, Ctx); break; case PPCII::MO_HA: + case PPCII::MO_PIC_HA_FLAG: Expr = PPCMCExpr::createHa(Expr, Ctx); break; } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp index 410f4cba97c6..494e4b52a5b5 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -16,6 +16,15 @@ // removal, and it would miss cleanups made possible following VSX // swap removal. // +// NOTE: We run the verifier after this pass in Asserts/Debug builds so it +// is important to keep the code valid after transformations. +// Common causes of errors stem from violating the contract specified +// by kill flags. Whenever a transformation changes the live range of +// a register, that register should be added to the work list using +// addRegToUpdate(RegsToUpdate, <Reg>). Furthermore, if a transformation +// is changing the definition of a register (i.e. removing the single +// definition of the original vreg), it needs to provide a dummy +// definition of that register using addDummyDef(<MBB>, <Reg>). //===---------------------------------------------------------------------===// #include "MCTargetDesc/PPCMCTargetDesc.h" @@ -26,6 +35,7 @@ #include "PPCMachineFunctionInfo.h" #include "PPCTargetMachine.h" #include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -93,6 +103,7 @@ struct PPCMIPeephole : public MachineFunctionPass { const PPCInstrInfo *TII; MachineFunction *MF; MachineRegisterInfo *MRI; + LiveVariables *LV; PPCMIPeephole() : MachineFunctionPass(ID) { initializePPCMIPeepholePass(*PassRegistry::getPassRegistry()); @@ -102,7 +113,8 @@ private: MachineDominatorTree *MDT; MachinePostDominatorTree *MPDT; MachineBlockFrequencyInfo *MBFI; - uint64_t EntryFreq; + BlockFrequency EntryFreq; + SmallSet<Register, 16> RegsToUpdate; // Initialize class variables. void initialize(MachineFunction &MFParm); @@ -114,16 +126,32 @@ private: bool eliminateRedundantCompare(); bool eliminateRedundantTOCSaves(std::map<MachineInstr *, bool> &TOCSaves); bool combineSEXTAndSHL(MachineInstr &MI, MachineInstr *&ToErase); - bool emitRLDICWhenLoweringJumpTables(MachineInstr &MI); + bool emitRLDICWhenLoweringJumpTables(MachineInstr &MI, + MachineInstr *&ToErase); void UpdateTOCSaves(std::map<MachineInstr *, bool> &TOCSaves, MachineInstr *MI); + // A number of transformations will eliminate the definition of a register + // as all of its uses will be removed. However, this leaves a register + // without a definition for LiveVariables. Such transformations should + // use this function to provide a dummy definition of the register that + // will simply be removed by DCE. + void addDummyDef(MachineBasicBlock &MBB, MachineInstr *At, Register Reg) { + BuildMI(MBB, At, At->getDebugLoc(), TII->get(PPC::IMPLICIT_DEF), Reg); + } + void addRegToUpdateWithLine(Register Reg, int Line); + void convertUnprimedAccPHIs(const PPCInstrInfo *TII, MachineRegisterInfo *MRI, + SmallVectorImpl<MachineInstr *> &PHIs, + Register Dst); + public: void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired<LiveVariables>(); AU.addRequired<MachineDominatorTree>(); AU.addRequired<MachinePostDominatorTree>(); AU.addRequired<MachineBlockFrequencyInfo>(); + AU.addPreserved<LiveVariables>(); AU.addPreserved<MachineDominatorTree>(); AU.addPreserved<MachinePostDominatorTree>(); AU.addPreserved<MachineBlockFrequencyInfo>(); @@ -140,10 +168,26 @@ public: "TOC pointer used in a function using PC-Relative addressing!"); if (skipFunction(MF.getFunction())) return false; - return simplifyCode(); + bool Changed = simplifyCode(); +#ifndef NDEBUG + if (Changed) + MF.verify(this, "Error in PowerPC MI Peephole optimization, compile with " + "-mllvm -disable-ppc-peephole"); +#endif + return Changed; } }; +#define addRegToUpdate(R) addRegToUpdateWithLine(R, __LINE__) +void PPCMIPeephole::addRegToUpdateWithLine(Register Reg, int Line) { + if (!Register::isVirtualRegister(Reg)) + return; + if (RegsToUpdate.insert(Reg).second) + LLVM_DEBUG(dbgs() << "Adding register: " << Register::virtReg2Index(Reg) + << " on line " << Line + << " for re-computation of kill flags\n"); +} + // Initialize class variables. void PPCMIPeephole::initialize(MachineFunction &MFParm) { MF = &MFParm; @@ -151,8 +195,10 @@ void PPCMIPeephole::initialize(MachineFunction &MFParm) { MDT = &getAnalysis<MachineDominatorTree>(); MPDT = &getAnalysis<MachinePostDominatorTree>(); MBFI = &getAnalysis<MachineBlockFrequencyInfo>(); + LV = &getAnalysis<LiveVariables>(); EntryFreq = MBFI->getEntryFreq(); TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo(); + RegsToUpdate.clear(); LLVM_DEBUG(dbgs() << "*** PowerPC MI peephole pass ***\n\n"); LLVM_DEBUG(MF->dump()); } @@ -254,7 +300,7 @@ void PPCMIPeephole::UpdateTOCSaves( PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>(); MachineBasicBlock *Entry = &MF->front(); - uint64_t CurrBlockFreq = MBFI->getBlockFreq(MI->getParent()).getFrequency(); + BlockFrequency CurrBlockFreq = MBFI->getBlockFreq(MI->getParent()); // If the block in which the TOC save resides is in a block that // post-dominates Entry, or a block that is hotter than entry (keep in mind @@ -338,10 +384,9 @@ static bool collectUnprimedAccPHIs(MachineRegisterInfo *MRI, // primed accumulator PHI nodes. The list is traversed in reverse order to // change all the PHI operands of a PHI node before changing the node itself. // We keep a map to associate each changed PHI node to its non-changed form. -static void convertUnprimedAccPHIs(const PPCInstrInfo *TII, - MachineRegisterInfo *MRI, - SmallVectorImpl<MachineInstr *> &PHIs, - Register Dst) { +void PPCMIPeephole::convertUnprimedAccPHIs( + const PPCInstrInfo *TII, MachineRegisterInfo *MRI, + SmallVectorImpl<MachineInstr *> &PHIs, Register Dst) { DenseMap<MachineInstr *, MachineInstr *> ChangedPHIMap; for (MachineInstr *PHI : llvm::reverse(PHIs)) { SmallVector<std::pair<MachineOperand, MachineOperand>, 4> PHIOps; @@ -390,8 +435,11 @@ static void convertUnprimedAccPHIs(const PPCInstrInfo *TII, AccReg = MRI->createVirtualRegister(&PPC::ACCRCRegClass); MachineInstrBuilder NewPHI = BuildMI( *PHI->getParent(), PHI, PHI->getDebugLoc(), TII->get(PPC::PHI), AccReg); - for (auto RegMBB : PHIOps) + for (auto RegMBB : PHIOps) { NewPHI.add(RegMBB.first).add(RegMBB.second); + if (MRI->isSSA()) + addRegToUpdate(RegMBB.first.getReg()); + } ChangedPHIMap[PHI] = NewPHI.getInstr(); LLVM_DEBUG(dbgs() << "Converting PHI: "); LLVM_DEBUG(PHI->dump()); @@ -421,21 +469,51 @@ bool PPCMIPeephole::simplifyCode() { if (MI.isDebugInstr()) continue; - if (TII->convertToImmediateForm(MI)) { - // We don't erase anything in case the def has other uses. Let DCE - // remove it if it can be removed. - LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); - LLVM_DEBUG(MI.dump()); - NumConvertedToImmediateForm++; - SomethingChanged = true; - Simplified = true; + SmallSet<Register, 4> RRToRIRegsToUpdate; + if (!TII->convertToImmediateForm(MI, RRToRIRegsToUpdate)) continue; - } + for (Register R : RRToRIRegsToUpdate) + addRegToUpdate(R); + // The updated instruction may now have new register operands. + // Conservatively add them to recompute the flags as well. + for (const MachineOperand &MO : MI.operands()) + if (MO.isReg()) + addRegToUpdate(MO.getReg()); + // We don't erase anything in case the def has other uses. Let DCE + // remove it if it can be removed. + LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); + LLVM_DEBUG(MI.dump()); + NumConvertedToImmediateForm++; + SomethingChanged = true; + Simplified = true; + continue; } } } while (SomethingChanged && FixedPointRegToImm); } + // Since we are deleting this instruction, we need to run LiveVariables + // on any of its definitions that are marked as needing an update since + // we can't run LiveVariables on a deleted register. This only needs + // to be done for defs since uses will have their own defining + // instructions so we won't be running LiveVariables on a deleted reg. + auto recomputeLVForDyingInstr = [&]() { + if (RegsToUpdate.empty()) + return; + for (MachineOperand &MO : ToErase->operands()) { + if (!MO.isReg() || !MO.isDef() || !RegsToUpdate.count(MO.getReg())) + continue; + Register RegToUpdate = MO.getReg(); + RegsToUpdate.erase(RegToUpdate); + // If some transformation has introduced an additional definition of + // this register (breaking SSA), we can safely convert this def to + // a def of an invalid register as the instruction is going away. + if (!MRI->getUniqueVRegDef(RegToUpdate)) + MO.setReg(PPC::NoRegister); + LV->recomputeForSingleDefVirtReg(RegToUpdate); + } + }; + for (MachineBasicBlock &MBB : *MF) { for (MachineInstr &MI : MBB) { @@ -444,6 +522,7 @@ bool PPCMIPeephole::simplifyCode() { if (ToErase) { LLVM_DEBUG(dbgs() << "Deleting instruction: "); LLVM_DEBUG(ToErase->dump()); + recomputeLVForDyingInstr(); ToErase->eraseFromParent(); ToErase = nullptr; } @@ -503,12 +582,16 @@ bool PPCMIPeephole::simplifyCode() { if (!MI.getOperand(1).isImm() || MI.getOperand(1).getImm() != 0) break; Register MIDestReg = MI.getOperand(0).getReg(); + bool Folded = false; for (MachineInstr& UseMI : MRI->use_instructions(MIDestReg)) - Simplified |= TII->onlyFoldImmediate(UseMI, MI, MIDestReg); + Folded |= TII->onlyFoldImmediate(UseMI, MI, MIDestReg); if (MRI->use_nodbg_empty(MIDestReg)) { ++NumLoadImmZeroFoldedAndRemoved; ToErase = &MI; } + if (Folded) + addRegToUpdate(MIDestReg); + Simplified |= Folded; break; } case PPC::STW: @@ -579,6 +662,7 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(1)); + addRegToUpdate(MI.getOperand(1).getReg()); ToErase = &MI; Simplified = true; } @@ -608,6 +692,7 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(1)); + addRegToUpdate(MI.getOperand(1).getReg()); ToErase = &MI; Simplified = true; } @@ -618,9 +703,13 @@ bool PPCMIPeephole::simplifyCode() { else if ((Immed == 0 || Immed == 3) && DefImmed == 2) { LLVM_DEBUG(dbgs() << "Optimizing swap/splat => splat: "); LLVM_DEBUG(MI.dump()); + addRegToUpdate(MI.getOperand(1).getReg()); + addRegToUpdate(MI.getOperand(2).getReg()); MI.getOperand(1).setReg(DefReg1); MI.getOperand(2).setReg(DefReg2); MI.getOperand(3).setImm(3 - Immed); + addRegToUpdate(DefReg1); + addRegToUpdate(DefReg2); Simplified = true; } @@ -629,9 +718,12 @@ bool PPCMIPeephole::simplifyCode() { else if (Immed == 2 && DefImmed == 2) { LLVM_DEBUG(dbgs() << "Optimizing swap/swap => copy: "); LLVM_DEBUG(MI.dump()); + addRegToUpdate(MI.getOperand(1).getReg()); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(DefMI->getOperand(1)); + addRegToUpdate(DefMI->getOperand(0).getReg()); + addRegToUpdate(DefMI->getOperand(1).getReg()); ToErase = &MI; Simplified = true; } @@ -648,6 +740,7 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(1)); + addRegToUpdate(MI.getOperand(1).getReg()); break; } // Splat fed by another splat - switch the output of the first @@ -669,6 +762,7 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(1)); + addRegToUpdate(MI.getOperand(1).getReg()); } else if ((Immed == 0 || Immed == 3 || Immed == 2) && TII->isLoadFromConstantPool(DefMI)) { const Constant *C = TII->getConstantFromConstantPool(DefMI); @@ -682,6 +776,7 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(1)); + addRegToUpdate(MI.getOperand(1).getReg()); } } break; @@ -724,6 +819,7 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(OpNo)); + addRegToUpdate(MI.getOperand(OpNo).getReg()); ToErase = &MI; Simplified = true; } @@ -747,7 +843,9 @@ bool PPCMIPeephole::simplifyCode() { LLVM_DEBUG(dbgs() << "Changing splat immediate from " << SplatImm << " to " << NewElem << " in instruction: "); LLVM_DEBUG(MI.dump()); - MI.getOperand(1).setReg(ShiftOp1); + addRegToUpdate(MI.getOperand(OpNo).getReg()); + addRegToUpdate(ShiftOp1); + MI.getOperand(OpNo).setReg(ShiftOp1); MI.getOperand(2).setImm(NewElem); } } @@ -797,7 +895,9 @@ bool PPCMIPeephole::simplifyCode() { LLVM_DEBUG(MI.dump()); LLVM_DEBUG(dbgs() << "Through instruction:\n"); LLVM_DEBUG(DefMI->dump()); - RoundInstr->eraseFromParent(); + addRegToUpdate(ConvReg1); + addRegToUpdate(FRSPDefines); + ToErase = RoundInstr; } }; @@ -844,6 +944,13 @@ bool PPCMIPeephole::simplifyCode() { else if (MIIs64Bit) Opc = PPC::LHA8; + addRegToUpdate(NarrowReg); + addRegToUpdate(MI.getOperand(0).getReg()); + + // We are removing a definition of NarrowReg which will cause + // problems in AliveBlocks. Add an implicit def that will be + // removed so that AliveBlocks are updated correctly. + addDummyDef(MBB, &MI, NarrowReg); LLVM_DEBUG(dbgs() << "Zero-extending load\n"); LLVM_DEBUG(SrcMI->dump()); LLVM_DEBUG(dbgs() << "and sign-extension\n"); @@ -909,6 +1016,13 @@ bool PPCMIPeephole::simplifyCode() { if (!IsWordAligned && (Opc == PPC::LWA || Opc == PPC::LWA_32)) break; + addRegToUpdate(NarrowReg); + addRegToUpdate(MI.getOperand(0).getReg()); + + // We are removing a definition of NarrowReg which will cause + // problems in AliveBlocks. Add an implicit def that will be + // removed so that AliveBlocks are updated correctly. + addDummyDef(MBB, &MI, NarrowReg); LLVM_DEBUG(dbgs() << "Zero-extending load\n"); LLVM_DEBUG(SrcMI->dump()); LLVM_DEBUG(dbgs() << "and sign-extension\n"); @@ -981,6 +1095,7 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .addReg(SrcReg); + addRegToUpdate(SrcReg); ToErase = &MI; Simplified = true; NumEliminatedZExt++; @@ -1071,23 +1186,96 @@ bool PPCMIPeephole::simplifyCode() { BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(Op1); + addRegToUpdate(Op1.getReg()); + addRegToUpdate(Op2.getReg()); ToErase = &MI; Simplified = true; NumOptADDLIs++; break; } case PPC::RLDICR: { - Simplified |= emitRLDICWhenLoweringJumpTables(MI) || + Simplified |= emitRLDICWhenLoweringJumpTables(MI, ToErase) || combineSEXTAndSHL(MI, ToErase); break; } + case PPC::ANDI_rec: + case PPC::ANDI8_rec: + case PPC::ANDIS_rec: + case PPC::ANDIS8_rec: { + Register TrueReg = + TRI->lookThruCopyLike(MI.getOperand(1).getReg(), MRI); + if (!TrueReg.isVirtual() || !MRI->hasOneNonDBGUse(TrueReg)) + break; + + MachineInstr *SrcMI = MRI->getVRegDef(TrueReg); + if (!SrcMI) + break; + + unsigned SrcOpCode = SrcMI->getOpcode(); + if (SrcOpCode != PPC::RLDICL && SrcOpCode != PPC::RLDICR) + break; + + Register SrcReg, DstReg; + SrcReg = SrcMI->getOperand(1).getReg(); + DstReg = MI.getOperand(1).getReg(); + const TargetRegisterClass *SrcRC = MRI->getRegClassOrNull(SrcReg); + const TargetRegisterClass *DstRC = MRI->getRegClassOrNull(DstReg); + if (DstRC != SrcRC) + break; + + uint64_t AndImm = MI.getOperand(2).getImm(); + if (MI.getOpcode() == PPC::ANDIS_rec || + MI.getOpcode() == PPC::ANDIS8_rec) + AndImm <<= 16; + uint64_t LZeroAndImm = llvm::countl_zero<uint64_t>(AndImm); + uint64_t RZeroAndImm = llvm::countr_zero<uint64_t>(AndImm); + uint64_t ImmSrc = SrcMI->getOperand(3).getImm(); + + // We can transfer `RLDICL/RLDICR + ANDI_rec/ANDIS_rec` to `ANDI_rec 0` + // if all bits to AND are already zero in the input. + bool PatternResultZero = + (SrcOpCode == PPC::RLDICL && (RZeroAndImm + ImmSrc > 63)) || + (SrcOpCode == PPC::RLDICR && LZeroAndImm > ImmSrc); + + // We can eliminate RLDICL/RLDICR if it's used to clear bits and all + // bits cleared will be ANDed with 0 by ANDI_rec/ANDIS_rec. + bool PatternRemoveRotate = + SrcMI->getOperand(2).getImm() == 0 && + ((SrcOpCode == PPC::RLDICL && LZeroAndImm >= ImmSrc) || + (SrcOpCode == PPC::RLDICR && (RZeroAndImm + ImmSrc > 63))); + + if (!PatternResultZero && !PatternRemoveRotate) + break; + + LLVM_DEBUG(dbgs() << "Combining pair: "); + LLVM_DEBUG(SrcMI->dump()); + LLVM_DEBUG(MI.dump()); + if (PatternResultZero) + MI.getOperand(2).setImm(0); + MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg()); + LLVM_DEBUG(dbgs() << "To: "); + LLVM_DEBUG(MI.dump()); + addRegToUpdate(MI.getOperand(1).getReg()); + addRegToUpdate(SrcMI->getOperand(0).getReg()); + Simplified = true; + break; + } case PPC::RLWINM: case PPC::RLWINM_rec: case PPC::RLWINM8: case PPC::RLWINM8_rec: { + // We might replace operand 1 of the instruction which will + // require we recompute kill flags for it. + Register OrigOp1Reg = MI.getOperand(1).isReg() + ? MI.getOperand(1).getReg() + : PPC::NoRegister; Simplified = TII->combineRLWINM(MI, &ToErase); - if (Simplified) + if (Simplified) { + addRegToUpdate(OrigOp1Reg); + if (MI.getOperand(1).isReg()) + addRegToUpdate(MI.getOperand(1).getReg()); ++NumRotatesCollapsed; + } break; } // We will replace TD/TW/TDI/TWI with an unconditional trap if it will @@ -1141,6 +1329,7 @@ bool PPCMIPeephole::simplifyCode() { // If the last instruction was marked for elimination, // remove it now. if (ToErase) { + recomputeLVForDyingInstr(); ToErase->eraseFromParent(); ToErase = nullptr; } @@ -1158,6 +1347,13 @@ bool PPCMIPeephole::simplifyCode() { // We try to eliminate redundant compare instruction. Simplified |= eliminateRedundantCompare(); + // If we have made any modifications and added any registers to the set of + // registers for which we need to update the kill flags, do so by recomputing + // LiveVariables for those registers. + for (Register Reg : RegsToUpdate) { + if (!MRI->reg_empty(Reg)) + LV->recomputeForSingleDefVirtReg(Reg); + } return Simplified; } @@ -1586,6 +1782,12 @@ bool PPCMIPeephole::eliminateRedundantCompare() { LLVM_DEBUG(BI1->dump()); LLVM_DEBUG(CMPI2->dump()); LLVM_DEBUG(BI2->dump()); + for (const MachineOperand &MO : CMPI1->operands()) + if (MO.isReg()) + addRegToUpdate(MO.getReg()); + for (const MachineOperand &MO : CMPI2->operands()) + if (MO.isReg()) + addRegToUpdate(MO.getReg()); // We adjust opcode, predicates and immediate as we determined above. if (NewOpCode != 0 && NewOpCode != CMPI1->getOpcode()) { @@ -1623,6 +1825,7 @@ bool PPCMIPeephole::eliminateRedundantCompare() { "We cannot support if an operand comes from this BB."); unsigned SrcReg = getIncomingRegForBlock(Inst, MBBtoMoveCmp); CMPI2->getOperand(I).setReg(SrcReg); + addRegToUpdate(SrcReg); } } auto I = MachineBasicBlock::iterator(MBBtoMoveCmp->getFirstTerminator()); @@ -1635,14 +1838,20 @@ bool PPCMIPeephole::eliminateRedundantCompare() { .addReg(BI1->getOperand(1).getReg()).addMBB(MBB1) .addReg(BI2->getOperand(1).getReg()).addMBB(MBBtoMoveCmp); BI2->getOperand(1).setReg(NewVReg); + addRegToUpdate(NewVReg); } else { // We finally eliminate compare instruction in MBB2. + // We do not need to treat CMPI2 specially here in terms of re-computing + // live variables even though it is being deleted because: + // - It defines a register that has a single use (already checked in + // eligibleForCompareElimination()) + // - The only user (BI2) is no longer using it so the register is dead (no + // def, no uses) + // - We do not attempt to recompute live variables for dead registers BI2->getOperand(1).setReg(BI1->getOperand(1).getReg()); CMPI2->eraseFromParent(); } - BI2->getOperand(1).setIsKill(true); - BI1->getOperand(1).setIsKill(false); LLVM_DEBUG(dbgs() << "into a compare and two branches:\n"); LLVM_DEBUG(CMPI1->dump()); @@ -1654,7 +1863,6 @@ bool PPCMIPeephole::eliminateRedundantCompare() { << " to handle partial redundancy.\n"); LLVM_DEBUG(CMPI2->dump()); } - Simplified = true; } @@ -1664,7 +1872,8 @@ bool PPCMIPeephole::eliminateRedundantCompare() { // We miss the opportunity to emit an RLDIC when lowering jump tables // since ISEL sees only a single basic block. When selecting, the clear // and shift left will be in different blocks. -bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI) { +bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI, + MachineInstr *&ToErase) { if (MI.getOpcode() != PPC::RLDICR) return false; @@ -1710,8 +1919,8 @@ bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI) { MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg()); MI.getOperand(2).setImm(NewSH); MI.getOperand(3).setImm(NewMB); - MI.getOperand(1).setIsKill(SrcMI->getOperand(1).isKill()); - SrcMI->getOperand(1).setIsKill(false); + addRegToUpdate(MI.getOperand(1).getReg()); + addRegToUpdate(SrcMI->getOperand(0).getReg()); LLVM_DEBUG(dbgs() << "To: "); LLVM_DEBUG(MI.dump()); @@ -1720,7 +1929,7 @@ bool PPCMIPeephole::emitRLDICWhenLoweringJumpTables(MachineInstr &MI) { if (MRI->use_nodbg_empty(SrcReg)) { assert(!SrcMI->hasImplicitDef() && "Not expecting an implicit def with this instr."); - SrcMI->eraseFromParent(); + ToErase = SrcMI; } return true; } @@ -1793,8 +2002,11 @@ bool PPCMIPeephole::combineSEXTAndSHL(MachineInstr &MI, LLVM_DEBUG(NewInstr->dump()); ++NumEXTSWAndSLDICombined; ToErase = &MI; - // SrcMI, which is extsw, is of no use now, erase it. - SrcMI->eraseFromParent(); + // SrcMI, which is extsw, is of no use now, but we don't erase it here so we + // can recompute its kill flags. We run DCE immediately after this pass + // to clean up dead instructions such as this. + addRegToUpdate(NewInstr->getOperand(1).getReg()); + addRegToUpdate(SrcMI->getOperand(0).getReg()); return true; } @@ -1805,6 +2017,7 @@ INITIALIZE_PASS_BEGIN(PPCMIPeephole, DEBUG_TYPE, INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree) +INITIALIZE_PASS_DEPENDENCY(LiveVariables) INITIALIZE_PASS_END(PPCMIPeephole, DEBUG_TYPE, "PowerPC MI Peephole Optimization", false, false) diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp index bf1c39a3a3a2..7ad6ef8c3928 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMacroFusion.cpp @@ -286,7 +286,7 @@ static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, namespace llvm { -std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation () { +std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation() { return createMacroFusionDAGMutation(shouldScheduleAdjacent); } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp new file mode 100644 index 000000000000..d9465e86d896 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp @@ -0,0 +1,365 @@ +//===-- PPCMergeStringPool.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This transformation tries to merge the strings in the module into one pool +// of strings. The idea is to reduce the number of TOC entries in the module so +// that instead of having one TOC entry for each string there is only one global +// TOC entry and all of the strings are referenced off of that one entry plus +// an offset. +// +//===----------------------------------------------------------------------===// + +#include "PPC.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/DomTreeUpdater.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopIterator.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" + +#define DEBUG_TYPE "ppc-merge-strings" + +STATISTIC(NumPooledStrings, "Number of Strings Pooled"); + +using namespace llvm; + +static cl::opt<unsigned> + MaxStringsPooled("ppc-max-strings-pooled", cl::Hidden, cl::init(-1), + cl::desc("Maximum Number of Strings to Pool.")); + +static cl::opt<unsigned> + MinStringsBeforePool("ppc-min-strings-before-pool", cl::Hidden, cl::init(2), + cl::desc("Minimum number of string candidates before " + "pooling is considered.")); + +namespace { +struct { + bool operator()(const GlobalVariable *LHS, const GlobalVariable *RHS) const { + // First priority is alignment. + // If elements are sorted in terms of alignment then there won't be an + // issue with incorrect alignment that would require padding. + Align LHSAlign = LHS->getAlign().valueOrOne(); + Align RHSAlign = RHS->getAlign().valueOrOne(); + if (LHSAlign > RHSAlign) + return true; + else if (LHSAlign < RHSAlign) + return false; + + // Next priority is the number of uses. + // Smaller offsets are easier to materialize because materializing a large + // offset may require more than one instruction. (ie addis, addi). + if (LHS->getNumUses() > RHS->getNumUses()) + return true; + else if (LHS->getNumUses() < RHS->getNumUses()) + return false; + + const Constant *ConstLHS = LHS->getInitializer(); + const ConstantDataSequential *ConstDataLHS = + dyn_cast<ConstantDataSequential>(ConstLHS); + unsigned LHSSize = + ConstDataLHS->getNumElements() * ConstDataLHS->getElementByteSize(); + const Constant *ConstRHS = RHS->getInitializer(); + const ConstantDataSequential *ConstDataRHS = + dyn_cast<ConstantDataSequential>(ConstRHS); + unsigned RHSSize = + ConstDataRHS->getNumElements() * ConstDataRHS->getElementByteSize(); + + // Finally smaller constants should go first. This is, again, trying to + // minimize the offsets into the final struct. + return LHSSize < RHSSize; + } +} CompareConstants; + +class PPCMergeStringPool : public ModulePass { +public: + static char ID; + PPCMergeStringPool() : ModulePass(ID) {} + + bool runOnModule(Module &M) override { return mergeModuleStringPool(M); } + + StringRef getPassName() const override { return "PPC Merge String Pool"; } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addPreserved<DominatorTreeWrapperPass>(); + AU.addPreserved<LoopInfoWrapperPass>(); + AU.addPreserved<ScalarEvolutionWrapperPass>(); + AU.addPreserved<SCEVAAWrapperPass>(); + } + +private: + // Globals in a Module are already unique so a set is not required and a + // vector will do. + std::vector<GlobalVariable *> MergeableStrings; + Align MaxAlignment; + Type *PooledStructType; + LLVMContext *Context; + void collectCandidateConstants(Module &M); + bool mergeModuleStringPool(Module &M); + void replaceUsesWithGEP(GlobalVariable *GlobalToReplace, GlobalVariable *GPool, + unsigned ElementIndex); +}; + + +// In order for a constant to be pooled we need to be able to replace all of +// the uses for that constant. This function checks all of the uses to make +// sure that they can be replaced. +static bool hasReplaceableUsers(GlobalVariable &GV) { + for (User *CurrentUser : GV.users()) { + // Instruction users are always valid. + if (isa<Instruction>(CurrentUser)) + continue; + + // We cannot replace GlobalValue users because they are not just nodes + // in IR. To replace a user like this we would need to create a new + // GlobalValue with the replacement and then try to delete the original + // GlobalValue. Deleting the original would only happen if it has no other + // uses. + if (isa<GlobalValue>(CurrentUser)) + return false; + + // We only support Instruction and Constant users. + if (!isa<Constant>(CurrentUser)) + return false; + } + + return true; +} + +// Run through all of the constants in the module and determine if they are +// valid candidates to be merged into the string pool. Valid candidates will +// be added to MergeableStrings. +void PPCMergeStringPool::collectCandidateConstants(Module &M) { + SmallVector<GlobalValue *, 4> UsedV; + collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false); + SmallVector<GlobalValue *, 4> UsedVCompiler; + collectUsedGlobalVariables(M, UsedVCompiler, /*CompilerUsed=*/true); + // Combine all of the Global Variables marked as used into a SmallPtrSet for + // faster lookup inside the loop. + SmallPtrSet<GlobalValue *, 8> AllUsedGlobals; + AllUsedGlobals.insert(UsedV.begin(), UsedV.end()); + AllUsedGlobals.insert(UsedVCompiler.begin(), UsedVCompiler.end()); + + for (GlobalVariable &Global : M.globals()) { + LLVM_DEBUG(dbgs() << "Looking at global:"); + LLVM_DEBUG(Global.dump()); + LLVM_DEBUG(dbgs() << "isConstant() " << Global.isConstant() << "\n"); + LLVM_DEBUG(dbgs() << "hasInitializer() " << Global.hasInitializer() + << "\n"); + + // We can only pool constants. + if (!Global.isConstant() || !Global.hasInitializer()) + continue; + + // If a global constant has a section we do not try to pool it because + // there is no guarantee that other constants will also be in the same + // section. Trying to pool constants from different sections (or no + // section) means that the pool has to be in multiple sections at the same + // time. + if (Global.hasSection()) + continue; + + // Do not pool constants with metadata because we should not add metadata + // to the pool when that metadata refers to a single constant in the pool. + if (Global.hasMetadata()) + continue; + + ConstantDataSequential *ConstData = + dyn_cast<ConstantDataSequential>(Global.getInitializer()); + + // If the constant is undef then ConstData will be null. + if (!ConstData) + continue; + + // Do not pool globals that are part of llvm.used or llvm.compiler.end. + if (AllUsedGlobals.contains(&Global)) + continue; + + if (!hasReplaceableUsers(Global)) + continue; + + Align AlignOfGlobal = Global.getAlign().valueOrOne(); + + // TODO: At this point do not allow over-aligned types. Adding a type + // with larger alignment may lose the larger alignment once it is + // added to the struct. + // Fix this in a future patch. + if (AlignOfGlobal.value() > ConstData->getElementByteSize()) + continue; + + // Make sure that the global is only visible inside the compilation unit. + if (Global.getLinkage() != GlobalValue::PrivateLinkage && + Global.getLinkage() != GlobalValue::InternalLinkage) + continue; + + LLVM_DEBUG(dbgs() << "Constant data of Global: "); + LLVM_DEBUG(ConstData->dump()); + LLVM_DEBUG(dbgs() << "\n\n"); + + MergeableStrings.push_back(&Global); + if (MaxAlignment < AlignOfGlobal) + MaxAlignment = AlignOfGlobal; + + // If we have already reached the maximum number of pooled strings then + // there is no point in looking for more. + if (MergeableStrings.size() >= MaxStringsPooled) + break; + } +} + +bool PPCMergeStringPool::mergeModuleStringPool(Module &M) { + + LLVM_DEBUG(dbgs() << "Merging string pool for module: " << M.getName() + << "\n"); + LLVM_DEBUG(dbgs() << "Number of globals is: " << M.global_size() << "\n"); + + collectCandidateConstants(M); + + // If we have too few constants in the module that are merge candidates we + // will skip doing the merging. + if (MergeableStrings.size() < MinStringsBeforePool) + return false; + + // Sort the global constants to make access more efficient. + std::sort(MergeableStrings.begin(), MergeableStrings.end(), CompareConstants); + + SmallVector<Constant *> ConstantsInStruct; + for (GlobalVariable *GV : MergeableStrings) + ConstantsInStruct.push_back(GV->getInitializer()); + + // Use an anonymous struct to pool the strings. + // TODO: This pass uses a single anonymous struct for all of the pooled + // entries. This may cause a performance issue in the situation where + // computing the offset requires two instructions (addis, addi). For the + // future we may want to split this into multiple structs. + Constant *ConstantPool = ConstantStruct::getAnon(ConstantsInStruct); + PooledStructType = ConstantPool->getType(); + + // The GlobalVariable constructor calls + // MM->insertGlobalVariable(PooledGlobal). + GlobalVariable *PooledGlobal = + new GlobalVariable(M, PooledStructType, + /* isConstant */ true, GlobalValue::PrivateLinkage, + ConstantPool, "__ModuleStringPool"); + PooledGlobal->setAlignment(MaxAlignment); + + LLVM_DEBUG(dbgs() << "Constructing global variable for string pool: "); + LLVM_DEBUG(PooledGlobal->dump()); + + Context = &M.getContext(); + size_t ElementIndex = 0; + for (GlobalVariable *GV : MergeableStrings) { + + LLVM_DEBUG(dbgs() << "The global:\n"); + LLVM_DEBUG(GV->dump()); + LLVM_DEBUG(dbgs() << "Has " << GV->getNumUses() << " uses.\n"); + + // Access to the pooled constant strings require an offset. Add a GEP + // before every use in order to compute this offset. + replaceUsesWithGEP(GV, PooledGlobal, ElementIndex); + + // This GV has no more uses so we can erase it. + if (GV->use_empty()) + GV->eraseFromParent(); + + NumPooledStrings++; + ElementIndex++; + } + return true; +} + +static bool userHasOperand(User *TheUser, GlobalVariable *GVOperand) { + for (Value *Op : TheUser->operands()) + if (Op == GVOperand) + return true; + return false; +} + +// For pooled strings we need to add the offset into the pool for each string. +// This is done by adding a Get Element Pointer (GEP) before each user. This +// function adds the GEP. +void PPCMergeStringPool::replaceUsesWithGEP(GlobalVariable *GlobalToReplace, + GlobalVariable *GPool, + unsigned ElementIndex) { + SmallVector<Value *, 2> Indices; + Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), 0)); + Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), ElementIndex)); + + // Need to save a temporary copy of each user list because we remove uses + // as we replace them. + SmallVector<User *> Users; + for (User *CurrentUser : GlobalToReplace->users()) + Users.push_back(CurrentUser); + + for (User *CurrentUser : Users) { + Instruction *UserInstruction = dyn_cast<Instruction>(CurrentUser); + Constant *UserConstant = dyn_cast<Constant>(CurrentUser); + + // At this point we expect that the user is either an instruction or a + // constant. + assert((UserConstant || UserInstruction) && + "Expected the user to be an instruction or a constant."); + + // The user was not found so it must have been replaced earlier. + if (!userHasOperand(CurrentUser, GlobalToReplace)) + continue; + + // We cannot replace operands in globals so we ignore those. + if (isa<GlobalValue>(CurrentUser)) + continue; + + if (!UserInstruction) { + // User is a constant type. + Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr( + PooledStructType, GPool, Indices); + UserConstant->handleOperandChange(GlobalToReplace, ConstGEP); + continue; + } + + if (PHINode *UserPHI = dyn_cast<PHINode>(UserInstruction)) { + // GEP instructions cannot be added before PHI nodes. + // With getInBoundsGetElementPtr we create the GEP and then replace it + // inline into the PHI. + Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr( + PooledStructType, GPool, Indices); + UserPHI->replaceUsesOfWith(GlobalToReplace, ConstGEP); + continue; + } + // The user is a valid instruction that is not a PHINode. + GetElementPtrInst *GEPInst = + GetElementPtrInst::Create(PooledStructType, GPool, Indices); + GEPInst->insertBefore(UserInstruction); + + LLVM_DEBUG(dbgs() << "Inserting GEP before:\n"); + LLVM_DEBUG(UserInstruction->dump()); + + LLVM_DEBUG(dbgs() << "Replacing this global:\n"); + LLVM_DEBUG(GlobalToReplace->dump()); + LLVM_DEBUG(dbgs() << "with this:\n"); + LLVM_DEBUG(GEPInst->dump()); + + // After the GEP is inserted the GV can be replaced. + CurrentUser->replaceUsesOfWith(GlobalToReplace, GEPInst); + } +} + +} // namespace + +char PPCMergeStringPool::ID = 0; + +INITIALIZE_PASS(PPCMergeStringPool, DEBUG_TYPE, "PPC Merge String Pool", false, + false) + +ModulePass *llvm::createPPCMergeStringPoolPass() { + return new PPCMergeStringPool(); +} diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp index 6f1b34843343..6e3bf26a598a 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCPreEmitPeephole.cpp @@ -14,7 +14,6 @@ #include "PPC.h" #include "PPCInstrInfo.h" #include "PPCSubtarget.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -240,7 +239,7 @@ static bool hasPCRelativeForm(MachineInstr &Use) { return false; // Finally return true only if the GOT flag is present. - return (SymbolOp.getTargetFlags() & PPCII::MO_GOT_FLAG); + return PPCInstrInfo::hasGOTFlag(SymbolOp.getTargetFlags()); } bool addLinkerOpt(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) { @@ -495,7 +494,8 @@ static bool hasPCRelativeForm(MachineInstr &Use) { } } MachineInstr *DefMIToErase = nullptr; - if (TII->convertToImmediateForm(MI, &DefMIToErase)) { + SmallSet<Register, 4> UpdatedRegs; + if (TII->convertToImmediateForm(MI, UpdatedRegs, &DefMIToErase)) { Changed = true; NumRRConvertedInPreEmit++; LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h index 11dbbce42f61..36b8a24ba502 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -172,58 +172,6 @@ public: Register getBaseRegister(const MachineFunction &MF) const; bool hasBasePointer(const MachineFunction &MF) const; - /// stripRegisterPrefix - This method strips the character prefix from a - /// register name so that only the number is left. Used by for linux asm. - static const char *stripRegisterPrefix(const char *RegName) { - switch (RegName[0]) { - case 'a': - if (RegName[1] == 'c' && RegName[2] == 'c') - return RegName + 3; - break; - case 'f': - if (RegName[1] == 'p') - return RegName + 2; - [[fallthrough]]; - case 'r': - case 'v': - if (RegName[1] == 's') { - if (RegName[2] == 'p') - return RegName + 3; - return RegName + 2; - } - return RegName + 1; - case 'c': - if (RegName[1] == 'r') - return RegName + 2; - break; - case 'w': - // For wacc and wacc_hi - if (RegName[1] == 'a' && RegName[2] == 'c' && RegName[3] == 'c') { - if (RegName[4] == '_') - return RegName + 7; - else - return RegName + 4; - } - break; - case 'd': - // For dmr, dmrp, dmrrow, dmrrowp - if (RegName[1] == 'm' && RegName[2] == 'r') { - if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w' && - RegName[6] == 'p') - return RegName + 7; - else if (RegName[3] == 'r' && RegName[4] == 'o' && RegName[5] == 'w') - return RegName + 6; - else if (RegName[3] == 'p') - return RegName + 4; - else - return RegName + 3; - } - break; - } - - return RegName; - } - bool isNonallocatableRegisterCalleeSave(MCRegister Reg) const override { return Reg == PPC::LR || Reg == PPC::LR8; } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td index 6151faf403aa..375e63654db1 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCRegisterInfo.td @@ -798,6 +798,7 @@ def directbrtarget : Operand<OtherVT> { def absdirectbrtarget : Operand<OtherVT> { let PrintMethod = "printAbsBranchOperand"; let EncoderMethod = "getAbsDirectBrEncoding"; + let DecoderMethod = "decodeDirectBrTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; } def PPCCondBrAsmOperand : AsmOperandClass { @@ -814,6 +815,7 @@ def condbrtarget : Operand<OtherVT> { def abscondbrtarget : Operand<OtherVT> { let PrintMethod = "printAbsBranchOperand"; let EncoderMethod = "getAbsCondBrEncoding"; + let DecoderMethod = "decodeCondBrTarget"; let ParserMatchClass = PPCCondBrAsmOperand; } def calltarget : Operand<iPTR> { @@ -826,6 +828,7 @@ def calltarget : Operand<iPTR> { def abscalltarget : Operand<iPTR> { let PrintMethod = "printAbsBranchOperand"; let EncoderMethod = "getAbsDirectBrEncoding"; + let DecoderMethod = "decodeDirectBrTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; } def PPCCRBitMaskOperand : AsmOperandClass { diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td index 25be37718af2..f922f8a7d985 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP10.td @@ -29,8 +29,8 @@ def P10Model : SchedMachineModel { let LoopMicroOpBufferSize = 60; let CompleteModel = 1; - // Do not support SPE (Signal Procesing Engine) on Power 10. - let UnsupportedFeatures = [HasSPE, IsE500, IsBookE, IsISAFuture]; + // Power 10 does not support instructions from SPE, Book E and HTM. + let UnsupportedFeatures = [HasSPE, IsE500, IsBookE, IsISAFuture, HasHTM]; } let SchedModel = P10Model in { @@ -87,27 +87,27 @@ let SchedModel = P10Model in { } def P10W_BF_22C : SchedWriteRes<[P10_BF]> { - let ResourceCycles = [ 5 ]; + let ReleaseAtCycles = [ 5 ]; let Latency = 22; } def P10W_BF_24C : SchedWriteRes<[P10_BF]> { - let ResourceCycles = [ 8 ]; + let ReleaseAtCycles = [ 8 ]; let Latency = 24; } def P10W_BF_26C : SchedWriteRes<[P10_BF]> { - let ResourceCycles = [ 5 ]; + let ReleaseAtCycles = [ 5 ]; let Latency = 26; } def P10W_BF_27C : SchedWriteRes<[P10_BF]> { - let ResourceCycles = [ 7 ]; + let ReleaseAtCycles = [ 7 ]; let Latency = 27; } def P10W_BF_36C : SchedWriteRes<[P10_BF]> { - let ResourceCycles = [ 10 ]; + let ReleaseAtCycles = [ 10 ]; let Latency = 36; } @@ -128,134 +128,134 @@ let SchedModel = P10Model in { } def P10W_DF_24C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 16 ]; + let ReleaseAtCycles = [ 16 ]; let Latency = 24; } def P10W_DF_25C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 17 ]; + let ReleaseAtCycles = [ 17 ]; let Latency = 25; } def P10W_DF_26C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 18 ]; + let ReleaseAtCycles = [ 18 ]; let Latency = 26; } def P10W_DF_32C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 22 ]; + let ReleaseAtCycles = [ 22 ]; let Latency = 32; } def P10W_DF_33C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 25 ]; + let ReleaseAtCycles = [ 25 ]; let Latency = 33; } def P10W_DF_34C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 25 ]; + let ReleaseAtCycles = [ 25 ]; let Latency = 34; } def P10W_DF_38C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 30 ]; + let ReleaseAtCycles = [ 30 ]; let Latency = 38; } def P10W_DF_40C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 17 ]; + let ReleaseAtCycles = [ 17 ]; let Latency = 40; } def P10W_DF_43C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 34 ]; + let ReleaseAtCycles = [ 34 ]; let Latency = 43; } def P10W_DF_59C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 49 ]; + let ReleaseAtCycles = [ 49 ]; let Latency = 59; } def P10W_DF_61C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 12 ]; + let ReleaseAtCycles = [ 12 ]; let Latency = 61; } def P10W_DF_68C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 15 ]; + let ReleaseAtCycles = [ 15 ]; let Latency = 68; } def P10W_DF_77C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 67 ]; + let ReleaseAtCycles = [ 67 ]; let Latency = 77; } def P10W_DF_87C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 12 ]; + let ReleaseAtCycles = [ 12 ]; let Latency = 87; } def P10W_DF_100C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 32 ]; + let ReleaseAtCycles = [ 32 ]; let Latency = 100; } def P10W_DF_174C : SchedWriteRes<[P10_DF]> { - let ResourceCycles = [ 33 ]; + let ReleaseAtCycles = [ 33 ]; let Latency = 174; } // A DV pipeline may take from 20 to 83 cycles to complete. // Some DV operations may keep the pipeline busy for up to 33 cycles. def P10W_DV_20C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 10 ]; + let ReleaseAtCycles = [ 10 ]; let Latency = 20; } def P10W_DV_25C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 10 ]; + let ReleaseAtCycles = [ 10 ]; let Latency = 25; } def P10W_DV_27C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 10 ]; + let ReleaseAtCycles = [ 10 ]; let Latency = 27; } def P10W_DV_41C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 10 ]; + let ReleaseAtCycles = [ 10 ]; let Latency = 41; } def P10W_DV_43C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 21 ]; + let ReleaseAtCycles = [ 21 ]; let Latency = 43; } def P10W_DV_47C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 21 ]; + let ReleaseAtCycles = [ 21 ]; let Latency = 47; } def P10W_DV_54C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 33 ]; + let ReleaseAtCycles = [ 33 ]; let Latency = 54; } def P10W_DV_60C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 33 ]; + let ReleaseAtCycles = [ 33 ]; let Latency = 60; } def P10W_DV_75C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 21 ]; + let ReleaseAtCycles = [ 21 ]; let Latency = 75; } def P10W_DV_83C : SchedWriteRes<[P10_DV]> { - let ResourceCycles = [ 33 ]; + let ReleaseAtCycles = [ 33 ]; let Latency = 83; } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td index 5a8c1eb2b837..93399e5ddbca 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP7.td @@ -6,383 +6,10 @@ // //===----------------------------------------------------------------------===// // -// This file defines the itinerary class data for the POWER7 processor. +// This file defines the SchedModel for the POWER7 processor. // //===----------------------------------------------------------------------===// -// Primary reference: -// IBM POWER7 multicore server processor -// B. Sinharoy, et al. -// IBM J. Res. & Dev. (55) 3. May/June 2011. - -// Scheduling for the P7 involves tracking two types of resources: -// 1. The dispatch bundle slots -// 2. The functional unit resources - -// Dispatch units: -def P7_DU1 : FuncUnit; -def P7_DU2 : FuncUnit; -def P7_DU3 : FuncUnit; -def P7_DU4 : FuncUnit; -def P7_DU5 : FuncUnit; -def P7_DU6 : FuncUnit; - -def P7_LS1 : FuncUnit; // Load/Store pipeline 1 -def P7_LS2 : FuncUnit; // Load/Store pipeline 2 - -def P7_FX1 : FuncUnit; // FX pipeline 1 -def P7_FX2 : FuncUnit; // FX pipeline 2 - -// VS pipeline 1 (vector integer ops. always here) -def P7_VS1 : FuncUnit; // VS pipeline 1 -// VS pipeline 2 (128-bit stores and perms. here) -def P7_VS2 : FuncUnit; // VS pipeline 2 - -def P7_CRU : FuncUnit; // CR unit (CR logicals and move-from-SPRs) -def P7_BRU : FuncUnit; // BR unit - -// Notes: -// Each LSU pipeline can also execute FX add and logical instructions. -// Each LSU pipeline can complete a load or store in one cycle. -// -// Each store is broken into two parts, AGEN goes to the LSU while a -// "data steering" op. goes to the FXU or VSU. -// -// FX loads have a two cycle load-to-use latency (so one "bubble" cycle). -// VSU loads have a three cycle load-to-use latency (so two "bubble" cycle). -// -// Frequent FX ops. take only one cycle and results can be used again in the -// next cycle (there is a self-bypass). Getting results from the other FX -// pipeline takes an additional cycle. -// -// The VSU XS is similar to the POWER6, but with a pipeline length of 2 cycles -// (instead of 3 cycles on the POWER6). VSU XS handles vector FX-style ops. -// Dispatch of an instruction to VS1 that uses four single prec. inputs -// (either to a float or XC op). prevents dispatch in that cycle to VS2 of any -// floating point instruction. -// -// The VSU PM is similar to the POWER6, but with a pipeline length of 3 cycles -// (instead of 4 cycles on the POWER6). vsel is handled by the PM pipeline -// (unlike on the POWER6). -// -// FMA from the VSUs can forward results in 6 cycles. VS1 XS and vector FP -// share the same write-back, and have a 5-cycle latency difference, so the -// IFU/IDU will not dispatch an XS instructon 5 cycles after a vector FP -// op. has been dispatched to VS1. -// -// Three cycles after an L1 cache hit, a dependent VSU instruction can issue. -// -// Instruction dispatch groups have (at most) four non-branch instructions, and -// two branches. Unlike on the POWER4/5, a branch does not automatically -// end the dispatch group, but a second branch must be the last in the group. - -def P7Itineraries : ProcessorItineraries< - [P7_DU1, P7_DU2, P7_DU3, P7_DU4, P7_DU5, P7_DU6, - P7_LS1, P7_LS2, P7_FX1, P7_FX2, P7_VS1, P7_VS2, P7_CRU, P7_BRU], [], [ - InstrItinData<IIC_IntSimple , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2, - P7_LS1, P7_LS2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntGeneral , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntISEL, [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_FX1, P7_FX2], 0>, - InstrStage<1, [P7_BRU]>], - [1, 1, 1, 1]>, - InstrItinData<IIC_IntCompare , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - // FIXME: Add record-form itinerary data. - InstrItinData<IIC_IntDivW , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<36, [P7_FX1, P7_FX2]>], - [36, 1, 1]>, - InstrItinData<IIC_IntDivD , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<68, [P7_FX1, P7_FX2]>], - [68, 1, 1]>, - InstrItinData<IIC_IntMulHW , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntMulHWU , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntMulHD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntMulLI , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntRotate , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntRotateD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntRotateDI , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntShift , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntTrapW , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1]>, - InstrItinData<IIC_IntTrapD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1]>, - InstrItinData<IIC_BrB , [InstrStage<1, [P7_DU5, P7_DU6], 0>, - InstrStage<1, [P7_BRU]>], - [3, 1, 1]>, - InstrItinData<IIC_BrCR , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_CRU]>], - [3, 1, 1]>, - InstrItinData<IIC_BrMCR , [InstrStage<1, [P7_DU5, P7_DU6], 0>, - InstrStage<1, [P7_BRU]>], - [3, 1, 1]>, - InstrItinData<IIC_BrMCRX , [InstrStage<1, [P7_DU5, P7_DU6], 0>, - InstrStage<1, [P7_BRU]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLoad , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [2, 1, 1]>, - InstrItinData<IIC_LdStLoadUpd , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [2, 2, 1, 1]>, - InstrItinData<IIC_LdStLoadUpdX, [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [2, 1, 1]>, - InstrItinData<IIC_LdStLDU , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [2, 2, 1, 1]>, - InstrItinData<IIC_LdStLDUX , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLFD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLVecX , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLFDU , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLFDUX , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLHA , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLHAU , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [4, 4, 1, 1]>, - InstrItinData<IIC_LdStLHAUX , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [4, 4, 1, 1]>, - InstrItinData<IIC_LdStLWA , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLWARX, [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLDARX, [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLMW , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [2, 1, 1]>, - InstrItinData<IIC_LdStStore , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTU , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [2, 1, 1, 1]>, - InstrItinData<IIC_LdStSTUX , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2]>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [2, 1, 1, 1]>, - InstrItinData<IIC_LdStSTFD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTFDU , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_FX1, P7_FX2], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [2, 1, 1, 1]>, - InstrItinData<IIC_LdStSTVEBX , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2], 0>, - InstrStage<1, [P7_VS2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTDCX , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTWCX , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_LS1, P7_LS2]>], - [1, 1, 1]>, - InstrItinData<IIC_BrMCRX , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_DU2], 0>, - InstrStage<1, [P7_DU3], 0>, - InstrStage<1, [P7_DU4], 0>, - InstrStage<1, [P7_CRU]>, - InstrStage<1, [P7_FX1, P7_FX2]>], - [3, 1]>, // mtcr - InstrItinData<IIC_SprMFCR , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_CRU]>], - [6, 1]>, - InstrItinData<IIC_SprMFCRF , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_CRU]>], - [3, 1]>, - InstrItinData<IIC_SprMTSPR , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_FX1]>], - [4, 1]>, // mtctr - InstrItinData<IIC_FPGeneral , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [5, 1, 1]>, - InstrItinData<IIC_FPAddSub , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [5, 1, 1]>, - InstrItinData<IIC_FPCompare , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [8, 1, 1]>, - InstrItinData<IIC_FPDivD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [33, 1, 1]>, - InstrItinData<IIC_FPDivS , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [27, 1, 1]>, - InstrItinData<IIC_FPSqrtD , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [44, 1, 1]>, - InstrItinData<IIC_FPSqrtS , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [32, 1, 1]>, - InstrItinData<IIC_FPFused , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [5, 1, 1, 1]>, - InstrItinData<IIC_FPRes , [InstrStage<1, [P7_DU1, P7_DU2, - P7_DU3, P7_DU4], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [5, 1, 1]>, - InstrItinData<IIC_VecGeneral , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_VS1]>], - [2, 1, 1]>, - InstrItinData<IIC_VecVSL , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_VS1]>], - [2, 1, 1]>, - InstrItinData<IIC_VecVSR , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_VS1]>], - [2, 1, 1]>, - InstrItinData<IIC_VecFP , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [6, 1, 1]>, - InstrItinData<IIC_VecFPCompare, [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [6, 1, 1]>, - InstrItinData<IIC_VecFPRound , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_VS1, P7_VS2]>], - [6, 1, 1]>, - InstrItinData<IIC_VecComplex , [InstrStage<1, [P7_DU1], 0>, - InstrStage<1, [P7_VS1]>], - [7, 1, 1]>, - InstrItinData<IIC_VecPerm , [InstrStage<1, [P7_DU1, P7_DU2], 0>, - InstrStage<1, [P7_VS2]>], - [3, 1, 1]> -]>; - -// ===---------------------------------------------------------------------===// -// P7 machine model for scheduling and other instruction cost heuristics. - def P7Model : SchedMachineModel { let IssueWidth = 6; // 4 (non-branch) instructions are dispatched per cycle. // Note that the dispatch bundle size is 6 (including @@ -394,11 +21,295 @@ def P7Model : SchedMachineModel { // Itineraries are queried instead. let MispredictPenalty = 16; + let MicroOpBufferSize = 44; + // Try to make sure we have at least 10 dispatch groups in a loop. let LoopMicroOpBufferSize = 40; let CompleteModel = 0; - let Itineraries = P7Itineraries; + let UnsupportedFeatures = [HasSPE, PrefixInstrs, MMA, + PairedVectorMemops, IsISA3_0, IsISA2_07, + PCRelativeMemops, IsISA3_1, IsISAFuture]; } +let SchedModel = P7Model in { + def P7_LSU_FXU: ProcResource<4>; + def P7_LSU: ProcResource<2> { + let Super = P7_LSU_FXU; + } + def P7_FXU: ProcResource<2> { + let Super = P7_LSU_FXU; + } + // Implemented as two 2-way SIMD operations for double- and single-precision. + def P7_FPU: ProcResource<4>; + // Scalar binary floating point instructions can only use two FPUs. + def P7_ScalarFPU: ProcResource<2> { + let Super = P7_FPU; + } + def P7_VectorFPU: ProcResource<2> { + let Super = P7_FPU; + } + // Executing simple FX, complex FX, permute and 4-way SIMD single-precision FP ops + def P7_VMX: ProcResource<1>; + def P7_VPM: ProcResource<1> { + let Super = P7_VMX; + let BufferSize = 1; + } + def P7_VXS: ProcResource<1> { + let Super = P7_VMX; + } + def P7_DFU: ProcResource<1>; + def P7_BRU: ProcResource<1>; + def P7_CRU: ProcResource<1>; + + def P7_PORT_LS : ProcResource<2>; + def P7_PORT_FX : ProcResource<2>; + def P7_PORT_FP : ProcResource<2>; + def P7_PORT_BR : ProcResource<1>; + def P7_PORT_CR : ProcResource<1>; + + def P7_DISP_LS : SchedWriteRes<[P7_PORT_LS]>; + def P7_DISP_FX : SchedWriteRes<[P7_PORT_FX]>; + def P7_DISP_FP : SchedWriteRes<[P7_PORT_FP]>; + def P7_DISP_BR : SchedWriteRes<[P7_PORT_BR]>; + def P7_DISP_CR : SchedWriteRes<[P7_PORT_CR]>; + + def P7_BRU_NONE : SchedWriteRes<[P7_BRU]>; + def P7_BRU_3C : SchedWriteRes<[P7_BRU]> { let Latency = 3; } + def P7_BRU_4C : SchedWriteRes<[P7_BRU]> { let Latency = 4; } + def P7_CRU_NONE : SchedWriteRes<[P7_CRU]>; + def P7_CRU_3C : SchedWriteRes<[P7_CRU]> { let Latency = 3; } + def P7_CRU_6C : SchedWriteRes<[P7_CRU]> { let Latency = 6; } + def P7_LSU_NONE : SchedWriteRes<[P7_LSU]>; + def P7_LSU_2C : SchedWriteRes<[P7_LSU]> { let Latency = 2; } + def P7_LSU_3C : SchedWriteRes<[P7_LSU]> { let Latency = 3; } + def P7_LSU_4C : SchedWriteRes<[P7_LSU]> { let Latency = 4; } + def P7_FXU_NONE : SchedWriteRes<[P7_FXU]>; + def P7_FXU_2C : SchedWriteRes<[P7_FXU]> { let Latency = 2; } + def P7_FXU_3C : SchedWriteRes<[P7_FXU]> { let Latency = 3; } + def P7_FXU_4C : SchedWriteRes<[P7_FXU]> { let Latency = 4; } + def P7_FXU_5C : SchedWriteRes<[P7_FXU]> { let Latency = 5; } + def P7_FXU_38C : SchedWriteRes<[P7_FXU]> { let Latency = 38; } + def P7_FXU_69C : SchedWriteRes<[P7_FXU]> { let Latency = 69; } + def P7_LSU_FXU_2C : SchedWriteRes<[P7_LSU_FXU]> { let Latency = 2; } + def P7_FPU_NONE : SchedWriteRes<[P7_FPU]>; + def P7_VectorFPU_6C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 6; } + def P7_VectorFPU_25C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 25; } + def P7_VectorFPU_30C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 30; } + def P7_VectorFPU_31C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 31; } + def P7_VectorFPU_42C : SchedWriteRes<[P7_VectorFPU]> { let Latency = 42; } + def P7_ScalarFPU_6C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 6; } + def P7_ScalarFPU_8C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 8; } + def P7_ScalarFPU_27C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 27; } + def P7_ScalarFPU_31C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 31; } + def P7_ScalarFPU_32C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 32; } + def P7_ScalarFPU_33C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 33; } + def P7_ScalarFPU_42C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 42; } + def P7_ScalarFPU_44C : SchedWriteRes<[P7_ScalarFPU]> { let Latency = 44; } + def P7_VXS_2C : SchedWriteRes<[P7_VXS]> { let Latency = 2; } + def P7_VPM_3C : SchedWriteRes<[P7_VPM]> { let Latency = 3; } + + // Instruction of BRU pipeline + + def : InstRW<[P7_BRU_NONE, P7_DISP_BR], + (instregex "^B(L)?(A)?(8)?(_NOP|_NOTOC)?(_TLS|_RM)?(_)?$")>; + + def : InstRW<[P7_BRU_3C, P7_DISP_BR], (instrs + BDZLRLp, BDZLRm, BDZLRp, BDZLm, BDZLp, BDZm, BDZp, + BDNZ, BDNZ8, BDNZA, BDNZAm, BDNZAp, BDNZL, BDNZLA, BDNZLAm, BDNZLAp, BDNZLR, + BDNZLR8, BDNZLRL, BDNZLRLm, BDNZLRLp, BDNZLRm, BDNZLRp, BDNZLm, BDNZLp, + BDNZm, BDNZp, BDZ, BDZ8, BDZA, BDZAm, BDZAp, BDZL, BDZLA, BDZLAm, BDZLAp, + BDZLR, BDZLR8, BDZLRL, BDZLRLm, BLR, BLR8, BLRL, BCL, BCLR, BCLRL, BCLRLn, + BCLRn, BCLalways, BCLn, BCTR, BCTR8, BCTRL, BCTRL8, BCTRL8_LDinto_toc, + BCTRL8_LDinto_toc_RM, BCTRL8_RM, BCTRL_LWZinto_toc, BCTRL_LWZinto_toc_RM, + BCTRL_RM, BCn, BC, BCC, BCCA, BCCCTR, BCCCTR8, BCCCTRL, BCCCTRL8, BCCL, + BCCLA, BCCLR, BCCLRL, BCCTR, BCCTR8, BCCTR8n, BCCTRL, BCCTRL8, + BCCCTR, BCCCTR8, BCCCTRL, BCCCTRL8, BCCL, BCCLA, BCCLR, BCCLRL, BCCTR, + BCCTR8, BCCTR8n, BCCTRL, BCCTRL8, BCCTRL8n, BCCTRLn, BCCTRn, gBC, gBCA, + gBCAat, gBCCTR, gBCCTRL, gBCL, gBCLA, gBCLAat, gBCLR, gBCLRL, gBCLat, gBCat, + MFCTR, MFCTR8, MFLR, MFLR8 + )>; + + def : InstRW<[P7_BRU_4C], (instrs MTLR, MTLR8, MTCTR, MTCTR8, MTCTR8loop, MTCTRloop)>; + + // Instructions of CRU pipeline + + def : InstRW<[P7_CRU_NONE], (instrs MFCR, MFCR8)>; + def : InstRW<[P7_CRU_3C], (instrs MCRF)>; + def : InstRW<[P7_CRU_6C, P7_DISP_CR], (instrs + CR6SET, CR6UNSET, CRSET, CRUNSET, + CRAND, CRANDC, CREQV, CRNAND, CRNOR, CRNOT, CROR, CRORC + )>; + + // Instructions of LSU and FXU pipelines + + def : InstRW<[P7_LSU_NONE, P7_DISP_LS], (instrs LMW, LWARX, LWARXL, LDARX, LDARXL)>; + def : InstRW<[P7_LSU_2C, P7_DISP_LS], (instrs LHBRX, LHBRX8, LWBRX, LWBRX8)>; + def : InstRW<[P7_LSU_3C], (instrs MFSR, MFSRIN)>; + + def : InstRW<[P7_LSU_3C, P7_DISP_LS], (instrs + LFS, LFSX, LFSXTLS, LFSXTLS_, LFD, LFDX, LFDXTLS, LFDXTLS_, LXSDX, LXVD2X, + LXVW4X, LXVDSX + )>; + + def : InstRW<[P7_LSU_3C, P7_FXU_3C, P7_DISP_LS], (instrs + LFSU, LFSUX, LFDU, LFDUX)>; + + def : InstRW<[P7_LSU_NONE, P7_FPU_NONE, P7_DISP_LS], (instrs + STXSDX, STXVD2X, STXVW4X)>; + + def : InstRW<[P7_LSU_4C, P7_FXU_4C, P7_DISP_LS], (instrs + LBARX, LBZCIX, LDBRX, LDCIX, LFIWAX, LFIWZX, LHARX, LHZCIX, LSWI, LVEBX, + LVEHX, LVEWX, LVSL, LVSR, LVX, LVXL, LWZCIX, + STFD, STFDU, STFDUX, STFDX, STFIWX, STFS, STFSU, STFSUX, STFSX, + STHCIX, STSWI, STVEBX, STVEHX, STVEWX, STVX, STVXL, STWCIX, + LHA, LHA8, LHAX, LHAX8, LWA, LWAX, LWAX_32, LWA_32, LHAU, LHAU8, + LHAUX, LHAUX8, LWAUX + )>; + + def : InstRW<[P7_LSU_NONE, P7_FXU_NONE, P7_DISP_LS], (instrs + STB, STB8, STH, STH8, STW, STW8, STD, STBX, STBX8, STHX, STHX8, STWX, + STWX8, STDX, STHBRX, STWBRX, STMW, STWCX, STDCX, STDU, STHU, STHU8, + STBU, STBU8, STWU, STWU8, STDUX, STWUX, STWUX8, STHUX, STHUX8, STBUX, STBUX8 + )>; + + def : InstRW<[P7_LSU_2C, P7_FXU_2C, P7_DISP_LS], (instrs + LWZU, LWZU8, LHZU, LHZU8, LBZU, LBZU8, LDU, + LWZUX, LWZUX8, LHZUX, LHZUX8, LBZUX, LBZUX8, LDUX + )>; + + def : InstRW<[P7_LSU_FXU_2C, P7_DISP_FX], (instrs + (instregex "^(ADD|L)I(S)?(8)?$"), + (instregex "^(ADD|SUBF)(4|8)(TLS)?(_)?(_rec)?$"), + (instregex "^(X)?ORI(S)?(8)?$"), + (instregex "^(X)OR(8)?(_rec)?$"), + ADDIC, ADDIC8, SUBFIC, SUBFIC8, SUBFZE, SUBFZE8, + ADDE, ADDE8, ADDME, ADDME8, SUBFME, SUBFME8, + NEG, NEG8, NEG8_rec, NEG_rec, NEG8O, NEGO, + ANDI_rec, ANDIS_rec, AND, AND8, AND_rec, AND8_rec, + NAND, NAND8, NAND_rec, NAND8_rec, NOR, NOR8, NOR_rec, NOR8_rec, + EQV, EQV8, EQV_rec, EQV8_rec, ANDC, ANDC8, ANDC_rec, ANDC8_rec, + ORC, ORC8, ORC_rec, ORC8_rec + )>; + + def : InstRW<[P7_FXU_2C, P7_DISP_FX], (instrs + CMPD, CMPDI, CMPLD, CMPLDI, CMPLW, CMPLWI, CMPW, CMPWI, + EXTSB8_32_64, EXTSB8_rec, EXTSH8_32_64, EXTSH8_rec, EXTSW_32, + EXTSW_32_64, EXTSW_32_64_rec, POPCNTB, POPCNTB8, POPCNTD, POPCNTW, + ADDPCIS, ANDI8_rec, ANDIS8_rec, SUBFUS, SUBFUS_rec, + ADD4O, ADD8O, ADDC, ADDC8, SUBFO, SUBF8O, SUBFC, SUBFC8, + ADDIC_rec, ADDE8_rec, ADDE_rec, SUBFE8_rec, SUBFE_rec, + ADDME8_rec, ADDME_rec, SUBFME8_rec, SUBFME_rec, ADDZE8_rec, ADDZE_rec, + SUBFZE_rec, SUBFZE8_rec, ADD8O_rec, SUBFO_rec, SUBF8O_rec, ADD4O_rec, + ADD8O_rec, SUBF8O_rec, SUBFO_rec, ADDE8O, ADDEO, SUBFE8O, SUBFEO, ADDME8O, + ADDMEO, SUBFME8O, SUBFMEO, ADDZE8O, ADDZEO, SUBFZE8O, SUBFZEO, NEG8O_rec, + NEGO_rec, ADDEO, ADDE8O, SUBFEO, SUBFE8O, ADDMEO, SUBFMEO, SUBFME8O, ADDME8O, + ADDZEO, ADDZE8O, SUBFZEO, SUBFZE8O, NEG8O_rec, NEGO_rec, + ADDE8O_rec, ADDEO_rec, ADDMEO_rec, ADDME8O_rec, SUBFMEO_rec, SUBFME8O_rec, + ADDZEO_rec, ADDZE8O_rec, SUBFZEO_rec, SUBFZE8O_rec, + ADDC8_rec, ADDC_rec, ADDCO, ADDCO_rec, ADDC8O, ADDC8O_rec, + SUBFC8_rec, SUBFC_rec, SUBFCO, SUBFC8O, SUBFCO_rec, SUBFC8O_rec, + EXTSB, EXTSB8, EXTSB_rec, EXTSH, EXTSH8, EXTSH_rec, EXTSW, EXTSW_rec, + RLDICL, RLDICL_rec, RLDICR, RLDICR_rec, RLDIC, RLDIC_rec, + RLWINM, RLWINM8, RLWINM_rec, RLDCL, RLDCL_rec, RLDCR, RLDCR_rec, + RLWNM, RLWNM8, RLWNM_rec, RLDIMI, RLDIMI_rec, + RLDICL_32, RLDICL_32_64, RLDICL_32_rec, RLDICR_32, RLWINM8_rec, RLWNM8_rec, + SLD, SLD_rec, SLW, SLW8, SLW_rec, SLW8_rec, SRD, SRD_rec, SRW, SRW8, SRW_rec, + SRW8_rec, SRADI, SRADI_rec, SRAWI, SRAWI_rec, SRAD, SRAD_rec, SRAW, SRAW_rec, + SRADI_32, SUBFE, SUBFE8, SUBFE8O_rec, SUBFEO_rec + )>; + + def : InstRW<[P7_FXU_3C, P7_DISP_FX], (instregex "^CNT(L|T)Z(D|W)(8)?(M)?(_rec)?$")>; + + def : InstRW<[P7_FXU_5C, P7_DISP_FX], (instrs + MULLI, MULLI8, MULLW, MULHW, MULHWU, MULLD, MULHD, MULHDU, MULLWO, MULLDO, + MULLW_rec, MULLD_rec, MULHD_rec, MULHW_rec, MULHDU_rec, MULHWU_rec, MULLWO_rec, + MULLDO_rec + )>; + + def : InstRW<[P7_FXU_38C, P7_DISP_FX], (instrs + DIVDE, DIVDEO, DIVDEO_rec, DIVDEU, DIVDEUO, DIVDEUO_rec, DIVDEU_rec, DIVDE_rec, + DIVWE, DIVWEO, DIVWEO_rec, DIVWEU, DIVWEUO, DIVWEUO_rec, DIVWEU_rec, DIVWE_rec, + DIVW, DIVWU, DIVWU_rec, DIVWO, DIVWO_rec, DIVWUO, DIVWUO_rec, DIVW_rec + )>; + + def : InstRW<[P7_FXU_69C, P7_DISP_FX], (instrs + DIVD, DIVDU, DIVDO, DIVDO_rec, DIVDUO, DIVDUO_rec, DIVDU_rec, DIVD_rec)>; + + // Instructions of FPU and VMX pipeline + + def : InstRW<[P7_ScalarFPU_6C, P7_DISP_FP], (instrs + (instregex "^F(N)?(M)?(R|ADD|SUB|ABS|NEG|NABS|UL)(D|S)?(_rec)?$"), + (instregex "^FC(T|F)I(D|W)(U)?(S)?(Z)?(_rec)?$"), + (instregex "^XS(N)?M(SUB|ADD)(A|M)(D|S)P$"), + (instregex "^XS(NEG|ABS|NABS|ADD|SUB|MUL)(D|S)P(s)?$"), + FRE, FRES_rec, FRE_rec, FRSP_rec, FTDIV, FTSQRT, + FRSP, FRES, FRSQRTE, FRSQRTES, FRSQRTES_rec, FRSQRTE_rec, FSELD, FSELS, + FSELD_rec, FSELS_rec, FCPSGND, FCPSGND_rec, FCPSGNS, FCPSGNS_rec, + FRIMD, FRIMD_rec, FRIMS, FRIMS_rec, FRIND, FRIND_rec, FRINS, FRINS_rec, + FRIPD, FRIPD_rec, FRIPS, FRIPS_rec, FRIZD, FRIZD_rec, FRIZS, FRIZS_rec, + XSCPSGNDP, XSCVDPSP, XSCVDPSXDS, XSCVDPSXDSs, XSCVDPSXWS, XSCVDPSXWSs, + XSCVDPUXDS, XSCVDPUXDSs, XSCVDPUXWS, XSCVDPUXWSs, XSCVSPDP, XSCVSXDDP, + XSCVUXDDP, XSMAXDP, XSMINDP, XSRDPI, XSRDPIC, XSRDPIM, XSRDPIP, XSRDPIZ, + XSREDP, XSRSQRTEDP, XSTDIVDP, XSTSQRTDP, XSCMPODP, XSCMPUDP + )>; + + def : InstRW<[P7_VectorFPU_6C, P7_DISP_FP], (instrs + (instregex "^XV(N)?(M)?(ADD|SUB)(A|M)?(D|S)P$"), + (instregex "^XV(MAX|MIN|MUL|NEG|ABS|ADD|NABS)(D|S)P$"), + XVCMPEQDP, XVCMPEQDP_rec, XVCMPGEDP, XVCMPGEDP_rec, XVCMPGTDP, XVCMPGTDP_rec, + XVCPSGNDP, XVCVDPSXDS, XVCVDPSXWS, XVCVDPUXDS, XVCVDPUXWS, XVCVSPSXDS, + XVCVSPSXWS, XVCVSPUXDS, XVCVSPUXWS, XVCVSXDDP, XVCVSXWDP, XVCVUXDDP, + XVCVUXWDP, XVRDPI, XVRDPIC, XVRDPIM, XVRDPIP, XVRDPIZ, XVREDP, + XVRSPI, XVRSPIC, XVRSPIM, XVRSPIP, XVRSPIZ, XVRSQRTEDP, XVTDIVDP, + XVTSQRTDP + )>; + + // TODO: Altivec instructions are not listed in Book IV. + def : InstRW<[P7_VPM_3C, P7_DISP_FP], (instrs + (instregex "^VPK(S|U)(H|W)(S|U)(S|M)$"), + (instregex "^VUPK(H|L)(S|P)(X|B|H)$"), + VPERM, XXMRGHW, XXMRGLW, XXPERMDI, XXPERMDIs, XXSLDWI, XXSLDWIs, + VSPLTB, VSPLTBs, VSPLTH, VSPLTHs, VSPLTISB, VSPLTISH, VSPLTISW, VSPLTW, + XXSPLTW, XXSPLTWs, VSEL, XXSEL, VPKPX + )>; + + def : InstRW<[P7_VXS_2C, P7_DISP_FP], (instrs + (instregex "^VADD(U|S)(B|H|W)(S|M)$"), + (instregex "^V(MAX|MIN)(S|U)(B|H|W)$"), + (instregex "^V(MRG)(L|H)(B|H|W)$"), + XXLORf, XXLXORdpz, XXLXORspz, XXLXORz, XVRSQRTESP, XVRESP, + XVTDIVSP, XVTSQRTSP, XVCMPEQSP, XVCMPEQSP_rec, XVCMPGESP, XVCMPGESP_rec, + XVCMPGTSP, XVCMPGTSP_rec, XVCVSXDSP, XVCVSXWSP, XVCVUXDSP, XVCVUXWSP, + XVCPSGNSP, XVCVDPSP, VADDCUW, VADDFP, VAND, VANDC, VAVGSB, VAVGSH, + VAVGSW, VAVGUB, VAVGUH, VAVGUW, VCFSX, VCFUX, VCMPBFP, VCMPBFP_rec, + VCMPEQFP, VCMPEQFP_rec, VCMPEQUB, VCMPEQUB_rec, VCMPEQUH, VCMPEQUH_rec, + VCMPEQUW, VCMPEQUW_rec, VCMPGEFP, VCMPGEFP_rec, VCMPGTFP, VCMPGTFP_rec, + VCMPGTSB, VCMPGTSB_rec, VCMPGTSH, VCMPGTSH_rec, VCMPGTSW, VCMPGTSW_rec, + VCMPGTUB, VCMPGTUB_rec, VCMPGTUH, VCMPGTUH_rec, VCMPGTUW, VCMPGTUW_rec, + VCTSXS, VCTUXS, VEXPTEFP, VLOGEFP, VNOR, VOR, + VMADDFP, VMHADDSHS, VMHRADDSHS, VMLADDUHM, VNMSUBFP, VMAXFP, VMINFP, + VMSUMMBM, VMSUMSHM, VMSUMSHS, VMSUMUBM, VMSUMUDM, VMSUMUHM, VMSUMUHS, + VMULESB, VMULESH, VMULEUB, VMULEUH, VMULOSB, VMULOSH, VMULOUB, VMULOUH, + VREFP, VRFIM, VRFIN, VRFIP, VRFIZ, VRLB, VRLH, VRLW, VRSQRTEFP, + VSR, VSRAB, VSRAH, VSRAW, VSRB, VSRH, VSRO, VSRW, VSUBCUW, VSL, VSLB, + VSLDOI, VSLH, VSLO, VSLW, VSUBFP, VSUBSBS, VSUBSHS, VSUBSWS, VSUBUBM, + VSUBUBS, VSUBUHM, VSUBUHS, VSUBUWM, VSUBUWS, VSUM2SWS, VSUM4SBS, VSUM4SHS, + VSUM4UBS, VSUMSWS, VXOR, XXLAND, XXLANDC, XXLNOR, XXLOR, XXLXOR + )>; + + def : InstRW<[P7_ScalarFPU_8C, P7_DISP_FP], + (instrs FCMPOD, FCMPOS, FCMPUD, FCMPUS)>; + def : InstRW<[P7_ScalarFPU_27C, P7_DISP_FP], (instrs FDIVS, FDIVS_rec)>; + def : InstRW<[P7_ScalarFPU_31C, P7_DISP_FP], (instrs XSDIVDP)>; + def : InstRW<[P7_ScalarFPU_32C, P7_DISP_FP], (instrs FSQRTS, XSSQRTSP, FSQRTS_rec)>; + def : InstRW<[P7_ScalarFPU_33C, P7_DISP_FP], (instrs FDIV, FDIV_rec)>; + def : InstRW<[P7_ScalarFPU_42C, P7_DISP_FP], (instrs XSSQRTDP)>; + def : InstRW<[P7_ScalarFPU_44C, P7_DISP_FP], (instrs FSQRT, FSQRT_rec)>; + + def : InstRW<[P7_VectorFPU_25C, P7_DISP_FP], (instrs XVDIVSP)>; + def : InstRW<[P7_VectorFPU_30C, P7_DISP_FP], (instrs XVSQRTSP)>; + def : InstRW<[P7_VectorFPU_31C, P7_DISP_FP], (instrs XVDIVDP)>; + def : InstRW<[P7_VectorFPU_42C, P7_DISP_FP], (instrs XVSQRTDP)>; +} diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td index 70a58f42a98a..3a2d9d9b3bc1 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP8.td @@ -6,408 +6,332 @@ // //===----------------------------------------------------------------------===// // -// This file defines the itinerary class data for the POWER8 processor. +// This file defines the SchedModel for the POWER8 processor. // //===----------------------------------------------------------------------===// -// Scheduling for the P8 involves tracking two types of resources: -// 1. The dispatch bundle slots -// 2. The functional unit resources +def P8Model : SchedMachineModel { + let IssueWidth = 8; + let LoadLatency = 3; + let MispredictPenalty = 16; + let LoopMicroOpBufferSize = 60; + let MicroOpBufferSize = 64; + // TODO: Due to limitation of instruction definitions, non-P8 instructions + // are required to be listed here. Change this after it got fixed. + let CompleteModel = 0; + let UnsupportedFeatures = [HasSPE, PrefixInstrs, MMA, + PairedVectorMemops, PCRelativeMemops, + IsISA3_0, IsISA3_1, IsISAFuture]; +} -// Dispatch units: -def P8_DU1 : FuncUnit; -def P8_DU2 : FuncUnit; -def P8_DU3 : FuncUnit; -def P8_DU4 : FuncUnit; -def P8_DU5 : FuncUnit; -def P8_DU6 : FuncUnit; -def P8_DU7 : FuncUnit; // Only branch instructions will use DU7,DU8 -def P8_DU8 : FuncUnit; +let SchedModel = P8Model in { + // Power8 Pipeline Units: -// 10 insns per cycle (2-LU, 2-LSU, 2-FXU, 2-FPU, 1-CRU, 1-BRU). + def P8_LU_LS_FX : ProcResource<6>; + def P8_LU_LS : ProcResource<4> { let Super = P8_LU_LS_FX; } + def P8_LS : ProcResource<2> { let Super = P8_LU_LS; } + def P8_LU : ProcResource<2> { let Super = P8_LU_LS; } + def P8_FX : ProcResource<2> { let Super = P8_LU_LS_FX; } + def P8_DFU : ProcResource<1>; + def P8_BR : ProcResource<1> { let BufferSize = 16; } + def P8_CY : ProcResource<1>; + def P8_CRL : ProcResource<1>; + def P8_VMX : ProcResource<2>; + def P8_PM : ProcResource<2> { + // This is workaround for scheduler to respect latency of long permute chain. + let BufferSize = 1; + let Super = P8_VMX; + } + def P8_XS : ProcResource<2> { let Super = P8_VMX; } + def P8_VX : ProcResource<2> { let Super = P8_VMX; } + def P8_FPU : ProcResource<4>; + // Units for scalar, 2xDouble and 4xSingle + def P8_FP_Scal : ProcResource<2> { let Super = P8_FPU; } + def P8_FP_2x64 : ProcResource<2> { let Super = P8_FPU; } + def P8_FP_4x32 : ProcResource<2> { let Super = P8_FPU; } -def P8_LU1 : FuncUnit; // Loads or fixed-point operations 1 -def P8_LU2 : FuncUnit; // Loads or fixed-point operations 2 + // Power8 Dispatch Ports: + // Two ports to do loads or fixed-point operations. + // Two ports to do stores, fixed-point loads, or fixed-point operations. + // Two ports for fixed-point operations. + // Two issue ports shared by 2 DFP/2 VSX/2 VMX/1 CY/1 DFP operations. + // One for branch operations. + // One for condition register operations. -// Load/Store pipelines can handle Stores, fixed-point loads, and simple -// fixed-point operations. -def P8_LSU1 : FuncUnit; // Load/Store pipeline 1 -def P8_LSU2 : FuncUnit; // Load/Store pipeline 2 + // TODO: Model dispatch of cracked instructions. -// Fixed Point unit -def P8_FXU1 : FuncUnit; // FX pipeline 1 -def P8_FXU2 : FuncUnit; // FX pipeline 2 + // Six ports in total are available for fixed-point operations. + def P8_PORT_ALLFX : ProcResource<6>; + // Four ports in total are available for fixed-point load operations. + def P8_PORT_FXLD : ProcResource<4> { let Super = P8_PORT_ALLFX; } + // Two ports to do loads or fixed-point operations. + def P8_PORT_LD_FX : ProcResource<2> { let Super = P8_PORT_FXLD; } + // Two ports to do stores, fixed-point loads, or fixed-point operations. + def P8_PORT_ST_FXLD_FX : ProcResource<2> { let Super = P8_PORT_FXLD; } + // Two issue ports shared by two floating-point, two VSX, two VMX, one crypto, + // and one DFP operations. + def P8_PORT_VMX_FP : ProcResource<2>; + // One port for branch operation. + def P8_PORT_BR : ProcResource<1>; + // One port for condition register operation. + def P8_PORT_CR : ProcResource<1>; -// The Floating-Point Unit (FPU) and Vector Media Extension (VMX) units -// are combined on P7 and newer into a Vector Scalar Unit (VSU). -// The P8 Instruction latency documents still refers to the unit as the -// FPU, so keep in mind that FPU==VSU. -// In contrast to the P7, the VMX units on P8 are symmetric, so no need to -// split vector integer ops or 128-bit load/store/perms to the specific units. -def P8_FPU1 : FuncUnit; // VS pipeline 1 -def P8_FPU2 : FuncUnit; // VS pipeline 2 + def P8_ISSUE_FX : SchedWriteRes<[P8_PORT_ALLFX]>; + def P8_ISSUE_FXLD : SchedWriteRes<[P8_PORT_FXLD]>; + def P8_ISSUE_LD : SchedWriteRes<[P8_PORT_LD_FX]>; + def P8_ISSUE_ST : SchedWriteRes<[P8_PORT_ST_FXLD_FX]>; + def P8_ISSUE_VSX : SchedWriteRes<[P8_PORT_VMX_FP]>; + def P8_ISSUE_BR : SchedWriteRes<[P8_PORT_BR]>; + def P8_ISSUE_CR : SchedWriteRes<[P8_PORT_CR]>; -def P8_CRU : FuncUnit; // CR unit (CR logicals and move-from-SPRs) -def P8_BRU : FuncUnit; // BR unit + // Power8 Instruction Latency & Port Groups: -def P8Itineraries : ProcessorItineraries< - [P8_DU1, P8_DU2, P8_DU3, P8_DU4, P8_DU5, P8_DU6, P8_DU7, P8_DU8, - P8_LU1, P8_LU2, P8_LSU1, P8_LSU2, P8_FXU1, P8_FXU2, - P8_FPU1, P8_FPU2, P8_CRU, P8_BRU], [], [ - InstrItinData<IIC_IntSimple , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2, - P8_LU1, P8_LU2, - P8_LSU1, P8_LSU2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntGeneral , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2, P8_LU1, - P8_LU2, P8_LSU1, P8_LSU2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntISEL, [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2], 0>, - InstrStage<1, [P8_BRU]>], - [1, 1, 1, 1]>, - InstrItinData<IIC_IntCompare , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntDivW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<15, [P8_FXU1, P8_FXU2]>], - [15, 1, 1]>, - InstrItinData<IIC_IntDivD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<23, [P8_FXU1, P8_FXU2]>], - [23, 1, 1]>, - InstrItinData<IIC_IntMulHW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntMulHWU , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntMulHD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntMulLI , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [4, 1, 1]>, - InstrItinData<IIC_IntRotate , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntRotateD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntRotateDI , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntShift , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [1, 1, 1]>, - InstrItinData<IIC_IntTrapW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [1, 1]>, - InstrItinData<IIC_IntTrapD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [1, 1]>, - InstrItinData<IIC_BrB , [InstrStage<1, [P8_DU7, P8_DU8], 0>, - InstrStage<1, [P8_BRU]>], - [3, 1, 1]>, - // FIXME - the Br* groups below are not branch related, so should probably - // be renamed. - // IIC_BrCR consists of the cr* instructions. (crand,crnor,creqv, etc). - // and should be 'First' in dispatch. - InstrItinData<IIC_BrCR , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_CRU]>], - [3, 1, 1]>, - // IIC_BrMCR consists of the mcrf instruction. - InstrItinData<IIC_BrMCR , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_CRU]>], - [3, 1, 1]>, - // IIC_BrMCRX consists of mcrxr (obsolete instruction) and mtcrf, which - // should be first in the dispatch group. - InstrItinData<IIC_BrMCRX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [3, 1, 1]>, - InstrItinData<IIC_BrMCRX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [3, 1]>, - InstrItinData<IIC_LdStLoad , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2]>], - [2, 1, 1]>, - InstrItinData<IIC_LdStLoadUpd , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2 ], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [2, 2, 1, 1]>, - // Update-Indexed form loads/stores are no longer first and last in the - // dispatch group. They are simply cracked, so require DU1,DU2. - InstrItinData<IIC_LdStLoadUpdX, [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2]>], - [2, 1, 1]>, - InstrItinData<IIC_LdStLDU , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [2, 2, 1, 1]>, - InstrItinData<IIC_LdStLDUX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLFD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LU1, P8_LU2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLVecX , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LU1, P8_LU2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLFDU , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLFDUX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [3, 3, 1, 1]>, - InstrItinData<IIC_LdStLHA , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2, - P8_LU1, P8_LU2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLHAU , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [4, 4, 1, 1]>, - // first+last in dispatch group. - InstrItinData<IIC_LdStLHAUX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_DU3], 0>, - InstrStage<1, [P8_DU4], 0>, - InstrStage<1, [P8_DU5], 0>, - InstrStage<1, [P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [4, 4, 1, 1]>, - InstrItinData<IIC_LdStLWA , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2]>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLWARX, [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_DU3], 0>, - InstrStage<1, [P8_DU4], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2]>], - [3, 1, 1]>, - // first+last - InstrItinData<IIC_LdStLDARX, [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_DU3], 0>, - InstrStage<1, [P8_DU4], 0>, - InstrStage<1, [P8_DU5], 0>, - InstrStage<1, [P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2]>], - [3, 1, 1]>, - InstrItinData<IIC_LdStLMW , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2, - P8_LU1, P8_LU2]>], - [2, 1, 1]>, -// Stores are dual-issued from the issue queue, so may only take up one -// dispatch slot. The instruction will be broken into two IOPS. The agen -// op is issued to the LSU, and the data op (register fetch) is issued -// to either the LU (GPR store) or the VSU (FPR store). - InstrItinData<IIC_LdStStore , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2]>, - InstrStage<1, [P8_LU1, P8_LU2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LU1, P8_LU2, - P8_LSU1, P8_LSU2]>] - [1, 1, 1]>, - InstrItinData<IIC_LdStSTU , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LU1, P8_LU2, - P8_LSU1, P8_LSU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [2, 1, 1, 1]>, - // First+last - InstrItinData<IIC_LdStSTUX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_DU3], 0>, - InstrStage<1, [P8_DU4], 0>, - InstrStage<1, [P8_DU5], 0>, - InstrStage<1, [P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [2, 1, 1, 1]>, - InstrItinData<IIC_LdStSTFD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTFDU , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [2, 1, 1, 1]>, - InstrItinData<IIC_LdStSTVEBX , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTDCX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_DU3], 0>, - InstrStage<1, [P8_DU4], 0>, - InstrStage<1, [P8_DU5], 0>, - InstrStage<1, [P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2], 0>, - InstrStage<1, [P8_LU1, P8_LU2]>], - [1, 1, 1]>, - InstrItinData<IIC_LdStSTWCX , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_DU2], 0>, - InstrStage<1, [P8_DU3], 0>, - InstrStage<1, [P8_DU4], 0>, - InstrStage<1, [P8_DU5], 0>, - InstrStage<1, [P8_DU6], 0>, - InstrStage<1, [P8_LSU1, P8_LSU2], 0>, - InstrStage<1, [P8_LU1, P8_LU2]>], - [1, 1, 1]>, - InstrItinData<IIC_SprMFCR , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_CRU]>], - [6, 1]>, - InstrItinData<IIC_SprMFCRF , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_CRU]>], - [3, 1]>, - InstrItinData<IIC_SprMTSPR , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FXU1, P8_FXU2]>], - [4, 1]>, // mtctr - InstrItinData<IIC_FPGeneral , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [5, 1, 1]>, - InstrItinData<IIC_FPAddSub , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [5, 1, 1]>, - InstrItinData<IIC_FPCompare , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [8, 1, 1]>, - InstrItinData<IIC_FPDivD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [33, 1, 1]>, - InstrItinData<IIC_FPDivS , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [27, 1, 1]>, - InstrItinData<IIC_FPSqrtD , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [44, 1, 1]>, - InstrItinData<IIC_FPSqrtS , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [32, 1, 1]>, - InstrItinData<IIC_FPFused , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [5, 1, 1, 1]>, - InstrItinData<IIC_FPRes , [InstrStage<1, [P8_DU1, P8_DU2, P8_DU3, - P8_DU4, P8_DU5, P8_DU6], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [5, 1, 1]>, - InstrItinData<IIC_VecGeneral , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [2, 1, 1]>, - InstrItinData<IIC_VecVSL , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [2, 1, 1]>, - InstrItinData<IIC_VecVSR , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [2, 1, 1]>, - InstrItinData<IIC_VecFP , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [6, 1, 1]>, - InstrItinData<IIC_VecFPCompare, [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [6, 1, 1]>, - InstrItinData<IIC_VecFPRound , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [6, 1, 1]>, - InstrItinData<IIC_VecComplex , [InstrStage<1, [P8_DU1], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [7, 1, 1]>, - InstrItinData<IIC_VecPerm , [InstrStage<1, [P8_DU1, P8_DU2], 0>, - InstrStage<1, [P8_FPU1, P8_FPU2]>], - [3, 1, 1]> -]>; + def P8_LS_LU_NONE : SchedWriteRes<[P8_LU, P8_LS]>; + def P8_LS_FP_NONE : SchedWriteRes<[P8_LS, P8_FPU]>; + def P8_LU_or_LS_3C : SchedWriteRes<[P8_LU_LS]> { let Latency = 3; } + def P8_LS_FX_3C : SchedWriteRes<[P8_LS, P8_FX]> { let Latency = 3; } + def P8_LU_or_LS_or_FX_2C : SchedWriteRes<[P8_LU_LS_FX]> { let Latency = 2; } + def P8_LU_or_LS_FX_3C : SchedWriteRes<[P8_LU_LS, P8_FX]> { let Latency = 3; } + def P8_FX_NONE : SchedWriteRes<[P8_FX]>; + def P8_FX_1C : SchedWriteRes<[P8_FX]> { let Latency = 1; } + def P8_FX_2C : SchedWriteRes<[P8_FX]> { let Latency = 2; } + def P8_FX_3C : SchedWriteRes<[P8_FX]> { let Latency = 3; } + def P8_FX_5C : SchedWriteRes<[P8_FX]> { let Latency = 5; } + def P8_FX_10C : SchedWriteRes<[P8_FX]> { let Latency = 10; } + def P8_FX_23C : SchedWriteRes<[P8_FX]> { let Latency = 23; } + def P8_FX_15C : SchedWriteRes<[P8_FX]> { let Latency = 15; } + def P8_FX_41C : SchedWriteRes<[P8_FX]> { let Latency = 41; } + def P8_BR_2C : SchedWriteRes<[P8_BR]> { let Latency = 2; } + def P8_CR_NONE : SchedWriteRes<[P8_CRL]>; + def P8_CR_3C : SchedWriteRes<[P8_CRL]> { let Latency = 3; } + def P8_CR_5C : SchedWriteRes<[P8_CRL]> { let Latency = 5; } + def P8_LU_5C : SchedWriteRes<[P8_LU]> { let Latency = 5; } + def P8_LU_FX_5C : SchedWriteRes<[P8_LU, P8_FX]> { let Latency = 5; } + def P8_LS_FP_FX_2C : SchedWriteRes<[P8_LS, P8_FPU, P8_FX]> { let Latency = 2; } + def P8_LS_FP_FX_3C : SchedWriteRes<[P8_LS, P8_FPU, P8_FX]> { let Latency = 3; } + def P8_LS_3C : SchedWriteRes<[P8_LS]> { let Latency = 3; } + def P8_FP_3C : SchedWriteRes<[P8_FPU]> { let Latency = 3; } + def P8_FP_Scal_6C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 6; } + def P8_FP_4x32_6C : SchedWriteRes<[P8_FP_4x32]> { let Latency = 6; } + def P8_FP_2x64_6C : SchedWriteRes<[P8_FP_2x64]> { let Latency = 6; } + def P8_FP_26C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 26; } + def P8_FP_28C : SchedWriteRes<[P8_FP_4x32]> { let Latency = 28; } + def P8_FP_31C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 31; } + def P8_FP_Scal_32C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 32; } + def P8_FP_2x64_32C : SchedWriteRes<[P8_FP_2x64]> { let Latency = 32; } + def P8_FP_4x32_32C : SchedWriteRes<[P8_FP_4x32]> { let Latency = 32; } + def P8_FP_Scal_43C : SchedWriteRes<[P8_FP_Scal]> { let Latency = 43; } + def P8_FP_2x64_43C : SchedWriteRes<[P8_FP_2x64]> { let Latency = 43; } + def P8_XS_2C : SchedWriteRes<[P8_XS]> { let Latency = 2; } + def P8_PM_2C : SchedWriteRes<[P8_PM]> { let Latency = 2; } + def P8_XS_4C : SchedWriteRes<[P8_XS]> { let Latency = 4; } + def P8_VX_7C : SchedWriteRes<[P8_VX]> { let Latency = 7; } + def P8_XS_9C : SchedWriteRes<[P8_XS]> { let Latency = 9; } + def P8_CY_6C : SchedWriteRes<[P8_CY]> { let Latency = 6; } + def P8_DFU_13C : SchedWriteRes<[P8_DFU]> { let Latency = 13; } + def P8_DFU_15C : SchedWriteRes<[P8_DFU]> { let Latency = 15; } + def P8_DFU_17C : SchedWriteRes<[P8_DFU]> { let Latency = 17; } + def P8_DFU_25C : SchedWriteRes<[P8_DFU]> { let Latency = 25; } + def P8_DFU_32C : SchedWriteRes<[P8_DFU]> { let Latency = 32; } + def P8_DFU_34C : SchedWriteRes<[P8_DFU]> { let Latency = 34; } + def P8_DFU_40C : SchedWriteRes<[P8_DFU]> { let Latency = 40; } + def P8_DFU_90C : SchedWriteRes<[P8_DFU]> { let Latency = 90; } + def P8_DFU_96C : SchedWriteRes<[P8_DFU]> { let Latency = 96; } + def P8_DFU_172C : SchedWriteRes<[P8_DFU]> { let Latency = 172; } + // Direct move instructions + def P8_DM_5C : SchedWriteRes<[]> { let Latency = 5; } -// ===---------------------------------------------------------------------===// -// P8 machine model for scheduling and other instruction cost heuristics. -// P8 has an 8 insn dispatch group (6 non-branch, 2 branch) and can issue up -// to 10 insns per cycle (2-LU, 2-LSU, 2-FXU, 2-FPU, 1-CRU, 1-BRU). + // Instructions of CR pipeline -def P8Model : SchedMachineModel { - let IssueWidth = 8; // up to 8 instructions dispatched per cycle. - // up to six non-branch instructions. - // up to two branches in a dispatch group. + def : InstRW<[P8_CR_NONE, P8_ISSUE_CR], (instrs MFCR, MFCR8)>; + def : InstRW<[P8_CR_3C, P8_ISSUE_CR], (instrs MFOCRF, MFOCRF8)>; + def : InstRW<[P8_CR_5C, P8_ISSUE_CR], (instrs MFLR, MFLR8, MFCTR, MFCTR8)>; - let LoadLatency = 3; // Optimistic load latency assuming bypass. - // This is overriden by OperandCycles if the - // Itineraries are queried instead. - let MispredictPenalty = 16; + // Instructions of CY pipeline - // Try to make sure we have at least 10 dispatch groups in a loop. - let LoopMicroOpBufferSize = 60; + def : InstRW<[P8_CY_6C, P8_ISSUE_VSX], (instrs + VCIPHER, VCIPHERLAST, VNCIPHER, VNCIPHERLAST, VPMSUMB, VPMSUMD, VPMSUMH, VPMSUMW, VSBOX)>; - let CompleteModel = 0; + // Instructions of FPU pipeline - let Itineraries = P8Itineraries; -} + def : InstRW<[P8_FP_26C, P8_ISSUE_VSX], (instrs (instregex "^FDIVS(_rec)?$"), XSDIVSP)>; + def : InstRW<[P8_FP_28C, P8_ISSUE_VSX], (instrs XVDIVSP)>; + def : InstRW<[P8_FP_31C, P8_ISSUE_VSX], (instregex "^FSQRTS(_rec)?$")>; + def : InstRW<[P8_FP_Scal_32C, P8_ISSUE_VSX], (instrs FDIV, FDIV_rec, XSDIVDP)>; + def : InstRW<[P8_FP_2x64_32C, P8_ISSUE_VSX], (instrs XVDIVDP)>; + def : InstRW<[P8_FP_4x32_32C, P8_ISSUE_VSX], (instrs XVSQRTSP)>; + def : InstRW<[P8_FP_Scal_43C, P8_ISSUE_VSX], (instrs FSQRT, FSQRT_rec, XSSQRTDP)>; + def : InstRW<[P8_FP_2x64_43C, P8_ISSUE_VSX], (instrs XVSQRTDP)>; + + def : InstRW<[P8_FP_3C, P8_ISSUE_VSX], (instrs + MTFSFI_rec, MTFSF_rec, MTFSFI, MTFSFIb, MTFSF, MTFSFb, MTFSB0, MTFSB1)>; + + def : InstRW<[P8_FP_Scal_6C, P8_ISSUE_VSX], (instrs + (instregex "^F(N)?M(ADD|SUB)(S)?(_rec)?$"), + (instregex "^XS(N)?M(ADD|SUB)(A|M)(D|S)P$"), + (instregex "^FC(F|T)I(D|W)(U)?(S|Z)?(_rec)?$"), + (instregex "^(F|XS)(ABS|CPSGN|ADD|MUL|NABS|RE|NEG|SUB|SEL|RSQRTE)(D|S)?(P)?(s)?(_rec)?$"), + (instregex "^FRI(M|N|P|Z)(D|S)(_rec)?$"), + (instregex "^XSCVDP(S|U)X(W|D)S(s)?$"), + (instregex "^XSCV(S|U)XD(D|S)P$"), + (instregex "^XSCV(D|S)P(S|D)P(N)?$"), + (instregex "^XSRDPI(C|M|P|Z)?$"), + FMR, FRSP, FMR_rec, FRSP_rec, XSRSP)>; + + def : InstRW<[P8_FP_4x32_6C, P8_ISSUE_VSX], (instrs + (instregex "^XV(N)?M(ADD|SUB)(A|M)SP$"), + (instregex "^VRFI(M|N|P|Z)$"), + XVRSQRTESP, XVSUBSP, VADDFP, VEXPTEFP, VLOGEFP, VMADDFP, VNMSUBFP, VREFP, + VRSQRTEFP, VSUBFP, XVCVSXWSP, XVCVUXWSP, XVMULSP, XVNABSSP, XVNEGSP, XVRESP, + XVCVDPSP, XVCVSXDSP, XVCVUXDSP, XVABSSP, XVADDSP, XVCPSGNSP)>; + + def : InstRW<[P8_FP_2x64_6C, P8_ISSUE_VSX], (instrs + (instregex "^XVR(D|S)PI(C|M|P|Z)?$"), + (instregex "^XVCV(S|U)X(D|W)DP$"), + (instregex "^XVCV(D|W|S)P(S|U)X(D|W)S$"), + (instregex "^XV(N)?(M)?(RSQRTE|CPSGN|SUB|ADD|ABS|UL|NEG|RE)(A|M)?DP$"), + XVCVSPDP)>; + + // Instructions of FX, LU or LS pipeline + + def : InstRW<[P8_FX_NONE, P8_ISSUE_FX], (instrs TDI, TWI, TD, TW, MTCRF, MTCRF8, MTOCRF, MTOCRF8)>; + def : InstRW<[P8_FX_1C, P8_ISSUE_FX], (instregex "^RLWIMI(8)?$")>; + // TODO: Pipeline of logical instructions might be LS or FX + def : InstRW<[P8_FX_2C, P8_ISSUE_FX], (instrs + (instregex "^(N|X)?(EQV|AND|OR)(I)?(S|C)?(8)?(_rec)?$"), + (instregex "^EXTS(B|H|W)(8)?(_32)?(_64)?(_rec)?$"), + (instregex "^RL(D|W)(I)?(NM|C)(L|R)?(8)?(_32)?(_64)?(_rec)?$"), + (instregex "^S(L|R)(A)?(W|D)(I)?(8)?(_rec|_32)?$"), + (instregex "^(ADD|SUBF)(M|Z)?(C|E)?(4|8)?O(_rec)?$"), + (instregex "^(ADD|SUBF)(M|Z)?E(8)?_rec$"), + (instregex "^(ADD|SUBF|NEG)(4|8)?_rec$"), + NOP, ADDG6S, ADDG6S8, ADDZE, ADDZE8, ADDIC_rec, NEGO_rec, ADDC, ADDC8, SUBFC, SUBFC8, + ADDC_rec, ADDC8_rec, SUBFC_rec, SUBFC8_rec, COPY, NEG8O_rec, + RLDIMI, RLDIMI_rec, RLWIMI8_rec, RLWIMI_rec)>; + + def : InstRW<[P8_FX_3C], (instregex "^(POP)?CNT(LZ)?(B|W|D)(8)?(_rec)?$")>; + def : InstRW<[P8_FX_5C, P8_ISSUE_FX], (instrs + (instregex "^MUL(H|L)(I|W|D)(8)?(U|O)?(_rec)?$"), + CMPDI,CMPWI,CMPD,CMPW,CMPLDI,CMPLWI,CMPLD,CMPLW, + ISEL, ISEL8, MTLR, MTLR8, MTCTR, MTCTR8, MTCTR8loop, MTCTRloop)>; + + def : InstRW<[P8_FX_10C, P8_ISSUE_VSX], (instregex "^MFTB(8)?$")>; + def : InstRW<[P8_FX_15C, P8_ISSUE_FX], (instregex "^DIVW(U)?$")>; + + def : InstRW<[P8_FX_23C, P8_ISSUE_FX], (instregex "^DIV(D|WE)(U)?$")>; + def : InstRW<[P8_FX_41C], (instrs + (instregex "^DIV(D|W)(E)?(U)?O(_rec)?$"), + (instregex "^DIV(D|W)(E)?(U)?_rec$"), + DIVDE, DIVDEU)>; + + def : InstRW<[P8_LS_3C, P8_ISSUE_FX], (instrs MFSR, MFSRIN)>; + + def : InstRW<[P8_LU_5C, P8_ISSUE_LD], (instrs + LFS, LFSX, LFD, LFDX, LFDXTLS, LFDXTLS_, LXVD2X, LXVW4X, LXVDSX, LVEBX, LVEHX, LVEWX, + LVX, LVXL, LXSDX, LFIWAX, LFIWZX, LFSXTLS, LFSXTLS_, LXVB16X, LXVD2X, LXSIWZX, + DFLOADf64, XFLOADf64, LIWZX)>; + def : InstRW<[P8_LS_FX_3C, P8_ISSUE_FXLD], (instrs LQ)>; + def : InstRW<[P8_LU_FX_5C, P8_ISSUE_LD], (instregex "^LF(D|S)U(X)?$")>; + + def : InstRW<[P8_LS_FP_NONE, P8_ISSUE_ST], (instrs + STXSDX, STXVD2X, STXVW4X, STFIWX, STFS, STFSX, STFD, STFDX, + STFDEPX, STFDXTLS, STFDXTLS_, STFSXTLS, STFSXTLS_, STXSIWX, STXSSP, STXSSPX)>; + + def : InstRW<[P8_LS_FP_FX_2C, P8_ISSUE_ST], (instrs STVEBX, STVEHX, STVEWX, STVX, STVXL)>; + def : InstRW<[P8_LS_FP_FX_3C, P8_ISSUE_ST], (instregex "^STF(D|S)U(X)?$")>; + + def : InstRW<[P8_LS_LU_NONE, P8_ISSUE_ST], (instrs + (instregex "^ST(B|H|W|D)(U)?(X)?(8|TLS)?(_)?(32)?$"), + STBCIX, STBCX, STBEPX, STDBRX, STDCIX, STDCX, STHBRX, STHCIX, STHCX, STHEPX, + STMW, STSWI, STWBRX, STWCIX, STWCX, STWEPX)>; + + def : InstRW<[P8_LU_or_LS_FX_3C, P8_ISSUE_FXLD], + (instregex "^L(B|H|W|D)(A|Z)?(U)?(X)?(8|TLS)?(_)?(32)?$")>; + + def : InstRW<[P8_LU_or_LS_3C, P8_ISSUE_FXLD], (instrs + LBARX, LBARXL, LBEPX, LBZCIX, LDARX, LDARXL, LDBRX, LDCIX, LFDEPX, LHARX, LHARXL, LHBRX, LXSIWAX, + LHBRX8, LHEPX, LHZCIX, LMW, LSWI, LVSL, LVSR, LWARX, LWARXL, LWBRX, LWBRX8, LWEPX, LWZCIX)>; + + def : InstRW<[P8_LU_or_LS_or_FX_2C, P8_ISSUE_FX], (instrs + (instregex "^ADDI(C)?(dtprel|tlsgd|toc)?(L)?(ADDR)?(32|8)?$"), + (instregex "^ADDIS(dtprel|tlsgd|toc|gotTprel)?(HA)?(32|8)?$"), + (instregex "^LI(S)?(8)?$"), + (instregex "^ADD(M)?(E)?(4|8)?(TLS)?(_)?$"), + (instregex "^SUBF(M|Z)?(E)?(IC)?(4|8)?$"), + (instregex "^NEG(8)?(O)?$"))>; + + // Instructions of PM pipeline + + def : InstRW<[P8_PM_2C, P8_ISSUE_VSX], (instrs + (instregex "^VPK(S|U)(H|W|D)(S|U)(M|S)$"), + (instregex "^VUPK(H|L)(P|S)(H|B|W|X)$"), + (instregex "^VSPLT(IS)?(B|H|W)(s)?$"), + (instregex "^(XX|V)MRG(E|O|H|L)(B|H|W)$"), + XXPERMDI, XXPERMDIs, XXSEL, XXSLDWI, XXSLDWIs, XXSPLTW, XXSPLTWs, VPERMXOR, + VPKPX, VPERM, VBPERMQ, VGBBD, VSEL, VSL, VSLDOI, VSLO, VSR, VSRO)>; + + def : InstRW<[P8_XS_2C, P8_ISSUE_VSX], (instrs + (instregex "^V(ADD|SUB)(S|U)(B|H|W|D)(M|S)$"), + (instregex "^X(S|V)(MAX|MIN)(D|S)P$"), + (instregex "^V(S)?(R)?(L)?(A)?(B|D|H|W)$"), + (instregex "^VAVG(S|U)(B|H|W)$"), + (instregex "^VM(AX|IN)(S|U)(B|H|W|D)$"), + (instregex "^(XX|V)(L)?(N)?(X)?(AND|OR|EQV)(C)?$"), + (instregex "^(X)?VCMP(EQ|GT|GE|B)(F|S|U)?(B|H|W|D|P|S)(P)?(_rec)?$"), + (instregex "^VCLZ(B|H|W|D)$"), + (instregex "^VPOPCNT(B|H|W)$"), + XXLORf, XXLXORdpz, XXLXORspz, XXLXORz, VEQV, VMAXFP, VMINFP, + VSHASIGMAD, VSHASIGMAW, VSUBCUW, VADDCUW, MFVSCR, MTVSCR)>; + + def : InstRW<[P8_XS_4C, P8_ISSUE_VSX], (instrs + (instregex "^V(ADD|SUB)(E)?(C)?UQ(M)?$"), + VPOPCNTD)>; + + def : InstRW<[P8_XS_9C, P8_ISSUE_CR], (instrs + (instregex "^(F|XS)CMP(O|U)(D|S)(P)?$"), + (instregex "^(F|XS|XV)T(DIV|SQRT)((D|S)P)?$"))>; + + // Instructions of VX pipeline + + def : InstRW<[P8_VX_7C, P8_ISSUE_VSX], (instrs + (instregex "^V(M)?SUM(2|4)?(M|S|U)(B|H|W)(M|S)$"), + (instregex "^VMUL(E|O)?(S|U)(B|H|W)(M)?$"), + VMHADDSHS, VMHRADDSHS, VMLADDUHM)>; + + // Instructions of BR pipeline + + def : InstRW<[P8_BR_2C, P8_ISSUE_BR], (instrs + (instregex "^(g)?B(C)?(C)?(CTR)?(L)?(A)?(R)?(L)?(8)?(_LD|_LWZ)?(always|into_toc|at)?(_RM)?(n)?$"), + (instregex "^BD(N)?Z(L)?(R|A)?(L)?(m|p|8)?$"), + (instregex "^BL(R|A)?(8)?(_NOP)?(_TLS)?(_)?(RM)?$"))>; + + // Instructions of DFP pipeline + // DFP operations also use float/vector/crypto issue ports. + def : InstRW<[P8_DFU_13C, P8_ISSUE_VSX], (instrs + (instregex "^DTST(D|S)(C|F|G)(Q)?$"), + (instregex "^D(Q|X)EX(Q)?(_rec)?$"), + (instregex "^D(ADD|SUB|IEX|QUA|RRND|RINTX|RINTN|CTDP|DEDPD|ENBCD)(_rec)?$"), + (instregex "^DSC(L|R)I(_rec)?$"), + BCDADD_rec, BCDSUB_rec, DCMPO, DCMPU, DTSTEX, DQUAI)>; + + def : InstRW<[P8_DFU_15C, P8_ISSUE_VSX], (instrs + (instregex "^DRINT(N|X)Q(_rec)?$"), + DCMPOQ, DCMPUQ, DRRNDQ, DRRNDQ_rec, DIEXQ, DIEXQ_rec, DQUAIQ, DQUAIQ_rec, + DTSTEXQ, DDEDPDQ, DDEDPDQ_rec, DENBCDQ, DENBCDQ_rec, DSCLIQ, DSCLIQ_rec, + DSCRIQ, DSCRIQ_rec, DCTQPQ, DCTQPQ_rec)>; + + def : InstRW<[P8_DFU_17C, P8_ISSUE_VSX], (instregex "^D(ADD|SUB|QUA)Q(_rec)?$")>; + def : InstRW<[P8_DFU_25C, P8_ISSUE_VSX], (instrs DRSP, DRSP_rec, DCTFIX, DCTFIX_rec)>; + def : InstRW<[P8_DFU_32C, P8_ISSUE_VSX], (instrs DCFFIX, DCFFIX_rec)>; + def : InstRW<[P8_DFU_34C, P8_ISSUE_VSX], (instrs DCFFIXQ, DCFFIXQ_rec)>; + def : InstRW<[P8_DFU_40C, P8_ISSUE_VSX], (instrs DMUL, DMUL_rec)>; + def : InstRW<[P8_DFU_90C, P8_ISSUE_VSX], (instrs DMULQ, DMULQ_rec)>; + def : InstRW<[P8_DFU_96C, P8_ISSUE_VSX], (instrs DDIV, DDIV_rec)>; + def : InstRW<[P8_DFU_172C, P8_ISSUE_VSX], (instrs DDIVQ, DDIVQ_rec)>; + + // Direct move instructions + + def : InstRW<[P8_DM_5C, P8_ISSUE_VSX], (instrs + MFVRD, MFVSRD, MFVRWZ, MFVSRWZ, MTVRD, MTVSRD, MTVRWA, MTVSRWA, MTVRWZ, MTVSRWZ)>; +} diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td index b763191d980e..36befceef4ac 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCScheduleP9.td @@ -227,17 +227,17 @@ let SchedModel = P9Model in { } def P9_DIV_16C_8 : SchedWriteRes<[DIV]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 16; } def P9_DIV_24C_8 : SchedWriteRes<[DIV]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 24; } def P9_DIV_40C_8 : SchedWriteRes<[DIV]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 40; } @@ -261,62 +261,62 @@ let SchedModel = P9Model in { } def P9_DP_22C_5 : SchedWriteRes<[DP]> { - let ResourceCycles = [5]; + let ReleaseAtCycles = [5]; let Latency = 22; } def P9_DPO_24C_8 : SchedWriteRes<[DPO]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 24; } def P9_DPE_24C_8 : SchedWriteRes<[DPE]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 24; } def P9_DP_26C_5 : SchedWriteRes<[DP]> { - let ResourceCycles = [5]; + let ReleaseAtCycles = [5]; let Latency = 22; } def P9_DPE_27C_10 : SchedWriteRes<[DP]> { - let ResourceCycles = [10]; + let ReleaseAtCycles = [10]; let Latency = 27; } def P9_DPO_27C_10 : SchedWriteRes<[DP]> { - let ResourceCycles = [10]; + let ReleaseAtCycles = [10]; let Latency = 27; } def P9_DP_33C_8 : SchedWriteRes<[DP]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 33; } def P9_DPE_33C_8 : SchedWriteRes<[DPE]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 33; } def P9_DPO_33C_8 : SchedWriteRes<[DPO]> { - let ResourceCycles = [8]; + let ReleaseAtCycles = [8]; let Latency = 33; } def P9_DP_36C_10 : SchedWriteRes<[DP]> { - let ResourceCycles = [10]; + let ReleaseAtCycles = [10]; let Latency = 36; } def P9_DPE_36C_10 : SchedWriteRes<[DP]> { - let ResourceCycles = [10]; + let ReleaseAtCycles = [10]; let Latency = 36; } def P9_DPO_36C_10 : SchedWriteRes<[DP]> { - let ResourceCycles = [10]; + let ReleaseAtCycles = [10]; let Latency = 36; } @@ -358,27 +358,27 @@ let SchedModel = P9Model in { def P9_DFU_23C : SchedWriteRes<[DFU]> { let Latency = 23; - let ResourceCycles = [11]; + let ReleaseAtCycles = [11]; } def P9_DFU_24C : SchedWriteRes<[DFU]> { let Latency = 24; - let ResourceCycles = [12]; + let ReleaseAtCycles = [12]; } def P9_DFU_37C : SchedWriteRes<[DFU]> { let Latency = 37; - let ResourceCycles = [25]; + let ReleaseAtCycles = [25]; } def P9_DFU_58C : SchedWriteRes<[DFU]> { let Latency = 58; - let ResourceCycles = [44]; + let ReleaseAtCycles = [44]; } def P9_DFU_76C : SchedWriteRes<[DFU]> { let Latency = 76; - let ResourceCycles = [62]; + let ReleaseAtCycles = [62]; } // 2 or 5 cycle latencies for the branch unit. diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 49400eefe4a9..c9740818c9bf 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -123,6 +123,11 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, // Determine endianness. IsLittleEndian = TM.isLittleEndian(); + + if (HasAIXSmallLocalExecTLS && (!TargetTriple.isOSAIX() || !IsPPC64)) + report_fatal_error( + "The aix-small-local-exec-tls attribute is only supported on AIX in " + "64-bit mode.\n", false); } bool PPCSubtarget::enableMachineScheduler() const { return true; } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp index 8120975c4fb2..81f078ab246e 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp @@ -100,7 +100,7 @@ protected: return true; for (const MachineOperand &MO : MI.operands()) { - if ((MO.getTargetFlags() & PPCII::MO_ACCESS_MASK) == PPCII::MO_TOC_LO) + if (MO.getTargetFlags() == PPCII::MO_TOC_LO) return true; } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index 3858d44e5099..d676fa86a10e 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -100,6 +100,11 @@ static cl::opt<bool> cl::desc("Expand eligible cr-logical binary ops to branches"), cl::init(true), cl::Hidden); +static cl::opt<bool> MergeStringPool( + "ppc-merge-string-pool", + cl::desc("Merge all of the strings in a module into one pool"), + cl::init(true), cl::Hidden); + static cl::opt<bool> EnablePPCGenScalarMASSEntries( "enable-ppc-gen-scalar-mass", cl::init(false), cl::desc("Enable lowering math functions to their corresponding MASS " @@ -137,6 +142,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTarget() { initializeGlobalISel(PR); initializePPCCTRLoopsPass(PR); initializePPCDAGToDAGISelPass(PR); + initializePPCMergeStringPoolPass(PR); } static bool isLittleEndianTriple(const Triple &T) { @@ -191,7 +197,7 @@ static std::string getDataLayoutString(const Triple &T) { return Ret; } -static std::string computeFSAdditions(StringRef FS, CodeGenOpt::Level OL, +static std::string computeFSAdditions(StringRef FS, CodeGenOptLevel OL, const Triple &TT) { std::string FullFS = std::string(FS); @@ -203,14 +209,14 @@ static std::string computeFSAdditions(StringRef FS, CodeGenOpt::Level OL, FullFS = "+64bit"; } - if (OL >= CodeGenOpt::Default) { + if (OL >= CodeGenOptLevel::Default) { if (!FullFS.empty()) FullFS = "+crbits," + FullFS; else FullFS = "+crbits"; } - if (OL != CodeGenOpt::None) { + if (OL != CodeGenOptLevel::None) { if (!FullFS.empty()) FullFS = "+invariant-function-descriptors," + FullFS; else @@ -236,9 +242,9 @@ static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, const TargetOptions &Options) { - if (Options.MCOptions.getABIName().startswith("elfv1")) + if (Options.MCOptions.getABIName().starts_with("elfv1")) return PPCTargetMachine::PPC_ABI_ELFv1; - else if (Options.MCOptions.getABIName().startswith("elfv2")) + else if (Options.MCOptions.getABIName().starts_with("elfv2")) return PPCTargetMachine::PPC_ABI_ELFv2; assert(Options.MCOptions.getABIName().empty() && @@ -259,8 +265,9 @@ static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, static Reloc::Model getEffectiveRelocModel(const Triple &TT, std::optional<Reloc::Model> RM) { - assert((!TT.isOSAIX() || !RM || *RM == Reloc::PIC_) && - "Invalid relocation model for AIX."); + if (TT.isOSAIX() && RM && *RM != Reloc::PIC_) + report_fatal_error("invalid relocation model, AIX only supports PIC", + false); if (RM) return *RM; @@ -339,7 +346,7 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT, const TargetOptions &Options, std::optional<Reloc::Model> RM, std::optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT) + CodeGenOptLevel OL, bool JIT) : LLVMTargetMachine(T, getDataLayoutString(TT), TT, CPU, computeFSAdditions(FS, OL, TT), Options, getEffectiveRelocModel(TT, RM), @@ -408,7 +415,7 @@ public: : TargetPassConfig(TM, PM) { // At any optimization level above -O0 we use the Machine Scheduler and not // the default Post RA List Scheduler. - if (TM.getOptLevel() != CodeGenOpt::None) + if (TM.getOptLevel() != CodeGenOptLevel::None) substitutePass(&PostRASchedulerID, &PostMachineSchedulerID); } @@ -448,7 +455,7 @@ TargetPassConfig *PPCTargetMachine::createPassConfig(PassManagerBase &PM) { } void PPCPassConfig::addIRPasses() { - if (TM->getOptLevel() != CodeGenOpt::None) + if (TM->getOptLevel() != CodeGenOptLevel::None) addPass(createPPCBoolRetToIntPass()); addPass(createAtomicExpandPass()); @@ -457,7 +464,7 @@ void PPCPassConfig::addIRPasses() { // Generate PowerPC target-specific entries for scalar math functions // that are available in IBM MASS (scalar) library. - if (TM->getOptLevel() == CodeGenOpt::Aggressive && + if (TM->getOptLevel() == CodeGenOptLevel::Aggressive && EnablePPCGenScalarMASSEntries) { TM->Options.PPCGenScalarMASSEntries = EnablePPCGenScalarMASSEntries; addPass(createPPCGenScalarMASSEntriesPass()); @@ -467,7 +474,7 @@ void PPCPassConfig::addIRPasses() { if (EnablePrefetch.getNumOccurrences() > 0) addPass(createLoopDataPrefetchPass()); - if (TM->getOptLevel() >= CodeGenOpt::Default && EnableGEPOpt) { + if (TM->getOptLevel() >= CodeGenOptLevel::Default && EnableGEPOpt) { // Call SeparateConstOffsetFromGEP pass to extract constants within indices // and lower a GEP with multiple indices to either arithmetic operations or // multiple GEPs with single index. @@ -484,10 +491,13 @@ void PPCPassConfig::addIRPasses() { } bool PPCPassConfig::addPreISel() { - if (!DisableInstrFormPrep && getOptLevel() != CodeGenOpt::None) + if (MergeStringPool && getOptLevel() != CodeGenOptLevel::None) + addPass(createPPCMergeStringPoolPass()); + + if (!DisableInstrFormPrep && getOptLevel() != CodeGenOptLevel::None) addPass(createPPCLoopInstrFormPrepPass(getPPCTargetMachine())); - if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None) + if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None) addPass(createHardwareLoopsLegacyPass()); return false; @@ -507,7 +517,7 @@ bool PPCPassConfig::addInstSelector() { addPass(createPPCISelDag(getPPCTargetMachine(), getOptLevel())); #ifndef NDEBUG - if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None) + if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None) addPass(createPPCCTRLoopsVerify()); #endif @@ -518,12 +528,12 @@ bool PPCPassConfig::addInstSelector() { void PPCPassConfig::addMachineSSAOptimization() { // Run CTR loops pass before any cfg modification pass to prevent the // canonical form of hardware loop from being destroied. - if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None) + if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None) addPass(createPPCCTRLoopsPass()); // PPCBranchCoalescingPass need to be done before machine sinking // since it merges empty blocks. - if (EnableBranchCoalescing && getOptLevel() != CodeGenOpt::None) + if (EnableBranchCoalescing && getOptLevel() != CodeGenOptLevel::None) addPass(createPPCBranchCoalescingPass()); TargetPassConfig::addMachineSSAOptimization(); // For little endian, remove where possible the vector swap instructions @@ -532,7 +542,7 @@ void PPCPassConfig::addMachineSSAOptimization() { !DisableVSXSwapRemoval) addPass(createPPCVSXSwapRemovalPass()); // Reduce the number of cr-logical ops. - if (ReduceCRLogical && getOptLevel() != CodeGenOpt::None) + if (ReduceCRLogical && getOptLevel() != CodeGenOptLevel::None) addPass(createPPCReduceCRLogicalsPass()); // Target-specific peephole cleanups performed after instruction // selection. @@ -543,7 +553,7 @@ void PPCPassConfig::addMachineSSAOptimization() { } void PPCPassConfig::addPreRegAlloc() { - if (getOptLevel() != CodeGenOpt::None) { + if (getOptLevel() != CodeGenOptLevel::None) { initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry()); insertPass(VSXFMAMutateEarly ? &RegisterCoalescerID : &MachineSchedulerID, &PPCVSXFMAMutateID); @@ -561,12 +571,12 @@ void PPCPassConfig::addPreRegAlloc() { if (EnableExtraTOCRegDeps) addPass(createPPCTOCRegDepsPass()); - if (getOptLevel() != CodeGenOpt::None) + if (getOptLevel() != CodeGenOptLevel::None) addPass(&MachinePipelinerID); } void PPCPassConfig::addPreSched2() { - if (getOptLevel() != CodeGenOpt::None) + if (getOptLevel() != CodeGenOptLevel::None) addPass(&IfConverterID); } @@ -574,7 +584,7 @@ void PPCPassConfig::addPreEmitPass() { addPass(createPPCPreEmitPeepholePass()); addPass(createPPCExpandISELPass()); - if (getOptLevel() != CodeGenOpt::None) + if (getOptLevel() != CodeGenOptLevel::None) addPass(createPPCEarlyReturnPass()); } diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h index 5d4571b7323a..56145a2eb39c 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetMachine.h @@ -39,7 +39,7 @@ public: PPCTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional<Reloc::Model> RM, - std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, + std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT); ~PPCTargetMachine() override; diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp index 8137b61f4982..062b53e24a0d 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -18,7 +18,6 @@ #include "llvm/IR/ProfDataUtils.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/KnownBits.h" #include "llvm/Transforms/InstCombine/InstCombiner.h" #include "llvm/Transforms/Utils/Local.h" #include <optional> @@ -27,6 +26,9 @@ using namespace llvm; #define DEBUG_TYPE "ppctti" +static cl::opt<bool> VecMaskCost("ppc-vec-mask-cost", +cl::desc("add masking cost for i1 vectors"), cl::init(true), cl::Hidden); + static cl::opt<bool> DisablePPCConstHoist("disable-ppc-constant-hoisting", cl::desc("disable constant hoisting on PPC"), cl::init(false), cl::Hidden); @@ -73,16 +75,14 @@ PPCTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const { if (getOrEnforceKnownAlignment( II.getArgOperand(0), Align(16), IC.getDataLayout(), &II, &IC.getAssumptionCache(), &IC.getDominatorTree()) >= 16) { - Value *Ptr = IC.Builder.CreateBitCast( - II.getArgOperand(0), PointerType::getUnqual(II.getType())); + Value *Ptr = II.getArgOperand(0); return new LoadInst(II.getType(), Ptr, "", false, Align(16)); } break; case Intrinsic::ppc_vsx_lxvw4x: case Intrinsic::ppc_vsx_lxvd2x: { // Turn PPC VSX loads into normal loads. - Value *Ptr = IC.Builder.CreateBitCast(II.getArgOperand(0), - PointerType::getUnqual(II.getType())); + Value *Ptr = II.getArgOperand(0); return new LoadInst(II.getType(), Ptr, Twine(""), false, Align(1)); } case Intrinsic::ppc_altivec_stvx: @@ -91,16 +91,14 @@ PPCTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const { if (getOrEnforceKnownAlignment( II.getArgOperand(1), Align(16), IC.getDataLayout(), &II, &IC.getAssumptionCache(), &IC.getDominatorTree()) >= 16) { - Type *OpPtrTy = PointerType::getUnqual(II.getArgOperand(0)->getType()); - Value *Ptr = IC.Builder.CreateBitCast(II.getArgOperand(1), OpPtrTy); + Value *Ptr = II.getArgOperand(1); return new StoreInst(II.getArgOperand(0), Ptr, false, Align(16)); } break; case Intrinsic::ppc_vsx_stxvw4x: case Intrinsic::ppc_vsx_stxvd2x: { // Turn PPC VSX stores into normal stores. - Type *OpPtrTy = PointerType::getUnqual(II.getArgOperand(0)->getType()); - Value *Ptr = IC.Builder.CreateBitCast(II.getArgOperand(1), OpPtrTy); + Value *Ptr = II.getArgOperand(1); return new StoreInst(II.getArgOperand(0), Ptr, false, Align(1)); } case Intrinsic::ppc_altivec_vperm: @@ -700,6 +698,9 @@ InstructionCost PPCTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, return Cost; } else if (Val->getScalarType()->isIntegerTy() && Index != -1U) { + unsigned EltSize = Val->getScalarSizeInBits(); + // Computing on 1 bit values requires extra mask or compare operations. + unsigned MaskCost = VecMaskCost && EltSize == 1 ? 1 : 0; if (ST->hasP9Altivec()) { if (ISD == ISD::INSERT_VECTOR_ELT) // A move-to VSR and a permute/insert. Assume vector operation cost @@ -721,12 +722,15 @@ InstructionCost PPCTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, // We need a vector extract (or mfvsrld). Assume vector operation cost. // The cost of the load constant for a vector extract is disregarded // (invariant, easily schedulable). - return CostFactor; + return CostFactor + MaskCost; - } else if (ST->hasDirectMove()) + } else if (ST->hasDirectMove()) { // Assume permute has standard cost. // Assume move-to/move-from VSR have 2x standard cost. - return 3; + if (ISD == ISD::INSERT_VECTOR_ELT) + return 3; + return 3 + MaskCost; + } } // Estimated cost of a load-hit-store delay. This was obtained |
