diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
| commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
| tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Target/PowerPC | |
| parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) | |
Notes
Diffstat (limited to 'lib/Target/PowerPC')
58 files changed, 6038 insertions, 2750 deletions
diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index d6db354e0215..56307a84f2e5 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -83,6 +83,16 @@ static const MCPhysReg FRegs[32] = { PPC::F24, PPC::F25, PPC::F26, PPC::F27, PPC::F28, PPC::F29, PPC::F30, PPC::F31 }; +static const MCPhysReg SPERegs[32] = { + PPC::S0, PPC::S1, PPC::S2, PPC::S3, + PPC::S4, PPC::S5, PPC::S6, PPC::S7, + PPC::S8, PPC::S9, PPC::S10, PPC::S11, + PPC::S12, PPC::S13, PPC::S14, PPC::S15, + PPC::S16, PPC::S17, PPC::S18, PPC::S19, + PPC::S20, PPC::S21, PPC::S22, PPC::S23, + PPC::S24, PPC::S25, PPC::S26, PPC::S27, + PPC::S28, PPC::S29, PPC::S30, PPC::S31 +}; static const MCPhysReg VFRegs[32] = { PPC::VF0, PPC::VF1, PPC::VF2, PPC::VF3, PPC::VF4, PPC::VF5, PPC::VF6, PPC::VF7, @@ -648,6 +658,16 @@ public: Inst.addOperand(MCOperand::createReg(QFRegs[getReg()])); } + void addRegSPE4RCOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(RRegs[getReg()])); + } + + void addRegSPERCOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(SPERegs[getReg()])); + } + void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(CRBITRegs[getCRBit()])); @@ -1394,6 +1414,12 @@ ExtractModifierFromExpr(const MCExpr *E, case MCSymbolRefExpr::VK_PPC_HA: Variant = PPCMCExpr::VK_PPC_HA; break; + case MCSymbolRefExpr::VK_PPC_HIGH: + Variant = PPCMCExpr::VK_PPC_HIGH; + break; + case MCSymbolRefExpr::VK_PPC_HIGHA: + Variant = PPCMCExpr::VK_PPC_HIGHA; + break; case MCSymbolRefExpr::VK_PPC_HIGHER: Variant = PPCMCExpr::VK_PPC_HIGHER; break; @@ -1973,6 +1999,10 @@ PPCAsmParser::applyModifierToExpr(const MCExpr *E, return PPCMCExpr::create(PPCMCExpr::VK_PPC_HI, E, false, Ctx); case MCSymbolRefExpr::VK_PPC_HA: return PPCMCExpr::create(PPCMCExpr::VK_PPC_HA, E, false, Ctx); + case MCSymbolRefExpr::VK_PPC_HIGH: + return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGH, E, false, Ctx); + case MCSymbolRefExpr::VK_PPC_HIGHA: + return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHA, E, false, Ctx); case MCSymbolRefExpr::VK_PPC_HIGHER: return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHER, E, false, Ctx); case MCSymbolRefExpr::VK_PPC_HIGHERA: diff --git a/lib/Target/PowerPC/CMakeLists.txt b/lib/Target/PowerPC/CMakeLists.txt index 3f173787114d..ff2776812845 100644 --- a/lib/Target/PowerPC/CMakeLists.txt +++ b/lib/Target/PowerPC/CMakeLists.txt @@ -1,15 +1,16 @@ set(LLVM_TARGET_DEFINITIONS PPC.td) -tablegen(LLVM PPCGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM PPCGenAsmMatcher.inc -gen-asm-matcher) +tablegen(LLVM PPCGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM PPCGenCallingConv.inc -gen-callingconv) +tablegen(LLVM PPCGenDAGISel.inc -gen-dag-isel) tablegen(LLVM PPCGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM PPCGenFastISel.inc -gen-fast-isel) +tablegen(LLVM PPCGenInstrInfo.inc -gen-instr-info) tablegen(LLVM PPCGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM PPCGenRegisterInfo.inc -gen-register-info) -tablegen(LLVM PPCGenInstrInfo.inc -gen-instr-info) -tablegen(LLVM PPCGenDAGISel.inc -gen-dag-isel) -tablegen(LLVM PPCGenFastISel.inc -gen-fast-isel) -tablegen(LLVM PPCGenCallingConv.inc -gen-callingconv) tablegen(LLVM PPCGenSubtargetInfo.inc -gen-subtarget) + add_public_tablegen_target(PowerPCCommonTableGen) add_llvm_target(PowerPCCodeGen @@ -49,5 +50,5 @@ add_llvm_target(PowerPCCodeGen add_subdirectory(AsmParser) add_subdirectory(Disassembler) add_subdirectory(InstPrinter) -add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) +add_subdirectory(TargetInfo) diff --git a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp index 11d22377611b..db01271b87e1 100644 --- a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -226,6 +226,17 @@ static const unsigned QFRegs[] = { PPC::QF28, PPC::QF29, PPC::QF30, PPC::QF31 }; +static const unsigned SPERegs[] = { + PPC::S0, PPC::S1, PPC::S2, PPC::S3, + PPC::S4, PPC::S5, PPC::S6, PPC::S7, + PPC::S8, PPC::S9, PPC::S10, PPC::S11, + PPC::S12, PPC::S13, PPC::S14, PPC::S15, + PPC::S16, PPC::S17, PPC::S18, PPC::S19, + PPC::S20, PPC::S21, PPC::S22, PPC::S23, + PPC::S24, PPC::S25, PPC::S26, PPC::S27, + PPC::S28, PPC::S29, PPC::S30, PPC::S31 +}; + template <std::size_t N> static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo, const unsigned (&Regs)[N]) { @@ -327,6 +338,18 @@ static DecodeStatus DecodeQFRCRegisterClass(MCInst &Inst, uint64_t RegNo, return decodeRegisterClass(Inst, RegNo, QFRegs); } +static DecodeStatus DecodeSPE4RCRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, GPRegs); +} + +static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, SPERegs); +} + #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass @@ -417,6 +440,51 @@ static DecodeStatus decodeMemRIX16Operands(MCInst &Inst, uint64_t Imm, return MCDisassembler::Success; } +static DecodeStatus decodeSPE8Operands(MCInst &Inst, uint64_t Imm, + int64_t Address, const void *Decoder) { + // Decode the spe8disp field (imm, reg), which has the low 5-bits as the + // displacement with 8-byte aligned, and the next 5 bits as the register #. + + uint64_t Base = Imm >> 5; + uint64_t Disp = Imm & 0x1F; + + assert(Base < 32 && "Invalid base register"); + + Inst.addOperand(MCOperand::createImm(Disp << 3)); + Inst.addOperand(MCOperand::createReg(GP0Regs[Base])); + return MCDisassembler::Success; +} + +static DecodeStatus decodeSPE4Operands(MCInst &Inst, uint64_t Imm, + int64_t Address, const void *Decoder) { + // Decode the spe4disp field (imm, reg), which has the low 5-bits as the + // displacement with 4-byte aligned, and the next 5 bits as the register #. + + uint64_t Base = Imm >> 5; + uint64_t Disp = Imm & 0x1F; + + assert(Base < 32 && "Invalid base register"); + + Inst.addOperand(MCOperand::createImm(Disp << 2)); + Inst.addOperand(MCOperand::createReg(GP0Regs[Base])); + return MCDisassembler::Success; +} + +static DecodeStatus decodeSPE2Operands(MCInst &Inst, uint64_t Imm, + int64_t Address, const void *Decoder) { + // Decode the spe2disp field (imm, reg), which has the low 5-bits as the + // displacement with 2-byte aligned, and the next 5 bits as the register #. + + uint64_t Base = Imm >> 5; + uint64_t Disp = Imm & 0x1F; + + assert(Base < 32 && "Invalid base register"); + + Inst.addOperand(MCOperand::createImm(Disp << 1)); + Inst.addOperand(MCOperand::createReg(GP0Regs[Base])); + return MCDisassembler::Success; +} + static DecodeStatus decodeCRBitMOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder) { // The cr bit encoding is 0x80 >> cr_reg_num. @@ -450,6 +518,11 @@ DecodeStatus PPCDisassembler::getInstruction(MCInst &MI, uint64_t &Size, decodeInstruction(DecoderTableQPX32, MI, Inst, Address, this, STI); if (result != MCDisassembler::Fail) return result; + } else if (STI.getFeatureBits()[PPC::FeatureSPE]) { + DecodeStatus result = + decodeInstruction(DecoderTableSPE32, MI, Inst, Address, this, STI); + if (result != MCDisassembler::Fail) + return result; } return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI); diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index 2a1de244da92..a405dd70c307 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/ErrorHandling.h" @@ -74,10 +75,9 @@ namespace { class PPCAsmBackend : public MCAsmBackend { const Target &TheTarget; - bool IsLittleEndian; public: - PPCAsmBackend(const Target &T, bool isLittle) : MCAsmBackend(), TheTarget(T), - IsLittleEndian(isLittle) {} + PPCAsmBackend(const Target &T, support::endianness Endian) + : MCAsmBackend(Endian), TheTarget(T) {} unsigned getNumFixupKinds() const override { return PPC::NumTargetFixupKinds; @@ -110,12 +110,15 @@ public: assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); - return (IsLittleEndian? InfosLE : InfosBE)[Kind - FirstTargetFixupKind]; + return (Endian == support::little + ? InfosLE + : InfosBE)[Kind - FirstTargetFixupKind]; } void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, - uint64_t Value, bool IsResolved) const override { + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override { Value = adjustFixupValue(Fixup.getKind(), Value); if (!Value) return; // Doesn't change encoding. @@ -126,7 +129,7 @@ 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 = IsLittleEndian ? i : (NumBytes - 1 - i); + unsigned Idx = Endian == support::little ? i : (NumBytes - 1 - i); Data[Offset + i] |= uint8_t((Value >> (Idx * 8)) & 0xff); } } @@ -155,7 +158,8 @@ public: } } - bool mayNeedRelaxation(const MCInst &Inst) const override { + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { // FIXME. return false; } @@ -174,12 +178,12 @@ public: llvm_unreachable("relaxInstruction() unimplemented"); } - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override { + bool writeNopData(raw_ostream &OS, uint64_t Count) const override { uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) - OW->write32(0x60000000); + support::endian::write<uint32_t>(OS, 0x60000000, Endian); - OW->WriteZeros(Count % 4); + OS.write_zeros(Count % 4); return true; } @@ -190,10 +194,6 @@ public: assert(Name == "ppc32" && "Unknown target name!"); return 4; } - - bool isLittleEndian() const { - return IsLittleEndian; - } }; } // end anonymous namespace @@ -202,13 +202,12 @@ public: namespace { class DarwinPPCAsmBackend : public PPCAsmBackend { public: - DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T, false) { } + DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T, support::big) { } - std::unique_ptr<MCObjectWriter> - createObjectWriter(raw_pwrite_stream &OS) const override { + std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const override { bool is64 = getPointerSize() == 8; return createPPCMachObjectWriter( - OS, /*Is64Bit=*/is64, (is64 ? MachO::CPU_TYPE_POWERPC64 : MachO::CPU_TYPE_POWERPC), MachO::CPU_SUBTYPE_POWERPC_ALL); @@ -218,26 +217,29 @@ namespace { class ELFPPCAsmBackend : public PPCAsmBackend { uint8_t OSABI; public: - ELFPPCAsmBackend(const Target &T, bool IsLittleEndian, uint8_t OSABI) : - PPCAsmBackend(T, IsLittleEndian), OSABI(OSABI) { } + ELFPPCAsmBackend(const Target &T, support::endianness Endian, + uint8_t OSABI) + : PPCAsmBackend(T, Endian), OSABI(OSABI) {} - std::unique_ptr<MCObjectWriter> - createObjectWriter(raw_pwrite_stream &OS) const override { + std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const override { bool is64 = getPointerSize() == 8; - return createPPCELFObjectWriter(OS, is64, isLittleEndian(), OSABI); + return createPPCELFObjectWriter(is64, OSABI); } }; } // end anonymous namespace MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, + const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, - const Triple &TT, StringRef CPU, const MCTargetOptions &Options) { + const Triple &TT = STI.getTargetTriple(); if (TT.isOSDarwin()) return new DarwinPPCAsmBackend(T); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); bool IsLittleEndian = TT.getArch() == Triple::ppc64le; - return new ELFPPCAsmBackend(T, IsLittleEndian, OSABI); + return new ELFPPCAsmBackend( + T, IsLittleEndian ? support::little : support::big, OSABI); } diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 44ee9733b16e..a3caf9a7a5ee 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -55,6 +55,10 @@ static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target, return MCSymbolRefExpr::VK_PPC_HI; case PPCMCExpr::VK_PPC_HA: return MCSymbolRefExpr::VK_PPC_HA; + case PPCMCExpr::VK_PPC_HIGH: + return MCSymbolRefExpr::VK_PPC_HIGH; + case PPCMCExpr::VK_PPC_HIGHA: + return MCSymbolRefExpr::VK_PPC_HIGHA; case PPCMCExpr::VK_PPC_HIGHERA: return MCSymbolRefExpr::VK_PPC_HIGHERA; case PPCMCExpr::VK_PPC_HIGHER: @@ -151,6 +155,12 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, case MCSymbolRefExpr::VK_PPC_HA: Type = ELF::R_PPC_ADDR16_HA; break; + case MCSymbolRefExpr::VK_PPC_HIGH: + Type = ELF::R_PPC64_ADDR16_HIGH; + break; + case MCSymbolRefExpr::VK_PPC_HIGHA: + Type = ELF::R_PPC64_ADDR16_HIGHA; + break; case MCSymbolRefExpr::VK_PPC_HIGHER: Type = ELF::R_PPC64_ADDR16_HIGHER; break; @@ -199,6 +209,12 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, case MCSymbolRefExpr::VK_PPC_TPREL_HA: Type = ELF::R_PPC_TPREL16_HA; break; + case MCSymbolRefExpr::VK_PPC_TPREL_HIGH: + Type = ELF::R_PPC64_TPREL16_HIGH; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA: + Type = ELF::R_PPC64_TPREL16_HIGHA; + break; case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: Type = ELF::R_PPC64_TPREL16_HIGHER; break; @@ -223,6 +239,12 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, case MCSymbolRefExpr::VK_PPC_DTPREL_HA: Type = ELF::R_PPC64_DTPREL16_HA; break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH: + Type = ELF::R_PPC64_DTPREL16_HIGH; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA: + Type = ELF::R_PPC64_DTPREL16_HIGHA; + break; case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: Type = ELF::R_PPC64_DTPREL16_HIGHER; break; @@ -417,9 +439,7 @@ bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, } } -std::unique_ptr<MCObjectWriter> -llvm::createPPCELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, - bool IsLittleEndian, uint8_t OSABI) { - auto MOTW = llvm::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI); - return createELFObjectWriter(std::move(MOTW), OS, IsLittleEndian); +std::unique_ptr<MCObjectTargetWriter> +llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) { + return llvm::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI); } diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp index 92c8c224b71b..2b948ca60028 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -122,25 +122,18 @@ public: // Output the constant in big/little endian byte order. unsigned Size = Desc.getSize(); + support::endianness E = IsLittleEndian ? support::little : support::big; switch (Size) { case 0: break; case 4: - if (IsLittleEndian) { - support::endian::Writer<support::little>(OS).write<uint32_t>(Bits); - } else { - support::endian::Writer<support::big>(OS).write<uint32_t>(Bits); - } + support::endian::write<uint32_t>(OS, Bits, E); break; case 8: // If we emit a pair of instructions, the first one is // always in the top 32 bits, even on little-endian. - if (IsLittleEndian) { - uint64_t Swapped = (Bits << 32) | (Bits >> 32); - support::endian::Writer<support::little>(OS).write<uint64_t>(Swapped); - } else { - support::endian::Writer<support::big>(OS).write<uint64_t>(Bits); - } + support::endian::write<uint32_t>(OS, Bits >> 32, E); + support::endian::write<uint32_t>(OS, Bits, E); break; default: llvm_unreachable("Invalid instruction size"); diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp index 54f664314578..32e6a0bdd65f 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp @@ -44,6 +44,8 @@ void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { case VK_PPC_LO: OS << "@l"; break; case VK_PPC_HI: OS << "@h"; break; case VK_PPC_HA: OS << "@ha"; break; + case VK_PPC_HIGH: OS << "@high"; break; + case VK_PPC_HIGHA: OS << "@higha"; break; case VK_PPC_HIGHER: OS << "@higher"; break; case VK_PPC_HIGHERA: OS << "@highera"; break; case VK_PPC_HIGHEST: OS << "@highest"; break; @@ -75,6 +77,10 @@ PPCMCExpr::evaluateAsInt64(int64_t Value) const { return (Value >> 16) & 0xffff; case VK_PPC_HA: return ((Value + 0x8000) >> 16) & 0xffff; + case VK_PPC_HIGH: + return (Value >> 16) & 0xffff; + case VK_PPC_HIGHA: + return ((Value + 0x8000) >> 16) & 0xffff; case VK_PPC_HIGHER: return (Value >> 32) & 0xffff; case VK_PPC_HIGHERA: @@ -125,6 +131,12 @@ PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res, case VK_PPC_HA: Modifier = MCSymbolRefExpr::VK_PPC_HA; break; + case VK_PPC_HIGH: + Modifier = MCSymbolRefExpr::VK_PPC_HIGH; + break; + case VK_PPC_HIGHA: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHA; + break; case VK_PPC_HIGHERA: Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; break; diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h index d42a111cc43e..8bb4791d13dd 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h @@ -23,6 +23,8 @@ public: VK_PPC_LO, VK_PPC_HI, VK_PPC_HA, + VK_PPC_HIGH, + VK_PPC_HIGHA, VK_PPC_HIGHER, VK_PPC_HIGHERA, VK_PPC_HIGHEST, diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h index 80a74c09a598..316fd2ccf358 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -27,8 +27,9 @@ class MCAsmBackend; class MCCodeEmitter; class MCContext; class MCInstrInfo; -class MCObjectWriter; +class MCObjectTargetWriter; class MCRegisterInfo; +class MCSubtargetInfo; class MCTargetOptions; class Target; class Triple; @@ -43,20 +44,16 @@ MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx); -MCAsmBackend *createPPCAsmBackend(const Target &T, const MCRegisterInfo &MRI, - const Triple &TT, StringRef CPU, +MCAsmBackend *createPPCAsmBackend(const Target &T, const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, const MCTargetOptions &Options); /// Construct an PPC ELF object writer. -std::unique_ptr<MCObjectWriter> createPPCELFObjectWriter(raw_pwrite_stream &OS, - bool Is64Bit, - bool IsLittleEndian, - uint8_t OSABI); +std::unique_ptr<MCObjectTargetWriter> createPPCELFObjectWriter(bool Is64Bit, + uint8_t OSABI); /// Construct a PPC Mach-O object writer. -std::unique_ptr<MCObjectWriter> createPPCMachObjectWriter(raw_pwrite_stream &OS, - bool Is64Bit, - uint32_t CPUType, - uint32_t CPUSubtype); +std::unique_ptr<MCObjectTargetWriter> +createPPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype); /// Returns true iff Val consists of one contiguous run of 1s with any number of /// 0s on either side. The 1s are allowed to wrap from LSB to MSB, so diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp index 4b9055ec7041..ff6cf584da23 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp @@ -374,10 +374,8 @@ void PPCMachObjectWriter::RecordPPCRelocation( Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE); } -std::unique_ptr<MCObjectWriter> -llvm::createPPCMachObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, - uint32_t CPUType, uint32_t CPUSubtype) { - return createMachObjectWriter( - llvm::make_unique<PPCMachObjectWriter>(Is64Bit, CPUType, CPUSubtype), OS, - /*IsLittleEndian=*/false); +std::unique_ptr<MCObjectTargetWriter> +llvm::createPPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, + uint32_t CPUSubtype) { + return llvm::make_unique<PPCMachObjectWriter>(Is64Bit, CPUType, CPUSubtype); } diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h index 603ac960133f..fe7e7aeeb182 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h @@ -50,6 +50,9 @@ namespace PPC { PRED_UN_PLUS = (3 << 5) | 15, PRED_NU_PLUS = (3 << 5) | 7, + // SPE scalar compare instructions always set the GT bit. + PRED_SPE = PRED_GT, + // When dealing with individual condition-register bits, we have simple set // and unset predicates. PRED_BIT_SET = 1024, diff --git a/lib/Target/PowerPC/P9InstrResources.td b/lib/Target/PowerPC/P9InstrResources.td index dc6ed16e53ce..34df8452fe16 100644 --- a/lib/Target/PowerPC/P9InstrResources.td +++ b/lib/Target/PowerPC/P9InstrResources.td @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This file defines resources required by some of P9 instruction. This is part -// P9 processor model used for instruction scheduling. Not every instruction -// is listed here. Instructions in this file belong to itinerary classes that -// have instructions with different resource requirements. +// This file defines the resources required by P9 instructions. This is part +// P9 processor model used for instruction scheduling. This file should contain +// all of the instructions that may be used on Power 9. This is not just +// instructions that are new on Power 9 but also instructions that were +// available on earlier architectures and are still used in Power 9. // // The makeup of the P9 CPU is modeled as follows: // - Each CPU is made up of two superslices. @@ -31,85 +32,37 @@ //===----------------------------------------------------------------------===// // Two cycle ALU vector operation that uses an entire superslice. -// Uses both ALU units (the even ALUE and odd ALUO units), two pipelines -// (EXECE, EXECO) and all three dispatches (DISP) to the given superslice. +// Uses both ALU units (the even ALUE and odd ALUO units), two pipelines +// (EXECE, EXECO) and all three dispatches (DISP) to the given superslice. def : InstRW<[P9_ALUE_2C, P9_ALUO_2C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - VADDCUW, - VADDUBM, - VADDUDM, - VADDUHM, - VADDUWM, - VAND, - VANDC, - VCMPEQUB, - VCMPEQUD, - VCMPEQUH, - VCMPEQUW, - VCMPNEB, - VCMPNEH, - VCMPNEW, - VCMPNEZB, - VCMPNEZH, - VCMPNEZW, + (instregex "VADDU(B|H|W|D)M$"), + (instregex "VAND(C)?$"), + (instregex "VEXTS(B|H|W)2(D|W)(s)?$"), + (instregex "V_SET0(B|H)?$"), + (instregex "VS(R|L)(B|H|W|D)$"), + (instregex "VSUBU(B|H|W|D)M$"), + (instregex "VPOPCNT(B|H)$"), + (instregex "VRL(B|H|W|D)$"), + (instregex "VSRA(B|H|W|D)$"), + (instregex "XV(N)?ABS(D|S)P$"), + (instregex "XVCPSGN(D|S)P$"), + (instregex "XV(I|X)EXP(D|S)P$"), + (instregex "VRL(D|W)(MI|NM)$"), + (instregex "VMRG(E|O)W$"), + MTVSRDD, VEQV, - VEXTSB2D, - VEXTSB2W, - VEXTSH2D, - VEXTSH2W, - VEXTSW2D, - VRLB, - VRLD, - VRLDMI, - VRLDNM, - VRLH, - VRLW, - VRLWMI, - VRLWNM, - VSRAB, - VSRAD, - VSRAH, - VSRAW, - VSRB, - VSRD, - VSRH, - VSRW, - VSLB, - VSLD, - VSLH, - VSLW, - VMRGEW, - VMRGOW, VNAND, VNEGD, VNEGW, VNOR, VOR, VORC, - VPOPCNTB, - VPOPCNTH, VSEL, - VSUBUBM, - VSUBUDM, - VSUBUHM, - VSUBUWM, VXOR, - V_SET0B, - V_SET0H, - V_SET0, - XVABSDP, - XVABSSP, - XVCPSGNDP, - XVCPSGNSP, - XVIEXPDP, - XVNABSDP, - XVNABSSP, XVNEGDP, XVNEGSP, - XVXEXPDP, - XVIEXPSP, - XVXEXPSP, XXLAND, XXLANDC, XXLEQV, @@ -119,6 +72,9 @@ def : InstRW<[P9_ALUE_2C, P9_ALUO_2C, IP_EXECE_1C, IP_EXECO_1C, XXLORf, XXLORC, XXLXOR, + XXLXORdpz, + XXLXORspz, + XXLXORz, XXSEL, XSABSQP, XSCPSGNQP, @@ -129,54 +85,89 @@ def : InstRW<[P9_ALUE_2C, P9_ALUO_2C, IP_EXECE_1C, IP_EXECO_1C, )>; // Restricted Dispatch ALU operation for 3 cycles. The operation runs on a -// slingle slice. However, since it is Restricted it requires all 3 dispatches -// (DISP) for that superslice. +// slingle slice. However, since it is Restricted it requires all 3 dispatches +// (DISP) for that superslice. def : InstRW<[P9_ALU_3C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - FCMPUS, - FCMPUD, - XSTSTDCDP, - XSTSTDCSP + (instregex "TABORT(D|W)C(I)?$"), + (instregex "MTFSB(0|1)$"), + (instregex "MFFSC(D)?RN(I)?$"), + (instregex "CMPRB(8)?$"), + (instregex "TD(I)?$"), + (instregex "TW(I)?$"), + (instregex "FCMPU(S|D)$"), + (instregex "XSTSTDC(S|D)P$"), + FTDIV, + FTSQRT, + CMPEQB )>; // Standard Dispatch ALU operation for 3 cycles. Only one slice used. def : InstRW<[P9_ALU_3C, IP_EXEC_1C, DISP_1C, DISP_1C], (instrs - XSMAXCDP, - XSMAXDP, - XSMAXJDP, - XSMINCDP, - XSMINDP, - XSMINJDP, + (instregex "XSMAX(C|J)?DP$"), + (instregex "XSMIN(C|J)?DP$"), + (instregex "XSCMP(EQ|EXP|GE|GT|O|U)DP$"), + (instregex "CNT(L|T)Z(D|W)(8)?(o)?$"), + (instregex "POPCNT(D|W)$"), + (instregex "CMPB(8)?$"), XSTDIVDP, XSTSQRTDP, - XSCMPEQDP, - XSCMPEXPDP, - XSCMPGEDP, - XSCMPGTDP, - XSCMPODP, - XSCMPUDP, XSXSIGDP, - XSCVSPDPN + XSCVSPDPN, + SETB, + BPERMD )>; // Standard Dispatch ALU operation for 2 cycles. Only one slice used. def : InstRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C, DISP_1C], (instrs - ADDIStocHA, - ADDItocL, + (instregex "S(L|R)D$"), + (instregex "SRAD(I)?$"), + (instregex "EXTSWSLI$"), + (instregex "MFV(S)?RD$"), + (instregex "MTVSRD$"), + (instregex "MTVSRW(A|Z)$"), + (instregex "CMP(WI|LWI|W|LW)(8)?$"), + (instregex "CMP(L)?D(I)?$"), + (instregex "SUBF(I)?C(8)?$"), + (instregex "ANDI(S)?o(8)?$"), + (instregex "ADDC(8)?$"), + (instregex "ADDIC(8)?(o)?$"), + (instregex "ADD(8|4)(o)?$"), + (instregex "ADD(E|ME|ZE)(8)?(o)?$"), + (instregex "SUBF(E|ME|ZE)?(8)?(o)?$"), + (instregex "NEG(8)?(o)?$"), + (instregex "POPCNTB$"), + (instregex "ADD(I|IS)?(8)?$"), + (instregex "LI(S)?(8)?$"), + (instregex "(X)?OR(I|IS)?(8)?(o)?$"), + (instregex "NAND(8)?(o)?$"), + (instregex "AND(C)?(8)?(o)?$"), + (instregex "NOR(8)?(o)?$"), + (instregex "OR(C)?(8)?(o)?$"), + (instregex "EQV(8)?(o)?$"), + (instregex "EXTS(B|H|W)(8)?(_32)?(_64)?(o)?$"), + (instregex "ADD(4|8)(TLS)?(_)?$"), + (instregex "NEG(8)?$"), + (instregex "ADDI(S)?toc(HA|L)$"), + COPY, MCRF, MCRXRX, - SLD, - SRD, - SRAD, - SRADI, - RLDIC, XSNABSDP, XSXEXPDP, XSABSDP, XSNEGDP, - XSCPSGNDP + XSCPSGNDP, + MFVSRWZ, + SRADI_32, + RLDIC, + RFEBB, + LA, + TBEGIN, + TRECHKPT, + NOP, + WAIT )>; // Restricted Dispatch ALU operation for 2 cycles. The operation runs on a @@ -184,80 +175,50 @@ def : InstRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C, DISP_1C], // (DISP) for that superslice. def : InstRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - RLDCL, - RLDCR, + (instregex "RLDC(L|R)$"), + (instregex "RLWIMI(8)?$"), + (instregex "RLDIC(L|R)(_32)?(_64)?$"), + (instregex "M(F|T)OCRF(8)?$"), + (instregex "CR(6)?(UN)?SET$"), + (instregex "CR(N)?(OR|AND)(C)?$"), + (instregex "S(L|R)W(8)?$"), + (instregex "RLW(INM|NM)(8)?$"), + (instregex "F(N)?ABS(D|S)$"), + (instregex "FNEG(D|S)$"), + (instregex "FCPSGN(D|S)$"), + (instregex "SRAW(I)?$"), + (instregex "ISEL(8)?$"), RLDIMI, - RLDICL, - RLDICR, - RLDICL_32_64, XSIEXPDP, FMR, - FABSD, - FABSS, - FNABSD, - FNABSS, - FNEGD, - FNEGS, - FCPSGND, - FCPSGNS + CREQV, + CRXOR, + TRECLAIM, + TSR, + TABORT )>; // Three cycle ALU vector operation that uses an entire superslice. -// Uses both ALU units (the even ALUE and odd ALUO units), two pipelines -// (EXECE, EXECO) and all three dispatches (DISP) to the given superslice. +// Uses both ALU units (the even ALUE and odd ALUO units), two pipelines +// (EXECE, EXECO) and all three dispatches (DISP) to the given superslice. def : InstRW<[P9_ALUE_3C, P9_ALUO_3C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], (instrs + (instregex "M(T|F)VSCR$"), + (instregex "VCMPNEZ(B|H|W)$"), + (instregex "VCMPEQU(B|H|W|D)$"), + (instregex "VCMPNE(B|H|W)$"), + (instregex "VABSDU(B|H|W)$"), + (instregex "VADDU(B|H|W)S$"), + (instregex "VAVG(S|U)(B|H|W)$"), + (instregex "VCMP(EQ|GE|GT)FP(o)?$"), + (instregex "VCMPBFP(o)?$"), + (instregex "VC(L|T)Z(B|H|W|D)$"), + (instregex "VADDS(B|H|W)S$"), + (instregex "V(MIN|MAX)FP$"), + (instregex "V(MIN|MAX)(S|U)(B|H|W|D)$"), VBPERMD, - VABSDUB, - VABSDUH, - VABSDUW, - VADDUBS, - VADDUHS, - VADDUWS, - VAVGSB, - VAVGSH, - VAVGSW, - VAVGUB, - VAVGUH, - VAVGUW, - VCMPEQFP, - VCMPEQFPo, - VCMPGEFP, - VCMPGEFPo, - VCMPBFP, - VCMPBFPo, - VCMPGTFP, - VCMPGTFPo, - VCLZB, - VCLZD, - VCLZH, - VCLZW, - VCTZB, - VCTZD, - VCTZH, - VCTZW, - VADDSBS, - VADDSHS, - VADDSWS, - VMINFP, - VMINSB, - VMINSD, - VMINSH, - VMINSW, - VMINUB, - VMINUD, - VMINUH, - VMINUW, - VMAXFP, - VMAXSB, - VMAXSD, - VMAXSH, - VMAXSW, - VMAXUB, - VMAXUD, - VMAXUH, - VMAXUW, + VADDCUW, VPOPCNTW, VPOPCNTD, VPRTYBD, @@ -434,47 +395,38 @@ def : InstRW<[P9_DPE_7C, P9_DPO_7C, IP_EXECE_1C, IP_EXECO_1C, VSUMSWS )>; + +// 5 cycle Restricted DP operation. One DP unit, one EXEC pipeline and all three +// dispatch units for the superslice. +def : InstRW<[P9_DP_5C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "MADD(HD|HDU|LD)$"), + (instregex "MUL(HD|HW|LD|LI|LI8|LW)(U)?$") +)>; + // 7 cycle Restricted DP operation. One DP unit, one EXEC pipeline and all three // dispatch units for the superslice. def : InstRW<[P9_DP_7C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], (instrs FRSP, - FRIND, - FRINS, - FRIPD, - FRIPS, - FRIZD, - FRIZS, - FRIMD, - FRIMS, - FRE, - FRES, - FRSQRTE, - FRSQRTES, - FMADDS, - FMADD, - FMSUBS, - FMSUB, + (instregex "FRI(N|P|Z|M)(D|S)$"), + (instregex "FRE(S)?$"), + (instregex "FADD(S)?$"), + (instregex "FMSUB(S)?$"), + (instregex "FMADD(S)?$"), + (instregex "FSUB(S)?$"), + (instregex "FCFID(U)?(S)?$"), + (instregex "FCTID(U)?(Z)?$"), + (instregex "FCTIW(U)?(Z)?$"), + (instregex "FRSQRTE(S)?$"), FNMADDS, FNMADD, FNMSUBS, FNMSUB, FSELD, FSELS, - FADDS, FMULS, FMUL, - FSUBS, - FCFID, - FCTID, - FCTIDZ, - FCFIDU, - FCFIDS, - FCFIDUS, - FCTIDUZ, - FCTIWUZ, - FCTIW, - FCTIWZ, XSMADDADP, XSMADDASP, XSMADDMDP, @@ -495,16 +447,40 @@ def : InstRW<[P9_DP_7C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], XSNMSUBMSP )>; -// 7 cycle Restricted DP operation and one 2 cycle ALU operation. +// 7 cycle Restricted DP operation and one 3 cycle ALU operation. +// These operations can be done in parallel. +// The DP is restricted so we need a full 5 dispatches. +def : InstRW<[P9_DP_7C, P9_ALU_3C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "FSEL(D|S)o$") +)>; + +// 5 Cycle Restricted DP operation and one 2 cycle ALU operation. +def : InstRW<[P9_DPOpAndALUOp_7C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "MUL(H|L)(D|W)(U)?o$") +)>; + +// 7 cycle Restricted DP operation and one 3 cycle ALU operation. +// These operations must be done sequentially. // The DP is restricted so we need a full 5 dispatches. -def : InstRW<[P9_DPOpAndALUOp_9C, IP_EXEC_1C, IP_EXEC_1C, +def : InstRW<[P9_DPOpAndALU2Op_10C, IP_EXEC_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - FMULo, - FMADDo, - FMSUBo, - FNMADDo, - FNMSUBo + (instregex "FRI(N|P|Z|M)(D|S)o$"), + (instregex "FRE(S)?o$"), + (instregex "FADD(S)?o$"), + (instregex "FSUB(S)?o$"), + (instregex "F(N)?MSUB(S)?o$"), + (instregex "F(N)?MADD(S)?o$"), + (instregex "FCFID(U)?(S)?o$"), + (instregex "FCTID(U)?(Z)?o$"), + (instregex "FCTIW(U)?(Z)?o$"), + (instregex "FMUL(S)?o$"), + (instregex "FRSQRTE(S)?o$"), + FRSPo )>; // 7 cycle DP operation. One DP unit, one EXEC pipeline and two dispatch units. @@ -520,6 +496,8 @@ def : InstRW<[P9_DP_7C, IP_EXEC_1C, DISP_1C, DISP_1C], XSCVDPUXDS, XSCVDPUXDSs, XSCVDPUXWS, + XSCVDPSXWSs, + XSCVDPUXWSs, XSCVHPDP, XSCVSPDP, XSCVSXDDP, @@ -533,12 +511,12 @@ def : InstRW<[P9_DP_7C, IP_EXEC_1C, DISP_1C, DISP_1C], XSRDPIZ, XSREDP, XSRESP, - //XSRSP, XSRSQRTEDP, XSRSQRTESP, XSSUBDP, XSSUBSP, - XSCVDPSPN + XSCVDPSPN, + XSRSP )>; // Three Cycle PM operation. Only one PM unit per superslice so we use the whole @@ -546,13 +524,18 @@ def : InstRW<[P9_DP_7C, IP_EXEC_1C, DISP_1C, DISP_1C], // dispatches. def : InstRW<[P9_PM_3C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C, DISP_1C], (instrs + (instregex "LVS(L|R)$"), + (instregex "VSPLTIS(W|H|B)$"), + (instregex "VSPLT(W|H|B)(s)?$"), + (instregex "V_SETALLONES(B|H)?$"), + (instregex "VEXTRACTU(B|H|W)$"), + (instregex "VINSERT(B|H|W|D)$"), + MFVSRLD, + MTVSRWS, VBPERMQ, VCLZLSBB, VCTZLSBB, VEXTRACTD, - VEXTRACTUB, - VEXTRACTUH, - VEXTRACTUW, VEXTUBLX, VEXTUBRX, VEXTUHLX, @@ -560,10 +543,6 @@ def : InstRW<[P9_PM_3C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C, DISP_1C], VEXTUWLX, VEXTUWRX, VGBBD, - VINSERTB, - VINSERTD, - VINSERTH, - VINSERTW, VMRGHB, VMRGHH, VMRGHW, @@ -591,14 +570,6 @@ def : InstRW<[P9_PM_3C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C, DISP_1C], VSLDOI, VSLO, VSLV, - VSPLTB, - VSPLTBs, - VSPLTH, - VSPLTHs, - VSPLTISB, - VSPLTISH, - VSPLTISW, - VSPLTW, VSR, VSRO, VSRV, @@ -642,7 +613,17 @@ def : InstRW<[P9_PM_3C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C, DISP_1C], XSCMPOQP, XSCMPUQP, XSTSTDCQP, - XSXSIGQP + XSXSIGQP, + BCDCFNo, + BCDCFZo, + BCDCPSGNo, + BCDCTNo, + BCDCTZo, + BCDSETSGNo, + BCDSo, + BCDTRUNCo, + BCDUSo, + BCDUTRUNCo )>; // 12 Cycle DFU operation. Only one DFU unit per CPU so we use a whole @@ -650,6 +631,7 @@ def : InstRW<[P9_PM_3C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C, DISP_1C], // dispatches. def : InstRW<[P9_DFU_12C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], (instrs + BCDSRo, XSADDQP, XSADDQPO, XSCVDPQP, @@ -662,11 +644,20 @@ def : InstRW<[P9_DFU_12C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], XSCVSDQP, XSCVUDQP, XSRQPI, + XSRQPIX, XSRQPXP, XSSUBQP, XSSUBQPO )>; +// 23 Cycle DFU operation. Only one DFU unit per CPU so we use a whole +// superslice. That includes both exec pipelines (EXECO, EXECE) and all three +// dispatches. +def : InstRW<[P9_DFU_23C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + BCDCTSQo +)>; + // 24 Cycle DFU operation. Only one DFU unit per CPU so we use a whole // superslice. That includes both exec pipelines (EXECO, EXECE) and all three // dispatches. @@ -684,6 +675,14 @@ def : InstRW<[P9_DFU_24C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], XSNMSUBQPO )>; +// 37 Cycle DFU operation. Only one DFU unit per CPU so we use a whole +// superslice. That includes both exec pipelines (EXECO, EXECE) and all three +// dispatches. +def : InstRW<[P9_DFU_37C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + BCDCFSQo +)>; + // 58 Cycle DFU operation. Only one DFU unit per CPU so we use a whole // superslice. That includes both exec pipelines (EXECO, EXECE) and all three // dispatches. @@ -702,23 +701,58 @@ def : InstRW<[P9_DFU_76C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], XSSQRTQPO )>; -// 5 Cycle load uses a single slice. +// 6 Cycle Load uses a single slice. +def : InstRW<[P9_LS_6C, IP_AGEN_1C, DISP_1C, DISP_1C], + (instrs + (instregex "LXVL(L)?") +)>; + +// 5 Cycle Load uses a single slice. def : InstRW<[P9_LS_5C, IP_AGEN_1C, DISP_1C, DISP_1C], (instrs + (instregex "LVE(B|H|W)X$"), + (instregex "LVX(L)?"), + (instregex "LXSI(B|H)ZX$"), LXSDX, + LXVB16X, LXVD2X, + LXVWSX, LXSIWZX, LXV, LXVX, LXSD, DFLOADf64, - XFLOADf64 + XFLOADf64, + LIWZX )>; -// 4 Cycle load uses a single slice. +// 4 Cycle Load uses a single slice. def : InstRW<[P9_LS_4C, IP_AGEN_1C, DISP_1C, DISP_1C], (instrs - COPY + (instregex "DCB(F|T|ST)(EP)?$"), + (instregex "DCBZ(L)?(EP)?$"), + (instregex "DCBTST(EP)?$"), + (instregex "CP_COPY(8)?$"), + (instregex "CP_PASTE(8)?$"), + (instregex "ICBI(EP)?$"), + (instregex "ICBT(LS)?$"), + (instregex "LBARX(L)?$"), + (instregex "LBZ(CIX|8|X|X8|XTLS|XTLS_32)?(_)?$"), + (instregex "LD(ARX|ARXL|BRX|CIX|X|XTLS)?(_)?$"), + (instregex "LH(A|B)RX(L)?(8)?$"), + (instregex "LHZ(8|CIX|X|X8|XTLS|XTLS_32)?(_)?$"), + (instregex "LWARX(L)?$"), + (instregex "LWBRX(8)?$"), + (instregex "LWZ(8|CIX|X|X8|XTLS|XTLS_32)?(_)?$"), + CP_ABORT, + DARN, + EnforceIEIO, + ISYNC, + MSGSYNC, + TLBSYNC, + SYNC, + LMW, + LSWI )>; // 4 Cycle Restricted load uses a single slice but the dispatch for the whole @@ -730,6 +764,58 @@ def : InstRW<[P9_LS_4C, IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C], LFD )>; +// Cracked Load Instructions. +// Load instructions that can be done in parallel. +def : InstRW<[P9_LS_4C, P9_LS_4C, IP_AGEN_1C, IP_AGEN_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + SLBIA, + SLBIE, + SLBMFEE, + SLBMFEV, + SLBMTE, + TLBIEL +)>; + +// Cracked Load Instruction. +// Requires Load and ALU pieces totaling 6 cycles. The Load and ALU +// operations can be run in parallel. +def : InstRW<[P9_LS_4C, P9_ALU_2C, IP_EXEC_1C, IP_AGEN_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "L(W|H)ZU(X)?(8)?$"), + TEND +)>; + +// Cracked Store Instruction +// Consecutive Store and ALU instructions. The store is restricted and requires +// three dispatches. +def : InstRW<[P9_StoreAndALUOp_3C, IP_EXEC_1C, IP_EXEC_1C, IP_AGEN_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "ST(B|H|W|D)CX$") +)>; + +// Cracked Load Instruction. +// Two consecutive load operations for a total of 8 cycles. +def : InstRW<[P9_LoadAndLoadOp_8C, IP_AGEN_1C, IP_AGEN_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + LDMX +)>; + +// Cracked Load instruction. +// Requires consecutive Load and ALU pieces totaling 6 cycles. The Load and ALU +// operations cannot be done at the same time and so their latencies are added. +def : InstRW<[P9_LoadAndALUOp_6C, IP_EXEC_1C, IP_AGEN_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "LHA(X)?(8)?$"), + (instregex "CP_PASTE(8)?o$"), + (instregex "LWA(X)?(_32)?$"), + TCHECK +)>; + // Cracked Restricted Load instruction. // Requires consecutive Load and ALU pieces totaling 6 cycles. The Load and ALU // operations cannot be done at the same time and so their latencies are added. @@ -737,9 +823,7 @@ def : InstRW<[P9_LS_4C, IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C], def : InstRW<[P9_LoadAndALUOp_6C, IP_EXEC_1C, IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - LFIWAX, - LFSX, - LFS + LFIWAX )>; // Cracked Load instruction. @@ -749,13 +833,42 @@ def : InstRW<[P9_LoadAndALUOp_6C, IP_EXEC_1C, IP_AGEN_1C, def : InstRW<[P9_LoadAndALUOp_7C, IP_AGEN_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - LXSSPX, LXSIWAX, + LIWAX +)>; + +// Cracked Load instruction. +// Requires consecutive Load (4 cycles) and ALU (3 cycles) pieces totaling 7 +// cycles. The Load and ALU operations cannot be done at the same time and so +// their latencies are added. +// Full 6 dispatches are required as this is a restricted instruction. +def : InstRW<[P9_LoadAndALU2Op_7C, IP_AGEN_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + LFSX, + LFS +)>; + +// Cracked Load instruction. +// Requires consecutive Load and ALU pieces totaling 8 cycles. The Load and ALU +// operations cannot be done at the same time and so their latencies are added. +// Full 4 dispatches are required as this is a cracked instruction. +def : InstRW<[P9_LoadAndALU2Op_8C, IP_AGEN_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs LXSSP, - DFLOADf32, + LXSSPX, XFLOADf32, - LIWAX, - LIWZX + DFLOADf32 +)>; + +// Cracked 3-Way Load Instruction +// Load with two ALU operations that depend on each other +def : InstRW<[P9_LoadAndALUOp_6C, P9_ALU_2C, IP_AGEN_1C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "LHAU(X)?(8)?$"), + LWAUX )>; // Cracked Load that requires the PM resource. @@ -767,8 +880,8 @@ def : InstRW<[P9_LoadAndALUOp_7C, IP_AGEN_1C, IP_EXEC_1C, def : InstRW<[P9_LoadAndPMOp_8C, IP_AGEN_1C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs + LXVH8X, LXVDSX, - LXVWSX, LXVW4X )>; @@ -776,29 +889,52 @@ def : InstRW<[P9_LoadAndPMOp_8C, IP_AGEN_1C, IP_EXECE_1C, IP_EXECO_1C, // all three dispatches for the superslice. def : InstRW<[P9_LS_1C, IP_EXEC_1C, IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - STFS, - STFD, - STFIWX, - STFSX, - STFDX, - STXSDX, - STXSSPX, - STXSIWX, - DFSTOREf32, - DFSTOREf64, - XFSTOREf32, - XFSTOREf64, - STIWX + (instregex "STF(S|D|IWX|SX|DX)$"), + (instregex "STXS(D|DX|SPX|IWX|IBX|IHX|SP)(v)?$"), + (instregex "STW(8)?$"), + (instregex "(D|X)FSTORE(f32|f64)$"), + (instregex "ST(W|H|D)BRX$"), + (instregex "ST(B|H|D)(8)?$"), + (instregex "ST(B|W|H|D)(CI)?X(TLS|TLS_32)?(8)?(_)?$"), + STIWX, + SLBIEG, + STMW, + STSWI, + TLBIE )>; -// Store operation that requires the whole superslice. +// Vector Store Instruction +// Requires the whole superslice and therefore requires all three dispatches +// as well as both the Even and Odd exec pipelines. def : InstRW<[P9_LS_1C, IP_EXECE_1C, IP_EXECO_1C, IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - STXVD2X, - STXVW4X + (instregex "STVE(B|H|W)X$"), + (instregex "STVX(L)?$"), + (instregex "STXV(B16X|H8X|W4X|D2X|L|LL|X)?$") +)>; + +// 5 Cycle DIV operation. Only one DIV unit per superslice so we use the whole +// superslice. That includes both exec pipelines (EXECO, EXECE) and all three +// dispatches. +def : InstRW<[P9_DIV_5C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "MTCTR(8)?(loop)?$"), + (instregex "MTLR(8)?$") )>; +// 12 Cycle DIV operation. Only one DIV unit per superslice so we use the whole +// superslice. That includes both exec pipelines (EXECO, EXECE) and all three +// dispatches. +def : InstRW<[P9_DIV_12C, IP_EXECE_1C, IP_EXECO_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "M(T|F)VRSAVE(v)?$"), + (instregex "M(T|F)PMR$"), + (instregex "M(T|F)TB(8)?$"), + (instregex "MF(SPR|CTR|LR)(8)?$"), + (instregex "M(T|F)MSR(D)?$"), + (instregex "MTSPR(8)?$") +)>; // 16 Cycle DIV operation. Only one DIV unit per superslice so we use the whole // superslice. That includes both exec pipelines (EXECO, EXECE) and all three @@ -839,6 +975,15 @@ def : InstRW<[P9_DIV_40C_8, IP_EXECO_1C, IP_EXECE_1C, // Cracked DIV and ALU operation. Requires one full slice for the ALU operation // and one full superslice for the DIV operation since there is only one DIV // per superslice. Latency of DIV plus ALU is 26. +def : InstRW<[P9_IntDivAndALUOp_18C_8, IP_EXECE_1C, IP_EXECO_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "DIVW(U)?(O)?o$") +)>; + +// Cracked DIV and ALU operation. Requires one full slice for the ALU operation +// and one full superslice for the DIV operation since there is only one DIV +// per superslice. Latency of DIV plus ALU is 26. def : InstRW<[P9_IntDivAndALUOp_26C_8, IP_EXECE_1C, IP_EXECO_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs @@ -868,16 +1013,40 @@ def : InstRW<[P9_IntDivAndALUOp_42C_8, IP_EXECE_1C, IP_EXECO_1C, IP_EXEC_1C, def : InstRW<[P9_ALU_2C, P9_ALU_2C, IP_EXEC_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - MTOCRF, - MTOCRF8, MTCRF, MTCRF8 )>; -// Cracked, restricted, ALU operations. +// Cracked ALU operations. // Here the two ALU ops can actually be done in parallel and therefore the // latencies are not added together. Otherwise this is like having two -// instructions running together on two pipelines and 6 dispatches. +// instructions running together on two pipelines and 4 dispatches. +// ALU ops are 2 cycles each. +def : InstRW<[P9_ALU_2C, P9_ALU_2C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "ADDC(8)?o$"), + (instregex "SUBFC(8)?o$") +)>; + +// Cracked ALU operations. +// Two ALU ops can be done in parallel. +// One is three cycle ALU the ohter is a two cycle ALU. +// One of the ALU ops is restricted the other is not so we have a total of +// 5 dispatches. +def : InstRW<[P9_ALU_2C, P9_ALU_3C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "F(N)?ABS(D|S)o$"), + (instregex "FCPSGN(D|S)o$"), + (instregex "FNEG(D|S)o$"), + FMRo +)>; + +// Cracked ALU operations. +// Here the two ALU ops can actually be done in parallel and therefore the +// latencies are not added together. Otherwise this is like having two +// instructions running together on two pipelines and 4 dispatches. // ALU ops are 3 cycles each. def : InstRW<[P9_ALU_3C, P9_ALU_3C, IP_EXEC_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], @@ -885,7 +1054,63 @@ def : InstRW<[P9_ALU_3C, P9_ALU_3C, IP_EXEC_1C, IP_EXEC_1C, MCRFS )>; -// FP Div instructions in IIC_FPDivD and IIC_FPDivS. +// Cracked Restricted ALU operations. +// Here the two ALU ops can actually be done in parallel and therefore the +// latencies are not added together. Otherwise this is like having two +// instructions running together on two pipelines and 6 dispatches. +// ALU ops are 3 cycles each. +def : InstRW<[P9_ALU_3C, P9_ALU_3C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "MTFSF(b|o)?$"), + (instregex "MTFSFI(o)?$") +)>; + +// Cracked instruction made of two ALU ops. +// The two ops cannot be done in parallel. +// One of the ALU ops is restricted and takes 3 dispatches. +def : InstRW<[P9_ALUOpAndALUOp_4C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "RLD(I)?C(R|L)o$"), + (instregex "RLW(IMI|INM|NM)(8)?o$"), + (instregex "SLW(8)?o$"), + (instregex "SRAW(I)?o$"), + (instregex "SRW(8)?o$"), + RLDICL_32o, + RLDIMIo +)>; + +// Cracked instruction made of two ALU ops. +// The two ops cannot be done in parallel. +// Both of the ALU ops are restricted and take 3 dispatches. +def : InstRW<[P9_ALU2OpAndALU2Op_6C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "MFFS(L|CE|o)?$") +)>; + +// Cracked ALU instruction composed of three consecutive 2 cycle loads for a +// total of 6 cycles. All of the ALU operations are also restricted so each +// takes 3 dispatches for a total of 9. +def : InstRW<[P9_ALUOpAndALUOpAndALUOp_6C, IP_EXEC_1C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, + DISP_1C, DISP_1C], + (instrs + (instregex "MFCR(8)?$") +)>; + +// Cracked instruction made of two ALU ops. +// The two ops cannot be done in parallel. +def : InstRW<[P9_ALUOpAndALUOp_4C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "EXTSWSLIo$"), + (instregex "SRAD(I)?o$"), + SLDo, + SRDo, + RLDICo +)>; // 33 Cycle DP Instruction Restricted. Takes one slice and 3 dispatches. def : InstRW<[P9_DP_33C_8, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], @@ -893,13 +1118,66 @@ def : InstRW<[P9_DP_33C_8, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], FDIV )>; -// 33 Cycle DP Instruction Restricted and Cracked with 2 Cycle ALU. -def : InstRW<[P9_DPOpAndALUOp_35C_8, IP_EXEC_1C, IP_EXEC_1C, +// 33 Cycle DP Instruction Restricted and Cracked with 3 Cycle ALU. +def : InstRW<[P9_DPOpAndALU2Op_36C_8, IP_EXEC_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs FDIVo )>; +// 36 Cycle DP Instruction. +// Instruction can be done on a single slice. +def : InstRW<[P9_DP_36C_10, IP_EXEC_1C, DISP_1C, DISP_1C], + (instrs + XSSQRTDP +)>; + +// 36 Cycle DP Instruction Restricted. Takes one slice and 3 dispatches. +def : InstRW<[P9_DP_36C_10, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + FSQRT +)>; + +// 36 Cycle DP Vector Instruction. +def : InstRW<[P9_DPE_36C_10, P9_DPO_36C_10, IP_EXECE_1C, IP_EXECO_1C, + DISP_1C, DISP_1C, DISP_1C], + (instrs + XVSQRTDP +)>; + +// 27 Cycle DP Vector Instruction. +def : InstRW<[P9_DPE_27C_10, P9_DPO_27C_10, IP_EXECE_1C, IP_EXECO_1C, + DISP_1C, DISP_1C, DISP_1C], + (instrs + XVSQRTSP +)>; + +// 36 Cycle DP Instruction Restricted and Cracked with 3 Cycle ALU. +def : InstRW<[P9_DPOpAndALU2Op_39C_10, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + FSQRTo +)>; + +// 26 Cycle DP Instruction. +def : InstRW<[P9_DP_26C_5, IP_EXEC_1C, DISP_1C, DISP_1C], + (instrs + XSSQRTSP +)>; + +// 26 Cycle DP Instruction Restricted. Takes one slice and 3 dispatches. +def : InstRW<[P9_DP_26C_5, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + FSQRTS +)>; + +// 26 Cycle DP Instruction Restricted and Cracked with 3 Cycle ALU. +def : InstRW<[P9_DPOpAndALU2Op_29C_5, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + FSQRTSo +)>; + // 33 Cycle DP Instruction. Takes one slice and 2 dispatches. def : InstRW<[P9_DP_33C_8, IP_EXEC_1C, DISP_1C, DISP_1C], (instrs @@ -913,7 +1191,7 @@ def : InstRW<[P9_DP_22C_5, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], )>; // 22 Cycle DP Instruction Restricted and Cracked with 2 Cycle ALU. -def : InstRW<[P9_DPOpAndALUOp_24C_5, IP_EXEC_1C, IP_EXEC_1C, +def : InstRW<[P9_DPOpAndALU2Op_25C_5, IP_EXEC_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs FDIVSo @@ -943,24 +1221,41 @@ def : InstRW<[P9_DPE_33C_8, P9_DPO_33C_8, IP_EXECE_1C, IP_EXECO_1C, XVDIVDP )>; -// Load instructions in IIC_LdStLFDU and IIC_LdStLFDUX. - // Instruction cracked into three pieces. One Load and two ALU operations. // The Load and one of the ALU ops cannot be run at the same time and so the // latencies are added together for 6 cycles. The remainaing ALU is 2 cycles. // Both the load and the ALU that depends on it are restricted and so they take // a total of 6 dispatches. The final 2 dispatches come from the second ALU op. // The two EXEC pipelines are for the 2 ALUs while the AGEN is for the load. -def : InstRW<[P9_LoadAndALUOp_6C, P9_ALU_2C, +def : InstRW<[P9_LoadAndALU2Op_7C, P9_ALU_2C, IP_AGEN_1C, IP_EXEC_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - LFSU, - LFSUX + (instregex "LF(SU|SUX)$") +)>; + +// Cracked instruction made up of a Store and an ALU. The ALU does not depend on +// the store and so it can be run at the same time as the store. The store is +// also restricted. +def : InstRW<[P9_LS_1C, P9_ALU_2C, IP_AGEN_1C, IP_EXEC_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "STF(S|D)U(X)?$"), + (instregex "ST(B|H|W|D)U(X)?(8)?$") )>; // Cracked instruction made up of a Load and an ALU. The ALU does not depend on +// the load and so it can be run at the same time as the load. +def : InstRW<[P9_LS_4C, P9_ALU_2C, IP_AGEN_1C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + (instregex "LBZU(X)?(8)?$"), + (instregex "LDU(X)?$") +)>; + + +// Cracked instruction made up of a Load and an ALU. The ALU does not depend on // the load and so it can be run at the same time as the load. The load is also // restricted. 3 dispatches are from the restricted load while the other two // are from the ALU. The AGEN pipeline is from the load and the EXEC pipeline @@ -968,8 +1263,7 @@ def : InstRW<[P9_LoadAndALUOp_6C, P9_ALU_2C, def : InstRW<[P9_LS_4C, P9_ALU_2C, IP_AGEN_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - LFDU, - LFDUX + (instregex "LF(DU|DUX)$") )>; // Crypto Instructions @@ -979,13 +1273,147 @@ def : InstRW<[P9_LS_4C, P9_ALU_2C, IP_AGEN_1C, IP_EXEC_1C, // dispatches. def : InstRW<[P9_CY_6C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C, DISP_1C], (instrs - VPMSUMB, - VPMSUMD, - VPMSUMH, - VPMSUMW, - VCIPHER, - VCIPHERLAST, - VNCIPHER, - VNCIPHERLAST, - VSBOX + (instregex "VPMSUM(B|H|W|D)$"), + (instregex "V(N)?CIPHER(LAST)?$"), + VSBOX )>; + +// Branch Instructions + +// Two Cycle Branch +def : InstRW<[P9_BR_2C, DISP_1C, DISP_1C], + (instrs + (instregex "BCCCTR(L)?(8)?$"), + (instregex "BCCL(A|R|RL)?$"), + (instregex "BCCTR(L)?(8)?(n)?$"), + (instregex "BD(N)?Z(8|A|Am|Ap|m|p)?$"), + (instregex "BD(N)?ZL(A|Am|Ap|R|R8|RL|RLm|RLp|Rm|Rp|m|p)?$"), + (instregex "BL(_TLS)?$"), + (instregex "BL8(_TLS|_NOP|_NOP_TLS|_TLS_)?$"), + (instregex "BLA(8|8_NOP)?$"), + (instregex "BLR(8|L)?$"), + (instregex "TAILB(A)?(8)?$"), + (instregex "TAILBCTR(8)?$"), + (instregex "gBC(A|Aat|CTR|CTRL|L|LA|LAat|LR|LRL|Lat|at)?$"), + (instregex "BCLR(L)?(n)?$"), + (instregex "BCTR(L)?(8)?$"), + B, + BA, + BC, + BCC, + BCCA, + BCL, + BCLalways, + BCLn, + BCTRL8_LDinto_toc, + BCn, + CTRL_DEP +)>; + +// Five Cycle Branch with a 2 Cycle ALU Op +// Operations must be done consecutively and not in parallel. +def : InstRW<[P9_BROpAndALUOp_7C, IP_EXEC_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C], + (instrs + ADDPCIS +)>; + +// Special Extracted Instructions For Atomics + +// Atomic Load +def : InstRW<[P9_LS_1C, P9_LS_1C, P9_LS_4C, P9_LS_4C, P9_LS_4C, + IP_EXEC_1C, IP_EXEC_1C, IP_AGEN_1C, IP_AGEN_1C, IP_AGEN_1C, + IP_AGEN_1C, IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, + DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, + DISP_1C], + (instrs + (instregex "L(D|W)AT$") +)>; + +// Atomic Store +def : InstRW<[P9_LS_1C, P9_LS_4C, P9_LS_4C, IP_EXEC_1C, IP_AGEN_1C, IP_AGEN_1C, + IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, + DISP_1C], + (instrs + (instregex "ST(D|W)AT$") +)>; + +// Signal Processing Engine (SPE) Instructions +// These instructions are not supported on Power 9 +def : InstRW<[], + (instrs + BRINC, + EVABS, + EVEQV, + EVMRA, + EVNAND, + EVNEG, + (instregex "EVADD(I)?W$"), + (instregex "EVADD(SM|SS|UM|US)IAAW$"), + (instregex "EVAND(C)?$"), + (instregex "EVCMP(EQ|GTS|GTU|LTS|LTU)$"), + (instregex "EVCNTL(S|Z)W$"), + (instregex "EVDIVW(S|U)$"), + (instregex "EVEXTS(B|H)$"), + (instregex "EVLD(H|W|D)(X)?$"), + (instregex "EVLHH(E|OS|OU)SPLAT(X)?$"), + (instregex "EVLWHE(X)?$"), + (instregex "EVLWHO(S|U)(X)?$"), + (instregex "EVLW(H|W)SPLAT(X)?$"), + (instregex "EVMERGE(HI|LO|HILO|LOHI)$"), + (instregex "EVMHEG(S|U)M(F|I)A(A|N)$"), + (instregex "EVMHES(M|S)(F|I)(A|AA|AAW|ANW)?$"), + (instregex "EVMHEU(M|S)I(A|AA|AAW|ANW)?$"), + (instregex "EVMHOG(U|S)M(F|I)A(A|N)$"), + (instregex "EVMHOS(M|S)(F|I)(A|AA|AAW|ANW)?$"), + (instregex "EVMHOU(M|S)I(A|AA|ANW|AAW)?$"), + (instregex "EVMWHS(M|S)(F|FA|I|IA)$"), + (instregex "EVMWHUMI(A)?$"), + (instregex "EVMWLS(M|S)IA(A|N)W$"), + (instregex "EVMWLU(M|S)I(A|AA|AAW|ANW)?$"), + (instregex "EVMWSM(F|I)(A|AA|AN)?$"), + (instregex "EVMWSSF(A|AA|AN)?$"), + (instregex "EVMWUMI(A|AA|AN)?$"), + (instregex "EV(N|X)?OR(C)?$"), + (instregex "EVR(LW|LWI|NDW)$"), + (instregex "EVSLW(I)?$"), + (instregex "EVSPLAT(F)?I$"), + (instregex "EVSRW(I)?(S|U)$"), + (instregex "EVST(DD|DH|DW|WHE|WHO|WWE|WWO)(X)?$"), + (instregex "EVSUBF(S|U)(M|S)IAAW$"), + (instregex "EVSUB(I)?FW$") +)> { let Unsupported = 1; } + +// General Instructions without scheduling support. +def : InstRW<[], + (instrs + (instregex "(H)?RFI(D)?$"), + (instregex "DSS(ALL)?$"), + (instregex "DST(ST)?(T)?(64)?$"), + (instregex "ICBL(C|Q)$"), + (instregex "L(W|H|B)EPX$"), + (instregex "ST(W|H|B)EPX$"), + (instregex "(L|ST)FDEPX$"), + (instregex "M(T|F)SR(IN)?$"), + (instregex "M(T|F)DCR$"), + (instregex "NOP_GT_PWR(6|7)$"), + (instregex "TLB(IA|IVAX|SX|SX2|SX2D|LD|LI|RE|RE2|WE|WE2)$"), + (instregex "WRTEE(I)?$"), + ATTN, + CLRBHRB, + MFBHRBE, + MBAR, + MSYNC, + SLBSYNC, + NAP, + STOP, + TRAP, + RFCI, + RFDI, + RFMCI, + SC, + DCBA, + DCBI, + DCCCI, + ICCCI +)> { let Unsupported = 1; } diff --git a/lib/Target/PowerPC/PPC.td b/lib/Target/PowerPC/PPC.td index 46502208b175..80ad4962a20f 100644 --- a/lib/Target/PowerPC/PPC.td +++ b/lib/Target/PowerPC/PPC.td @@ -35,6 +35,8 @@ def Directive970 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_970", "">; def Directive32 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_32", "">; def Directive64 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_64", "">; def DirectiveA2 : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_A2", "">; +def DirectiveE500 : SubtargetFeature<"", "DarwinDirective", + "PPC::DIR_E500", "">; def DirectiveE500mc : SubtargetFeature<"", "DarwinDirective", "PPC::DIR_E500mc", "">; def DirectiveE5500 : SubtargetFeature<"", "DarwinDirective", @@ -59,9 +61,12 @@ def Feature64BitRegs : SubtargetFeature<"64bitregs","Use64BitRegs", "true", "Enable 64-bit registers usage for ppc32 [beta]">; def FeatureCRBits : SubtargetFeature<"crbits", "UseCRBits", "true", "Use condition-register bits individually">; +def FeatureFPU : SubtargetFeature<"fpu","HasFPU","true", + "Enable classic FPU instructions", + [FeatureHardFloat]>; def FeatureAltivec : SubtargetFeature<"altivec","HasAltivec", "true", "Enable Altivec instructions", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureSPE : SubtargetFeature<"spe","HasSPE", "true", "Enable SPE instructions", [FeatureHardFloat]>; @@ -69,36 +74,36 @@ def FeatureMFOCRF : SubtargetFeature<"mfocrf","HasMFOCRF", "true", "Enable the MFOCRF instruction">; def FeatureFSqrt : SubtargetFeature<"fsqrt","HasFSQRT", "true", "Enable the fsqrt instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureFCPSGN : SubtargetFeature<"fcpsgn", "HasFCPSGN", "true", "Enable the fcpsgn instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureFRE : SubtargetFeature<"fre", "HasFRE", "true", "Enable the fre instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureFRES : SubtargetFeature<"fres", "HasFRES", "true", "Enable the fres instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureFRSQRTE : SubtargetFeature<"frsqrte", "HasFRSQRTE", "true", "Enable the frsqrte instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureFRSQRTES : SubtargetFeature<"frsqrtes", "HasFRSQRTES", "true", "Enable the frsqrtes instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureRecipPrec : SubtargetFeature<"recipprec", "HasRecipPrec", "true", "Assume higher precision reciprocal estimates">; def FeatureSTFIWX : SubtargetFeature<"stfiwx","HasSTFIWX", "true", "Enable the stfiwx instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureLFIWAX : SubtargetFeature<"lfiwax","HasLFIWAX", "true", "Enable the lfiwax instruction", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureFPRND : SubtargetFeature<"fprnd", "HasFPRND", "true", "Enable the fri[mnpz] instructions", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureFPCVT : SubtargetFeature<"fpcvt", "HasFPCVT", "true", "Enable fc[ft]* (unsigned and single-precision) and lfiwzx instructions", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureISEL : SubtargetFeature<"isel","HasISEL", "true", "Enable the isel instruction">; def FeatureBPERMD : SubtargetFeature<"bpermd", "HasBPERMD", "true", @@ -119,13 +124,15 @@ def FeatureMSYNC : SubtargetFeature<"msync", "HasOnlyMSYNC", "true", [FeatureBookE]>; def FeatureE500 : SubtargetFeature<"e500", "IsE500", "true", "Enable E500/E500mc instructions">; +def FeatureSecurePlt : SubtargetFeature<"secure-plt","SecurePlt", "true", + "Enable secure plt mode">; def FeaturePPC4xx : SubtargetFeature<"ppc4xx", "IsPPC4xx", "true", "Enable PPC 4xx instructions">; def FeaturePPC6xx : SubtargetFeature<"ppc6xx", "IsPPC6xx", "true", "Enable PPC 6xx instructions">; def FeatureQPX : SubtargetFeature<"qpx","HasQPX", "true", "Enable QPX instructions", - [FeatureHardFloat]>; + [FeatureFPU]>; def FeatureVSX : SubtargetFeature<"vsx","HasVSX", "true", "Enable VSX instructions", [FeatureAltivec]>; @@ -304,8 +311,8 @@ def : ProcessorModel<"450", PPC440Model, [Directive440, FeatureISEL, FeatureFRES, FeatureFRSQRTE, FeatureICBT, FeatureBookE, FeatureMSYNC, FeatureMFTB]>; -def : Processor<"601", G3Itineraries, [Directive601, FeatureHardFloat]>; -def : Processor<"602", G3Itineraries, [Directive602, FeatureHardFloat, +def : Processor<"601", G3Itineraries, [Directive601, FeatureFPU]>; +def : Processor<"602", G3Itineraries, [Directive602, FeatureFPU, FeatureMFTB]>; def : Processor<"603", G3Itineraries, [Directive603, FeatureFRES, FeatureFRSQRTE, @@ -356,6 +363,10 @@ def : ProcessorModel<"g5", G5Model, FeatureFRES, FeatureFRSQRTE, Feature64Bit /*, Feature64BitRegs */, FeatureMFTB, DeprecatedDST]>; +def : ProcessorModel<"e500", PPCE500Model, + [DirectiveE500, + FeatureICBT, FeatureBookE, + FeatureISEL, FeatureMFTB]>; def : ProcessorModel<"e500mc", PPCE500mcModel, [DirectiveE500mc, FeatureSTFIWX, FeatureICBT, FeatureBookE, @@ -465,4 +476,5 @@ def PPC : Target { let AssemblyParsers = [PPCAsmParser]; let AssemblyParserVariants = [PPCAsmParserVariant]; + let AllowRegisterRenaming = 1; } diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 17451900840a..a9da64cc216f 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -510,6 +510,32 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const Module *M = MF->getFunction().getParent(); PICLevel::Level PL = M->getPICLevel(); +#ifndef NDEBUG + // Validate that SPE and FPU are mutually exclusive in codegen + if (!MI->isInlineAsm()) { + for (const MachineOperand &MO: MI->operands()) { + if (MO.isReg()) { + unsigned Reg = MO.getReg(); + if (Subtarget->hasSPE()) { + if (PPC::F4RCRegClass.contains(Reg) || + PPC::F8RCRegClass.contains(Reg) || + PPC::QBRCRegClass.contains(Reg) || + PPC::QFRCRegClass.contains(Reg) || + PPC::QSRCRegClass.contains(Reg) || + PPC::VFRCRegClass.contains(Reg) || + PPC::VRRCRegClass.contains(Reg) || + PPC::VSFRCRegClass.contains(Reg) || + PPC::VSSRCRegClass.contains(Reg) + ) + llvm_unreachable("SPE targets cannot have FPRegs!"); + } else { + if (PPC::SPERCRegClass.contains(Reg)) + llvm_unreachable("SPE register found in FPU-targeted code!"); + } + } + } + } +#endif // Lower multi-instruction pseudo operations. switch (MI->getOpcode()) { default: break; @@ -563,33 +589,63 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Transform %rd = UpdateGBR(%rt, %ri) // Into: lwz %rt, .L0$poff - .L0$pb(%ri) // add %rd, %rt, %ri + // or into (if secure plt mode is on): + // addis r30, r30, .LTOC - .L0$pb@ha + // addi r30, r30, .LTOC - .L0$pb@l // Get the offset from the GOT Base Register to the GOT LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin); - MCSymbol *PICOffset = - MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(); - TmpInst.setOpcode(PPC::LWZ); - const MCExpr *Exp = - MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); - const MCExpr *PB = - MCSymbolRefExpr::create(MF->getPICBaseSymbol(), - MCSymbolRefExpr::VK_None, - OutContext); - const MCOperand TR = TmpInst.getOperand(1); - const MCOperand PICR = TmpInst.getOperand(0); + if (Subtarget->isSecurePlt() && isPositionIndependent() ) { + unsigned PICR = TmpInst.getOperand(0).getReg(); + MCSymbol *LTOCSymbol = OutContext.getOrCreateSymbol(StringRef(".LTOC")); + const MCExpr *PB = + MCSymbolRefExpr::create(MF->getPICBaseSymbol(), + OutContext); - // Step 1: lwz %rt, .L$poff - .L$pb(%ri) - TmpInst.getOperand(1) = - MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext)); - TmpInst.getOperand(0) = TR; - TmpInst.getOperand(2) = PICR; - EmitToStreamer(*OutStreamer, TmpInst); + const MCExpr *LTOCDeltaExpr = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(LTOCSymbol, OutContext), + PB, OutContext); - TmpInst.setOpcode(PPC::ADD4); - TmpInst.getOperand(0) = PICR; - TmpInst.getOperand(1) = TR; - TmpInst.getOperand(2) = PICR; - EmitToStreamer(*OutStreamer, TmpInst); - return; + const MCExpr *LTOCDeltaHi = + PPCMCExpr::createHa(LTOCDeltaExpr, false, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS) + .addReg(PICR) + .addReg(PICR) + .addExpr(LTOCDeltaHi)); + + const MCExpr *LTOCDeltaLo = + PPCMCExpr::createLo(LTOCDeltaExpr, false, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI) + .addReg(PICR) + .addReg(PICR) + .addExpr(LTOCDeltaLo)); + return; + } else { + MCSymbol *PICOffset = + MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(); + TmpInst.setOpcode(PPC::LWZ); + const MCExpr *Exp = + MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); + const MCExpr *PB = + MCSymbolRefExpr::create(MF->getPICBaseSymbol(), + MCSymbolRefExpr::VK_None, + OutContext); + const MCOperand TR = TmpInst.getOperand(1); + const MCOperand PICR = TmpInst.getOperand(0); + + // Step 1: lwz %rt, .L$poff - .L$pb(%ri) + TmpInst.getOperand(1) = + MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext)); + TmpInst.getOperand(0) = TR; + TmpInst.getOperand(2) = PICR; + EmitToStreamer(*OutStreamer, TmpInst); + + TmpInst.setOpcode(PPC::ADD4); + TmpInst.getOperand(0) = PICR; + TmpInst.getOperand(1) = TR; + TmpInst.getOperand(2) = PICR; + EmitToStreamer(*OutStreamer, TmpInst); + return; + } } case PPC::LWZtoc: { // Transform %r3 = LWZtoc @min1, %r2 @@ -741,11 +797,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { else if (MO.isGlobal()) { const GlobalValue *GV = MO.getGlobal(); MOSymbol = getSymbol(GV); - DEBUG( - unsigned char GVFlags = Subtarget->classifyGlobalReference(GV); - assert((GVFlags & PPCII::MO_NLP_FLAG) && - "LDtocL used on symbol that could be accessed directly is " - "invalid. Must match ADDIStocHA.")); + LLVM_DEBUG( + unsigned char GVFlags = Subtarget->classifyGlobalReference(GV); + assert((GVFlags & PPCII::MO_NLP_FLAG) && + "LDtocL used on symbol that could be accessed directly is " + "invalid. Must match ADDIStocHA.")); MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); } @@ -770,11 +826,9 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { if (MO.isGlobal()) { const GlobalValue *GV = MO.getGlobal(); - DEBUG( - unsigned char GVFlags = Subtarget->classifyGlobalReference(GV); - assert ( - !(GVFlags & PPCII::MO_NLP_FLAG) && - "Interposable definitions must use indirect access.")); + LLVM_DEBUG(unsigned char GVFlags = Subtarget->classifyGlobalReference(GV); + assert(!(GVFlags & PPCII::MO_NLP_FLAG) && + "Interposable definitions must use indirect access.")); MOSymbol = getSymbol(GV); } else if (MO.isCPI()) { MOSymbol = GetCPISymbol(MO.getIndex()); @@ -1233,7 +1287,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { if (!Subtarget->isPPC64()) { const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>(); - if (PPCFI->usesPICBase()) { + if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) { MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(); MCSymbol *PICBase = MF->getPICBaseSymbol(); OutStreamer->EmitLabel(RelocSymbol); @@ -1255,7 +1309,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { if (Subtarget->isELFv2ABI()) { // In the Large code model, we allow arbitrary displacements between // the text section and its associated TOC section. We place the - // full 8-byte offset to the TOC in memory immediatedly preceding + // full 8-byte offset to the TOC in memory immediately preceding // the function global entry point. if (TM.getCodeModel() == CodeModel::Large && !MF->getRegInfo().use_empty(PPC::X2)) { @@ -1458,6 +1512,7 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { "ppc750", "ppc970", "ppcA2", + "ppce500", "ppce500mc", "ppce5500", "power3", diff --git a/lib/Target/PowerPC/PPCBranchCoalescing.cpp b/lib/Target/PowerPC/PPCBranchCoalescing.cpp index 32d801b13ded..bbb977f090c5 100644 --- a/lib/Target/PowerPC/PPCBranchCoalescing.cpp +++ b/lib/Target/PowerPC/PPCBranchCoalescing.cpp @@ -60,7 +60,7 @@ namespace llvm { /// expands to the following machine code: /// /// %bb.0: derived from LLVM BB %entry -/// Live Ins: %f1 %f3 %x6 +/// liveins: %f1 %f3 %x6 /// <SNIP1> /// %0 = COPY %f1; F8RC:%0 /// %5 = CMPLWI killed %4, 0; CRRC:%5 GPRC:%4 @@ -98,7 +98,7 @@ namespace llvm { /// If all conditions are meet, IR should collapse to: /// /// %bb.0: derived from LLVM BB %entry -/// Live Ins: %f1 %f3 %x6 +/// liveins: %f1 %f3 %x6 /// <SNIP1> /// %0 = COPY %f1; F8RC:%0 /// %5 = CMPLWI killed %4, 0; CRRC:%5 GPRC:%4 @@ -236,18 +236,18 @@ void PPCBranchCoalescing::initialize(MachineFunction &MF) { ///\return true if and only if the branch can be coalesced, false otherwise /// bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) { - DEBUG(dbgs() << "Determine if branch block " << Cand.BranchBlock->getNumber() - << " can be coalesced:"); + LLVM_DEBUG(dbgs() << "Determine if branch block " + << Cand.BranchBlock->getNumber() << " can be coalesced:"); MachineBasicBlock *FalseMBB = nullptr; if (TII->analyzeBranch(*Cand.BranchBlock, Cand.BranchTargetBlock, FalseMBB, Cand.Cond)) { - DEBUG(dbgs() << "TII unable to Analyze Branch - skip\n"); + LLVM_DEBUG(dbgs() << "TII unable to Analyze Branch - skip\n"); return false; } for (auto &I : Cand.BranchBlock->terminators()) { - DEBUG(dbgs() << "Looking at terminator : " << I << "\n"); + LLVM_DEBUG(dbgs() << "Looking at terminator : " << I << "\n"); if (!I.isBranch()) continue; @@ -265,14 +265,14 @@ bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) { // must then be extended to prove that none of the implicit operands are // changed in the blocks that are combined during coalescing. if (I.getNumOperands() != I.getNumExplicitOperands()) { - DEBUG(dbgs() << "Terminator contains implicit operands - skip : " << I - << "\n"); + LLVM_DEBUG(dbgs() << "Terminator contains implicit operands - skip : " + << I << "\n"); return false; } } if (Cand.BranchBlock->isEHPad() || Cand.BranchBlock->hasEHPadSuccessor()) { - DEBUG(dbgs() << "EH Pad - skip\n"); + LLVM_DEBUG(dbgs() << "EH Pad - skip\n"); return false; } @@ -280,13 +280,13 @@ bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) { // FalseMBB is null, and BranchTargetBlock is a successor to BranchBlock) if (!Cand.BranchTargetBlock || FalseMBB || !Cand.BranchBlock->isSuccessor(Cand.BranchTargetBlock)) { - DEBUG(dbgs() << "Does not form a triangle - skip\n"); + LLVM_DEBUG(dbgs() << "Does not form a triangle - skip\n"); return false; } // Ensure there are only two successors if (Cand.BranchBlock->succ_size() != 2) { - DEBUG(dbgs() << "Does not have 2 successors - skip\n"); + LLVM_DEBUG(dbgs() << "Does not have 2 successors - skip\n"); return false; } @@ -305,18 +305,19 @@ bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) { assert(Succ && "Expecting a valid fall-through block\n"); if (!Succ->empty()) { - DEBUG(dbgs() << "Fall-through block contains code -- skip\n"); - return false; + LLVM_DEBUG(dbgs() << "Fall-through block contains code -- skip\n"); + return false; } if (!Succ->isSuccessor(Cand.BranchTargetBlock)) { - DEBUG(dbgs() - << "Successor of fall through block is not branch taken block\n"); - return false; + LLVM_DEBUG( + dbgs() + << "Successor of fall through block is not branch taken block\n"); + return false; } Cand.FallThroughBlock = Succ; - DEBUG(dbgs() << "Valid Candidate\n"); + LLVM_DEBUG(dbgs() << "Valid Candidate\n"); return true; } @@ -331,7 +332,7 @@ bool PPCBranchCoalescing::identicalOperands( ArrayRef<MachineOperand> OpList1, ArrayRef<MachineOperand> OpList2) const { if (OpList1.size() != OpList2.size()) { - DEBUG(dbgs() << "Operand list is different size\n"); + LLVM_DEBUG(dbgs() << "Operand list is different size\n"); return false; } @@ -339,8 +340,8 @@ bool PPCBranchCoalescing::identicalOperands( const MachineOperand &Op1 = OpList1[i]; const MachineOperand &Op2 = OpList2[i]; - DEBUG(dbgs() << "Op1: " << Op1 << "\n" - << "Op2: " << Op2 << "\n"); + LLVM_DEBUG(dbgs() << "Op1: " << Op1 << "\n" + << "Op2: " << Op2 << "\n"); if (Op1.isIdenticalTo(Op2)) { // filter out instructions with physical-register uses @@ -348,10 +349,10 @@ bool PPCBranchCoalescing::identicalOperands( // If the physical register is constant then we can assume the value // has not changed between uses. && !(Op1.isUse() && MRI->isConstantPhysReg(Op1.getReg()))) { - DEBUG(dbgs() << "The operands are not provably identical.\n"); + LLVM_DEBUG(dbgs() << "The operands are not provably identical.\n"); return false; } - DEBUG(dbgs() << "Op1 and Op2 are identical!\n"); + LLVM_DEBUG(dbgs() << "Op1 and Op2 are identical!\n"); continue; } @@ -364,14 +365,14 @@ bool PPCBranchCoalescing::identicalOperands( MachineInstr *Op1Def = MRI->getVRegDef(Op1.getReg()); MachineInstr *Op2Def = MRI->getVRegDef(Op2.getReg()); if (TII->produceSameValue(*Op1Def, *Op2Def, MRI)) { - DEBUG(dbgs() << "Op1Def: " << *Op1Def << " and " << *Op2Def - << " produce the same value!\n"); + LLVM_DEBUG(dbgs() << "Op1Def: " << *Op1Def << " and " << *Op2Def + << " produce the same value!\n"); } else { - DEBUG(dbgs() << "Operands produce different values\n"); + LLVM_DEBUG(dbgs() << "Operands produce different values\n"); return false; } } else { - DEBUG(dbgs() << "The operands are not provably identical.\n"); + LLVM_DEBUG(dbgs() << "The operands are not provably identical.\n"); return false; } } @@ -395,7 +396,7 @@ void PPCBranchCoalescing::moveAndUpdatePHIs(MachineBasicBlock *SourceMBB, MachineBasicBlock::iterator ME = SourceMBB->getFirstNonPHI(); if (MI == ME) { - DEBUG(dbgs() << "SourceMBB contains no PHI instructions.\n"); + LLVM_DEBUG(dbgs() << "SourceMBB contains no PHI instructions.\n"); return; } @@ -425,19 +426,19 @@ bool PPCBranchCoalescing::canMoveToBeginning(const MachineInstr &MI, const MachineBasicBlock &TargetMBB ) const { - DEBUG(dbgs() << "Checking if " << MI << " can move to beginning of " - << TargetMBB.getNumber() << "\n"); + LLVM_DEBUG(dbgs() << "Checking if " << MI << " can move to beginning of " + << TargetMBB.getNumber() << "\n"); for (auto &Def : MI.defs()) { // Looking at Def for (auto &Use : MRI->use_instructions(Def.getReg())) { if (Use.isPHI() && Use.getParent() == &TargetMBB) { - DEBUG(dbgs() << " *** used in a PHI -- cannot move ***\n"); - return false; + LLVM_DEBUG(dbgs() << " *** used in a PHI -- cannot move ***\n"); + return false; } } } - DEBUG(dbgs() << " Safe to move to the beginning.\n"); + LLVM_DEBUG(dbgs() << " Safe to move to the beginning.\n"); return true; } @@ -456,22 +457,23 @@ bool PPCBranchCoalescing::canMoveToEnd(const MachineInstr &MI, const MachineBasicBlock &TargetMBB ) const { - DEBUG(dbgs() << "Checking if " << MI << " can move to end of " - << TargetMBB.getNumber() << "\n"); + LLVM_DEBUG(dbgs() << "Checking if " << MI << " can move to end of " + << TargetMBB.getNumber() << "\n"); for (auto &Use : MI.uses()) { if (Use.isReg() && TargetRegisterInfo::isVirtualRegister(Use.getReg())) { MachineInstr *DefInst = MRI->getVRegDef(Use.getReg()); if (DefInst->isPHI() && DefInst->getParent() == MI.getParent()) { - DEBUG(dbgs() << " *** Cannot move this instruction ***\n"); + LLVM_DEBUG(dbgs() << " *** Cannot move this instruction ***\n"); return false; } else { - DEBUG(dbgs() << " *** def is in another block -- safe to move!\n"); + LLVM_DEBUG( + dbgs() << " *** def is in another block -- safe to move!\n"); } } } - DEBUG(dbgs() << " Safe to move to the end.\n"); + LLVM_DEBUG(dbgs() << " Safe to move to the end.\n"); return true; } @@ -541,15 +543,17 @@ bool PPCBranchCoalescing::canMerge(CoalescingCandidateInfo &SourceRegion, for (auto &Def : I->defs()) for (auto &Use : MRI->use_instructions(Def.getReg())) { if (Use.isPHI() && Use.getParent() == SourceRegion.BranchTargetBlock) { - DEBUG(dbgs() << "PHI " << *I << " defines register used in another " - "PHI within branch target block -- can't merge\n"); + LLVM_DEBUG(dbgs() + << "PHI " << *I + << " defines register used in another " + "PHI within branch target block -- can't merge\n"); NumPHINotMoved++; return false; } if (Use.getParent() == SourceRegion.BranchBlock) { - DEBUG(dbgs() << "PHI " << *I - << " defines register used in this " - "block -- all must move down\n"); + LLVM_DEBUG(dbgs() << "PHI " << *I + << " defines register used in this " + "block -- all must move down\n"); SourceRegion.MustMoveDown = true; } } @@ -562,13 +566,13 @@ bool PPCBranchCoalescing::canMerge(CoalescingCandidateInfo &SourceRegion, E = SourceRegion.BranchBlock->end(); I != E; ++I) { if (!canMoveToBeginning(*I, *SourceRegion.BranchTargetBlock)) { - DEBUG(dbgs() << "Instruction " << *I - << " cannot move down - must move up!\n"); + LLVM_DEBUG(dbgs() << "Instruction " << *I + << " cannot move down - must move up!\n"); SourceRegion.MustMoveUp = true; } if (!canMoveToEnd(*I, *TargetRegion.BranchBlock)) { - DEBUG(dbgs() << "Instruction " << *I - << " cannot move up - must move down!\n"); + LLVM_DEBUG(dbgs() << "Instruction " << *I + << " cannot move up - must move down!\n"); SourceRegion.MustMoveDown = true; } } @@ -719,10 +723,10 @@ bool PPCBranchCoalescing::runOnMachineFunction(MachineFunction &MF) { bool didSomething = false; - DEBUG(dbgs() << "******** Branch Coalescing ********\n"); + LLVM_DEBUG(dbgs() << "******** Branch Coalescing ********\n"); initialize(MF); - DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n"); CoalescingCandidateInfo Cand1, Cand2; // Walk over blocks and find candidates to merge @@ -752,24 +756,27 @@ bool PPCBranchCoalescing::runOnMachineFunction(MachineFunction &MF) { "Branch-taken block should post-dominate first candidate"); if (!identicalOperands(Cand1.Cond, Cand2.Cond)) { - DEBUG(dbgs() << "Blocks " << Cand1.BranchBlock->getNumber() << " and " - << Cand2.BranchBlock->getNumber() - << " have different branches\n"); + LLVM_DEBUG(dbgs() << "Blocks " << Cand1.BranchBlock->getNumber() + << " and " << Cand2.BranchBlock->getNumber() + << " have different branches\n"); break; } if (!canMerge(Cand2, Cand1)) { - DEBUG(dbgs() << "Cannot merge blocks " << Cand1.BranchBlock->getNumber() - << " and " << Cand2.BranchBlock->getNumber() << "\n"); + LLVM_DEBUG(dbgs() << "Cannot merge blocks " + << Cand1.BranchBlock->getNumber() << " and " + << Cand2.BranchBlock->getNumber() << "\n"); NumBlocksNotCoalesced++; continue; } - DEBUG(dbgs() << "Merging blocks " << Cand1.BranchBlock->getNumber() - << " and " << Cand1.BranchTargetBlock->getNumber() << "\n"); + LLVM_DEBUG(dbgs() << "Merging blocks " << Cand1.BranchBlock->getNumber() + << " and " << Cand1.BranchTargetBlock->getNumber() + << "\n"); MergedCandidates = mergeCandidates(Cand2, Cand1); if (MergedCandidates) didSomething = true; - DEBUG(dbgs() << "Function after merging: "; MF.dump(); dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "Function after merging: "; MF.dump(); + dbgs() << "\n"); } while (MergedCandidates); } @@ -779,6 +786,6 @@ bool PPCBranchCoalescing::runOnMachineFunction(MachineFunction &MF) { MF.verify(nullptr, "Error in code produced by branch coalescing"); #endif // NDEBUG - DEBUG(dbgs() << "Finished Branch Coalescing\n"); + LLVM_DEBUG(dbgs() << "Finished Branch Coalescing\n"); return didSomething; } diff --git a/lib/Target/PowerPC/PPCCTRLoops.cpp b/lib/Target/PowerPC/PPCCTRLoops.cpp index fc638829378a..6b9e2383e36f 100644 --- a/lib/Target/PowerPC/PPCCTRLoops.cpp +++ b/lib/Target/PowerPC/PPCCTRLoops.cpp @@ -30,11 +30,14 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/CFG.h" #include "llvm/Analysis/CodeMetrics.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopIterator.h" #include "llvm/Analysis/ScalarEvolutionExpander.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/CodeGen/TargetSchedule.h" #include "llvm/IR/Constants.h" @@ -50,8 +53,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/LoopUtils.h" #ifndef NDEBUG @@ -403,15 +406,16 @@ bool PPCCTRLoops::mightUseCTR(BasicBlock *BB) { } if (Opcode) { - MVT VTy = TLI->getSimpleValueType( - *DL, CI->getArgOperand(0)->getType(), true); - if (VTy == MVT::Other) + EVT EVTy = + TLI->getValueType(*DL, CI->getArgOperand(0)->getType(), true); + + if (EVTy == MVT::Other) return true; - if (TLI->isOperationLegalOrCustom(Opcode, VTy)) + if (TLI->isOperationLegalOrCustom(Opcode, EVTy)) continue; - else if (VTy.isVector() && - TLI->isOperationLegalOrCustom(Opcode, VTy.getScalarType())) + else if (EVTy.isVector() && + TLI->isOperationLegalOrCustom(Opcode, EVTy.getScalarType())) continue; return true; @@ -454,13 +458,16 @@ bool PPCCTRLoops::mightUseCTR(BasicBlock *BB) { return true; } + // FREM is always a call. + if (J->getOpcode() == Instruction::FRem) + return true; + if (STI->useSoftFloat()) { switch(J->getOpcode()) { case Instruction::FAdd: case Instruction::FSub: case Instruction::FMul: case Instruction::FDiv: - case Instruction::FRem: case Instruction::FPTrunc: case Instruction::FPExt: case Instruction::FPToUI: @@ -500,13 +507,19 @@ bool PPCCTRLoops::convertToCTRLoop(Loop *L) { // Process nested loops first. for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) { MadeChange |= convertToCTRLoop(*I); - DEBUG(dbgs() << "Nested loop converted\n"); + LLVM_DEBUG(dbgs() << "Nested loop converted\n"); } // If a nested loop has been converted, then we can't convert this loop. if (MadeChange) return MadeChange; + // Bail out if the loop has irreducible control flow. + LoopBlocksRPO RPOT(L); + RPOT.perform(LI); + if (containsIrreducibleCFG<const BasicBlock *>(RPOT, *LI)) + return false; + #ifndef NDEBUG // Stop trying after reaching the limit (if any). int Limit = CTRLoopLimit; @@ -527,14 +540,35 @@ bool PPCCTRLoops::convertToCTRLoop(Loop *L) { SmallVector<BasicBlock*, 4> ExitingBlocks; L->getExitingBlocks(ExitingBlocks); + // If there is an exit edge known to be frequently taken, + // we should not transform this loop. + for (auto &BB : ExitingBlocks) { + Instruction *TI = BB->getTerminator(); + if (!TI) continue; + + if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { + uint64_t TrueWeight = 0, FalseWeight = 0; + if (!BI->isConditional() || + !BI->extractProfMetadata(TrueWeight, FalseWeight)) + continue; + + // If the exit path is more frequent than the loop path, + // we return here without further analysis for this loop. + bool TrueIsExit = !L->contains(BI->getSuccessor(0)); + if (( TrueIsExit && FalseWeight < TrueWeight) || + (!TrueIsExit && FalseWeight > TrueWeight)) + return MadeChange; + } + } + BasicBlock *CountedExitBlock = nullptr; const SCEV *ExitCount = nullptr; BranchInst *CountedExitBranch = nullptr; for (SmallVectorImpl<BasicBlock *>::iterator I = ExitingBlocks.begin(), IE = ExitingBlocks.end(); I != IE; ++I) { const SCEV *EC = SE->getExitCount(L, *I); - DEBUG(dbgs() << "Exit Count for " << *L << " from block " << - (*I)->getName() << ": " << *EC << "\n"); + LLVM_DEBUG(dbgs() << "Exit Count for " << *L << " from block " + << (*I)->getName() << ": " << *EC << "\n"); if (isa<SCEVCouldNotCompute>(EC)) continue; if (const SCEVConstant *ConstEC = dyn_cast<SCEVConstant>(EC)) { @@ -546,9 +580,15 @@ bool PPCCTRLoops::convertToCTRLoop(Loop *L) { if (SE->getTypeSizeInBits(EC->getType()) > (TM->isPPC64() ? 64 : 32)) continue; + // If this exiting block is contained in a nested loop, it is not eligible + // for insertion of the branch-and-decrement since the inner loop would + // end up messing up the value in the CTR. + if (LI->getLoopFor(*I) != L) + continue; + // We now have a loop-invariant count of loop iterations (which is not the // constant zero) for which we know that this loop will not exit via this - // exisiting block. + // existing block. // We need to make sure that this block will run on every loop iteration. // For this to be true, we must dominate all blocks with backedges. Such @@ -602,7 +642,8 @@ bool PPCCTRLoops::convertToCTRLoop(Loop *L) { if (!Preheader) return MadeChange; - DEBUG(dbgs() << "Preheader for exit count: " << Preheader->getName() << "\n"); + LLVM_DEBUG(dbgs() << "Preheader for exit count: " << Preheader->getName() + << "\n"); // Insert the count into the preheader and replace the condition used by the // selected branch. @@ -690,11 +731,12 @@ check_block: } if (I != BI && clobbersCTR(*I)) { - DEBUG(dbgs() << printMBBReference(*MBB) << " (" << MBB->getFullName() - << ") instruction " << *I << " clobbers CTR, invalidating " - << printMBBReference(*BI->getParent()) << " (" - << BI->getParent()->getFullName() << ") instruction " << *BI - << "\n"); + LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " (" << MBB->getFullName() + << ") instruction " << *I + << " clobbers CTR, invalidating " + << printMBBReference(*BI->getParent()) << " (" + << BI->getParent()->getFullName() << ") instruction " + << *BI << "\n"); return false; } @@ -708,10 +750,10 @@ check_block: if (CheckPreds) { queue_preds: if (MachineFunction::iterator(MBB) == MBB->getParent()->begin()) { - DEBUG(dbgs() << "Unable to find a MTCTR instruction for " - << printMBBReference(*BI->getParent()) << " (" - << BI->getParent()->getFullName() << ") instruction " << *BI - << "\n"); + LLVM_DEBUG(dbgs() << "Unable to find a MTCTR instruction for " + << printMBBReference(*BI->getParent()) << " (" + << BI->getParent()->getFullName() << ") instruction " + << *BI << "\n"); return false; } diff --git a/lib/Target/PowerPC/PPCCallingConv.td b/lib/Target/PowerPC/PPCCallingConv.td index a4f4c8688cc1..12c581023234 100644 --- a/lib/Target/PowerPC/PPCCallingConv.td +++ b/lib/Target/PowerPC/PPCCallingConv.td @@ -45,6 +45,30 @@ def RetCC_PPC64_AnyReg : CallingConv<[ CCCustom<"CC_PPC_AnyReg_Error"> ]>; +// Return-value convention for PowerPC coldcc. +def RetCC_PPC_Cold : CallingConv<[ + // Use the same return registers as RetCC_PPC, but limited to only + // one return value. The remaining return values will be saved to + // the stack. + CCIfType<[i32, i1], CCIfSubtarget<"isPPC64()", CCPromoteToType<i64>>>, + CCIfType<[i1], CCIfNotSubtarget<"isPPC64()", CCPromoteToType<i32>>>, + + CCIfType<[i32], CCAssignToReg<[R3]>>, + CCIfType<[i64], CCAssignToReg<[X3]>>, + CCIfType<[i128], CCAssignToReg<[X3]>>, + + CCIfType<[f32], CCAssignToReg<[F1]>>, + CCIfType<[f64], CCAssignToReg<[F1]>>, + CCIfType<[f128], CCIfSubtarget<"hasP9Vector()", CCAssignToReg<[V2]>>>, + + CCIfType<[v4f64, v4f32, v4i1], + CCIfSubtarget<"hasQPX()", CCAssignToReg<[QF1]>>>, + + CCIfType<[v16i8, v8i16, v4i32, v2i64, v1i128, v4f32, v2f64], + CCIfSubtarget<"hasAltivec()", + CCAssignToReg<[V2]>>> +]>; + // Return-value convention for PowerPC def RetCC_PPC : CallingConv<[ CCIfCC<"CallingConv::AnyReg", CCDelegateTo<RetCC_PPC64_AnyReg>>, @@ -59,8 +83,19 @@ def RetCC_PPC : CallingConv<[ // Floating point types returned as "direct" go into F1 .. F8; note that // only the ELFv2 ABI fully utilizes all these registers. - CCIfType<[f32], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>, - CCIfType<[f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>, + CCIfNotSubtarget<"hasSPE()", + CCIfType<[f32], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>>, + CCIfNotSubtarget<"hasSPE()", + CCIfType<[f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>>, + CCIfSubtarget<"hasSPE()", + CCIfType<[f32], CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>>, + CCIfSubtarget<"hasSPE()", + CCIfType<[f64], CCAssignToReg<[S3, S4, S5, S6, S7, S8, S9, S10]>>>, + + // For P9, f128 are passed in vector registers. + CCIfType<[f128], + CCIfSubtarget<"hasP9Vector()", + CCAssignToReg<[V2, V3, V4, V5, V6, V7, V8, V9]>>>, // QPX vectors are returned in QF1 and QF2. CCIfType<[v4f64, v4f32, v4i1], @@ -117,6 +152,9 @@ def RetCC_PPC64_ELF_FIS : CallingConv<[ CCIfType<[i128], CCAssignToReg<[X3, X4, X5, X6]>>, CCIfType<[f32], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>, CCIfType<[f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>, + CCIfType<[f128], + CCIfSubtarget<"hasP9Vector()", + CCAssignToReg<[V2, V3, V4, V5, V6, V7, V8, V9]>>>, CCIfType<[v4f64, v4f32, v4i1], CCIfSubtarget<"hasQPX()", CCAssignToReg<[QF1, QF2]>>>, CCIfType<[v16i8, v8i16, v4i32, v2i64, v1i128, v4f32, v2f64], @@ -156,7 +194,15 @@ def CC_PPC32_SVR4_Common : CallingConv<[ CCIfType<[f64], CCIfSplit<CCCustom<"CC_PPC32_SVR4_Custom_AlignFPArgRegs">>>, // FP values are passed in F1 - F8. - CCIfType<[f32, f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>, + CCIfType<[f32, f64], + CCIfNotSubtarget<"hasSPE()", + CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>>, + CCIfType<[f64], + CCIfSubtarget<"hasSPE()", + CCAssignToReg<[S3, S4, S5, S6, S7, S8, S9, S10]>>>, + CCIfType<[f32], + CCIfSubtarget<"hasSPE()", + CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>>, // Split arguments have an alignment of 8 bytes on the stack. CCIfType<[i32], CCIfSplit<CCAssignToStack<4, 8>>>, @@ -165,13 +211,18 @@ def CC_PPC32_SVR4_Common : CallingConv<[ // Floats are stored in double precision format, thus they have the same // alignment and size as doubles. - CCIfType<[f32,f64], CCAssignToStack<8, 8>>, + // With SPE floats are stored as single precision, so have alignment and + // size of int. + CCIfType<[f32,f64], CCIfNotSubtarget<"hasSPE()", CCAssignToStack<8, 8>>>, + CCIfType<[f32], CCIfSubtarget<"hasSPE()", CCAssignToStack<4, 4>>>, + CCIfType<[f64], CCIfSubtarget<"hasSPE()", CCAssignToStack<8, 8>>>, // QPX vectors that are stored in double precision need 32-byte alignment. CCIfType<[v4f64, v4i1], CCAssignToStack<32, 32>>, - // Vectors get 16-byte stack slots that are 16-byte aligned. - CCIfType<[v16i8, v8i16, v4i32, v4f32, v2f64, v2i64], CCAssignToStack<16, 16>> + // Vectors and float128 get 16-byte stack slots that are 16-byte aligned. + CCIfType<[v16i8, v8i16, v4i32, v4f32, v2f64, v2i64], CCAssignToStack<16, 16>>, + CCIfType<[f128], CCIfSubtarget<"hasP9Vector()", CCAssignToStack<16, 16>>> ]>; // This calling convention puts vector arguments always on the stack. It is used @@ -192,6 +243,11 @@ def CC_PPC32_SVR4 : CallingConv<[ CCIfType<[v16i8, v8i16, v4i32, v2i64, v1i128, v4f32, v2f64], CCIfSubtarget<"hasAltivec()", CCAssignToReg<[V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13]>>>, + + // Float128 types treated as vector arguments. + CCIfType<[f128], + CCIfSubtarget<"hasP9Vector()", CCAssignToReg<[V2, V3, V4, V5, V6, V7, + V8, V9, V10, V11, V12, V13]>>>, CCDelegateTo<CC_PPC32_SVR4_Common> ]>; @@ -227,15 +283,23 @@ def CSR_Darwin32 : CalleeSavedRegs<(add R13, R14, R15, R16, R17, R18, R19, R20, def CSR_Darwin32_Altivec : CalleeSavedRegs<(add CSR_Darwin32, CSR_Altivec)>; -def CSR_SVR432 : CalleeSavedRegs<(add R14, R15, R16, R17, R18, R19, R20, - R21, R22, R23, R24, R25, R26, R27, R28, - R29, R30, R31, F14, F15, F16, F17, F18, +// SPE does not use FPRs, so break out the common register set as base. +def CSR_SVR432_COMM : CalleeSavedRegs<(add R14, R15, R16, R17, R18, R19, R20, + R21, R22, R23, R24, R25, R26, R27, + R28, R29, R30, R31, CR2, CR3, CR4 + )>; +def CSR_SVR432 : CalleeSavedRegs<(add CSR_SVR432_COMM, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, - F27, F28, F29, F30, F31, CR2, CR3, CR4 + F27, F28, F29, F30, F31 )>; +def CSR_SPE : CalleeSavedRegs<(add S14, S15, S16, S17, S18, S19, S20, S21, S22, + S23, S24, S25, S26, S27, S28, S29, S30, S31 + )>; def CSR_SVR432_Altivec : CalleeSavedRegs<(add CSR_SVR432, CSR_Altivec)>; +def CSR_SVR432_SPE : CalleeSavedRegs<(add CSR_SVR432_COMM, CSR_SPE)>; + def CSR_Darwin64 : CalleeSavedRegs<(add X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, F14, F15, F16, F17, F18, @@ -271,6 +335,36 @@ def CSR_SVR464_R2_Altivec_ViaCopy : CalleeSavedRegs<(add CSR_SVR464_R2_Altivec)> def CSR_NoRegs : CalleeSavedRegs<(add)>; +// coldcc calling convection marks most registers as non-volatile. +// Do not include r1 since the stack pointer is never considered a CSR. +// Do not include r2, since it is the TOC register and is added depending +// on wether or not the function uses the TOC and is a non-leaf. +// Do not include r0,r11,r13 as they are optional in functional linkage +// and value may be altered by inter-library calls. +// Do not include r12 as it is used as a scratch register. +// Do not include return registers r3, f1, v2. +def CSR_SVR32_ColdCC : CalleeSavedRegs<(add (sequence "R%u", 4, 10), + (sequence "R%u", 14, 31), + F0, (sequence "F%u", 2, 31), + (sequence "CR%u", 0, 7))>; + +def CSR_SVR32_ColdCC_Altivec : CalleeSavedRegs<(add CSR_SVR32_ColdCC, + (sequence "V%u", 0, 1), + (sequence "V%u", 3, 31))>; + +def CSR_SVR64_ColdCC : CalleeSavedRegs<(add (sequence "X%u", 4, 10), + (sequence "X%u", 14, 31), + F0, (sequence "F%u", 2, 31), + (sequence "CR%u", 0, 7))>; + +def CSR_SVR64_ColdCC_R2: CalleeSavedRegs<(add CSR_SVR64_ColdCC, X2)>; + +def CSR_SVR64_ColdCC_Altivec : CalleeSavedRegs<(add CSR_SVR64_ColdCC, + (sequence "V%u", 0, 1), + (sequence "V%u", 3, 31))>; + +def CSR_SVR64_ColdCC_R2_Altivec : CalleeSavedRegs<(add CSR_SVR64_ColdCC_Altivec, X2)>; + def CSR_64_AllRegs: CalleeSavedRegs<(add X0, (sequence "X%u", 3, 10), (sequence "X%u", 14, 31), (sequence "F%u", 0, 31), diff --git a/lib/Target/PowerPC/PPCEarlyReturn.cpp b/lib/Target/PowerPC/PPCEarlyReturn.cpp index 1699463c0a4b..ed5e496b32fd 100644 --- a/lib/Target/PowerPC/PPCEarlyReturn.cpp +++ b/lib/Target/PowerPC/PPCEarlyReturn.cpp @@ -128,7 +128,7 @@ protected: if (J->getOperand(i).isMBB() && J->getOperand(i).getMBB() == &ReturnMBB) OtherReference = true; - } else if (!J->isTerminator() && !J->isDebugValue()) + } else if (!J->isTerminator() && !J->isDebugInstr()) break; if (J == (*PI)->begin()) diff --git a/lib/Target/PowerPC/PPCExpandISEL.cpp b/lib/Target/PowerPC/PPCExpandISEL.cpp index b00e98b63e34..fe41e1b36a5d 100644 --- a/lib/Target/PowerPC/PPCExpandISEL.cpp +++ b/lib/Target/PowerPC/PPCExpandISEL.cpp @@ -117,7 +117,7 @@ public: /// instruction is still generated by default on targets that support them. /// /// \return true if ISEL should be expanded into if-then-else code sequence; - /// false if ISEL instruction should be generated, i.e. not expaned. + /// false if ISEL instruction should be generated, i.e. not expanded. /// static bool isExpandISELEnabled(const MachineFunction &MF); @@ -126,11 +126,11 @@ public: #endif bool runOnMachineFunction(MachineFunction &MF) override { - DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n"); initialize(MF); if (!collectISELInstructions()) { - DEBUG(dbgs() << "No ISEL instructions in this function\n"); + LLVM_DEBUG(dbgs() << "No ISEL instructions in this function\n"); return false; } @@ -170,9 +170,10 @@ bool PPCExpandISEL::collectISELInstructions() { #ifndef NDEBUG void PPCExpandISEL::DumpISELInstructions() const { for (const auto &I : ISELInstructions) { - DEBUG(dbgs() << printMBBReference(*MF->getBlockNumbered(I.first)) << ":\n"); + LLVM_DEBUG(dbgs() << printMBBReference(*MF->getBlockNumbered(I.first)) + << ":\n"); for (const auto &VI : I.second) - DEBUG(dbgs() << " "; VI->print(dbgs())); + LLVM_DEBUG(dbgs() << " "; VI->print(dbgs())); } } #endif @@ -192,9 +193,10 @@ void PPCExpandISEL::expandAndMergeISELs() { bool ExpandISELEnabled = isExpandISELEnabled(*MF); for (auto &BlockList : ISELInstructions) { - DEBUG(dbgs() << "Expanding ISEL instructions in " - << printMBBReference(*MF->getBlockNumbered(BlockList.first)) - << "\n"); + LLVM_DEBUG( + dbgs() << "Expanding ISEL instructions in " + << printMBBReference(*MF->getBlockNumbered(BlockList.first)) + << "\n"); BlockISELList &CurrentISELList = BlockList.second; auto I = CurrentISELList.begin(); auto E = CurrentISELList.end(); @@ -210,7 +212,8 @@ void PPCExpandISEL::expandAndMergeISELs() { // as it would be ISEL %R0, %ZERO, %R0, %CRN. if (useSameRegister(Dest, TrueValue) && useSameRegister(Dest, FalseValue)) { - DEBUG(dbgs() << "Remove redudant ISEL instruction: " << **I << "\n"); + LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction: " << **I + << "\n"); // FIXME: if the CR field used has no other uses, we could eliminate the // instruction that defines it. This would have to be done manually // since this pass runs too late to run DCE after it. @@ -223,8 +226,9 @@ void PPCExpandISEL::expandAndMergeISELs() { // condition as it would be ISEL %RX, %ZERO, %R0, %CRN, which makes it // safe to fold ISEL to MR(OR) instead of ADDI. MachineBasicBlock *MBB = (*I)->getParent(); - DEBUG(dbgs() << "Fold the ISEL instruction to an unconditonal copy:\n"); - DEBUG(dbgs() << "ISEL: " << **I << "\n"); + LLVM_DEBUG( + dbgs() << "Fold the ISEL instruction to an unconditional copy:\n"); + LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n"); NumFolded++; // Note: we're using both the TrueValue and FalseValue operands so as // not to lose the kill flag if it is set on either of them. @@ -235,8 +239,8 @@ void PPCExpandISEL::expandAndMergeISELs() { (*I)->eraseFromParent(); I++; } else if (ExpandISELEnabled) { // Normal cases expansion enabled - DEBUG(dbgs() << "Expand ISEL instructions:\n"); - DEBUG(dbgs() << "ISEL: " << **I << "\n"); + LLVM_DEBUG(dbgs() << "Expand ISEL instructions:\n"); + LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n"); BlockISELList SubISELList; SubISELList.push_back(*I++); // Collect the ISELs that can be merged together. @@ -244,7 +248,7 @@ void PPCExpandISEL::expandAndMergeISELs() { // may be redundant or foldable to a register copy. So we still keep // the handleSpecialCases() downstream to handle them. while (I != E && canMerge(SubISELList.back(), *I)) { - DEBUG(dbgs() << "ISEL: " << **I << "\n"); + LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n"); SubISELList.push_back(*I++); } @@ -264,7 +268,7 @@ void PPCExpandISEL::handleSpecialCases(BlockISELList &BIL, auto MI = BIL.begin(); while (MI != BIL.end()) { assert(isISEL(**MI) && "Expecting an ISEL instruction"); - DEBUG(dbgs() << "ISEL: " << **MI << "\n"); + LLVM_DEBUG(dbgs() << "ISEL: " << **MI << "\n"); MachineOperand &Dest = (*MI)->getOperand(0); MachineOperand &TrueValue = (*MI)->getOperand(1); @@ -281,7 +285,7 @@ void PPCExpandISEL::handleSpecialCases(BlockISELList &BIL, // Special case 1, all registers used by ISEL are the same one. if (!IsADDIInstRequired && !IsORIInstRequired) { - DEBUG(dbgs() << "Remove redudant ISEL instruction."); + LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction."); // FIXME: if the CR field used has no other uses, we could eliminate the // instruction that defines it. This would have to be done manually // since this pass runs too late to run DCE after it. @@ -300,7 +304,8 @@ void PPCExpandISEL::handleSpecialCases(BlockISELList &BIL, // be zero. In this case, the useSameRegister method will return false, // thereby preventing this ISEL from being folded. if (useSameRegister(TrueValue, FalseValue) && (BIL.size() == 1)) { - DEBUG(dbgs() << "Fold the ISEL instruction to an unconditonal copy."); + LLVM_DEBUG( + dbgs() << "Fold the ISEL instruction to an unconditional copy."); NumFolded++; // Note: we're using both the TrueValue and FalseValue operands so as // not to lose the kill flag if it is set on either of them. @@ -439,11 +444,10 @@ void PPCExpandISEL::populateBlocks(BlockISELList &BIL) { // condition is false MachineOperand &ConditionRegister = MI->getOperand(3); // Condition - DEBUG(dbgs() << "Dest: " << Dest << "\n"); - DEBUG(dbgs() << "TrueValue: " << TrueValue << "\n"); - DEBUG(dbgs() << "FalseValue: " << FalseValue << "\n"); - DEBUG(dbgs() << "ConditionRegister: " << ConditionRegister << "\n"); - + LLVM_DEBUG(dbgs() << "Dest: " << Dest << "\n"); + LLVM_DEBUG(dbgs() << "TrueValue: " << TrueValue << "\n"); + LLVM_DEBUG(dbgs() << "FalseValue: " << FalseValue << "\n"); + LLVM_DEBUG(dbgs() << "ConditionRegister: " << ConditionRegister << "\n"); // If the Dest Register and True Value Register are not the same one, we // need the True Block. diff --git a/lib/Target/PowerPC/PPCFastISel.cpp b/lib/Target/PowerPC/PPCFastISel.cpp index 402e29cdff72..b00655b50229 100644 --- a/lib/Target/PowerPC/PPCFastISel.cpp +++ b/lib/Target/PowerPC/PPCFastISel.cpp @@ -153,7 +153,8 @@ class PPCFastISel final : public FastISel { return RC->getID() == PPC::VSSRCRegClassID; } bool PPCEmitCmp(const Value *Src1Value, const Value *Src2Value, - bool isZExt, unsigned DestReg); + bool isZExt, unsigned DestReg, + const PPC::Predicate Pred); bool PPCEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, const TargetRegisterClass *RC, bool IsZExt = true, unsigned FP64LoadOpc = PPC::LFD); @@ -206,6 +207,8 @@ CCAssignFn *PPCFastISel::usePPC32CCs(unsigned Flag) { return CC_PPC32_SVR4_ByVal; else if (Flag == 3) return CC_PPC32_SVR4_VarArg; + else if (Flag == 4) + return RetCC_PPC_Cold; else return RetCC_PPC; } @@ -219,7 +222,7 @@ static Optional<PPC::Predicate> getComparePred(CmpInst::Predicate Pred) { // result consists of 4 bits, indicating lt, eq, gt and un (unordered), // only one of which will be set. The result is generated by fcmpu // instruction. However, bc instruction only inspects one of the first 3 - // bits, so when un is set, bc instruction may jump to to an undesired + // bits, so when un is set, bc instruction may jump to an undesired // place. // // More specifically, if we expect an unordered comparison and un is set, we @@ -464,6 +467,7 @@ bool PPCFastISel::PPCEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, bool IsZExt, unsigned FP64LoadOpc) { unsigned Opc; bool UseOffset = true; + bool HasSPE = PPCSubTarget->hasSPE(); // If ResultReg is given, it determines the register class of the load. // Otherwise, RC is the register class to use. If the result of the @@ -475,8 +479,8 @@ bool PPCFastISel::PPCEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, const TargetRegisterClass *UseRC = (ResultReg ? MRI.getRegClass(ResultReg) : (RC ? RC : - (VT == MVT::f64 ? &PPC::F8RCRegClass : - (VT == MVT::f32 ? &PPC::F4RCRegClass : + (VT == MVT::f64 ? (HasSPE ? &PPC::SPERCRegClass : &PPC::F8RCRegClass) : + (VT == MVT::f32 ? (HasSPE ? &PPC::SPE4RCRegClass : &PPC::F4RCRegClass) : (VT == MVT::i64 ? &PPC::G8RC_and_G8RC_NOX0RegClass : &PPC::GPRC_and_GPRC_NOR0RegClass))))); @@ -505,7 +509,7 @@ bool PPCFastISel::PPCEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, UseOffset = ((Addr.Offset & 3) == 0); break; case MVT::f32: - Opc = PPC::LFS; + Opc = PPCSubTarget->hasSPE() ? PPC::SPELWZ : PPC::LFS; break; case MVT::f64: Opc = FP64LoadOpc; @@ -576,6 +580,8 @@ bool PPCFastISel::PPCEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, case PPC::LD: Opc = PPC::LDX; break; case PPC::LFS: Opc = IsVSSRC ? PPC::LXSSPX : PPC::LFSX; break; case PPC::LFD: Opc = IsVSFRC ? PPC::LXSDX : PPC::LFDX; break; + case PPC::EVLDD: Opc = PPC::EVLDDX; break; + case PPC::SPELWZ: Opc = PPC::SPELWZX; break; } auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), @@ -618,7 +624,8 @@ bool PPCFastISel::SelectLoad(const Instruction *I) { AssignedReg ? MRI.getRegClass(AssignedReg) : nullptr; unsigned ResultReg = 0; - if (!PPCEmitLoad(VT, ResultReg, Addr, RC)) + if (!PPCEmitLoad(VT, ResultReg, Addr, RC, true, + PPCSubTarget->hasSPE() ? PPC::EVLDD : PPC::LFD)) return false; updateValueMap(I, ResultReg); return true; @@ -651,10 +658,10 @@ bool PPCFastISel::PPCEmitStore(MVT VT, unsigned SrcReg, Address &Addr) { UseOffset = ((Addr.Offset & 3) == 0); break; case MVT::f32: - Opc = PPC::STFS; + Opc = PPCSubTarget->hasSPE() ? PPC::SPESTW : PPC::STFS; break; case MVT::f64: - Opc = PPC::STFD; + Opc = PPCSubTarget->hasSPE() ? PPC::EVSTDD : PPC::STFD; break; } @@ -719,6 +726,8 @@ bool PPCFastISel::PPCEmitStore(MVT VT, unsigned SrcReg, Address &Addr) { case PPC::STD: Opc = PPC::STDX; break; case PPC::STFS: Opc = IsVSSRC ? PPC::STXSSPX : PPC::STFSX; break; case PPC::STFD: Opc = IsVSFRC ? PPC::STXSDX : PPC::STFDX; break; + case PPC::EVSTDD: Opc = PPC::EVSTDDX; break; + case PPC::SPESTW: Opc = PPC::SPESTWX; break; } auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) @@ -792,11 +801,12 @@ bool PPCFastISel::SelectBranch(const Instruction *I) { unsigned CondReg = createResultReg(&PPC::CRRCRegClass); if (!PPCEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned(), - CondReg)) + CondReg, PPCPred)) return false; BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::BCC)) - .addImm(PPCPred).addReg(CondReg).addMBB(TBB); + .addImm(PPCSubTarget->hasSPE() ? PPC::PRED_SPE : PPCPred) + .addReg(CondReg).addMBB(TBB); finishCondBranch(BI->getParent(), TBB, FBB); return true; } @@ -820,7 +830,8 @@ bool PPCFastISel::SelectBranch(const Instruction *I) { // Attempt to emit a compare of the two source values. Signed and unsigned // comparisons are supported. Return false if we can't handle it. bool PPCFastISel::PPCEmitCmp(const Value *SrcValue1, const Value *SrcValue2, - bool IsZExt, unsigned DestReg) { + bool IsZExt, unsigned DestReg, + const PPC::Predicate Pred) { Type *Ty = SrcValue1->getType(); EVT SrcEVT = TLI.getValueType(DL, Ty, true); if (!SrcEVT.isSimple()) @@ -836,6 +847,7 @@ bool PPCFastISel::PPCEmitCmp(const Value *SrcValue1, const Value *SrcValue2, // similar to ARM in this regard. long Imm = 0; bool UseImm = false; + const bool HasSPE = PPCSubTarget->hasSPE(); // Only 16-bit integer constants can be represented in compares for // PowerPC. Others will be materialized into a register. @@ -854,10 +866,38 @@ bool PPCFastISel::PPCEmitCmp(const Value *SrcValue1, const Value *SrcValue2, switch (SrcVT.SimpleTy) { default: return false; case MVT::f32: - CmpOpc = PPC::FCMPUS; + if (HasSPE) { + switch (Pred) { + default: return false; + case PPC::PRED_EQ: + CmpOpc = PPC::EFSCMPEQ; + break; + case PPC::PRED_LT: + CmpOpc = PPC::EFSCMPLT; + break; + case PPC::PRED_GT: + CmpOpc = PPC::EFSCMPGT; + break; + } + } else + CmpOpc = PPC::FCMPUS; break; case MVT::f64: - CmpOpc = PPC::FCMPUD; + if (HasSPE) { + switch (Pred) { + default: return false; + case PPC::PRED_EQ: + CmpOpc = PPC::EFDCMPEQ; + break; + case PPC::PRED_LT: + CmpOpc = PPC::EFDCMPLT; + break; + case PPC::PRED_GT: + CmpOpc = PPC::EFDCMPGT; + break; + } + } else + CmpOpc = PPC::FCMPUD; break; case MVT::i1: case MVT::i8: @@ -945,9 +985,19 @@ bool PPCFastISel::SelectFPTrunc(const Instruction *I) { return false; // Round the result to single precision. - unsigned DestReg = createResultReg(&PPC::F4RCRegClass); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::FRSP), DestReg) - .addReg(SrcReg); + unsigned DestReg; + + if (PPCSubTarget->hasSPE()) { + DestReg = createResultReg(&PPC::SPE4RCRegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(PPC::EFSCFD), DestReg) + .addReg(SrcReg); + } else { + DestReg = createResultReg(&PPC::F4RCRegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(PPC::FRSP), DestReg) + .addReg(SrcReg); + } updateValueMap(I, DestReg); return true; @@ -1029,6 +1079,22 @@ bool PPCFastISel::SelectIToFP(const Instruction *I, bool IsSigned) { if (SrcReg == 0) return false; + // Shortcut for SPE. Doesn't need to store/load, since it's all in the GPRs + if (PPCSubTarget->hasSPE()) { + unsigned Opc; + if (DstVT == MVT::f32) + Opc = IsSigned ? PPC::EFSCFSI : PPC::EFSCFUI; + else + Opc = IsSigned ? PPC::EFDCFSI : PPC::EFDCFUI; + + unsigned DestReg = createResultReg(&PPC::SPERCRegClass); + // Generate the convert. + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DestReg) + .addReg(SrcReg); + updateValueMap(I, DestReg); + return true; + } + // We can only lower an unsigned convert if we have the newer // floating-point conversion operations. if (!IsSigned && !PPCSubTarget->hasFPCVT()) @@ -1123,8 +1189,9 @@ bool PPCFastISel::SelectFPToI(const Instruction *I, bool IsSigned) { if (DstVT != MVT::i32 && DstVT != MVT::i64) return false; - // If we don't have FCTIDUZ and we need it, punt to SelectionDAG. - if (DstVT == MVT::i64 && !IsSigned && !PPCSubTarget->hasFPCVT()) + // If we don't have FCTIDUZ, or SPE, and we need it, punt to SelectionDAG. + if (DstVT == MVT::i64 && !IsSigned && + !PPCSubTarget->hasFPCVT() && !PPCSubTarget->hasSPE()) return false; Value *Src = I->getOperand(0); @@ -1152,23 +1219,34 @@ bool PPCFastISel::SelectFPToI(const Instruction *I, bool IsSigned) { // Determine the opcode for the conversion, which takes place // entirely within FPRs. - unsigned DestReg = createResultReg(&PPC::F8RCRegClass); + unsigned DestReg; unsigned Opc; - if (DstVT == MVT::i32) + if (PPCSubTarget->hasSPE()) { + DestReg = createResultReg(&PPC::GPRCRegClass); if (IsSigned) - Opc = PPC::FCTIWZ; + Opc = InRC == &PPC::SPE4RCRegClass ? PPC::EFSCTSIZ : PPC::EFDCTSIZ; else - Opc = PPCSubTarget->hasFPCVT() ? PPC::FCTIWUZ : PPC::FCTIDZ; - else - Opc = IsSigned ? PPC::FCTIDZ : PPC::FCTIDUZ; + Opc = InRC == &PPC::SPE4RCRegClass ? PPC::EFSCTUIZ : PPC::EFDCTUIZ; + } else { + DestReg = createResultReg(&PPC::F8RCRegClass); + if (DstVT == MVT::i32) + if (IsSigned) + Opc = PPC::FCTIWZ; + else + Opc = PPCSubTarget->hasFPCVT() ? PPC::FCTIWUZ : PPC::FCTIDZ; + else + Opc = IsSigned ? PPC::FCTIDZ : PPC::FCTIDUZ; + } // Generate the convert. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), DestReg) .addReg(SrcReg); // Now move the integer value from a float register to an integer register. - unsigned IntReg = PPCMoveToIntReg(I, DstVT, DestReg, IsSigned); + unsigned IntReg = PPCSubTarget->hasSPE() ? DestReg : + PPCMoveToIntReg(I, DstVT, DestReg, IsSigned); + if (IntReg == 0) return false; @@ -1916,8 +1994,13 @@ unsigned PPCFastISel::PPCMaterializeFP(const ConstantFP *CFP, MVT VT) { unsigned Align = DL.getPrefTypeAlignment(CFP->getType()); assert(Align > 0 && "Unexpectedly missing alignment information!"); unsigned Idx = MCP.getConstantPoolIndex(cast<Constant>(CFP), Align); - const TargetRegisterClass *RC = - (VT == MVT::f32) ? &PPC::F4RCRegClass : &PPC::F8RCRegClass; + const bool HasSPE = PPCSubTarget->hasSPE(); + const TargetRegisterClass *RC; + if (HasSPE) + RC = ((VT == MVT::f32) ? &PPC::SPE4RCRegClass : &PPC::SPERCRegClass); + else + RC = ((VT == MVT::f32) ? &PPC::F4RCRegClass : &PPC::F8RCRegClass); + unsigned DestReg = createResultReg(RC); CodeModel::Model CModel = TM.getCodeModel(); @@ -1925,7 +2008,13 @@ unsigned PPCFastISel::PPCMaterializeFP(const ConstantFP *CFP, MVT VT) { MachinePointerInfo::getConstantPool(*FuncInfo.MF), MachineMemOperand::MOLoad, (VT == MVT::f32) ? 4 : 8, Align); - unsigned Opc = (VT == MVT::f32) ? PPC::LFS : PPC::LFD; + unsigned Opc; + + if (HasSPE) + Opc = ((VT == MVT::f32) ? PPC::SPELWZ : PPC::EVLDD); + else + Opc = ((VT == MVT::f32) ? PPC::LFS : PPC::LFD); + unsigned TmpReg = createResultReg(&PPC::G8RC_and_G8RC_NOX0RegClass); PPCFuncInfo->setUsesTOCBasePtr(); @@ -2261,7 +2350,8 @@ bool PPCFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo, unsigned ResultReg = MI->getOperand(0).getReg(); - if (!PPCEmitLoad(VT, ResultReg, Addr, nullptr, IsZExt)) + if (!PPCEmitLoad(VT, ResultReg, Addr, nullptr, IsZExt, + PPCSubTarget->hasSPE() ? PPC::EVLDD : PPC::LFD)) return false; MI->eraseFromParent(); diff --git a/lib/Target/PowerPC/PPCFrameLowering.cpp b/lib/Target/PowerPC/PPCFrameLowering.cpp index 7902da20a010..f0000c5bafd7 100644 --- a/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -173,7 +173,27 @@ const PPCFrameLowering::SpillSlot *PPCFrameLowering::getCalleeSavedSpillSlots( {PPC::V23, -144}, {PPC::V22, -160}, {PPC::V21, -176}, - {PPC::V20, -192}}; + {PPC::V20, -192}, + + // SPE register save area (overlaps Vector save area). + {PPC::S31, -8}, + {PPC::S30, -16}, + {PPC::S29, -24}, + {PPC::S28, -32}, + {PPC::S27, -40}, + {PPC::S26, -48}, + {PPC::S25, -56}, + {PPC::S24, -64}, + {PPC::S23, -72}, + {PPC::S22, -80}, + {PPC::S21, -88}, + {PPC::S20, -96}, + {PPC::S19, -104}, + {PPC::S18, -112}, + {PPC::S17, -120}, + {PPC::S16, -128}, + {PPC::S15, -136}, + {PPC::S14, -144}}; static const SpillSlot Offsets64[] = { // Floating-point register save area offsets. @@ -1615,7 +1635,7 @@ void PPCFrameLowering::determineCalleeSaves(MachineFunction &MF, } // Make sure we don't explicitly spill r31, because, for example, we have - // some inline asm which explicity clobbers it, when we otherwise have a + // some inline asm which explicitly clobbers it, when we otherwise have a // frame pointer and are using r31's spill slot for the prologue/epilogue // code. Same goes for the base pointer and the PIC base register. if (needsFP(MF)) @@ -1676,7 +1696,7 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF, unsigned MinGPR = PPC::R31; unsigned MinG8R = PPC::X31; unsigned MinFPR = PPC::F31; - unsigned MinVR = PPC::V31; + unsigned MinVR = Subtarget.hasSPE() ? PPC::S31 : PPC::V31; bool HasGPSaveArea = false; bool HasG8SaveArea = false; @@ -1691,7 +1711,8 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF, for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); - if (PPC::GPRCRegClass.contains(Reg)) { + if (PPC::GPRCRegClass.contains(Reg) || + PPC::SPE4RCRegClass.contains(Reg)) { HasGPSaveArea = true; GPRegs.push_back(CSI[i]); @@ -1720,7 +1741,10 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF, ; // do nothing, as we already know whether CRs are spilled } else if (PPC::VRSAVERCRegClass.contains(Reg)) { HasVRSAVESaveArea = true; - } else if (PPC::VRRCRegClass.contains(Reg)) { + } else if (PPC::VRRCRegClass.contains(Reg) || + PPC::SPERCRegClass.contains(Reg)) { + // Altivec and SPE are mutually exclusive, but have the same stack + // alignment requirements, so overload the save area for both cases. HasVRSaveArea = true; VRegs.push_back(CSI[i]); @@ -1863,8 +1887,10 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF, LowerBound -= 4; // The VRSAVE save area is always 4 bytes long. } + // Both Altivec and SPE have the same alignment and padding requirements + // within the stack frame. if (HasVRSaveArea) { - // Insert alignment padding, we need 16-byte alignment. Note: for postive + // Insert alignment padding, we need 16-byte alignment. Note: for positive // number the alignment formula is : y = (x + (n-1)) & (~(n-1)). But since // we are using negative number here (the stack grows downward). We should // use formula : y = x & (~(n-1)). Where x is the size before aligning, n @@ -1950,7 +1976,14 @@ PPCFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, bool IsCRField = PPC::CR2 <= Reg && Reg <= PPC::CR4; // Add the callee-saved register as live-in; it's killed at the spill. - MBB.addLiveIn(Reg); + // Do not do this for callee-saved registers that are live-in to the + // function because they will already be marked live-in and this will be + // adding it for a second time. It is an error to add the same register + // to the set more than once. + const MachineRegisterInfo &MRI = MF->getRegInfo(); + bool IsLiveIn = MRI.isLiveIn(Reg); + if (!IsLiveIn) + MBB.addLiveIn(Reg); if (CRSpilled && IsCRField) { CRMIB.addReg(Reg, RegState::ImplicitKill); @@ -1980,7 +2013,10 @@ PPCFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, } } else { const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(MBB, MI, Reg, true, + // Use !IsLiveIn for the kill flag. + // We do not want to kill registers that are live in this function + // before their use because they will become undefined registers. + TII.storeRegToStackSlot(MBB, MI, Reg, !IsLiveIn, CSI[i].getFrameIdx(), RC, TRI); } } @@ -2149,6 +2185,8 @@ PPCFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, } bool PPCFrameLowering::enableShrinkWrapping(const MachineFunction &MF) const { + if (MF.getInfo<PPCFunctionInfo>()->shrinkWrapDisabled()) + return false; return (MF.getSubtarget<PPCSubtarget>().isSVR4ABI() && MF.getSubtarget<PPCSubtarget>().isPPC64()); } diff --git a/lib/Target/PowerPC/PPCFrameLowering.h b/lib/Target/PowerPC/PPCFrameLowering.h index f845d5a9ac64..01c155594c44 100644 --- a/lib/Target/PowerPC/PPCFrameLowering.h +++ b/lib/Target/PowerPC/PPCFrameLowering.h @@ -30,7 +30,7 @@ class PPCFrameLowering: public TargetFrameLowering { const unsigned BasePointerSaveOffset; /** - * \brief Find register[s] that can be used in function prologue and epilogue + * Find register[s] that can be used in function prologue and epilogue * * Find register[s] that can be use as scratch register[s] in function * prologue and epilogue to save various registers (Link Register, Base @@ -67,7 +67,7 @@ class PPCFrameLowering: public TargetFrameLowering { bool twoUniqueScratchRegsRequired(MachineBasicBlock *MBB) const; /** - * \brief Create branch instruction for PPC::TCRETURN* (tail call return) + * Create branch instruction for PPC::TCRETURN* (tail call return) * * \param[in] MBB that is terminated by PPC::TCRETURN* */ diff --git a/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/lib/Target/PowerPC/PPCHazardRecognizers.cpp index f327396370f6..551220466901 100644 --- a/lib/Target/PowerPC/PPCHazardRecognizers.cpp +++ b/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -180,9 +180,9 @@ void PPCDispatchGroupSBHazardRecognizer::EmitInstruction(SUnit *SU) { CurGroup.clear(); CurSlots = CurBranches = 0; } else { - DEBUG(dbgs() << "**** Adding to dispatch group: SU(" << - SU->NodeNum << "): "); - DEBUG(DAG->dumpNode(SU)); + LLVM_DEBUG(dbgs() << "**** Adding to dispatch group: SU(" << SU->NodeNum + << "): "); + LLVM_DEBUG(DAG->dumpNode(SU)); unsigned NSlots; bool MustBeFirst = mustComeFirst(MCID, NSlots); @@ -268,7 +268,7 @@ PPCHazardRecognizer970::PPCHazardRecognizer970(const ScheduleDAG &DAG) } void PPCHazardRecognizer970::EndDispatchGroup() { - DEBUG(errs() << "=== Start of dispatch group\n"); + LLVM_DEBUG(errs() << "=== Start of dispatch group\n"); NumIssued = 0; // Structural hazard info. @@ -330,7 +330,7 @@ getHazardType(SUnit *SU, int Stalls) { MachineInstr *MI = SU->getInstr(); - if (MI->isDebugValue()) + if (MI->isDebugInstr()) return NoHazard; unsigned Opcode = MI->getOpcode(); @@ -388,7 +388,7 @@ getHazardType(SUnit *SU, int Stalls) { void PPCHazardRecognizer970::EmitInstruction(SUnit *SU) { MachineInstr *MI = SU->getInstr(); - if (MI->isDebugValue()) + if (MI->isDebugInstr()) return; unsigned Opcode = MI->getOpcode(); diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index d3a223fe03e0..6cec664d1e66 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -32,7 +32,6 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/SelectionDAGNodes.h" @@ -53,6 +52,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -101,6 +101,11 @@ static cl::opt<bool> EnableBranchHint( cl::desc("Enable static hinting of branches on ppc"), cl::Hidden); +static cl::opt<bool> EnableTLSOpt( + "ppc-tls-opt", cl::init(true), + cl::desc("Enable tls optimization peephole"), + cl::Hidden); + enum ICmpInGPRType { ICGPR_All, ICGPR_None, ICGPR_I32, ICGPR_I64, ICGPR_NonExtIn, ICGPR_Zext, ICGPR_Sext, ICGPR_ZextI32, ICGPR_SextI32, ICGPR_ZextI64, ICGPR_SextI64 }; @@ -199,6 +204,14 @@ namespace { bool tryBitPermutation(SDNode *N); bool tryIntCompareInGPR(SDNode *N); + // tryTLSXFormLoad - Convert an ISD::LOAD fed by a PPCISD::ADD_TLS into + // an X-Form load instruction with the offset being a relocation coming from + // the PPCISD::ADD_TLS. + bool tryTLSXFormLoad(LoadSDNode *N); + // tryTLSXFormStore - Convert an ISD::STORE fed by a PPCISD::ADD_TLS into + // an X-Form store instruction with the offset being a relocation coming from + // the PPCISD::ADD_TLS. + bool tryTLSXFormStore(StoreSDNode *N); /// SelectCC - Select a comparison of the specified values with the /// specified condition code, returning the CR# of the expression. SDValue SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, @@ -314,6 +327,7 @@ private: bool isOffsetMultipleOf(SDNode *N, unsigned Val) const; void transferMemOperands(SDNode *N, SDNode *Result); + MachineSDNode *flipSignBit(const SDValue &N, SDNode **SignBit = nullptr); }; } // end anonymous namespace @@ -417,6 +431,16 @@ SDNode *PPCDAGToDAGISel::getGlobalBaseReg() { BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); } } else { + // We must ensure that this sequence is dominated by the prologue. + // FIXME: This is a bit of a big hammer since we don't get the benefits + // of shrink-wrapping whenever we emit this instruction. Considering + // this is used in any function where we emit a jump table, this may be + // a significant limitation. We should consider inserting this in the + // block where it is used and then commoning this sequence up if it + // appears in multiple places. + // Note: on ISA 3.0 cores, we can use lnia (addpcis) instead of + // MovePCtoLR8. + MF->getInfo<PPCFunctionInfo>()->setShrinkWrapDisabled(true); GlobalBaseReg = RegInfo->createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass); BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR8)); BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR8), GlobalBaseReg); @@ -494,10 +518,10 @@ static unsigned getBranchHint(unsigned PCC, FunctionLoweringInfo *FuncInfo, if (std::max(TProb, FProb) / Threshold < std::min(TProb, FProb)) return PPC::BR_NO_HINT; - DEBUG(dbgs() << "Use branch hint for '" << FuncInfo->Fn->getName() << "::" - << BB->getName() << "'\n" - << " -> " << TBB->getName() << ": " << TProb << "\n" - << " -> " << FBB->getName() << ": " << FProb << "\n"); + LLVM_DEBUG(dbgs() << "Use branch hint for '" << FuncInfo->Fn->getName() + << "::" << BB->getName() << "'\n" + << " -> " << TBB->getName() << ": " << TProb << "\n" + << " -> " << FBB->getName() << ": " << FProb << "\n"); const BasicBlockSDNode *BBDN = cast<BasicBlockSDNode>(DestMBB); @@ -572,6 +596,90 @@ bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask, return false; } +bool PPCDAGToDAGISel::tryTLSXFormStore(StoreSDNode *ST) { + SDValue Base = ST->getBasePtr(); + if (Base.getOpcode() != PPCISD::ADD_TLS) + return false; + SDValue Offset = ST->getOffset(); + if (!Offset.isUndef()) + return false; + + SDLoc dl(ST); + EVT MemVT = ST->getMemoryVT(); + EVT RegVT = ST->getValue().getValueType(); + + unsigned Opcode; + switch (MemVT.getSimpleVT().SimpleTy) { + default: + return false; + case MVT::i8: { + Opcode = (RegVT == MVT::i32) ? PPC::STBXTLS_32 : PPC::STBXTLS; + break; + } + case MVT::i16: { + Opcode = (RegVT == MVT::i32) ? PPC::STHXTLS_32 : PPC::STHXTLS; + break; + } + case MVT::i32: { + Opcode = (RegVT == MVT::i32) ? PPC::STWXTLS_32 : PPC::STWXTLS; + break; + } + case MVT::i64: { + Opcode = PPC::STDXTLS; + break; + } + } + SDValue Chain = ST->getChain(); + SDVTList VTs = ST->getVTList(); + SDValue Ops[] = {ST->getValue(), Base.getOperand(0), Base.getOperand(1), + Chain}; + SDNode *MN = CurDAG->getMachineNode(Opcode, dl, VTs, Ops); + transferMemOperands(ST, MN); + ReplaceNode(ST, MN); + return true; +} + +bool PPCDAGToDAGISel::tryTLSXFormLoad(LoadSDNode *LD) { + SDValue Base = LD->getBasePtr(); + if (Base.getOpcode() != PPCISD::ADD_TLS) + return false; + SDValue Offset = LD->getOffset(); + if (!Offset.isUndef()) + return false; + + SDLoc dl(LD); + EVT MemVT = LD->getMemoryVT(); + EVT RegVT = LD->getValueType(0); + unsigned Opcode; + switch (MemVT.getSimpleVT().SimpleTy) { + default: + return false; + case MVT::i8: { + Opcode = (RegVT == MVT::i32) ? PPC::LBZXTLS_32 : PPC::LBZXTLS; + break; + } + case MVT::i16: { + Opcode = (RegVT == MVT::i32) ? PPC::LHZXTLS_32 : PPC::LHZXTLS; + break; + } + case MVT::i32: { + Opcode = (RegVT == MVT::i32) ? PPC::LWZXTLS_32 : PPC::LWZXTLS; + break; + } + case MVT::i64: { + Opcode = PPC::LDXTLS; + break; + } + } + SDValue Chain = LD->getChain(); + SDVTList VTs = LD->getVTList(); + SDValue Ops[] = {Base.getOperand(0), Base.getOperand(1), Chain}; + SDNode *MN = CurDAG->getMachineNode(Opcode, dl, VTs, Ops); + transferMemOperands(LD, MN); + ReplaceNode(LD, MN); + return true; +} + /// Turn an or of two masked values into the rotate left word immediate then /// mask insert (rlwimi) instruction. bool PPCDAGToDAGISel::tryBitfieldInsert(SDNode *N) { @@ -1023,8 +1131,8 @@ class BitPermutationSelector { BitGroup(SDValue V, unsigned R, unsigned S, unsigned E) : V(V), RLAmt(R), StartIdx(S), EndIdx(E), Repl32(false), Repl32CR(false), Repl32Coalesced(false) { - DEBUG(dbgs() << "\tbit group for " << V.getNode() << " RLAmt = " << R << - " [" << S << ", " << E << "]\n"); + LLVM_DEBUG(dbgs() << "\tbit group for " << V.getNode() << " RLAmt = " << R + << " [" << S << ", " << E << "]\n"); } }; @@ -1053,6 +1161,10 @@ class BitPermutationSelector { return true; else if (NumGroups < Other.NumGroups) return false; + else if (RLAmt == 0 && Other.RLAmt != 0) + return true; + else if (RLAmt != 0 && Other.RLAmt == 0) + return false; else if (FirstGroupStartIdx < Other.FirstGroupStartIdx) return true; return false; @@ -1180,7 +1292,7 @@ class BitPermutationSelector { Bits[i] = ValueBit(ValueBit::ConstZero); return std::make_pair(Interesting, &Bits); - } + } } for (unsigned i = 0; i < NumBits; ++i) @@ -1258,7 +1370,7 @@ class BitPermutationSelector { BitGroups[BitGroups.size()-1].EndIdx == Bits.size()-1 && BitGroups[0].V == BitGroups[BitGroups.size()-1].V && BitGroups[0].RLAmt == BitGroups[BitGroups.size()-1].RLAmt) { - DEBUG(dbgs() << "\tcombining final bit group with initial one\n"); + LLVM_DEBUG(dbgs() << "\tcombining final bit group with initial one\n"); BitGroups[BitGroups.size()-1].EndIdx = BitGroups[0].EndIdx; BitGroups.erase(BitGroups.begin()); } @@ -1266,7 +1378,9 @@ class BitPermutationSelector { } // Take all (SDValue, RLAmt) pairs and sort them by the number of groups - // associated with each. If there is a degeneracy, pick the one that occurs + // associated with each. If the number of groups are same, we prefer a group + // which does not require rotate, i.e. RLAmt is 0, to avoid the first rotate + // instruction. If there is a degeneracy, pick the one that occurs // first (in the final value). void collectValueRotInfo() { ValueRots.clear(); @@ -1287,7 +1401,7 @@ class BitPermutationSelector { for (auto &I : ValueRots) { ValueRotsVec.push_back(I.second); } - std::sort(ValueRotsVec.begin(), ValueRotsVec.end()); + llvm::sort(ValueRotsVec.begin(), ValueRotsVec.end()); } // In 64-bit mode, rlwinm and friends have a rotation operator that @@ -1336,6 +1450,20 @@ class BitPermutationSelector { }; for (auto &BG : BitGroups) { + // If this bit group has RLAmt of 0 and will not be merged with + // another bit group, we don't benefit from Repl32. We don't mark + // such group to give more freedom for later instruction selection. + if (BG.RLAmt == 0) { + auto PotentiallyMerged = [this](BitGroup & BG) { + for (auto &BG2 : BitGroups) + if (&BG != &BG2 && BG.V == BG2.V && + (BG2.RLAmt == 0 || BG2.RLAmt == 32)) + return true; + return false; + }; + if (!PotentiallyMerged(BG)) + continue; + } if (BG.StartIdx < 32 && BG.EndIdx < 32) { if (IsAllLow32(BG)) { if (BG.RLAmt >= 32) { @@ -1345,9 +1473,9 @@ class BitPermutationSelector { BG.Repl32 = true; - DEBUG(dbgs() << "\t32-bit replicated bit group for " << - BG.V.getNode() << " RLAmt = " << BG.RLAmt << - " [" << BG.StartIdx << ", " << BG.EndIdx << "]\n"); + LLVM_DEBUG(dbgs() << "\t32-bit replicated bit group for " + << BG.V.getNode() << " RLAmt = " << BG.RLAmt << " [" + << BG.StartIdx << ", " << BG.EndIdx << "]\n"); } } } @@ -1361,11 +1489,11 @@ class BitPermutationSelector { if (I->Repl32 && IP->Repl32 && I->V == IP->V && I->RLAmt == IP->RLAmt && I->StartIdx == (IP->EndIdx + 1) % 64 && I != IP) { - DEBUG(dbgs() << "\tcombining 32-bit replicated bit group for " << - I->V.getNode() << " RLAmt = " << I->RLAmt << - " [" << I->StartIdx << ", " << I->EndIdx << - "] with group with range [" << - IP->StartIdx << ", " << IP->EndIdx << "]\n"); + LLVM_DEBUG(dbgs() << "\tcombining 32-bit replicated bit group for " + << I->V.getNode() << " RLAmt = " << I->RLAmt << " [" + << I->StartIdx << ", " << I->EndIdx + << "] with group with range [" << IP->StartIdx << ", " + << IP->EndIdx << "]\n"); IP->EndIdx = I->EndIdx; IP->Repl32CR = IP->Repl32CR || I->Repl32CR; @@ -1389,12 +1517,12 @@ class BitPermutationSelector { IP->EndIdx == 31 && IN->StartIdx == 0 && I != IP && IsAllLow32(*I)) { - DEBUG(dbgs() << "\tcombining bit group for " << - I->V.getNode() << " RLAmt = " << I->RLAmt << - " [" << I->StartIdx << ", " << I->EndIdx << - "] with 32-bit replicated groups with ranges [" << - IP->StartIdx << ", " << IP->EndIdx << "] and [" << - IN->StartIdx << ", " << IN->EndIdx << "]\n"); + LLVM_DEBUG(dbgs() << "\tcombining bit group for " << I->V.getNode() + << " RLAmt = " << I->RLAmt << " [" << I->StartIdx + << ", " << I->EndIdx + << "] with 32-bit replicated groups with ranges [" + << IP->StartIdx << ", " << IP->EndIdx << "] and [" + << IN->StartIdx << ", " << IN->EndIdx << "]\n"); if (IP == IN) { // There is only one other group; change it to cover the whole @@ -1503,15 +1631,15 @@ class BitPermutationSelector { (unsigned) (ANDIMask != 0 && ANDISMask != 0) + (unsigned) (bool) Res; - DEBUG(dbgs() << "\t\trotation groups for " << VRI.V.getNode() << - " RL: " << VRI.RLAmt << ":" << - "\n\t\t\tisel using masking: " << NumAndInsts << - " using rotates: " << VRI.NumGroups << "\n"); + LLVM_DEBUG(dbgs() << "\t\trotation groups for " << VRI.V.getNode() + << " RL: " << VRI.RLAmt << ":" + << "\n\t\t\tisel using masking: " << NumAndInsts + << " using rotates: " << VRI.NumGroups << "\n"); if (NumAndInsts >= VRI.NumGroups) continue; - DEBUG(dbgs() << "\t\t\t\tusing masking\n"); + LLVM_DEBUG(dbgs() << "\t\t\t\tusing masking\n"); if (InstCnt) *InstCnt += NumAndInsts; @@ -1859,10 +1987,10 @@ class BitPermutationSelector { FirstBG = false; } - DEBUG(dbgs() << "\t\trotation groups for " << VRI.V.getNode() << - " RL: " << VRI.RLAmt << (VRI.Repl32 ? " (32):" : ":") << - "\n\t\t\tisel using masking: " << NumAndInsts << - " using rotates: " << NumRLInsts << "\n"); + LLVM_DEBUG(dbgs() << "\t\trotation groups for " << VRI.V.getNode() + << " RL: " << VRI.RLAmt << (VRI.Repl32 ? " (32):" : ":") + << "\n\t\t\tisel using masking: " << NumAndInsts + << " using rotates: " << NumRLInsts << "\n"); // When we'd use andi/andis, we bias toward using the rotates (andi only // has a record form, and is cracked on POWER cores). However, when using @@ -1876,7 +2004,7 @@ class BitPermutationSelector { if ((Use32BitInsts || MoreBG) && NumAndInsts == NumRLInsts) continue; - DEBUG(dbgs() << "\t\t\t\tusing masking\n"); + LLVM_DEBUG(dbgs() << "\t\t\t\tusing masking\n"); if (InstCnt) *InstCnt += NumAndInsts; @@ -2127,9 +2255,9 @@ public: return nullptr; Bits = std::move(*Result.second); - DEBUG(dbgs() << "Considering bit-permutation-based instruction" - " selection for: "); - DEBUG(N->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "Considering bit-permutation-based instruction" + " selection for: "); + LLVM_DEBUG(N->dump(CurDAG)); // Fill it RLAmt and set HasZeros. computeRotationAmounts(); @@ -2145,22 +2273,22 @@ public: // set of bit groups, and then mask in the zeros at the end. With early // masking, we only insert the non-zero parts of the result at every step. - unsigned InstCnt, InstCntLateMask; - DEBUG(dbgs() << "\tEarly masking:\n"); + unsigned InstCnt = 0, InstCntLateMask = 0; + LLVM_DEBUG(dbgs() << "\tEarly masking:\n"); SDNode *RN = Select(N, false, &InstCnt); - DEBUG(dbgs() << "\t\tisel would use " << InstCnt << " instructions\n"); + LLVM_DEBUG(dbgs() << "\t\tisel would use " << InstCnt << " instructions\n"); - DEBUG(dbgs() << "\tLate masking:\n"); + LLVM_DEBUG(dbgs() << "\tLate masking:\n"); SDNode *RNLM = Select(N, true, &InstCntLateMask); - DEBUG(dbgs() << "\t\tisel would use " << InstCntLateMask << - " instructions\n"); + LLVM_DEBUG(dbgs() << "\t\tisel would use " << InstCntLateMask + << " instructions\n"); if (InstCnt <= InstCntLateMask) { - DEBUG(dbgs() << "\tUsing early-masking for isel\n"); + LLVM_DEBUG(dbgs() << "\tUsing early-masking for isel\n"); return RN; } - DEBUG(dbgs() << "\tUsing late-masking for isel\n"); + LLVM_DEBUG(dbgs() << "\tUsing late-masking for isel\n"); return RNLM; } }; @@ -3288,7 +3416,7 @@ static bool allUsesExtend(SDValue Compare, SelectionDAG *CurDAG) { } /// Returns an equivalent of a SETCC node but with the result the same width as -/// the inputs. This can nalso be used for SELECT_CC if either the true or false +/// the inputs. This can also be used for SELECT_CC if either the true or false /// values is a power of two while the other is zero. SDValue IntegerCompareEliminator::getSETCCInGPR(SDValue Compare, SetccInGPROpts ConvOpts) { @@ -3488,10 +3616,63 @@ SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, Opc = PPC::CMPD; } } else if (LHS.getValueType() == MVT::f32) { - Opc = PPC::FCMPUS; + if (PPCSubTarget->hasSPE()) { + switch (CC) { + default: + case ISD::SETEQ: + case ISD::SETNE: + Opc = PPC::EFSCMPEQ; + break; + case ISD::SETLT: + case ISD::SETGE: + case ISD::SETOLT: + case ISD::SETOGE: + case ISD::SETULT: + case ISD::SETUGE: + Opc = PPC::EFSCMPLT; + break; + case ISD::SETGT: + case ISD::SETLE: + case ISD::SETOGT: + case ISD::SETOLE: + case ISD::SETUGT: + case ISD::SETULE: + Opc = PPC::EFSCMPGT; + break; + } + } else + Opc = PPC::FCMPUS; + } else if (LHS.getValueType() == MVT::f64) { + if (PPCSubTarget->hasSPE()) { + switch (CC) { + default: + case ISD::SETEQ: + case ISD::SETNE: + Opc = PPC::EFDCMPEQ; + break; + case ISD::SETLT: + case ISD::SETGE: + case ISD::SETOLT: + case ISD::SETOGE: + case ISD::SETULT: + case ISD::SETUGE: + Opc = PPC::EFDCMPLT; + break; + case ISD::SETGT: + case ISD::SETLE: + case ISD::SETOGT: + case ISD::SETOLE: + case ISD::SETUGT: + case ISD::SETULE: + Opc = PPC::EFDCMPGT; + break; + } + } else + Opc = PPCSubTarget->hasVSX() ? PPC::XSCMPUDP : PPC::FCMPUD; } else { - assert(LHS.getValueType() == MVT::f64 && "Unknown vt!"); - Opc = PPCSubTarget->hasVSX() ? PPC::XSCMPUDP : PPC::FCMPUD; + assert(LHS.getValueType() == MVT::f128 && "Unknown vt!"); + assert(PPCSubTarget->hasVSX() && "__float128 requires VSX"); + Opc = PPC::XSCMPUQP; } return SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i32, LHS, RHS), 0); } @@ -3765,7 +3946,7 @@ bool PPCDAGToDAGISel::trySETCC(SDNode *N) { // Altivec Vector compare instructions do not set any CR register by default and // vector compare operations return the same type as the operands. if (LHS.getValueType().isVector()) { - if (PPCSubTarget->hasQPX()) + if (PPCSubTarget->hasQPX() || PPCSubTarget->hasSPE()) return false; EVT VecVT = LHS.getValueType(); @@ -3795,6 +3976,12 @@ bool PPCDAGToDAGISel::trySETCC(SDNode *N) { SDValue CCReg = SelectCC(LHS, RHS, CC, dl); SDValue IntCR; + // SPE e*cmp* instructions only set the 'gt' bit, so hard-code that + // The correct compare instruction is already set by SelectCC() + if (PPCSubTarget->hasSPE() && LHS.getValueType().isFloatingPoint()) { + Idx = 1; + } + // Force the ccreg into CR7. SDValue CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32); @@ -3830,20 +4017,28 @@ bool PPCDAGToDAGISel::isOffsetMultipleOf(SDNode *N, unsigned Val) const { else if (STN) AddrOp = STN->getOperand(2); + // If the address points a frame object or a frame object with an offset, + // we need to check the object alignment. short Imm = 0; - if (AddrOp.getOpcode() == ISD::ADD) { + if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>( + AddrOp.getOpcode() == ISD::ADD ? AddrOp.getOperand(0) : + AddrOp)) { // If op0 is a frame index that is under aligned, we can't do it either, // because it is translated to r31 or r1 + slot + offset. We won't know the // slot number until the stack frame is finalized. - if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(AddrOp.getOperand(0))) { - const MachineFrameInfo &MFI = CurDAG->getMachineFunction().getFrameInfo(); - unsigned SlotAlign = MFI.getObjectAlignment(FI->getIndex()); - if ((SlotAlign % Val) != 0) - return false; - } - return isIntS16Immediate(AddrOp.getOperand(1), Imm) && !(Imm % Val); + const MachineFrameInfo &MFI = CurDAG->getMachineFunction().getFrameInfo(); + unsigned SlotAlign = MFI.getObjectAlignment(FI->getIndex()); + if ((SlotAlign % Val) != 0) + return false; + + // If we have an offset, we need further check on the offset. + if (AddrOp.getOpcode() != ISD::ADD) + return true; } + if (AddrOp.getOpcode() == ISD::ADD) + return isIntS16Immediate(AddrOp.getOperand(1), Imm) && !(Imm % Val); + // If the address comes from the outside, the offset will be zero. return AddrOp.getOpcode() == ISD::CopyFromReg; } @@ -3855,6 +4050,51 @@ void PPCDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) { cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); } +/// This method returns a node after flipping the MSB of each element +/// of vector integer type. Additionally, if SignBitVec is non-null, +/// this method sets a node with one at MSB of all elements +/// and zero at other bits in SignBitVec. +MachineSDNode * +PPCDAGToDAGISel::flipSignBit(const SDValue &N, SDNode **SignBitVec) { + SDLoc dl(N); + EVT VecVT = N.getValueType(); + if (VecVT == MVT::v4i32) { + if (SignBitVec) { + SDNode *ZV = CurDAG->getMachineNode(PPC::V_SET0, dl, MVT::v4i32); + *SignBitVec = CurDAG->getMachineNode(PPC::XVNEGSP, dl, VecVT, + SDValue(ZV, 0)); + } + return CurDAG->getMachineNode(PPC::XVNEGSP, dl, VecVT, N); + } + else if (VecVT == MVT::v8i16) { + SDNode *Hi = CurDAG->getMachineNode(PPC::LIS, dl, MVT::i32, + getI32Imm(0x8000, dl)); + SDNode *ScaImm = CurDAG->getMachineNode(PPC::ORI, dl, MVT::i32, + SDValue(Hi, 0), + getI32Imm(0x8000, dl)); + SDNode *VecImm = CurDAG->getMachineNode(PPC::MTVSRWS, dl, VecVT, + SDValue(ScaImm, 0)); + /* + Alternatively, we can do this as follow to use VRF instead of GPR. + vspltish 5, 1 + vspltish 6, 15 + vslh 5, 6, 5 + */ + if (SignBitVec) *SignBitVec = VecImm; + return CurDAG->getMachineNode(PPC::VADDUHM, dl, VecVT, N, + SDValue(VecImm, 0)); + } + else if (VecVT == MVT::v16i8) { + SDNode *VecImm = CurDAG->getMachineNode(PPC::XXSPLTIB, dl, MVT::i32, + getI32Imm(0x80, dl)); + if (SignBitVec) *SignBitVec = VecImm; + return CurDAG->getMachineNode(PPC::VADDUBM, dl, VecVT, N, + SDValue(VecImm, 0)); + } + else + llvm_unreachable("Unsupported vector data type for flipSignBit"); +} + // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. void PPCDAGToDAGISel::Select(SDNode *N) { @@ -3894,6 +4134,27 @@ void PPCDAGToDAGISel::Select(SDNode *N) { return; break; + case PPCISD::CALL: { + const Module *M = MF->getFunction().getParent(); + + if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || + !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || + M->getPICLevel() == PICLevel::SmallPIC) + break; + + SDValue Op = N->getOperand(1); + + if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) { + if (GA->getTargetFlags() == PPCII::MO_PLT) + getGlobalBaseReg(); + } + else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) { + if (ES->getTargetFlags() == PPCII::MO_PLT) + getGlobalBaseReg(); + } + } + break; + case PPCISD::GlobalBaseReg: ReplaceNode(N, getGlobalBaseReg()); return; @@ -3939,14 +4200,28 @@ void PPCDAGToDAGISel::Select(SDNode *N) { } } + case ISD::STORE: { + // Change TLS initial-exec D-form stores to X-form stores. + StoreSDNode *ST = cast<StoreSDNode>(N); + if (EnableTLSOpt && PPCSubTarget->isELFv2ABI() && + ST->getAddressingMode() != ISD::PRE_INC) + if (tryTLSXFormStore(ST)) + return; + break; + } case ISD::LOAD: { // Handle preincrement loads. LoadSDNode *LD = cast<LoadSDNode>(N); EVT LoadedVT = LD->getMemoryVT(); // Normal loads are handled by code generated from the .td file. - if (LD->getAddressingMode() != ISD::PRE_INC) + if (LD->getAddressingMode() != ISD::PRE_INC) { + // Change TLS initial-exec D-form loads to X-form loads. + if (EnableTLSOpt && PPCSubTarget->isELFv2ABI()) + if (tryTLSXFormLoad(LD)) + return; break; + } SDValue Offset = LD->getOffset(); if (Offset.getOpcode() == ISD::TargetConstant || @@ -4338,16 +4613,24 @@ void PPCDAGToDAGISel::Select(SDNode *N) { SelectCCOp = PPC::SELECT_CC_I4; else if (N->getValueType(0) == MVT::i64) SelectCCOp = PPC::SELECT_CC_I8; - else if (N->getValueType(0) == MVT::f32) + else if (N->getValueType(0) == MVT::f32) { if (PPCSubTarget->hasP8Vector()) SelectCCOp = PPC::SELECT_CC_VSSRC; + else if (PPCSubTarget->hasSPE()) + SelectCCOp = PPC::SELECT_CC_SPE4; else SelectCCOp = PPC::SELECT_CC_F4; - else if (N->getValueType(0) == MVT::f64) + } else if (N->getValueType(0) == MVT::f64) { if (PPCSubTarget->hasVSX()) SelectCCOp = PPC::SELECT_CC_VSFRC; + else if (PPCSubTarget->hasSPE()) + SelectCCOp = PPC::SELECT_CC_SPE; else SelectCCOp = PPC::SELECT_CC_F8; + } else if (N->getValueType(0) == MVT::f128) + SelectCCOp = PPC::SELECT_CC_F16; + else if (PPCSubTarget->hasSPE()) + SelectCCOp = PPC::SELECT_CC_SPE; else if (PPCSubTarget->hasQPX() && N->getValueType(0) == MVT::v4f64) SelectCCOp = PPC::SELECT_CC_QFRC; else if (PPCSubTarget->hasQPX() && N->getValueType(0) == MVT::v4f32) @@ -4633,6 +4916,55 @@ void PPCDAGToDAGISel::Select(SDNode *N) { return; } } + case ISD::ABS: { + assert(PPCSubTarget->hasP9Vector() && "ABS is supported with P9 Vector"); + + // For vector absolute difference, we use VABSDUW instruction of POWER9. + // Since VABSDU instructions are for unsigned integers, we need adjustment + // for signed integers. + // For abs(sub(a, b)), we generate VABSDUW(a+0x80000000, b+0x80000000). + // Otherwise, abs(sub(-1, 0)) returns 0xFFFFFFFF(=-1) instead of 1. + // For abs(a), we generate VABSDUW(a+0x80000000, 0x80000000). + EVT VecVT = N->getOperand(0).getValueType(); + SDNode *AbsOp = nullptr; + unsigned AbsOpcode; + + if (VecVT == MVT::v4i32) + AbsOpcode = PPC::VABSDUW; + else if (VecVT == MVT::v8i16) + AbsOpcode = PPC::VABSDUH; + else if (VecVT == MVT::v16i8) + AbsOpcode = PPC::VABSDUB; + else + llvm_unreachable("Unsupported vector data type for ISD::ABS"); + + // Even for signed integers, we can skip adjustment if all values are + // known to be positive (as signed integer) due to zero-extended inputs. + if (N->getOperand(0).getOpcode() == ISD::SUB && + N->getOperand(0)->getOperand(0).getOpcode() == ISD::ZERO_EXTEND && + N->getOperand(0)->getOperand(1).getOpcode() == ISD::ZERO_EXTEND) { + AbsOp = CurDAG->getMachineNode(AbsOpcode, dl, VecVT, + SDValue(N->getOperand(0)->getOperand(0)), + SDValue(N->getOperand(0)->getOperand(1))); + ReplaceNode(N, AbsOp); + return; + } + if (N->getOperand(0).getOpcode() == ISD::SUB) { + SDValue SubVal = N->getOperand(0); + SDNode *Op0 = flipSignBit(SubVal->getOperand(0)); + SDNode *Op1 = flipSignBit(SubVal->getOperand(1)); + AbsOp = CurDAG->getMachineNode(AbsOpcode, dl, VecVT, + SDValue(Op0, 0), SDValue(Op1, 0)); + } + else { + SDNode *Op1 = nullptr; + SDNode *Op0 = flipSignBit(N->getOperand(0), &Op1); + AbsOp = CurDAG->getMachineNode(AbsOpcode, dl, VecVT, SDValue(Op0, 0), + SDValue(Op1, 0)); + } + ReplaceNode(N, AbsOp); + return; + } } SelectCode(N); @@ -4924,8 +5256,7 @@ void PPCDAGToDAGISel::foldBoolExts(SDValue &Res, SDNode *&N) { } void PPCDAGToDAGISel::PreprocessISelDAG() { - SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); - ++Position; + SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end(); bool MadeChange = false; while (Position != CurDAG->allnodes_begin()) { @@ -4945,11 +5276,11 @@ void PPCDAGToDAGISel::PreprocessISelDAG() { foldBoolExts(Res, N); if (Res) { - DEBUG(dbgs() << "PPC DAG preprocessing replacing:\nOld: "); - DEBUG(N->dump(CurDAG)); - DEBUG(dbgs() << "\nNew: "); - DEBUG(Res.getNode()->dump(CurDAG)); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "PPC DAG preprocessing replacing:\nOld: "); + LLVM_DEBUG(N->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\nNew: "); + LLVM_DEBUG(Res.getNode()->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\n"); CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Res); MadeChange = true; @@ -5026,13 +5357,13 @@ void PPCDAGToDAGISel::SwapAllSelectUsers(SDNode *N) { User->getOperand(2), User->getOperand(1)); - DEBUG(dbgs() << "CR Peephole replacing:\nOld: "); - DEBUG(User->dump(CurDAG)); - DEBUG(dbgs() << "\nNew: "); - DEBUG(ResNode->dump(CurDAG)); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "CR Peephole replacing:\nOld: "); + LLVM_DEBUG(User->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\nNew: "); + LLVM_DEBUG(ResNode->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\n"); - ReplaceUses(User, ResNode); + ReplaceUses(User, ResNode); } } @@ -5083,6 +5414,8 @@ void PPCDAGToDAGISel::PeepholeCROps() { case PPC::SELECT_QFRC: case PPC::SELECT_QSRC: case PPC::SELECT_QBRC: + case PPC::SELECT_SPE: + case PPC::SELECT_SPE4: case PPC::SELECT_VRRC: case PPC::SELECT_VSFRC: case PPC::SELECT_VSSRC: @@ -5402,6 +5735,8 @@ void PPCDAGToDAGISel::PeepholeCROps() { case PPC::SELECT_QFRC: case PPC::SELECT_QSRC: case PPC::SELECT_QBRC: + case PPC::SELECT_SPE: + case PPC::SELECT_SPE4: case PPC::SELECT_VRRC: case PPC::SELECT_VSFRC: case PPC::SELECT_VSSRC: @@ -5440,11 +5775,11 @@ void PPCDAGToDAGISel::PeepholeCROps() { SwapAllSelectUsers(MachineNode); if (ResNode != MachineNode) { - DEBUG(dbgs() << "CR Peephole replacing:\nOld: "); - DEBUG(MachineNode->dump(CurDAG)); - DEBUG(dbgs() << "\nNew: "); - DEBUG(ResNode->dump(CurDAG)); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "CR Peephole replacing:\nOld: "); + LLVM_DEBUG(MachineNode->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\nNew: "); + LLVM_DEBUG(ResNode->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\n"); ReplaceUses(MachineNode, ResNode); IsModified = true; @@ -5613,8 +5948,7 @@ void PPCDAGToDAGISel::PeepholePPC64ZExt() { // unnecessary. When that happens, we remove it here, and redefine the // relevant 32-bit operation to be a 64-bit operation. - SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); - ++Position; + SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end(); bool MadeChange = false; while (Position != CurDAG->allnodes_begin()) { @@ -5739,25 +6073,25 @@ void PPCDAGToDAGISel::PeepholePPC64ZExt() { else NewVTs.push_back(VTs.VTs[i]); - DEBUG(dbgs() << "PPC64 ZExt Peephole morphing:\nOld: "); - DEBUG(PN->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "PPC64 ZExt Peephole morphing:\nOld: "); + LLVM_DEBUG(PN->dump(CurDAG)); CurDAG->SelectNodeTo(PN, NewOpcode, CurDAG->getVTList(NewVTs), Ops); - DEBUG(dbgs() << "\nNew: "); - DEBUG(PN->dump(CurDAG)); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "\nNew: "); + LLVM_DEBUG(PN->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\n"); } // Now we replace the original zero extend and its associated INSERT_SUBREG // with the value feeding the INSERT_SUBREG (which has now been promoted to // return an i64). - DEBUG(dbgs() << "PPC64 ZExt Peephole replacing:\nOld: "); - DEBUG(N->dump(CurDAG)); - DEBUG(dbgs() << "\nNew: "); - DEBUG(Op32.getNode()->dump(CurDAG)); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "PPC64 ZExt Peephole replacing:\nOld: "); + LLVM_DEBUG(N->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\nNew: "); + LLVM_DEBUG(Op32.getNode()->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\n"); ReplaceUses(N, Op32.getNode()); } @@ -5771,8 +6105,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { if (PPCSubTarget->isDarwin() || !PPCSubTarget->isPPC64()) return; - SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); - ++Position; + SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end(); while (Position != CurDAG->allnodes_begin()) { SDNode *N = &*--Position; @@ -5782,28 +6115,37 @@ void PPCDAGToDAGISel::PeepholePPC64() { unsigned FirstOp; unsigned StorageOpcode = N->getMachineOpcode(); + bool RequiresMod4Offset = false; switch (StorageOpcode) { default: continue; + case PPC::LWA: + case PPC::LD: + case PPC::DFLOADf64: + case PPC::DFLOADf32: + RequiresMod4Offset = true; + LLVM_FALLTHROUGH; case PPC::LBZ: case PPC::LBZ8: - case PPC::LD: case PPC::LFD: case PPC::LFS: case PPC::LHA: case PPC::LHA8: case PPC::LHZ: case PPC::LHZ8: - case PPC::LWA: case PPC::LWZ: case PPC::LWZ8: FirstOp = 0; break; + case PPC::STD: + case PPC::DFSTOREf64: + case PPC::DFSTOREf32: + RequiresMod4Offset = true; + LLVM_FALLTHROUGH; case PPC::STB: case PPC::STB8: - case PPC::STD: case PPC::STFD: case PPC::STFS: case PPC::STH: @@ -5850,9 +6192,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { // 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 ((StorageOpcode == PPC::LWA || - StorageOpcode == PPC::LD || - StorageOpcode == PPC::STD) && + if (RequiresMod4Offset && (!isa<ConstantSDNode>(Base.getOperand(1)) || Base.getConstantOperandVal(1) % 4 != 0)) continue; @@ -5914,8 +6254,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { if (auto *C = dyn_cast<ConstantSDNode>(ImmOpnd)) { Offset += C->getSExtValue(); - if ((StorageOpcode == PPC::LWA || StorageOpcode == PPC::LD || - StorageOpcode == PPC::STD) && (Offset % 4) != 0) + if (RequiresMod4Offset && (Offset % 4) != 0) continue; if (!isInt<16>(Offset)) @@ -5932,11 +6271,11 @@ void PPCDAGToDAGISel::PeepholePPC64() { // immediate and substitute them into the load or store. If // needed, update the target flags for the immediate operand to // reflect the necessary relocation information. - DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); - DEBUG(Base->dump(CurDAG)); - DEBUG(dbgs() << "\nN: "); - DEBUG(N->dump(CurDAG)); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); + LLVM_DEBUG(Base->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\nN: "); + LLVM_DEBUG(N->dump(CurDAG)); + LLVM_DEBUG(dbgs() << "\n"); // If the relocation information isn't already present on the // immediate operand, add it now. @@ -5947,9 +6286,8 @@ void PPCDAGToDAGISel::PeepholePPC64() { // We can't perform this optimization for data whose alignment // is insufficient for the instruction encoding. if (GV->getAlignment() < 4 && - (StorageOpcode == PPC::LD || StorageOpcode == PPC::STD || - StorageOpcode == PPC::LWA || (Offset % 4) != 0)) { - DEBUG(dbgs() << "Rejected this candidate for alignment.\n\n"); + (RequiresMod4Offset || (Offset % 4) != 0)) { + LLVM_DEBUG(dbgs() << "Rejected this candidate for alignment.\n\n"); continue; } ImmOpnd = CurDAG->getTargetGlobalAddress(GV, dl, MVT::i64, Offset, Flags); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index cea59de3e8a9..1e3e14c71144 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -47,7 +47,6 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" @@ -83,6 +82,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/KnownBits.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" @@ -111,6 +111,9 @@ cl::desc("disable unaligned load/store generation on PPC"), cl::Hidden); static cl::opt<bool> DisableSCO("disable-ppc-sco", cl::desc("disable sibling call optimization on ppc"), cl::Hidden); +static cl::opt<bool> EnableQuadPrecision("enable-ppc-quad-precision", +cl::desc("enable quad precision float support on ppc"), cl::Hidden); + STATISTIC(NumTailCalls, "Number of tail calls"); STATISTIC(NumSiblingCalls, "Number of sibling calls"); @@ -134,14 +137,22 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, // Set up the register classes. addRegisterClass(MVT::i32, &PPC::GPRCRegClass); if (!useSoftFloat()) { - addRegisterClass(MVT::f32, &PPC::F4RCRegClass); - addRegisterClass(MVT::f64, &PPC::F8RCRegClass); + if (hasSPE()) { + addRegisterClass(MVT::f32, &PPC::SPE4RCRegClass); + addRegisterClass(MVT::f64, &PPC::SPERCRegClass); + } else { + addRegisterClass(MVT::f32, &PPC::F4RCRegClass); + addRegisterClass(MVT::f64, &PPC::F8RCRegClass); + } } // Match BITREVERSE to customized fast code sequence in the td file. setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); setOperationAction(ISD::BITREVERSE, MVT::i64, Legal); + // Sub-word ATOMIC_CMP_SWAP need to ensure that the input is zero-extended. + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Custom); + // PowerPC has an i16 but no i8 (or i1) SEXTLOAD. for (MVT VT : MVT::integer_valuetypes()) { setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); @@ -156,15 +167,26 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal); setIndexedLoadAction(ISD::PRE_INC, MVT::i32, Legal); setIndexedLoadAction(ISD::PRE_INC, MVT::i64, Legal); - setIndexedLoadAction(ISD::PRE_INC, MVT::f32, Legal); - setIndexedLoadAction(ISD::PRE_INC, MVT::f64, Legal); setIndexedStoreAction(ISD::PRE_INC, MVT::i1, Legal); setIndexedStoreAction(ISD::PRE_INC, MVT::i8, Legal); setIndexedStoreAction(ISD::PRE_INC, MVT::i16, Legal); setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal); setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal); - setIndexedStoreAction(ISD::PRE_INC, MVT::f32, Legal); - setIndexedStoreAction(ISD::PRE_INC, MVT::f64, Legal); + if (!Subtarget.hasSPE()) { + setIndexedLoadAction(ISD::PRE_INC, MVT::f32, Legal); + setIndexedLoadAction(ISD::PRE_INC, MVT::f64, Legal); + setIndexedStoreAction(ISD::PRE_INC, MVT::f32, Legal); + setIndexedStoreAction(ISD::PRE_INC, MVT::f64, Legal); + } + + // PowerPC uses ADDC/ADDE/SUBC/SUBE to propagate carry. + const MVT ScalarIntVTs[] = { MVT::i32, MVT::i64 }; + for (MVT VT : ScalarIntVTs) { + setOperationAction(ISD::ADDC, VT, Legal); + setOperationAction(ISD::ADDE, VT, Legal); + setOperationAction(ISD::SUBC, VT, Legal); + setOperationAction(ISD::SUBE, VT, Legal); + } if (Subtarget.useCRBits()) { setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); @@ -198,9 +220,10 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, addRegisterClass(MVT::i1, &PPC::CRBITRCRegClass); } - // This is used in the ppcf128->int sequence. Note it has different semantics - // from FP_ROUND: that rounds to nearest, this rounds to zero. - setOperationAction(ISD::FP_ROUND_INREG, MVT::ppcf128, Custom); + // Expand ppcf128 to i32 by hand for the benefit of llvm-gcc bootstrap on + // PPC (the libcall is not available). + setOperationAction(ISD::FP_TO_SINT, MVT::ppcf128, Custom); + setOperationAction(ISD::FP_TO_UINT, MVT::ppcf128, Custom); // We do not currently implement these libm ops for PowerPC. setOperationAction(ISD::FFLOOR, MVT::ppcf128, Expand); @@ -250,13 +273,18 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::FSINCOS, MVT::f64, Expand); setOperationAction(ISD::FREM , MVT::f64, Expand); setOperationAction(ISD::FPOW , MVT::f64, Expand); - setOperationAction(ISD::FMA , MVT::f64, Legal); setOperationAction(ISD::FSIN , MVT::f32, Expand); setOperationAction(ISD::FCOS , MVT::f32, Expand); setOperationAction(ISD::FSINCOS, MVT::f32, Expand); setOperationAction(ISD::FREM , MVT::f32, Expand); setOperationAction(ISD::FPOW , MVT::f32, Expand); - setOperationAction(ISD::FMA , MVT::f32, Legal); + if (Subtarget.hasSPE()) { + setOperationAction(ISD::FMA , MVT::f64, Expand); + setOperationAction(ISD::FMA , MVT::f32, Expand); + } else { + setOperationAction(ISD::FMA , MVT::f64, Legal); + setOperationAction(ISD::FMA , MVT::f32, Legal); + } setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom); @@ -293,7 +321,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, // PowerPC does not have BSWAP, but we can use vector BSWAP instruction xxbrd // to speed up scalar BSWAP64. - // CTPOP or CTTZ were introduced in P8/P9 respectivelly + // CTPOP or CTTZ were introduced in P8/P9 respectively setOperationAction(ISD::BSWAP, MVT::i32 , Expand); if (Subtarget.isISA3_0()) { setOperationAction(ISD::BSWAP, MVT::i64 , Custom); @@ -339,12 +367,19 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::BR_JT, MVT::Other, Expand); - // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. - setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + if (Subtarget.hasSPE()) { + // SPE has built-in conversions + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal); + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal); + } else { + // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); - // PowerPC does not have [U|S]INT_TO_FP - setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); - setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); + // PowerPC does not have [U|S]INT_TO_FP + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); + } if (Subtarget.hasDirectMove() && isPPC64) { setOperationAction(ISD::BITCAST, MVT::f32, Legal); @@ -442,6 +477,12 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom); // Comparisons that require checking two conditions. + if (Subtarget.hasSPE()) { + setCondCodeAction(ISD::SETO, MVT::f32, Expand); + setCondCodeAction(ISD::SETO, MVT::f64, Expand); + setCondCodeAction(ISD::SETUO, MVT::f32, Expand); + setCondCodeAction(ISD::SETUO, MVT::f64, Expand); + } setCondCodeAction(ISD::SETULT, MVT::f32, Expand); setCondCodeAction(ISD::SETULT, MVT::f64, Expand); setCondCodeAction(ISD::SETUGT, MVT::f32, Expand); @@ -469,7 +510,10 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); } else { // PowerPC does not have FP_TO_UINT on 32-bit implementations. - setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); + if (Subtarget.hasSPE()) + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal); + else + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); } // With the instructions enabled under FPCVT, we can do everything. @@ -782,6 +826,46 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::SHL, MVT::v1i128, Legal); setOperationAction(ISD::SRL, MVT::v1i128, Legal); setOperationAction(ISD::SRA, MVT::v1i128, Expand); + + if (EnableQuadPrecision) { + addRegisterClass(MVT::f128, &PPC::VRRCRegClass); + setOperationAction(ISD::FADD, MVT::f128, Legal); + setOperationAction(ISD::FSUB, MVT::f128, Legal); + setOperationAction(ISD::FDIV, MVT::f128, Legal); + setOperationAction(ISD::FMUL, MVT::f128, Legal); + setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal); + // No extending loads to f128 on PPC. + for (MVT FPT : MVT::fp_valuetypes()) + setLoadExtAction(ISD::EXTLOAD, MVT::f128, FPT, Expand); + setOperationAction(ISD::FMA, MVT::f128, Legal); + setCondCodeAction(ISD::SETULT, MVT::f128, Expand); + setCondCodeAction(ISD::SETUGT, MVT::f128, Expand); + setCondCodeAction(ISD::SETUEQ, MVT::f128, Expand); + setCondCodeAction(ISD::SETOGE, MVT::f128, Expand); + setCondCodeAction(ISD::SETOLE, MVT::f128, Expand); + setCondCodeAction(ISD::SETONE, MVT::f128, Expand); + + setOperationAction(ISD::FTRUNC, MVT::f128, Legal); + setOperationAction(ISD::FRINT, MVT::f128, Legal); + setOperationAction(ISD::FFLOOR, MVT::f128, Legal); + setOperationAction(ISD::FCEIL, MVT::f128, Legal); + setOperationAction(ISD::FNEARBYINT, MVT::f128, Legal); + setOperationAction(ISD::FROUND, MVT::f128, Legal); + + setOperationAction(ISD::SELECT, MVT::f128, Expand); + setOperationAction(ISD::FP_ROUND, MVT::f64, Legal); + setOperationAction(ISD::FP_ROUND, MVT::f32, Legal); + setTruncStoreAction(MVT::f128, MVT::f64, Expand); + setTruncStoreAction(MVT::f128, MVT::f32, Expand); + setOperationAction(ISD::BITCAST, MVT::i128, Custom); + // No implementation for these ops for PowerPC. + setOperationAction(ISD::FSIN , MVT::f128, Expand); + setOperationAction(ISD::FCOS , MVT::f128, Expand); + setOperationAction(ISD::FPOW, MVT::f128, Expand); + setOperationAction(ISD::FPOWI, MVT::f128, Expand); + setOperationAction(ISD::FREM, MVT::f128, Expand); + } + } if (Subtarget.hasP9Altivec()) { @@ -1018,6 +1102,21 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setLibcallName(RTLIB::EXP2_PPCF128, "exp2l$LDBL128"); } + if (EnableQuadPrecision) { + setLibcallName(RTLIB::LOG_F128, "logf128"); + setLibcallName(RTLIB::LOG2_F128, "log2f128"); + setLibcallName(RTLIB::LOG10_F128, "log10f128"); + setLibcallName(RTLIB::EXP_F128, "expf128"); + setLibcallName(RTLIB::EXP2_F128, "exp2f128"); + setLibcallName(RTLIB::SIN_F128, "sinf128"); + setLibcallName(RTLIB::COS_F128, "cosf128"); + setLibcallName(RTLIB::POW_F128, "powf128"); + setLibcallName(RTLIB::FMIN_F128, "fminf128"); + setLibcallName(RTLIB::FMAX_F128, "fmaxf128"); + setLibcallName(RTLIB::POWI_F128, "__powikf2"); + setLibcallName(RTLIB::REM_F128, "fmodf128"); + } + // With 32 condition bits, we don't need to sink (and duplicate) compares // aggressively in CodeGenPrep. if (Subtarget.useCRBits()) { @@ -1033,6 +1132,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, default: break; case PPC::DIR_970: case PPC::DIR_A2: + case PPC::DIR_E500: case PPC::DIR_E500mc: case PPC::DIR_E5500: case PPC::DIR_PWR4: @@ -1123,10 +1223,28 @@ unsigned PPCTargetLowering::getByValTypeAlignment(Type *Ty, return Align; } +unsigned PPCTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context, + EVT VT) const { + if (Subtarget.hasSPE() && VT == MVT::f64) + return 2; + return PPCTargetLowering::getNumRegisters(Context, VT); +} + +MVT PPCTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context, + EVT VT) const { + if (Subtarget.hasSPE() && VT == MVT::f64) + return MVT::i32; + return PPCTargetLowering::getRegisterType(Context, VT); +} + bool PPCTargetLowering::useSoftFloat() const { return Subtarget.useSoftFloat(); } +bool PPCTargetLowering::hasSPE() const { + return Subtarget.hasSPE(); +} + const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((PPCISD::NodeType)Opcode) { case PPCISD::FIRST_NUMBER: break; @@ -1139,6 +1257,10 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::FCTIWZ: return "PPCISD::FCTIWZ"; case PPCISD::FCTIDUZ: return "PPCISD::FCTIDUZ"; case PPCISD::FCTIWUZ: return "PPCISD::FCTIWUZ"; + case PPCISD::FP_TO_UINT_IN_VSR: + return "PPCISD::FP_TO_UINT_IN_VSR,"; + case PPCISD::FP_TO_SINT_IN_VSR: + return "PPCISD::FP_TO_SINT_IN_VSR"; case PPCISD::FRE: return "PPCISD::FRE"; case PPCISD::FRSQRTE: return "PPCISD::FRSQRTE"; case PPCISD::STFIWX: return "PPCISD::STFIWX"; @@ -1154,6 +1276,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::Hi: return "PPCISD::Hi"; case PPCISD::Lo: return "PPCISD::Lo"; case PPCISD::TOC_ENTRY: return "PPCISD::TOC_ENTRY"; + case PPCISD::ATOMIC_CMP_SWAP_8: return "PPCISD::ATOMIC_CMP_SWAP_8"; + case PPCISD::ATOMIC_CMP_SWAP_16: return "PPCISD::ATOMIC_CMP_SWAP_16"; case PPCISD::DYNALLOC: return "PPCISD::DYNALLOC"; case PPCISD::DYNAREAOFFSET: return "PPCISD::DYNAREAOFFSET"; case PPCISD::GlobalBaseReg: return "PPCISD::GlobalBaseReg"; @@ -1190,6 +1314,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::SExtVElems: return "PPCISD::SExtVElems"; case PPCISD::LXVD2X: return "PPCISD::LXVD2X"; case PPCISD::STXVD2X: return "PPCISD::STXVD2X"; + case PPCISD::ST_VSR_SCAL_INT: + return "PPCISD::ST_VSR_SCAL_INT"; case PPCISD::COND_BRANCH: return "PPCISD::COND_BRANCH"; case PPCISD::BDNZ: return "PPCISD::BDNZ"; case PPCISD::BDZ: return "PPCISD::BDZ"; @@ -1226,6 +1352,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::QVESPLATI: return "PPCISD::QVESPLATI"; case PPCISD::QBFLT: return "PPCISD::QBFLT"; case PPCISD::QVLFSb: return "PPCISD::QVLFSb"; + case PPCISD::BUILD_FP128: return "PPCISD::BUILD_FP128"; } return nullptr; } @@ -1456,7 +1583,7 @@ bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, } /** - * \brief Common function used to match vmrgew and vmrgow shuffles + * Common function used to match vmrgew and vmrgow shuffles * * The indexOffset determines whether to look for even or odd words in * the shuffle mask. This is based on the of the endianness of the target @@ -1513,7 +1640,7 @@ static bool isVMerge(ShuffleVectorSDNode *N, unsigned IndexOffset, } /** - * \brief Determine if the specified shuffle mask is suitable for the vmrgew or + * Determine if the specified shuffle mask is suitable for the vmrgew or * vmrgow instructions. * * \param[in] N The shuffle vector SD Node to analyze @@ -2545,10 +2672,11 @@ SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, // 64-bit SVR4 ABI code is always position-independent. // The actual BlockAddress is stored in the TOC. - if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { - setUsesTOCBasePtr(DAG); + if (Subtarget.isSVR4ABI() && isPositionIndependent()) { + if (Subtarget.isPPC64()) + setUsesTOCBasePtr(DAG); SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset()); - return getTOCEntry(DAG, SDLoc(BASDN), true, GA); + return getTOCEntry(DAG, SDLoc(BASDN), Subtarget.isPPC64(), GA); } unsigned MOHiFlag, MOLoFlag; @@ -2566,7 +2694,7 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, // large models could be added if users need it, at the cost of // additional complexity. GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); - if (DAG.getTarget().Options.EmulatedTLS) + if (DAG.getTarget().useEmulatedTLS()) return LowerToTLSEmulatedModel(GA, DAG); SDLoc dl(GA); @@ -3111,7 +3239,7 @@ static unsigned CalculateStackSlotAlignment(EVT ArgVT, EVT OrigVT, if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 || ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 || ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 || - ArgVT == MVT::v1i128) + ArgVT == MVT::v1i128 || ArgVT == MVT::f128) Align = 16; // QPX vector types stored in double-precision are padded to a 32 byte // boundary. @@ -3191,7 +3319,7 @@ static bool CalculateStackSlotUsed(EVT ArgVT, EVT OrigVT, if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 || ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 || ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 || - ArgVT == MVT::v1i128) + ArgVT == MVT::v1i128 || ArgVT == MVT::f128) if (AvailableVRs > 0) { --AvailableVRs; return false; @@ -3280,7 +3408,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_32SVR4( // Reserve space for the linkage area on the stack. unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize(); CCInfo.AllocateStack(LinkageSize, PtrByteSize); - if (useSoftFloat()) + if (useSoftFloat() || hasSPE()) CCInfo.PreAnalyzeFormalArguments(Ins); CCInfo.AnalyzeFormalArguments(Ins, CC_PPC32_SVR4); @@ -3304,12 +3432,16 @@ SDValue PPCTargetLowering::LowerFormalArguments_32SVR4( case MVT::f32: if (Subtarget.hasP8Vector()) RC = &PPC::VSSRCRegClass; + else if (Subtarget.hasSPE()) + RC = &PPC::SPE4RCRegClass; else RC = &PPC::F4RCRegClass; break; case MVT::f64: if (Subtarget.hasVSX()) RC = &PPC::VSFRCRegClass; + else if (Subtarget.hasSPE()) + RC = &PPC::SPERCRegClass; else RC = &PPC::F8RCRegClass; break; @@ -3398,7 +3530,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_32SVR4( }; unsigned NumFPArgRegs = array_lengthof(FPArgRegs); - if (useSoftFloat()) + if (useSoftFloat() || hasSPE()) NumFPArgRegs = 0; FuncInfo->setVarArgsNumGPR(CCInfo.getFirstUnallocated(GPArgRegs)); @@ -3780,23 +3912,23 @@ SDValue PPCTargetLowering::LowerFormalArguments_64SVR4( case MVT::v2f64: case MVT::v2i64: case MVT::v1i128: + case MVT::f128: if (!Subtarget.hasQPX()) { - // These can be scalar arguments or elements of a vector array type - // passed directly. The latter are used to implement ELFv2 homogenous - // vector aggregates. - if (VR_idx != Num_VR_Regs) { - unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass); - ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); - ++VR_idx; - } else { - if (CallConv == CallingConv::Fast) - ComputeArgOffset(); - - needsLoad = true; - } - if (CallConv != CallingConv::Fast || needsLoad) - ArgOffset += 16; - break; + // These can be scalar arguments or elements of a vector array type + // passed directly. The latter are used to implement ELFv2 homogenous + // vector aggregates. + if (VR_idx != Num_VR_Regs) { + unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass); + ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); + ++VR_idx; + } else { + if (CallConv == CallingConv::Fast) + ComputeArgOffset(); + needsLoad = true; + } + if (CallConv != CallingConv::Fast || needsLoad) + ArgOffset += 16; + break; } // not QPX assert(ObjectVT.getSimpleVT().SimpleTy == MVT::v4f32 && @@ -4258,7 +4390,7 @@ static int CalculateTailCallSPDiff(SelectionDAG& DAG, bool isTailCall, PPCFunctionInfo *FI = DAG.getMachineFunction().getInfo<PPCFunctionInfo>(); unsigned CallerMinReservedArea = FI->getMinReservedArea(); int SPDiff = (int)CallerMinReservedArea - (int)ParamSize; - // Remember only if the new adjustement is bigger. + // Remember only if the new adjustment is bigger. if (SPDiff < FI->getTailCallSPDelta()) FI->setTailCallSPDelta(SPDiff); @@ -4397,13 +4529,18 @@ hasSameArgumentList(const Function *CallerFn, ImmutableCallSite CS) { static bool areCallingConvEligibleForTCO_64SVR4(CallingConv::ID CallerCC, CallingConv::ID CalleeCC) { - // Tail or Sibling call optimization (TCO/SCO) needs callee and caller to - // have the same calling convention. - if (CallerCC != CalleeCC) + // Tail calls are possible with fastcc and ccc. + auto isTailCallableCC = [] (CallingConv::ID CC){ + return CC == CallingConv::C || CC == CallingConv::Fast; + }; + if (!isTailCallableCC(CallerCC) || !isTailCallableCC(CalleeCC)) return false; - // Tail or Sibling calls can be done with fastcc/ccc. - return (CallerCC == CallingConv::Fast || CallerCC == CallingConv::C); + // We can safely tail call both fastcc and ccc callees from a c calling + // convention caller. If the caller is fastcc, we may have less stack space + // than a non-fastcc caller with the same signature so disable tail-calls in + // that case. + return CallerCC == CallingConv::C || CallerCC == CalleeCC; } bool @@ -4434,10 +4571,28 @@ PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4( // Callee contains any byval parameter is not supported, too. // Note: This is a quick work around, because in some cases, e.g. // caller's stack size > callee's stack size, we are still able to apply - // sibling call optimization. See: https://reviews.llvm.org/D23441#513574 + // sibling call optimization. For example, gcc is able to do SCO for caller1 + // in the following example, but not for caller2. + // struct test { + // long int a; + // char ary[56]; + // } gTest; + // __attribute__((noinline)) int callee(struct test v, struct test *b) { + // b->a = v.a; + // return 0; + // } + // void caller1(struct test a, struct test c, struct test *b) { + // callee(gTest, b); } + // void caller2(struct test *b) { callee(gTest, b); } if (any_of(Outs, [](const ISD::OutputArg& OA) { return OA.Flags.isByVal(); })) return false; + // If callee and caller use different calling conventions, we cannot pass + // parameters on stack since offsets for the parameter area may be different. + if (Caller.getCallingConv() != CalleeCC && + needStackSlotPassParameters(Subtarget, Outs)) + return false; + // No TCO/SCO on indirect call because Caller have to restore its TOC if (!isFunctionGlobalAddress(Callee) && !isa<ExternalSymbolSDNode>(Callee)) @@ -4911,7 +5066,11 @@ SDValue PPCTargetLowering::LowerCallResult( SmallVector<CCValAssign, 16> RVLocs; CCState CCRetInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, *DAG.getContext()); - CCRetInfo.AnalyzeCallResult(Ins, RetCC_PPC); + + CCRetInfo.AnalyzeCallResult( + Ins, (Subtarget.isSVR4ABI() && CallConv == CallingConv::Cold) + ? RetCC_PPC_Cold + : RetCC_PPC); // Copy all of the result registers out of their specified physreg. for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { @@ -5080,15 +5239,15 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, assert(isa<GlobalAddressSDNode>(Callee) && "Callee should be an llvm::Function object."); - DEBUG( - const GlobalValue *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal(); - const unsigned Width = 80 - strlen("TCO caller: ") - - strlen(", callee linkage: 0, 0"); - dbgs() << "TCO caller: " - << left_justify(DAG.getMachineFunction().getName(), Width) - << ", callee linkage: " - << GV->getVisibility() << ", " << GV->getLinkage() << "\n" - ); + LLVM_DEBUG( + const GlobalValue *GV = + cast<GlobalAddressSDNode>(Callee)->getGlobal(); + const unsigned Width = + 80 - strlen("TCO caller: ") - strlen(", callee linkage: 0, 0"); + dbgs() << "TCO caller: " + << left_justify(DAG.getMachineFunction().getName(), Width) + << ", callee linkage: " << GV->getVisibility() << ", " + << GV->getLinkage() << "\n"); } } @@ -5131,6 +5290,7 @@ SDValue PPCTargetLowering::LowerCall_32SVR4( // of the 32-bit SVR4 ABI stack frame layout. assert((CallConv == CallingConv::C || + CallConv == CallingConv::Cold || CallConv == CallingConv::Fast) && "Unknown calling convention!"); unsigned PtrByteSize = 4; @@ -5434,6 +5594,11 @@ SDValue PPCTargetLowering::LowerCall_64SVR4( // arguments that will be in registers. unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0; + // Avoid allocating parameter area for fastcc functions if all the arguments + // can be passed in the registers. + if (CallConv == CallingConv::Fast) + HasParameterArea = false; + // Add up all the space actually used. for (unsigned i = 0; i != NumOps; ++i) { ISD::ArgFlagsTy Flags = Outs[i].Flags; @@ -5444,9 +5609,11 @@ SDValue PPCTargetLowering::LowerCall_64SVR4( continue; if (CallConv == CallingConv::Fast) { - if (Flags.isByVal()) + if (Flags.isByVal()) { NumGPRsUsed += (Flags.getByValSize()+7)/8; - else + if (NumGPRsUsed > NumGPRs) + HasParameterArea = true; + } else { switch (ArgVT.getSimpleVT().SimpleTy) { default: llvm_unreachable("Unexpected ValueType for argument!"); case MVT::i1: @@ -5461,6 +5628,7 @@ SDValue PPCTargetLowering::LowerCall_64SVR4( case MVT::v2f64: case MVT::v2i64: case MVT::v1i128: + case MVT::f128: if (++NumVRsUsed <= NumVRs) continue; break; @@ -5483,6 +5651,8 @@ SDValue PPCTargetLowering::LowerCall_64SVR4( continue; break; } + HasParameterArea = true; + } } /* Respect alignment of argument on the stack. */ @@ -5839,6 +6009,7 @@ SDValue PPCTargetLowering::LowerCall_64SVR4( case MVT::v2f64: case MVT::v2i64: case MVT::v1i128: + case MVT::f128: if (!Subtarget.hasQPX()) { // These can be scalar arguments or elements of a vector array type // passed directly. The latter are used to implement ELFv2 homogenous @@ -6392,7 +6563,10 @@ PPCTargetLowering::CanLowerReturn(CallingConv::ID CallConv, LLVMContext &Context) const { SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context); - return CCInfo.CheckReturn(Outs, RetCC_PPC); + return CCInfo.CheckReturn( + Outs, (Subtarget.isSVR4ABI() && CallConv == CallingConv::Cold) + ? RetCC_PPC_Cold + : RetCC_PPC); } SDValue @@ -6404,7 +6578,10 @@ PPCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, *DAG.getContext()); - CCInfo.AnalyzeReturn(Outs, RetCC_PPC); + CCInfo.AnalyzeReturn(Outs, + (Subtarget.isSVR4ABI() && CallConv == CallingConv::Cold) + ? RetCC_PPC_Cold + : RetCC_PPC); SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); @@ -6824,7 +7001,7 @@ void PPCTargetLowering::LowerFP_TO_INTForReuse(SDValue Op, ReuseLoadInfo &RLI, RLI.MPI = MPI; } -/// \brief Custom lowers floating point to integer conversions to use +/// Custom lowers floating point to integer conversions to use /// the direct move instructions available in ISA 2.07 to avoid the /// need for load/store combinations. SDValue PPCTargetLowering::LowerFP_TO_INTDirectMove(SDValue Op, @@ -6861,6 +7038,51 @@ SDValue PPCTargetLowering::LowerFP_TO_INTDirectMove(SDValue Op, SDValue PPCTargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const SDLoc &dl) const { + + // FP to INT conversions are legal for f128. + if (EnableQuadPrecision && (Op->getOperand(0).getValueType() == MVT::f128)) + return Op; + + // Expand ppcf128 to i32 by hand for the benefit of llvm-gcc bootstrap on + // PPC (the libcall is not available). + if (Op.getOperand(0).getValueType() == MVT::ppcf128) { + if (Op.getValueType() == MVT::i32) { + if (Op.getOpcode() == ISD::FP_TO_SINT) { + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, + MVT::f64, Op.getOperand(0), + DAG.getIntPtrConstant(0, dl)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, + MVT::f64, Op.getOperand(0), + DAG.getIntPtrConstant(1, dl)); + + // Add the two halves of the long double in round-to-zero mode. + SDValue Res = DAG.getNode(PPCISD::FADDRTZ, dl, MVT::f64, Lo, Hi); + + // Now use a smaller FP_TO_SINT. + return DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Res); + } + if (Op.getOpcode() == ISD::FP_TO_UINT) { + const uint64_t TwoE31[] = {0x41e0000000000000LL, 0}; + APFloat APF = APFloat(APFloat::PPCDoubleDouble(), APInt(128, TwoE31)); + SDValue Tmp = DAG.getConstantFP(APF, dl, MVT::ppcf128); + // X>=2^31 ? (int)(X-2^31)+0x80000000 : (int)X + // FIXME: generated code sucks. + // TODO: Are there fast-math-flags to propagate to this FSUB? + SDValue True = DAG.getNode(ISD::FSUB, dl, MVT::ppcf128, + Op.getOperand(0), Tmp); + True = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, True); + True = DAG.getNode(ISD::ADD, dl, MVT::i32, True, + DAG.getConstant(0x80000000, dl, MVT::i32)); + SDValue False = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, + Op.getOperand(0)); + return DAG.getSelectCC(dl, Op.getOperand(0), Tmp, True, False, + ISD::SETGE); + } + } + + return SDValue(); + } + if (Subtarget.hasDirectMove() && Subtarget.isPPC64()) return LowerFP_TO_INTDirectMove(Op, DAG, dl); @@ -6942,7 +7164,7 @@ void PPCTargetLowering::spliceIntoChain(SDValue ResChain, DAG.UpdateNodeOperands(TF.getNode(), ResChain, NewResChain); } -/// \brief Analyze profitability of direct move +/// Analyze profitability of direct move /// prefer float load to int load plus direct move /// when there is no integer use of int load bool PPCTargetLowering::directMoveIsProfitable(const SDValue &Op) const { @@ -6972,7 +7194,7 @@ bool PPCTargetLowering::directMoveIsProfitable(const SDValue &Op) const { return false; } -/// \brief Custom lowers integer to floating point conversions to use +/// Custom lowers integer to floating point conversions to use /// the direct move instructions available in ISA 2.07 to avoid the /// need for load/store combinations. SDValue PPCTargetLowering::LowerINT_TO_FPDirectMove(SDValue Op, @@ -7008,6 +7230,10 @@ SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const { SDLoc dl(Op); + // Conversions to f128 are legal. + if (EnableQuadPrecision && (Op.getValueType() == MVT::f128)) + return Op; + if (Subtarget.hasQPX() && Op.getOperand(0).getValueType() == MVT::v4i1) { if (Op.getValueType() != MVT::v4f32 && Op.getValueType() != MVT::v4f64) return SDValue(); @@ -7524,6 +7750,23 @@ static bool haveEfficientBuildVectorPattern(BuildVectorSDNode *V, return !(IsSplat && IsLoad); } +// Lower BITCAST(f128, (build_pair i64, i64)) to BUILD_FP128. +SDValue PPCTargetLowering::LowerBITCAST(SDValue Op, SelectionDAG &DAG) const { + + SDLoc dl(Op); + SDValue Op0 = Op->getOperand(0); + + if (!EnableQuadPrecision || + (Op.getValueType() != MVT::f128 ) || + (Op0.getOpcode() != ISD::BUILD_PAIR) || + (Op0.getOperand(0).getValueType() != MVT::i64) || + (Op0.getOperand(1).getValueType() != MVT::i64)) + return SDValue(); + + return DAG.getNode(PPCISD::BUILD_FP128, dl, MVT::f128, Op0.getOperand(0), + Op0.getOperand(1)); +} + // If this is a case we can't handle, return null and let the default // expansion code take care of it. If we CAN select this case, and if it // selects to a single instruction, return Op. Otherwise, if we can codegen @@ -8811,6 +9054,42 @@ SDValue PPCTargetLowering::LowerBSWAP(SDValue Op, SelectionDAG &DAG) const { return Op; } +// ATOMIC_CMP_SWAP for i8/i16 needs to zero-extend its input since it will be +// compared to a value that is atomically loaded (atomic loads zero-extend). +SDValue PPCTargetLowering::LowerATOMIC_CMP_SWAP(SDValue Op, + SelectionDAG &DAG) const { + assert(Op.getOpcode() == ISD::ATOMIC_CMP_SWAP && + "Expecting an atomic compare-and-swap here."); + SDLoc dl(Op); + auto *AtomicNode = cast<AtomicSDNode>(Op.getNode()); + EVT MemVT = AtomicNode->getMemoryVT(); + if (MemVT.getSizeInBits() >= 32) + return Op; + + SDValue CmpOp = Op.getOperand(2); + // If this is already correctly zero-extended, leave it alone. + auto HighBits = APInt::getHighBitsSet(32, 32 - MemVT.getSizeInBits()); + if (DAG.MaskedValueIsZero(CmpOp, HighBits)) + return Op; + + // Clear the high bits of the compare operand. + unsigned MaskVal = (1 << MemVT.getSizeInBits()) - 1; + SDValue NewCmpOp = + DAG.getNode(ISD::AND, dl, MVT::i32, CmpOp, + DAG.getConstant(MaskVal, dl, MVT::i32)); + + // Replace the existing compare operand with the properly zero-extended one. + SmallVector<SDValue, 4> Ops; + for (int i = 0, e = AtomicNode->getNumOperands(); i < e; i++) + Ops.push_back(AtomicNode->getOperand(i)); + Ops[2] = NewCmpOp; + MachineMemOperand *MMO = AtomicNode->getMemOperand(); + SDVTList Tys = DAG.getVTList(MVT::i32, MVT::Other); + auto NodeTy = + (MemVT == MVT::i8) ? PPCISD::ATOMIC_CMP_SWAP_8 : PPCISD::ATOMIC_CMP_SWAP_16; + return DAG.getMemIntrinsicNode(NodeTy, dl, Tys, Ops, MemVT, MMO); +} + SDValue PPCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const { SDLoc dl(Op); @@ -9238,27 +9517,19 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::SETCC: return LowerSETCC(Op, DAG); case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG); - case ISD::VASTART: - return LowerVASTART(Op, DAG); - - case ISD::VAARG: - return LowerVAARG(Op, DAG); - case ISD::VACOPY: - return LowerVACOPY(Op, DAG); - - case ISD::STACKRESTORE: - return LowerSTACKRESTORE(Op, DAG); - - case ISD::DYNAMIC_STACKALLOC: - return LowerDYNAMIC_STACKALLOC(Op, DAG); + // Variable argument lowering. + case ISD::VASTART: return LowerVASTART(Op, DAG); + case ISD::VAARG: return LowerVAARG(Op, DAG); + case ISD::VACOPY: return LowerVACOPY(Op, DAG); + case ISD::STACKRESTORE: return LowerSTACKRESTORE(Op, DAG); + case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); case ISD::GET_DYNAMIC_AREA_OFFSET: return LowerGET_DYNAMIC_AREA_OFFSET(Op, DAG); - case ISD::EH_DWARF_CFA: - return LowerEH_DWARF_CFA(Op, DAG); - + // Exception handling lowering. + case ISD::EH_DWARF_CFA: return LowerEH_DWARF_CFA(Op, DAG); case ISD::EH_SJLJ_SETJMP: return lowerEH_SJLJ_SETJMP(Op, DAG); case ISD::EH_SJLJ_LONGJMP: return lowerEH_SJLJ_LONGJMP(Op, DAG); @@ -9267,8 +9538,7 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::TRUNCATE: return LowerTRUNCATE(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); case ISD::FP_TO_UINT: - case ISD::FP_TO_SINT: return LowerFP_TO_INT(Op, DAG, - SDLoc(Op)); + case ISD::FP_TO_SINT: return LowerFP_TO_INT(Op, DAG, SDLoc(Op)); case ISD::UINT_TO_FP: case ISD::SINT_TO_FP: return LowerINT_TO_FP(Op, DAG); case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG); @@ -9291,6 +9561,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { // For counter-based loop handling. case ISD::INTRINSIC_W_CHAIN: return SDValue(); + case ISD::BITCAST: return LowerBITCAST(Op, DAG); + // Frame & Return address. case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); @@ -9302,6 +9574,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { return LowerREM(Op, DAG); case ISD::BSWAP: return LowerBSWAP(Op, DAG); + case ISD::ATOMIC_CMP_SWAP: + return LowerATOMIC_CMP_SWAP(Op, DAG); } } @@ -9334,7 +9608,7 @@ void PPCTargetLowering::ReplaceNodeResults(SDNode *N, SDValue NewInt = DAG.getNode(N->getOpcode(), dl, VTs, N->getOperand(0), N->getOperand(1)); - Results.push_back(NewInt); + Results.push_back(DAG.getNode(ISD::TRUNCATE, dl, MVT::i1, NewInt)); Results.push_back(NewInt.getValue(1)); break; } @@ -9352,25 +9626,6 @@ void PPCTargetLowering::ReplaceNodeResults(SDNode *N, } return; } - case ISD::FP_ROUND_INREG: { - assert(N->getValueType(0) == MVT::ppcf128); - assert(N->getOperand(0).getValueType() == MVT::ppcf128); - SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, - MVT::f64, N->getOperand(0), - DAG.getIntPtrConstant(0, dl)); - SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, - MVT::f64, N->getOperand(0), - DAG.getIntPtrConstant(1, dl)); - - // Add the two halves of the long double in round-to-zero mode. - SDValue FPreg = DAG.getNode(PPCISD::FADDRTZ, dl, MVT::f64, Lo, Hi); - - // We know the low half is about to be thrown away, so just use something - // convenient. - Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::ppcf128, - FPreg, FPreg)); - return; - } case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: // LowerFP_TO_INT() can only handle f32 and f64. @@ -10017,6 +10272,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MI.getOpcode() == PPC::SELECT_CC_I8 || MI.getOpcode() == PPC::SELECT_CC_F4 || MI.getOpcode() == PPC::SELECT_CC_F8 || + MI.getOpcode() == PPC::SELECT_CC_F16 || MI.getOpcode() == PPC::SELECT_CC_QFRC || MI.getOpcode() == PPC::SELECT_CC_QSRC || MI.getOpcode() == PPC::SELECT_CC_QBRC || @@ -10024,13 +10280,18 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MI.getOpcode() == PPC::SELECT_CC_VSFRC || MI.getOpcode() == PPC::SELECT_CC_VSSRC || MI.getOpcode() == PPC::SELECT_CC_VSRC || + MI.getOpcode() == PPC::SELECT_CC_SPE4 || + MI.getOpcode() == PPC::SELECT_CC_SPE || MI.getOpcode() == PPC::SELECT_I4 || MI.getOpcode() == PPC::SELECT_I8 || MI.getOpcode() == PPC::SELECT_F4 || MI.getOpcode() == PPC::SELECT_F8 || + MI.getOpcode() == PPC::SELECT_F16 || MI.getOpcode() == PPC::SELECT_QFRC || MI.getOpcode() == PPC::SELECT_QSRC || MI.getOpcode() == PPC::SELECT_QBRC || + MI.getOpcode() == PPC::SELECT_SPE || + MI.getOpcode() == PPC::SELECT_SPE4 || MI.getOpcode() == PPC::SELECT_VRRC || MI.getOpcode() == PPC::SELECT_VSFRC || MI.getOpcode() == PPC::SELECT_VSSRC || @@ -10063,6 +10324,9 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, if (MI.getOpcode() == PPC::SELECT_I4 || MI.getOpcode() == PPC::SELECT_I8 || MI.getOpcode() == PPC::SELECT_F4 || MI.getOpcode() == PPC::SELECT_F8 || + MI.getOpcode() == PPC::SELECT_F16 || + MI.getOpcode() == PPC::SELECT_SPE4 || + MI.getOpcode() == PPC::SELECT_SPE || MI.getOpcode() == PPC::SELECT_QFRC || MI.getOpcode() == PPC::SELECT_QSRC || MI.getOpcode() == PPC::SELECT_QBRC || @@ -10615,6 +10879,7 @@ unsigned PPCTargetLowering::combineRepeatedFPDivisors() const { return 3; case PPC::DIR_440: case PPC::DIR_A2: + case PPC::DIR_E500: case PPC::DIR_E500mc: case PPC::DIR_E5500: return 2; @@ -10896,7 +11161,7 @@ SDValue PPCTargetLowering::ConvertSETCCToSubtract(SDNode *N, // Size of integers being compared has a critical role in the following // analysis, so we prefer to do this when all types are legal. - if (!DCI.isAfterLegalizeVectorOps()) + if (!DCI.isAfterLegalizeDAG()) return SDValue(); // If all users of SETCC extend its value to a legal integer type @@ -11494,7 +11759,7 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N, ShiftCst); } -/// \brief Reduces the number of fp-to-int conversion when building a vector. +/// Reduces the number of fp-to-int conversion when building a vector. /// /// If this vector is built out of floating to integer conversions, /// transform it to a vector built out of floating point values followed by a @@ -11574,7 +11839,7 @@ combineElementTruncationToVectorTruncation(SDNode *N, return SDValue(); } -/// \brief Reduce the number of loads when building a vector. +/// Reduce the number of loads when building a vector. /// /// Building a vector out of multiple loads can be converted to a load /// of the vector type if the loads are consecutive. If the loads are @@ -11882,10 +12147,12 @@ SDValue PPCTargetLowering::combineFPToIntToFP(SDNode *N, SDLoc dl(N); SDValue Op(N, 0); - // Don't handle ppc_fp128 here or i1 conversions. + // Don't handle ppc_fp128 here or conversions that are out-of-range capable + // from the hardware. if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64) return SDValue(); - if (Op.getOperand(0).getValueType() == MVT::i1) + if (Op.getOperand(0).getValueType().getSimpleVT() <= MVT(MVT::i1) || + Op.getOperand(0).getValueType().getSimpleVT() > MVT(MVT::i64)) return SDValue(); SDValue FirstOperand(Op.getOperand(0)); @@ -12105,6 +12372,64 @@ SDValue PPCTargetLowering::expandVSXStoreForLE(SDNode *N, return Store; } +// Handle DAG combine for STORE (FP_TO_INT F). +SDValue PPCTargetLowering::combineStoreFPToInt(SDNode *N, + DAGCombinerInfo &DCI) const { + + SelectionDAG &DAG = DCI.DAG; + SDLoc dl(N); + unsigned Opcode = N->getOperand(1).getOpcode(); + + assert((Opcode == ISD::FP_TO_SINT || Opcode == ISD::FP_TO_UINT) + && "Not a FP_TO_INT Instruction!"); + + SDValue Val = N->getOperand(1).getOperand(0); + EVT Op1VT = N->getOperand(1).getValueType(); + EVT ResVT = Val.getValueType(); + + // Floating point types smaller than 32 bits are not legal on Power. + if (ResVT.getScalarSizeInBits() < 32) + return SDValue(); + + // Only perform combine for conversion to i64/i32 or power9 i16/i8. + bool ValidTypeForStoreFltAsInt = + (Op1VT == MVT::i32 || Op1VT == MVT::i64 || + (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8))); + + if (ResVT == MVT::ppcf128 || !Subtarget.hasP8Altivec() || + cast<StoreSDNode>(N)->isTruncatingStore() || !ValidTypeForStoreFltAsInt) + return SDValue(); + + // Extend f32 values to f64 + if (ResVT.getScalarSizeInBits() == 32) { + Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + } + + // Set signed or unsigned conversion opcode. + unsigned ConvOpcode = (Opcode == ISD::FP_TO_SINT) ? + PPCISD::FP_TO_SINT_IN_VSR : + PPCISD::FP_TO_UINT_IN_VSR; + + Val = DAG.getNode(ConvOpcode, + dl, ResVT == MVT::f128 ? MVT::f128 : MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + + // Set number of bytes being converted. + unsigned ByteSize = Op1VT.getScalarSizeInBits() / 8; + SDValue Ops[] = { N->getOperand(0), Val, N->getOperand(2), + DAG.getIntPtrConstant(ByteSize, dl, false), + DAG.getValueType(Op1VT) }; + + Val = DAG.getMemIntrinsicNode(PPCISD::ST_VSR_SCAL_INT, dl, + DAG.getVTList(MVT::Other), Ops, + cast<StoreSDNode>(N)->getMemoryVT(), + cast<StoreSDNode>(N)->getMemOperand()); + + DCI.AddToWorklist(Val.getNode()); + return Val; +} + SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -12144,60 +12469,27 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, case ISD::UINT_TO_FP: return combineFPToIntToFP(N, DCI); case ISD::STORE: { - EVT Op1VT = N->getOperand(1).getValueType(); - bool ValidTypeForStoreFltAsInt = (Op1VT == MVT::i32) || - (Subtarget.hasP9Vector() && (Op1VT == MVT::i8 || Op1VT == MVT::i16)); - - // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)). - if (Subtarget.hasSTFIWX() && !cast<StoreSDNode>(N)->isTruncatingStore() && - N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && - ValidTypeForStoreFltAsInt && - N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) { - SDValue Val = N->getOperand(1).getOperand(0); - if (Val.getValueType() == MVT::f32) { - Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); - DCI.AddToWorklist(Val.getNode()); - } - Val = DAG.getNode(PPCISD::FCTIWZ, dl, MVT::f64, Val); - DCI.AddToWorklist(Val.getNode()); - if (Op1VT == MVT::i32) { - SDValue Ops[] = { - N->getOperand(0), Val, N->getOperand(2), - DAG.getValueType(N->getOperand(1).getValueType()) - }; - - Val = DAG.getMemIntrinsicNode(PPCISD::STFIWX, dl, - DAG.getVTList(MVT::Other), Ops, - cast<StoreSDNode>(N)->getMemoryVT(), - cast<StoreSDNode>(N)->getMemOperand()); - } else { - unsigned WidthInBytes = - N->getOperand(1).getValueType() == MVT::i8 ? 1 : 2; - SDValue WidthConst = DAG.getIntPtrConstant(WidthInBytes, dl, false); - - SDValue Ops[] = { - N->getOperand(0), Val, N->getOperand(2), WidthConst, - DAG.getValueType(N->getOperand(1).getValueType()) - }; - Val = DAG.getMemIntrinsicNode(PPCISD::STXSIX, dl, - DAG.getVTList(MVT::Other), Ops, - cast<StoreSDNode>(N)->getMemoryVT(), - cast<StoreSDNode>(N)->getMemOperand()); - } + EVT Op1VT = N->getOperand(1).getValueType(); + unsigned Opcode = N->getOperand(1).getOpcode(); - DCI.AddToWorklist(Val.getNode()); - return Val; + if (Opcode == ISD::FP_TO_SINT || Opcode == ISD::FP_TO_UINT) { + SDValue Val= combineStoreFPToInt(N, DCI); + if (Val) + return Val; } // Turn STORE (BSWAP) -> sthbrx/stwbrx. - if (cast<StoreSDNode>(N)->isUnindexed() && - N->getOperand(1).getOpcode() == ISD::BSWAP && + if (cast<StoreSDNode>(N)->isUnindexed() && Opcode == ISD::BSWAP && N->getOperand(1).getNode()->hasOneUse() && - (N->getOperand(1).getValueType() == MVT::i32 || - N->getOperand(1).getValueType() == MVT::i16 || - (Subtarget.hasLDBRX() && Subtarget.isPPC64() && - N->getOperand(1).getValueType() == MVT::i64))) { + (Op1VT == MVT::i32 || Op1VT == MVT::i16 || + (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) { + + // STBRX can only handle simple types. + EVT mVT = cast<StoreSDNode>(N)->getMemoryVT(); + if (mVT.isExtended()) + break; + SDValue BSwapOp = N->getOperand(1).getOperand(0); // Do an any-extend to 32-bits if this is a half-word input. if (BSwapOp.getValueType() == MVT::i16) @@ -12205,7 +12497,6 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, // If the type of BSWAP operand is wider than stored memory width // it need to be shifted to the right side before STBRX. - EVT mVT = cast<StoreSDNode>(N)->getMemoryVT(); if (Op1VT.bitsGT(mVT)) { int Shift = Op1VT.getSizeInBits() - mVT.getSizeInBits(); BSwapOp = DAG.getNode(ISD::SRL, dl, Op1VT, BSwapOp, @@ -12226,9 +12517,8 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, // STORE Constant:i32<0> -> STORE<trunc to i32> Constant:i64<0> // So it can increase the chance of CSE constant construction. - EVT VT = N->getOperand(1).getValueType(); if (Subtarget.isPPC64() && !DCI.isBeforeLegalize() && - isa<ConstantSDNode>(N->getOperand(1)) && VT == MVT::i32) { + isa<ConstantSDNode>(N->getOperand(1)) && Op1VT == MVT::i32) { // Need to sign-extended to 64-bits to handle negative values. EVT MemVT = cast<StoreSDNode>(N)->getMemoryVT(); uint64_t Val64 = SignExtend64(N->getConstantOperandVal(1), @@ -12246,8 +12536,8 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, // For little endian, VSX stores require generating xxswapd/lxvd2x. // Not needed on ISA 3.0 based CPUs since we have a non-permuting store. - if (VT.isSimple()) { - MVT StoreVT = VT.getSimpleVT(); + if (Op1VT.isSimple()) { + MVT StoreVT = Op1VT.getSimpleVT(); if (Subtarget.needsSwapsForVSXMemOps() && (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 || StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32)) @@ -13030,14 +13320,21 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, // really care overly much here so just give them all the same reg classes. case 'd': case 'f': - if (VT == MVT::f32 || VT == MVT::i32) - return std::make_pair(0U, &PPC::F4RCRegClass); - if (VT == MVT::f64 || VT == MVT::i64) - return std::make_pair(0U, &PPC::F8RCRegClass); - if (VT == MVT::v4f64 && Subtarget.hasQPX()) - return std::make_pair(0U, &PPC::QFRCRegClass); - if (VT == MVT::v4f32 && Subtarget.hasQPX()) - return std::make_pair(0U, &PPC::QSRCRegClass); + if (Subtarget.hasSPE()) { + if (VT == MVT::f32 || VT == MVT::i32) + return std::make_pair(0U, &PPC::SPE4RCRegClass); + if (VT == MVT::f64 || VT == MVT::i64) + return std::make_pair(0U, &PPC::SPERCRegClass); + } else { + if (VT == MVT::f32 || VT == MVT::i32) + return std::make_pair(0U, &PPC::F4RCRegClass); + if (VT == MVT::f64 || VT == MVT::i64) + return std::make_pair(0U, &PPC::F8RCRegClass); + if (VT == MVT::v4f64 && Subtarget.hasQPX()) + return std::make_pair(0U, &PPC::QFRCRegClass); + if (VT == MVT::v4f32 && Subtarget.hasQPX()) + return std::make_pair(0U, &PPC::QSRCRegClass); + } break; case 'v': if (VT == MVT::v4f64 && Subtarget.hasQPX()) @@ -13520,7 +13817,7 @@ EVT PPCTargetLowering::getOptimalMemOpType(uint64_t Size, return MVT::i32; } -/// \brief Returns true if it is beneficial to convert a load of a constant +/// Returns true if it is beneficial to convert a load of a constant /// to just the constant itself. bool PPCTargetLowering::shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const { @@ -13569,6 +13866,9 @@ bool PPCTargetLowering::isZExtFree(SDValue Val, EVT VT2) const { bool PPCTargetLowering::isFPExtFree(EVT DestVT, EVT SrcVT) const { assert(DestVT.isFloatingPoint() && SrcVT.isFloatingPoint() && "invalid fpext types"); + // Extending to float128 is not free. + if (DestVT == MVT::f128) + return false; return true; } @@ -13625,6 +13925,8 @@ bool PPCTargetLowering::isFMAFasterThanFMulAndFAdd(EVT VT) const { case MVT::f32: case MVT::f64: return true; + case MVT::f128: + return (EnableQuadPrecision && Subtarget.hasP9Vector()); default: break; } @@ -13853,3 +14155,20 @@ bool PPCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const { // If the function is local then we have a good chance at tail-calling it return getTargetMachine().shouldAssumeDSOLocal(*Caller->getParent(), Callee); } + +bool PPCTargetLowering:: +isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const { + const Value *Mask = AndI.getOperand(1); + // If the mask is suitable for andi. or andis. we should sink the and. + if (const ConstantInt *CI = dyn_cast<ConstantInt>(Mask)) { + // Can't handle constants wider than 64-bits. + if (CI->getBitWidth() > 64) + return false; + int64_t ConstVal = CI->getZExtValue(); + return isUInt<16>(ConstVal) || + (isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF)); + } + + // For non-constant masks, we can always use the record-form and. + return true; +} diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index b119e5b4a564..9b8d6435515b 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -20,7 +20,6 @@ #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetLowering.h" @@ -31,6 +30,7 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Type.h" +#include "llvm/Support/MachineValueType.h" #include <utility> namespace llvm { @@ -71,6 +71,9 @@ namespace llvm { /// unsigned integers with round toward zero. FCTIDUZ, FCTIWUZ, + /// Floating-point-to-interger conversion instructions + FP_TO_UINT_IN_VSR, FP_TO_SINT_IN_VSR, + /// VEXTS, ByteWidth - takes an input in VSFRC and produces an output in /// VSFRC that is sign-extended from ByteWidth to a 64-byte integer. VEXTS, @@ -186,6 +189,9 @@ namespace llvm { /// Direct move from a GPR to a VSX register (zero) MTVSRZ, + /// Direct move of 2 consective GPR to a VSX register. + BUILD_FP128, + /// Extract a subvector from signed integer vector and convert to FP. /// It is primarily used to convert a (widened) illegal integer vector /// type to a legal floating point vector type. @@ -426,10 +432,18 @@ namespace llvm { /// an xxswapd. STXVD2X, + /// Store scalar integers from VSR. + ST_VSR_SCAL_INT, + /// QBRC, CHAIN = QVLFSb CHAIN, Ptr /// The 4xf32 load used for v4i1 constants. QVLFSb, + /// ATOMIC_CMP_SWAP - the exact same as the target-independent nodes + /// except they ensure that the compare input is zero-extended for + /// sub-word versions because the atomic loads zero-extend. + ATOMIC_CMP_SWAP_8, ATOMIC_CMP_SWAP_16, + /// GPRC = TOC_ENTRY GA, TOC /// Loads the entry for GA from the TOC, where the TOC base is given by /// the last operand. @@ -560,6 +574,8 @@ namespace llvm { bool useSoftFloat() const override; + bool hasSPE() const; + MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { return MVT::i32; } @@ -760,7 +776,7 @@ namespace llvm { bool isFPExtFree(EVT DestVT, EVT SrcVT) const override; - /// \brief Returns true if it is beneficial to convert a load of a constant + /// Returns true if it is beneficial to convert a load of a constant /// to just the constant itself. bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override; @@ -817,7 +833,7 @@ namespace llvm { FastISel *createFastISel(FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const override; - /// \brief Returns true if an argument of type Ty needs to be passed in a + /// Returns true if an argument of type Ty needs to be passed in a /// contiguous block of registers in calling convention CallConv. bool functionArgumentNeedsConsecutiveRegisters( Type *Ty, CallingConv::ID CallConv, bool isVarArg) const override { @@ -855,6 +871,12 @@ namespace llvm { unsigned JTI, MCContext &Ctx) const override; + unsigned getNumRegistersForCallingConv(LLVMContext &Context, + EVT VT) const override; + + MVT getRegisterTypeForCallingConv(LLVMContext &Context, + EVT VT) const override; + private: struct ReuseLoadInfo { SDValue Ptr; @@ -879,6 +901,11 @@ namespace llvm { } }; + bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override { + // Addrspacecasts are always noops. + return true; + } + bool canReuseLoadAddress(SDValue Op, EVT MemVT, ReuseLoadInfo &RLI, SelectionDAG &DAG, ISD::LoadExtType ET = ISD::NON_EXTLOAD) const; @@ -955,6 +982,7 @@ namespace llvm { SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; SDValue LowerREM(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBSWAP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerATOMIC_CMP_SWAP(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const; @@ -1048,10 +1076,12 @@ namespace llvm { SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) const; SDValue DAGCombineExtBoolTrunc(SDNode *N, DAGCombinerInfo &DCI) const; SDValue DAGCombineBuildVector(SDNode *N, DAGCombinerInfo &DCI) const; SDValue DAGCombineTruncBoolExt(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue combineStoreFPToInt(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineFPToIntToFP(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSHL(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSRA(SDNode *N, DAGCombinerInfo &DCI) const; @@ -1090,6 +1120,7 @@ namespace llvm { // tail call. This will cause the optimizers to attempt to move, or // duplicate return instructions to help enable tail call optimizations. bool mayBeEmittedAsTailCall(const CallInst *CI) const override; + bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override; }; // end class PPCTargetLowering namespace PPC { diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index fdd28c2ff03f..cdd57c6a1118 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -244,8 +244,8 @@ let usesCustomInserter = 1 in { // Instructions to support atomic operations let mayLoad = 1, hasSideEffects = 0 in { -def LDARX : XForm_1<31, 84, (outs g8rc:$rD), (ins memrr:$ptr), - "ldarx $rD, $ptr", IIC_LdStLDARX, []>; +def LDARX : XForm_1_memOp<31, 84, (outs g8rc:$rD), (ins memrr:$ptr), + "ldarx $rD, $ptr", IIC_LdStLDARX, []>; // Instruction to support lock versions of atomics // (EH=1 - see Power ISA 2.07 Book II 4.4.2) @@ -259,8 +259,8 @@ def LDAT : X_RD5_RS5_IM5<31, 614, (outs g8rc:$rD), (ins g8rc:$rA, u5imm:$FC), } let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in -def STDCX : XForm_1<31, 214, (outs), (ins g8rc:$rS, memrr:$dst), - "stdcx. $rS, $dst", IIC_LdStSTDCX, []>, isDOT; +def STDCX : XForm_1_memOp<31, 214, (outs), (ins g8rc:$rS, memrr:$dst), + "stdcx. $rS, $dst", IIC_LdStSTDCX, []>, isDOT; let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in def STDAT : X_RD5_RS5_IM5<31, 742, (outs), (ins g8rc:$rS, g8rc:$rA, u5imm:$FC), @@ -499,7 +499,49 @@ defm ADD8 : XOForm_1r<31, 266, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB), def ADD8TLS : XOForm_1<31, 266, 0, (outs g8rc:$rT), (ins g8rc_nox0:$rA, tlsreg:$rB), "add $rT, $rA, $rB", IIC_IntSimple, [(set i64:$rT, (add i64:$rA, tglobaltlsaddr:$rB))]>; - +let mayLoad = 1 in { +def LBZXTLS : XForm_1<31, 87, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lbzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LHZXTLS : XForm_1<31, 279, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lhzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LWZXTLS : XForm_1<31, 23, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lwzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LDXTLS : XForm_1<31, 21, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "ldx $rD, $rA, $rB", IIC_LdStLD, []>, isPPC64; +def LBZXTLS_32 : XForm_1<31, 87, (outs gprc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lbzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LHZXTLS_32 : XForm_1<31, 279, (outs gprc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lhzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LWZXTLS_32 : XForm_1<31, 23, (outs gprc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lwzx $rD, $rA, $rB", IIC_LdStLoad, []>; + +} + +let mayStore = 1 in { +def STBXTLS : XForm_8<31, 215, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stbx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STHXTLS : XForm_8<31, 407, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "sthx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STWXTLS : XForm_8<31, 151, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stwx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STDXTLS : XForm_8<31, 149, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stdx $rS, $rA, $rB", IIC_LdStSTD, []>, isPPC64, + PPC970_DGroup_Cracked; +def STBXTLS_32 : XForm_8<31, 215, (outs), (ins gprc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stbx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STHXTLS_32 : XForm_8<31, 407, (outs), (ins gprc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "sthx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STWXTLS_32 : XForm_8<31, 151, (outs), (ins gprc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stwx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; + +} + let isCommutable = 1 in defm ADDC8 : XOForm_1rc<31, 10, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB), "addc", "$rT, $rA, $rB", IIC_IntGeneral, @@ -558,10 +600,37 @@ defm SUBFZE8 : XOForm_3rc<31, 200, 0, (outs g8rc:$rT), (ins g8rc:$rA), // FIXME: Duplicating this for the asm parser should be unnecessary, but the // previous definition must be marked as CodeGen only to prevent decoding // conflicts. -let isAsmParserOnly = 1 in +let isAsmParserOnly = 1 in { def ADD8TLS_ : XOForm_1<31, 266, 0, (outs g8rc:$rT), (ins g8rc:$rA, tlsreg:$rB), "add $rT, $rA, $rB", IIC_IntSimple, []>; +let mayLoad = 1 in { +def LBZXTLS_ : XForm_1<31, 87, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lbzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LHZXTLS_ : XForm_1<31, 279, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lhzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LWZXTLS_ : XForm_1<31, 23, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "lwzx $rD, $rA, $rB", IIC_LdStLoad, []>; +def LDXTLS_ : XForm_1<31, 21, (outs g8rc:$rD), (ins ptr_rc_nor0:$rA, tlsreg:$rB), + "ldx $rD, $rA, $rB", IIC_LdStLD, []>, isPPC64; +} + +let mayStore = 1 in { +def STBXTLS_ : XForm_8<31, 215, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stbx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STHXTLS_ : XForm_8<31, 407, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "sthx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STWXTLS_ : XForm_8<31, 151, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stwx $rS, $rA, $rB", IIC_LdStStore, []>, + PPC970_DGroup_Cracked; +def STDXTLS_ : XForm_8<31, 149, (outs), (ins g8rc:$rS, ptr_rc_nor0:$rA, tlsreg:$rB), + "stdx $rS, $rA, $rB", IIC_LdStSTD, []>, isPPC64, + PPC970_DGroup_Cracked; +} +} + let isCommutable = 1 in { defm MULHD : XOForm_1r<31, 73, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB), "mulhd", "$rT, $rA, $rB", IIC_IntMulHW, @@ -837,22 +906,22 @@ def LWA : DSForm_1<58, 2, (outs g8rc:$rD), (ins memrix:$src), (aligned4sextloadi32 ixaddr:$src))]>, isPPC64, PPC970_DGroup_Cracked; let Interpretation64Bit = 1, isCodeGenOnly = 1 in -def LHAX8: XForm_1<31, 343, (outs g8rc:$rD), (ins memrr:$src), - "lhax $rD, $src", IIC_LdStLHA, - [(set i64:$rD, (sextloadi16 xaddr:$src))]>, - PPC970_DGroup_Cracked; -def LWAX : XForm_1<31, 341, (outs g8rc:$rD), (ins memrr:$src), - "lwax $rD, $src", IIC_LdStLHA, - [(set i64:$rD, (sextloadi32 xaddr:$src))]>, isPPC64, - PPC970_DGroup_Cracked; +def LHAX8: XForm_1_memOp<31, 343, (outs g8rc:$rD), (ins memrr:$src), + "lhax $rD, $src", IIC_LdStLHA, + [(set i64:$rD, (sextloadi16 xaddr:$src))]>, + PPC970_DGroup_Cracked; +def LWAX : XForm_1_memOp<31, 341, (outs g8rc:$rD), (ins memrr:$src), + "lwax $rD, $src", IIC_LdStLHA, + [(set i64:$rD, (sextloadi32 xaddr:$src))]>, isPPC64, + PPC970_DGroup_Cracked; // For fast-isel: let isCodeGenOnly = 1, mayLoad = 1 in { def LWA_32 : DSForm_1<58, 2, (outs gprc:$rD), (ins memrix:$src), "lwa $rD, $src", IIC_LdStLWA, []>, isPPC64, PPC970_DGroup_Cracked; -def LWAX_32 : XForm_1<31, 341, (outs gprc:$rD), (ins memrr:$src), - "lwax $rD, $src", IIC_LdStLHA, []>, isPPC64, - PPC970_DGroup_Cracked; +def LWAX_32 : XForm_1_memOp<31, 341, (outs gprc:$rD), (ins memrr:$src), + "lwax $rD, $src", IIC_LdStLHA, []>, isPPC64, + PPC970_DGroup_Cracked; } // end fast-isel isCodeGenOnly // Update forms. @@ -866,16 +935,16 @@ def LHAU8 : DForm_1<43, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), // NO LWAU! let Interpretation64Bit = 1, isCodeGenOnly = 1 in -def LHAUX8 : XForm_1<31, 375, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), - (ins memrr:$addr), - "lhaux $rD, $addr", IIC_LdStLHAUX, - []>, RegConstraint<"$addr.ptrreg = $ea_result">, - NoEncode<"$ea_result">; -def LWAUX : XForm_1<31, 373, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), - (ins memrr:$addr), - "lwaux $rD, $addr", IIC_LdStLHAUX, - []>, RegConstraint<"$addr.ptrreg = $ea_result">, - NoEncode<"$ea_result">, isPPC64; +def LHAUX8 : XForm_1_memOp<31, 375, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memrr:$addr), + "lhaux $rD, $addr", IIC_LdStLHAUX, + []>, RegConstraint<"$addr.ptrreg = $ea_result">, + NoEncode<"$ea_result">; +def LWAUX : XForm_1_memOp<31, 373, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memrr:$addr), + "lwaux $rD, $addr", IIC_LdStLHAUX, + []>, RegConstraint<"$addr.ptrreg = $ea_result">, + NoEncode<"$ea_result">, isPPC64; } } @@ -892,47 +961,50 @@ def LWZ8 : DForm_1<32, (outs g8rc:$rD), (ins memri:$src), "lwz $rD, $src", IIC_LdStLoad, [(set i64:$rD, (zextloadi32 iaddr:$src))]>, isPPC64; -def LBZX8 : XForm_1<31, 87, (outs g8rc:$rD), (ins memrr:$src), - "lbzx $rD, $src", IIC_LdStLoad, - [(set i64:$rD, (zextloadi8 xaddr:$src))]>; -def LHZX8 : XForm_1<31, 279, (outs g8rc:$rD), (ins memrr:$src), - "lhzx $rD, $src", IIC_LdStLoad, - [(set i64:$rD, (zextloadi16 xaddr:$src))]>; -def LWZX8 : XForm_1<31, 23, (outs g8rc:$rD), (ins memrr:$src), - "lwzx $rD, $src", IIC_LdStLoad, - [(set i64:$rD, (zextloadi32 xaddr:$src))]>; +def LBZX8 : XForm_1_memOp<31, 87, (outs g8rc:$rD), (ins memrr:$src), + "lbzx $rD, $src", IIC_LdStLoad, + [(set i64:$rD, (zextloadi8 xaddr:$src))]>; +def LHZX8 : XForm_1_memOp<31, 279, (outs g8rc:$rD), (ins memrr:$src), + "lhzx $rD, $src", IIC_LdStLoad, + [(set i64:$rD, (zextloadi16 xaddr:$src))]>; +def LWZX8 : XForm_1_memOp<31, 23, (outs g8rc:$rD), (ins memrr:$src), + "lwzx $rD, $src", IIC_LdStLoad, + [(set i64:$rD, (zextloadi32 xaddr:$src))]>; // Update forms. let mayLoad = 1, hasSideEffects = 0 in { -def LBZU8 : DForm_1<35, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), (ins memri:$addr), +def LBZU8 : DForm_1<35, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memri:$addr), "lbzu $rD, $addr", IIC_LdStLoadUpd, []>, RegConstraint<"$addr.reg = $ea_result">, NoEncode<"$ea_result">; -def LHZU8 : DForm_1<41, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), (ins memri:$addr), +def LHZU8 : DForm_1<41, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memri:$addr), "lhzu $rD, $addr", IIC_LdStLoadUpd, []>, RegConstraint<"$addr.reg = $ea_result">, NoEncode<"$ea_result">; -def LWZU8 : DForm_1<33, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), (ins memri:$addr), +def LWZU8 : DForm_1<33, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memri:$addr), "lwzu $rD, $addr", IIC_LdStLoadUpd, []>, RegConstraint<"$addr.reg = $ea_result">, NoEncode<"$ea_result">; -def LBZUX8 : XForm_1<31, 119, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), - (ins memrr:$addr), - "lbzux $rD, $addr", IIC_LdStLoadUpdX, - []>, RegConstraint<"$addr.ptrreg = $ea_result">, - NoEncode<"$ea_result">; -def LHZUX8 : XForm_1<31, 311, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), - (ins memrr:$addr), - "lhzux $rD, $addr", IIC_LdStLoadUpdX, - []>, RegConstraint<"$addr.ptrreg = $ea_result">, - NoEncode<"$ea_result">; -def LWZUX8 : XForm_1<31, 55, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), - (ins memrr:$addr), - "lwzux $rD, $addr", IIC_LdStLoadUpdX, - []>, RegConstraint<"$addr.ptrreg = $ea_result">, - NoEncode<"$ea_result">; +def LBZUX8 : XForm_1_memOp<31, 119, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memrr:$addr), + "lbzux $rD, $addr", IIC_LdStLoadUpdX, + []>, RegConstraint<"$addr.ptrreg = $ea_result">, + NoEncode<"$ea_result">; +def LHZUX8 : XForm_1_memOp<31, 311, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memrr:$addr), + "lhzux $rD, $addr", IIC_LdStLoadUpdX, + []>, RegConstraint<"$addr.ptrreg = $ea_result">, + NoEncode<"$ea_result">; +def LWZUX8 : XForm_1_memOp<31, 55, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memrr:$addr), + "lwzux $rD, $addr", IIC_LdStLoadUpdX, + []>, RegConstraint<"$addr.ptrreg = $ea_result">, + NoEncode<"$ea_result">; } } } // Interpretation64Bit @@ -963,35 +1035,36 @@ def LDtocBA: Pseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc:$reg), [(set i64:$rD, (PPCtoc_entry tblockaddress:$disp, i64:$reg))]>, isPPC64; -def LDX : XForm_1<31, 21, (outs g8rc:$rD), (ins memrr:$src), - "ldx $rD, $src", IIC_LdStLD, - [(set i64:$rD, (load xaddr:$src))]>, isPPC64; -def LDBRX : XForm_1<31, 532, (outs g8rc:$rD), (ins memrr:$src), - "ldbrx $rD, $src", IIC_LdStLoad, - [(set i64:$rD, (PPClbrx xoaddr:$src, i64))]>, isPPC64; +def LDX : XForm_1_memOp<31, 21, (outs g8rc:$rD), (ins memrr:$src), + "ldx $rD, $src", IIC_LdStLD, + [(set i64:$rD, (load xaddr:$src))]>, isPPC64; +def LDBRX : XForm_1_memOp<31, 532, (outs g8rc:$rD), (ins memrr:$src), + "ldbrx $rD, $src", IIC_LdStLoad, + [(set i64:$rD, (PPClbrx xoaddr:$src, i64))]>, isPPC64; let mayLoad = 1, hasSideEffects = 0, isCodeGenOnly = 1 in { -def LHBRX8 : XForm_1<31, 790, (outs g8rc:$rD), (ins memrr:$src), - "lhbrx $rD, $src", IIC_LdStLoad, []>; -def LWBRX8 : XForm_1<31, 534, (outs g8rc:$rD), (ins memrr:$src), - "lwbrx $rD, $src", IIC_LdStLoad, []>; +def LHBRX8 : XForm_1_memOp<31, 790, (outs g8rc:$rD), (ins memrr:$src), + "lhbrx $rD, $src", IIC_LdStLoad, []>; +def LWBRX8 : XForm_1_memOp<31, 534, (outs g8rc:$rD), (ins memrr:$src), + "lwbrx $rD, $src", IIC_LdStLoad, []>; } let mayLoad = 1, hasSideEffects = 0 in { -def LDU : DSForm_1<58, 1, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), (ins memrix:$addr), +def LDU : DSForm_1<58, 1, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memrix:$addr), "ldu $rD, $addr", IIC_LdStLDU, []>, RegConstraint<"$addr.reg = $ea_result">, isPPC64, NoEncode<"$ea_result">; -def LDUX : XForm_1<31, 53, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), - (ins memrr:$addr), - "ldux $rD, $addr", IIC_LdStLDUX, - []>, RegConstraint<"$addr.ptrreg = $ea_result">, - NoEncode<"$ea_result">, isPPC64; +def LDUX : XForm_1_memOp<31, 53, (outs g8rc:$rD, ptr_rc_nor0:$ea_result), + (ins memrr:$addr), + "ldux $rD, $addr", IIC_LdStLDUX, + []>, RegConstraint<"$addr.ptrreg = $ea_result">, + NoEncode<"$ea_result">, isPPC64; def LDMX : XForm_1<31, 309, (outs g8rc:$rD), (ins memrr:$src), "ldmx $rD, $src", IIC_LdStLD, []>, isPPC64, - Requires<[IsISA3_0]>; + Requires<[IsISA3_0]>; } } @@ -1116,32 +1189,32 @@ def STH8 : DForm_1<44, (outs), (ins g8rc:$rS, memri:$src), def STW8 : DForm_1<36, (outs), (ins g8rc:$rS, memri:$src), "stw $rS, $src", IIC_LdStStore, [(truncstorei32 i64:$rS, iaddr:$src)]>; -def STBX8 : XForm_8<31, 215, (outs), (ins g8rc:$rS, memrr:$dst), - "stbx $rS, $dst", IIC_LdStStore, - [(truncstorei8 i64:$rS, xaddr:$dst)]>, - PPC970_DGroup_Cracked; -def STHX8 : XForm_8<31, 407, (outs), (ins g8rc:$rS, memrr:$dst), - "sthx $rS, $dst", IIC_LdStStore, - [(truncstorei16 i64:$rS, xaddr:$dst)]>, - PPC970_DGroup_Cracked; -def STWX8 : XForm_8<31, 151, (outs), (ins g8rc:$rS, memrr:$dst), - "stwx $rS, $dst", IIC_LdStStore, - [(truncstorei32 i64:$rS, xaddr:$dst)]>, - PPC970_DGroup_Cracked; +def STBX8 : XForm_8_memOp<31, 215, (outs), (ins g8rc:$rS, memrr:$dst), + "stbx $rS, $dst", IIC_LdStStore, + [(truncstorei8 i64:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; +def STHX8 : XForm_8_memOp<31, 407, (outs), (ins g8rc:$rS, memrr:$dst), + "sthx $rS, $dst", IIC_LdStStore, + [(truncstorei16 i64:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; +def STWX8 : XForm_8_memOp<31, 151, (outs), (ins g8rc:$rS, memrr:$dst), + "stwx $rS, $dst", IIC_LdStStore, + [(truncstorei32 i64:$rS, xaddr:$dst)]>, + PPC970_DGroup_Cracked; } // Interpretation64Bit // Normal 8-byte stores. def STD : DSForm_1<62, 0, (outs), (ins g8rc:$rS, memrix:$dst), "std $rS, $dst", IIC_LdStSTD, [(aligned4store i64:$rS, ixaddr:$dst)]>, isPPC64; -def STDX : XForm_8<31, 149, (outs), (ins g8rc:$rS, memrr:$dst), - "stdx $rS, $dst", IIC_LdStSTD, - [(store i64:$rS, xaddr:$dst)]>, isPPC64, - PPC970_DGroup_Cracked; -def STDBRX: XForm_8<31, 660, (outs), (ins g8rc:$rS, memrr:$dst), - "stdbrx $rS, $dst", IIC_LdStStore, - [(PPCstbrx i64:$rS, xoaddr:$dst, i64)]>, isPPC64, - PPC970_DGroup_Cracked; +def STDX : XForm_8_memOp<31, 149, (outs), (ins g8rc:$rS, memrr:$dst), + "stdx $rS, $dst", IIC_LdStSTD, + [(store i64:$rS, xaddr:$dst)]>, isPPC64, + PPC970_DGroup_Cracked; +def STDBRX: XForm_8_memOp<31, 660, (outs), (ins g8rc:$rS, memrr:$dst), + "stdbrx $rS, $dst", IIC_LdStStore, + [(PPCstbrx i64:$rS, xoaddr:$dst, i64)]>, isPPC64, + PPC970_DGroup_Cracked; } // Stores with Update (pre-inc). @@ -1157,29 +1230,38 @@ def STWU8 : DForm_1<37, (outs ptr_rc_nor0:$ea_res), (ins g8rc:$rS, memri:$dst), "stwu $rS, $dst", IIC_LdStStoreUpd, []>, RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">; -def STBUX8: XForm_8<31, 247, (outs ptr_rc_nor0:$ea_res), (ins g8rc:$rS, memrr:$dst), - "stbux $rS, $dst", IIC_LdStStoreUpd, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; -def STHUX8: XForm_8<31, 439, (outs ptr_rc_nor0:$ea_res), (ins g8rc:$rS, memrr:$dst), - "sthux $rS, $dst", IIC_LdStStoreUpd, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; -def STWUX8: XForm_8<31, 183, (outs ptr_rc_nor0:$ea_res), (ins g8rc:$rS, memrr:$dst), - "stwux $rS, $dst", IIC_LdStStoreUpd, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; +def STBUX8: XForm_8_memOp<31, 247, (outs ptr_rc_nor0:$ea_res), + (ins g8rc:$rS, memrr:$dst), + "stbux $rS, $dst", IIC_LdStStoreUpd, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; +def STHUX8: XForm_8_memOp<31, 439, (outs ptr_rc_nor0:$ea_res), + (ins g8rc:$rS, memrr:$dst), + "sthux $rS, $dst", IIC_LdStStoreUpd, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; +def STWUX8: XForm_8_memOp<31, 183, (outs ptr_rc_nor0:$ea_res), + (ins g8rc:$rS, memrr:$dst), + "stwux $rS, $dst", IIC_LdStStoreUpd, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; } // Interpretation64Bit -def STDU : DSForm_1<62, 1, (outs ptr_rc_nor0:$ea_res), (ins g8rc:$rS, memrix:$dst), +def STDU : DSForm_1<62, 1, (outs ptr_rc_nor0:$ea_res), + (ins g8rc:$rS, memrix:$dst), "stdu $rS, $dst", IIC_LdStSTDU, []>, RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">, isPPC64; -def STDUX : XForm_8<31, 181, (outs ptr_rc_nor0:$ea_res), (ins g8rc:$rS, memrr:$dst), - "stdux $rS, $dst", IIC_LdStSTDUX, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked, isPPC64; +def STDUX : XForm_8_memOp<31, 181, (outs ptr_rc_nor0:$ea_res), + (ins g8rc:$rS, memrr:$dst), + "stdux $rS, $dst", IIC_LdStSTDUX, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked, isPPC64; } // Patterns to match the pre-inc stores. We can't put the patterns on diff --git a/lib/Target/PowerPC/PPCInstrAltivec.td b/lib/Target/PowerPC/PPCInstrAltivec.td index e751c149b0b3..24969d7ef853 100644 --- a/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/lib/Target/PowerPC/PPCInstrAltivec.td @@ -408,46 +408,46 @@ def MTVSCR : VXForm_5<1604, (outs), (ins vrrc:$vB), [(int_ppc_altivec_mtvscr v4i32:$vB)]>; let PPC970_Unit = 2, mayLoad = 1, mayStore = 0 in { // Loads. -def LVEBX: XForm_1<31, 7, (outs vrrc:$vD), (ins memrr:$src), +def LVEBX: XForm_1_memOp<31, 7, (outs vrrc:$vD), (ins memrr:$src), "lvebx $vD, $src", IIC_LdStLoad, [(set v16i8:$vD, (int_ppc_altivec_lvebx xoaddr:$src))]>; -def LVEHX: XForm_1<31, 39, (outs vrrc:$vD), (ins memrr:$src), +def LVEHX: XForm_1_memOp<31, 39, (outs vrrc:$vD), (ins memrr:$src), "lvehx $vD, $src", IIC_LdStLoad, [(set v8i16:$vD, (int_ppc_altivec_lvehx xoaddr:$src))]>; -def LVEWX: XForm_1<31, 71, (outs vrrc:$vD), (ins memrr:$src), +def LVEWX: XForm_1_memOp<31, 71, (outs vrrc:$vD), (ins memrr:$src), "lvewx $vD, $src", IIC_LdStLoad, [(set v4i32:$vD, (int_ppc_altivec_lvewx xoaddr:$src))]>; -def LVX : XForm_1<31, 103, (outs vrrc:$vD), (ins memrr:$src), +def LVX : XForm_1_memOp<31, 103, (outs vrrc:$vD), (ins memrr:$src), "lvx $vD, $src", IIC_LdStLoad, [(set v4i32:$vD, (int_ppc_altivec_lvx xoaddr:$src))]>; -def LVXL : XForm_1<31, 359, (outs vrrc:$vD), (ins memrr:$src), +def LVXL : XForm_1_memOp<31, 359, (outs vrrc:$vD), (ins memrr:$src), "lvxl $vD, $src", IIC_LdStLoad, [(set v4i32:$vD, (int_ppc_altivec_lvxl xoaddr:$src))]>; } -def LVSL : XForm_1<31, 6, (outs vrrc:$vD), (ins memrr:$src), +def LVSL : XForm_1_memOp<31, 6, (outs vrrc:$vD), (ins memrr:$src), "lvsl $vD, $src", IIC_LdStLoad, [(set v16i8:$vD, (int_ppc_altivec_lvsl xoaddr:$src))]>, PPC970_Unit_LSU; -def LVSR : XForm_1<31, 38, (outs vrrc:$vD), (ins memrr:$src), +def LVSR : XForm_1_memOp<31, 38, (outs vrrc:$vD), (ins memrr:$src), "lvsr $vD, $src", IIC_LdStLoad, [(set v16i8:$vD, (int_ppc_altivec_lvsr xoaddr:$src))]>, PPC970_Unit_LSU; let PPC970_Unit = 2, mayStore = 1, mayLoad = 0 in { // Stores. -def STVEBX: XForm_8<31, 135, (outs), (ins vrrc:$rS, memrr:$dst), +def STVEBX: XForm_8_memOp<31, 135, (outs), (ins vrrc:$rS, memrr:$dst), "stvebx $rS, $dst", IIC_LdStStore, [(int_ppc_altivec_stvebx v16i8:$rS, xoaddr:$dst)]>; -def STVEHX: XForm_8<31, 167, (outs), (ins vrrc:$rS, memrr:$dst), +def STVEHX: XForm_8_memOp<31, 167, (outs), (ins vrrc:$rS, memrr:$dst), "stvehx $rS, $dst", IIC_LdStStore, [(int_ppc_altivec_stvehx v8i16:$rS, xoaddr:$dst)]>; -def STVEWX: XForm_8<31, 199, (outs), (ins vrrc:$rS, memrr:$dst), +def STVEWX: XForm_8_memOp<31, 199, (outs), (ins vrrc:$rS, memrr:$dst), "stvewx $rS, $dst", IIC_LdStStore, [(int_ppc_altivec_stvewx v4i32:$rS, xoaddr:$dst)]>; -def STVX : XForm_8<31, 231, (outs), (ins vrrc:$rS, memrr:$dst), +def STVX : XForm_8_memOp<31, 231, (outs), (ins vrrc:$rS, memrr:$dst), "stvx $rS, $dst", IIC_LdStStore, [(int_ppc_altivec_stvx v4i32:$rS, xoaddr:$dst)]>; -def STVXL : XForm_8<31, 487, (outs), (ins vrrc:$rS, memrr:$dst), +def STVXL : XForm_8_memOp<31, 487, (outs), (ins vrrc:$rS, memrr:$dst), "stvxl $rS, $dst", IIC_LdStStore, [(int_ppc_altivec_stvxl v4i32:$rS, xoaddr:$dst)]>; } @@ -705,7 +705,7 @@ def VSPLTH : VXForm_1<588, (outs vrrc:$vD), (ins u5imm:$UIMM, vrrc:$vB), (vsplth_shuffle:$UIMM v16i8:$vB, (undef)))]>; def VSPLTW : VXForm_1<652, (outs vrrc:$vD), (ins u5imm:$UIMM, vrrc:$vB), "vspltw $vD, $vB, $UIMM", IIC_VecPerm, - [(set v16i8:$vD, + [(set v16i8:$vD, (vspltw_shuffle:$UIMM v16i8:$vB, (undef)))]>; let isCodeGenOnly = 1 in { def VSPLTBs : VXForm_1<524, (outs vrrc:$vD), (ins u5imm:$UIMM, vfrc:$vB), @@ -962,7 +962,7 @@ def : Pat<(and v4i32:$A, (vnot_ppc v4i32:$B)), def : Pat<(fmul v4f32:$vA, v4f32:$vB), (VMADDFP $vA, $vB, - (v4i32 (VSLW (V_SETALLONES), (V_SETALLONES))))>; + (v4i32 (VSLW (v4i32 (V_SETALLONES)), (v4i32 (V_SETALLONES)))))>; // Fused multiply add and multiply sub for packed float. These are represented // separately from the real instructions above, for operations that must have @@ -991,7 +991,7 @@ def : Pat<(v8i16 (shl v8i16:$vA, v8i16:$vB)), def : Pat<(v4i32 (shl v4i32:$vA, v4i32:$vB)), (v4i32 (VSLW $vA, $vB))>; def : Pat<(v1i128 (shl v1i128:$vA, v1i128:$vB)), - (v1i128 (VSL (VSLO $vA, $vB), (VSPLTB 15, $vB)))>; + (v1i128 (VSL (v16i8 (VSLO $vA, $vB)), (v16i8 (VSPLTB 15, $vB))))>; def : Pat<(v16i8 (PPCshl v16i8:$vA, v16i8:$vB)), (v16i8 (VSLB $vA, $vB))>; def : Pat<(v8i16 (PPCshl v8i16:$vA, v8i16:$vB)), @@ -999,7 +999,7 @@ def : Pat<(v8i16 (PPCshl v8i16:$vA, v8i16:$vB)), def : Pat<(v4i32 (PPCshl v4i32:$vA, v4i32:$vB)), (v4i32 (VSLW $vA, $vB))>; def : Pat<(v1i128 (PPCshl v1i128:$vA, v1i128:$vB)), - (v1i128 (VSL (VSLO $vA, $vB), (VSPLTB 15, $vB)))>; + (v1i128 (VSL (v16i8 (VSLO $vA, $vB)), (v16i8 (VSPLTB 15, $vB))))>; def : Pat<(v16i8 (srl v16i8:$vA, v16i8:$vB)), (v16i8 (VSRB $vA, $vB))>; @@ -1008,7 +1008,7 @@ def : Pat<(v8i16 (srl v8i16:$vA, v8i16:$vB)), def : Pat<(v4i32 (srl v4i32:$vA, v4i32:$vB)), (v4i32 (VSRW $vA, $vB))>; def : Pat<(v1i128 (srl v1i128:$vA, v1i128:$vB)), - (v1i128 (VSR (VSRO $vA, $vB), (VSPLTB 15, $vB)))>; + (v1i128 (VSR (v16i8 (VSRO $vA, $vB)), (v16i8 (VSPLTB 15, $vB))))>; def : Pat<(v16i8 (PPCsrl v16i8:$vA, v16i8:$vB)), (v16i8 (VSRB $vA, $vB))>; def : Pat<(v8i16 (PPCsrl v8i16:$vA, v8i16:$vB)), @@ -1016,7 +1016,7 @@ def : Pat<(v8i16 (PPCsrl v8i16:$vA, v8i16:$vB)), def : Pat<(v4i32 (PPCsrl v4i32:$vA, v4i32:$vB)), (v4i32 (VSRW $vA, $vB))>; def : Pat<(v1i128 (PPCsrl v1i128:$vA, v1i128:$vB)), - (v1i128 (VSR (VSRO $vA, $vB), (VSPLTB 15, $vB)))>; + (v1i128 (VSR (v16i8 (VSRO $vA, $vB)), (v16i8 (VSPLTB 15, $vB))))>; def : Pat<(v16i8 (sra v16i8:$vA, v16i8:$vB)), (v16i8 (VSRAB $vA, $vB))>; @@ -1078,10 +1078,12 @@ def VMINUD : VX1_Int_Ty<706, "vminud", int_ppc_altivec_vminud, v2i64>; // Vector merge def VMRGEW : VXForm_1<1932, (outs vrrc:$vD), (ins vrrc:$vA, vrrc:$vB), "vmrgew $vD, $vA, $vB", IIC_VecFP, - [(set v16i8:$vD, (vmrgew_shuffle v16i8:$vA, v16i8:$vB))]>; + [(set v16i8:$vD, + (v16i8 (vmrgew_shuffle v16i8:$vA, v16i8:$vB)))]>; def VMRGOW : VXForm_1<1676, (outs vrrc:$vD), (ins vrrc:$vA, vrrc:$vB), "vmrgow $vD, $vA, $vB", IIC_VecFP, - [(set v16i8:$vD, (vmrgow_shuffle v16i8:$vA, v16i8:$vB))]>; + [(set v16i8:$vD, + (v16i8 (vmrgow_shuffle v16i8:$vA, v16i8:$vB)))]>; // Match vmrgew(x,x) and vmrgow(x,x) def:Pat<(vmrgew_unary_shuffle v16i8:$vA, undef), @@ -1502,18 +1504,4 @@ def VABSDUW : VXForm_1<1155, (outs vrrc:$vD), (ins vrrc:$vA, vrrc:$vB), "vabsduw $vD, $vA, $vB", IIC_VecGeneral, [(set v4i32:$vD, (int_ppc_altivec_vabsduw v4i32:$vA, v4i32:$vB))]>; -def : Pat<(v16i8:$vD (abs v16i8:$vA)), - (v16i8 (VABSDUB $vA, (V_SET0B)))>; -def : Pat<(v8i16:$vD (abs v8i16:$vA)), - (v8i16 (VABSDUH $vA, (V_SET0H)))>; -def : Pat<(v4i32:$vD (abs v4i32:$vA)), - (v4i32 (VABSDUW $vA, (V_SET0)))>; - -def : Pat<(v16i8:$vD (abs (sub v16i8:$vA, v16i8:$vB))), - (v16i8 (VABSDUB $vA, $vB))>; -def : Pat<(v8i16:$vD (abs (sub v8i16:$vA, v8i16:$vB))), - (v8i16 (VABSDUH $vA, $vB))>; -def : Pat<(v4i32:$vD (abs (sub v4i32:$vA, v4i32:$vB))), - (v4i32 (VABSDUW $vA, $vB))>; - } // end HasP9Altivec diff --git a/lib/Target/PowerPC/PPCInstrFormats.td b/lib/Target/PowerPC/PPCInstrFormats.td index f2845415ecb5..f5f4b46344cf 100644 --- a/lib/Target/PowerPC/PPCInstrFormats.td +++ b/lib/Target/PowerPC/PPCInstrFormats.td @@ -46,6 +46,10 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin> bits<1> UseVSXReg = 0; let TSFlags{6} = UseVSXReg; + // Indicate that this instruction is of type X-Form Load or Store + bits<1> XFormMemOp = 0; + let TSFlags{7} = XFormMemOp; + // Fields used for relation models. string BaseName = ""; @@ -71,6 +75,7 @@ class PPC970_Unit_VPERM { bits<3> PPC970_Unit = 6; } class PPC970_Unit_BRU { bits<3> PPC970_Unit = 7; } class UseVSXReg { bits<1> UseVSXReg = 1; } +class XFormMemOp { bits<1> XFormMemOp = 1; } // Two joined instructions; used to emit two adjacent instructions as one. // The itinerary from the first instruction is used for scheduling and @@ -109,6 +114,11 @@ class I2<bits<6> opcode1, bits<6> opcode2, dag OOL, dag IOL, string asmstr, bit Interpretation64Bit = 0; } +// Base class for all X-Form memory instructions +class IXFormMemOp<bits<6> opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> + :I<opcode, OOL, IOL, asmstr, itin>, XFormMemOp; + // 1.7.1 I-Form class IForm<bits<6> opcode, bit aa, bit lk, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> @@ -437,6 +447,11 @@ class XForm_base_r3xo<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asms let Inst{31} = RC; } +class XForm_base_r3xo_memOp<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, + list<dag> pattern> + : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern>, XFormMemOp; + class XForm_tlb<bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin> : XForm_base_r3xo<31, xo, OOL, IOL, asmstr, itin, []> { let RST = 0; @@ -469,9 +484,13 @@ class XForm_base_r3xo_swapped class XForm_1<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, - InstrItinClass itin, list<dag> pattern> + InstrItinClass itin, list<dag> pattern> : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern>; +class XForm_1_memOp<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> + : XForm_base_r3xo_memOp<opcode, xo, OOL, IOL, asmstr, itin, pattern>; + class XForm_1a<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern> { @@ -511,6 +530,10 @@ class XForm_8<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern>; +class XForm_8_memOp<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> + : XForm_base_r3xo_memOp<opcode, xo, OOL, IOL, asmstr, itin, pattern>; + class XForm_10<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : XForm_base_r3xo_swapped<opcode, xo, OOL, IOL, asmstr, itin> { @@ -692,24 +715,34 @@ class XForm_24_sync<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, } class XForm_24_eieio<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, - string asmstr, InstrItinClass itin, list<dag> pattern> + string asmstr, InstrItinClass itin, list<dag> pattern> : XForm_24_sync<opcode, xo, OOL, IOL, asmstr, itin, pattern> { let L = 0; } class XForm_25<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, - InstrItinClass itin, list<dag> pattern> + InstrItinClass itin, list<dag> pattern> : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern> { } +class XForm_25_memOp<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list<dag> pattern> + : XForm_base_r3xo_memOp<opcode, xo, OOL, IOL, asmstr, itin, pattern> { +} + class XForm_26<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern> { let A = 0; } +class XForm_28_memOp<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list<dag> pattern> + : XForm_base_r3xo_memOp<opcode, xo, OOL, IOL, asmstr, itin, pattern> { +} + class XForm_28<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, - InstrItinClass itin, list<dag> pattern> + InstrItinClass itin, list<dag> pattern> : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern> { } @@ -980,7 +1013,7 @@ class X_RD6_IMM8<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, // to specify an SDAG pattern for matching. class X_RD5_RS5_IM5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin> - : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, []> { + : XForm_base_r3xo_memOp<opcode, xo, OOL, IOL, asmstr, itin, []> { } class X_BF3<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, @@ -1018,6 +1051,10 @@ class XX1Form<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Inst{31} = XT{5}; } +class XX1Form_memOp<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list<dag> pattern> + : XX1Form<opcode, xo, OOL, IOL, asmstr, itin, pattern>, XFormMemOp; + class XX1_RS6_RD5_XO<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : XX1Form<opcode, xo, OOL, IOL, asmstr, itin, pattern> { @@ -2094,6 +2131,27 @@ class Z23Form_3<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, string asmstr, let Inst{31} = RC; } +class Z23Form_8<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> + : I<opcode, OOL, IOL, asmstr, itin> { + bits<5> VRT; + bit R; + bits<5> VRB; + bits<2> idx; + + let Pattern = pattern; + + bit RC = 0; // set by isDOT + + let Inst{6-10} = VRT; + let Inst{11-14} = 0; + let Inst{15} = R; + let Inst{16-20} = VRB; + let Inst{21-22} = idx; + let Inst{23-30} = xo; + let Inst{31} = RC; +} + //===----------------------------------------------------------------------===// class Pseudo<dag OOL, dag IOL, string asmstr, list<dag> pattern> : I<0, OOL, IOL, asmstr, NoItinerary> { @@ -2103,3 +2161,7 @@ class Pseudo<dag OOL, dag IOL, string asmstr, list<dag> pattern> let Inst{31-0} = 0; let hasNoSchedulingInfo = 1; } + +class PseudoXFormMemOp<dag OOL, dag IOL, string asmstr, list<dag> pattern> + : Pseudo<OOL, IOL, asmstr, pattern>, XFormMemOp; + diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index ffb5cc8757f2..4669719744bc 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -55,6 +55,8 @@ STATISTIC(CmpIselsConverted, "Number of ISELs that depend on comparison of constants converted"); STATISTIC(MissedConvertibleImmediateInstrs, "Number of compare-immediate instructions fed by constants"); +STATISTIC(NumRcRotatesConvertedToRcAnd, + "Number of record-form rotates converted to record-form andi"); static cl:: opt<bool> DisableCTRLoopAnal("disable-ppc-ctrloop-analysis", cl::Hidden, @@ -71,6 +73,28 @@ static cl::opt<bool> UseOldLatencyCalc("ppc-old-latency-calc", cl::Hidden, cl::desc("Use the old (incorrect) instruction latency calculation")); +// Index into the OpcodesForSpill array. +enum SpillOpcodeKey { + SOK_Int4Spill, + SOK_Int8Spill, + SOK_Float8Spill, + SOK_Float4Spill, + SOK_CRSpill, + SOK_CRBitSpill, + SOK_VRVectorSpill, + SOK_VSXVectorSpill, + SOK_VectorFloat8Spill, + SOK_VectorFloat4Spill, + SOK_VRSaveSpill, + SOK_QuadFloat8Spill, + SOK_QuadFloat4Spill, + SOK_QuadBitSpill, + SOK_SpillToVSR, + SOK_SPESpill, + SOK_SPE4Spill, + SOK_LastOpcodeSpill // This must be last on the enum. +}; + // Pin the vtable to this file. void PPCInstrInfo::anchor() {} @@ -275,23 +299,11 @@ bool PPCInstrInfo::isCoalescableExtInstr(const MachineInstr &MI, unsigned PPCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const { - // Note: This list must be kept consistent with LoadRegFromStackSlot. - switch (MI.getOpcode()) { - default: break; - case PPC::LD: - case PPC::LWZ: - case PPC::LFS: - case PPC::LFD: - case PPC::RESTORE_CR: - case PPC::RESTORE_CRBIT: - case PPC::LVX: - case PPC::LXVD2X: - case PPC::LXV: - case PPC::QVLFDX: - case PPC::QVLFSXs: - case PPC::QVLFDXb: - case PPC::RESTORE_VRSAVE: - case PPC::SPILLTOVSR_LD: + unsigned Opcode = MI.getOpcode(); + const unsigned *OpcodesForSpill = getLoadOpcodesForSpillArray(); + const unsigned *End = OpcodesForSpill + SOK_LastOpcodeSpill; + + if (End != std::find(OpcodesForSpill, End, Opcode)) { // Check for the operands added by addFrameReference (the immediate is the // offset which defaults to 0). if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() && @@ -299,7 +311,6 @@ unsigned PPCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, FrameIndex = MI.getOperand(2).getIndex(); return MI.getOperand(0).getReg(); } - break; } return 0; } @@ -329,31 +340,16 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable(const MachineInstr &MI, unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const { - // Note: This list must be kept consistent with StoreRegToStackSlot. - switch (MI.getOpcode()) { - default: break; - case PPC::STD: - case PPC::STW: - case PPC::STFS: - case PPC::STFD: - case PPC::SPILL_CR: - case PPC::SPILL_CRBIT: - case PPC::STVX: - case PPC::STXVD2X: - case PPC::STXV: - case PPC::QVSTFDX: - case PPC::QVSTFSXs: - case PPC::QVSTFDXb: - case PPC::SPILL_VRSAVE: - case PPC::SPILLTOVSR_ST: - // Check for the operands added by addFrameReference (the immediate is the - // offset which defaults to 0). + unsigned Opcode = MI.getOpcode(); + const unsigned *OpcodesForSpill = getStoreOpcodesForSpillArray(); + const unsigned *End = OpcodesForSpill + SOK_LastOpcodeSpill; + + if (End != std::find(OpcodesForSpill, End, Opcode)) { if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() && MI.getOperand(2).isFI()) { FrameIndex = MI.getOperand(2).getIndex(); return MI.getOperand(0).getReg(); } - break; } return 0; } @@ -955,8 +951,19 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, BuildMI(MBB, I, DL, get(PPC::MFVSRD), DestReg).addReg(SrcReg); getKillRegState(KillSrc); return; + } else if (PPC::SPERCRegClass.contains(SrcReg) && + PPC::SPE4RCRegClass.contains(DestReg)) { + BuildMI(MBB, I, DL, get(PPC::EFSCFD), DestReg).addReg(SrcReg); + getKillRegState(KillSrc); + return; + } else if (PPC::SPE4RCRegClass.contains(SrcReg) && + PPC::SPERCRegClass.contains(DestReg)) { + BuildMI(MBB, I, DL, get(PPC::EFDCFS), DestReg).addReg(SrcReg); + getKillRegState(KillSrc); + return; } + unsigned Opc; if (PPC::GPRCRegClass.contains(DestReg, SrcReg)) Opc = PPC::OR; @@ -989,6 +996,8 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, Opc = PPC::QVFMRb; else if (PPC::CRBITRCRegClass.contains(DestReg, SrcReg)) Opc = PPC::CROR; + else if (PPC::SPERCRegClass.contains(DestReg, SrcReg)) + Opc = PPC::EVOR; else llvm_unreachable("Impossible reg-to-reg copy"); @@ -1000,129 +1009,212 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, BuildMI(MBB, I, DL, MCID, DestReg).addReg(SrcReg, getKillRegState(KillSrc)); } -// This function returns true if a CR spill is necessary and false otherwise. -bool -PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF, - unsigned SrcReg, bool isKill, - int FrameIdx, - const TargetRegisterClass *RC, - SmallVectorImpl<MachineInstr*> &NewMIs, - bool &NonRI, bool &SpillsVRS) const{ - // Note: If additional store instructions are added here, - // update isStoreToStackSlot. +unsigned PPCInstrInfo::getStoreOpcodeForSpill(unsigned Reg, + const TargetRegisterClass *RC) + const { + const unsigned *OpcodesForSpill = getStoreOpcodesForSpillArray(); + int OpcodeIndex = 0; - DebugLoc DL; - if (PPC::GPRCRegClass.hasSubClassEq(RC) || - PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::G8RCRegClass.hasSubClassEq(RC) || - PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::F8RCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFD)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::F4RCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFS)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - } else if (PPC::CRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CR)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - return true; - } else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CRBIT)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - return true; - } else if (PPC::VRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STVX)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) { - unsigned Op = Subtarget.hasP9Vector() ? PPC::STXV : PPC::STXVD2X; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Op)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) { - unsigned Opc = Subtarget.hasP9Vector() ? PPC::DFSTOREf64 : PPC::STXSDX; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opc)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) { - unsigned Opc = Subtarget.hasP9Vector() ? PPC::DFSTOREf32 : PPC::STXSSPX; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opc)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) { - assert(Subtarget.isDarwin() && - "VRSAVE only needs spill/restore on Darwin"); - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_VRSAVE)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - SpillsVRS = true; - } else if (PPC::QFRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVSTFDX)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::QSRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVSTFSXs)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::QBRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVSTFDXb)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); - NonRI = true; - } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILLTOVSR_ST)) - .addReg(SrcReg, - getKillRegState(isKill)), - FrameIdx)); + if (RC != nullptr) { + if (PPC::GPRCRegClass.hasSubClassEq(RC) || + PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Int4Spill; + } else if (PPC::G8RCRegClass.hasSubClassEq(RC) || + PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Int8Spill; + } else if (PPC::F8RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Float8Spill; + } else if (PPC::F4RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Float4Spill; + } else if (PPC::SPERCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_SPESpill; + } else if (PPC::SPE4RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_SPE4Spill; + } else if (PPC::CRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_CRSpill; + } else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_CRBitSpill; + } else if (PPC::VRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VRVectorSpill; + } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VSXVectorSpill; + } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VectorFloat8Spill; + } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VectorFloat4Spill; + } else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VRSaveSpill; + } else if (PPC::QFRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_QuadFloat8Spill; + } else if (PPC::QSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_QuadFloat4Spill; + } else if (PPC::QBRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_QuadBitSpill; + } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_SpillToVSR; + } else { + llvm_unreachable("Unknown regclass!"); + } } else { - llvm_unreachable("Unknown regclass!"); + if (PPC::GPRCRegClass.contains(Reg) || + PPC::GPRC_NOR0RegClass.contains(Reg)) { + OpcodeIndex = SOK_Int4Spill; + } else if (PPC::G8RCRegClass.contains(Reg) || + PPC::G8RC_NOX0RegClass.contains(Reg)) { + OpcodeIndex = SOK_Int8Spill; + } else if (PPC::F8RCRegClass.contains(Reg)) { + OpcodeIndex = SOK_Float8Spill; + } else if (PPC::F4RCRegClass.contains(Reg)) { + OpcodeIndex = SOK_Float4Spill; + } else if (PPC::CRRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_CRSpill; + } else if (PPC::CRBITRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_CRBitSpill; + } else if (PPC::VRRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VRVectorSpill; + } else if (PPC::VSRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VSXVectorSpill; + } else if (PPC::VSFRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VectorFloat8Spill; + } else if (PPC::VSSRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VectorFloat4Spill; + } else if (PPC::VRSAVERCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VRSaveSpill; + } else if (PPC::QFRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_QuadFloat8Spill; + } else if (PPC::QSRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_QuadFloat4Spill; + } else if (PPC::QBRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_QuadBitSpill; + } else if (PPC::SPILLTOVSRRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_SpillToVSR; + } else { + llvm_unreachable("Unknown regclass!"); + } } + return OpcodesForSpill[OpcodeIndex]; +} - return false; +unsigned +PPCInstrInfo::getLoadOpcodeForSpill(unsigned Reg, + const TargetRegisterClass *RC) const { + const unsigned *OpcodesForSpill = getLoadOpcodesForSpillArray(); + int OpcodeIndex = 0; + + if (RC != nullptr) { + if (PPC::GPRCRegClass.hasSubClassEq(RC) || + PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Int4Spill; + } else if (PPC::G8RCRegClass.hasSubClassEq(RC) || + PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Int8Spill; + } else if (PPC::F8RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Float8Spill; + } else if (PPC::F4RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_Float4Spill; + } else if (PPC::SPERCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_SPESpill; + } else if (PPC::SPE4RCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_SPE4Spill; + } else if (PPC::CRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_CRSpill; + } else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_CRBitSpill; + } else if (PPC::VRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VRVectorSpill; + } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VSXVectorSpill; + } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VectorFloat8Spill; + } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VectorFloat4Spill; + } else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_VRSaveSpill; + } else if (PPC::QFRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_QuadFloat8Spill; + } else if (PPC::QSRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_QuadFloat4Spill; + } else if (PPC::QBRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_QuadBitSpill; + } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) { + OpcodeIndex = SOK_SpillToVSR; + } else { + llvm_unreachable("Unknown regclass!"); + } + } else { + if (PPC::GPRCRegClass.contains(Reg) || + PPC::GPRC_NOR0RegClass.contains(Reg)) { + OpcodeIndex = SOK_Int4Spill; + } else if (PPC::G8RCRegClass.contains(Reg) || + PPC::G8RC_NOX0RegClass.contains(Reg)) { + OpcodeIndex = SOK_Int8Spill; + } else if (PPC::F8RCRegClass.contains(Reg)) { + OpcodeIndex = SOK_Float8Spill; + } else if (PPC::F4RCRegClass.contains(Reg)) { + OpcodeIndex = SOK_Float4Spill; + } else if (PPC::CRRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_CRSpill; + } else if (PPC::CRBITRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_CRBitSpill; + } else if (PPC::VRRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VRVectorSpill; + } else if (PPC::VSRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VSXVectorSpill; + } else if (PPC::VSFRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VectorFloat8Spill; + } else if (PPC::VSSRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VectorFloat4Spill; + } else if (PPC::VRSAVERCRegClass.contains(Reg)) { + OpcodeIndex = SOK_VRSaveSpill; + } else if (PPC::QFRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_QuadFloat8Spill; + } else if (PPC::QSRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_QuadFloat4Spill; + } else if (PPC::QBRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_QuadBitSpill; + } else if (PPC::SPILLTOVSRRCRegClass.contains(Reg)) { + OpcodeIndex = SOK_SpillToVSR; + } else { + llvm_unreachable("Unknown regclass!"); + } + } + return OpcodesForSpill[OpcodeIndex]; } -void -PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned SrcReg, bool isKill, int FrameIdx, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { - MachineFunction &MF = *MBB.getParent(); - SmallVector<MachineInstr*, 4> NewMIs; +void PPCInstrInfo::StoreRegToStackSlot( + MachineFunction &MF, unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr *> &NewMIs) const { + unsigned Opcode = getStoreOpcodeForSpill(PPC::NoRegister, RC); + DebugLoc DL; PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); FuncInfo->setHasSpills(); + NewMIs.push_back(addFrameReference( + BuildMI(MF, DL, get(Opcode)).addReg(SrcReg, getKillRegState(isKill)), + FrameIdx)); + + if (PPC::CRRCRegClass.hasSubClassEq(RC) || + PPC::CRBITRCRegClass.hasSubClassEq(RC)) + FuncInfo->setSpillsCR(); + + if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) + FuncInfo->setSpillsVRSAVE(); + + if (isXFormMemOp(Opcode)) + FuncInfo->setHasNonRISpills(); +} + +void PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, + int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + MachineFunction &MF = *MBB.getParent(); + SmallVector<MachineInstr *, 4> NewMIs; + // We need to avoid a situation in which the value from a VRRC register is // spilled using an Altivec instruction and reloaded into a VSRC register // using a VSX instruction. The issue with this is that the VSX @@ -1132,16 +1224,7 @@ PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, // VSX instruction. RC = updatedRC(RC); - bool NonRI = false, SpillsVRS = false; - if (StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs, - NonRI, SpillsVRS)) - FuncInfo->setSpillsCR(); - - if (SpillsVRS) - FuncInfo->setSpillsVRSAVE(); - - if (NonRI) - FuncInfo->setHasNonRISpills(); + StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs); for (unsigned i = 0, e = NewMIs.size(); i != e; ++i) MBB.insert(MI, NewMIs[i]); @@ -1154,85 +1237,25 @@ PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, NewMIs.back()->addMemOperand(MF, MMO); } -bool PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL, +void PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL, unsigned DestReg, int FrameIdx, const TargetRegisterClass *RC, - SmallVectorImpl<MachineInstr *> &NewMIs, - bool &NonRI, bool &SpillsVRS) const { - // Note: If additional load instructions are added here, - // update isLoadFromStackSlot. + SmallVectorImpl<MachineInstr *> &NewMIs) + const { + unsigned Opcode = getLoadOpcodeForSpill(PPC::NoRegister, RC); + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opcode), DestReg), + FrameIdx)); + PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); - if (PPC::GPRCRegClass.hasSubClassEq(RC) || - PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ), - DestReg), FrameIdx)); - } else if (PPC::G8RCRegClass.hasSubClassEq(RC) || - PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LD), DestReg), - FrameIdx)); - } else if (PPC::F8RCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFD), DestReg), - FrameIdx)); - } else if (PPC::F4RCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFS), DestReg), - FrameIdx)); - } else if (PPC::CRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, - get(PPC::RESTORE_CR), DestReg), - FrameIdx)); - return true; - } else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, - get(PPC::RESTORE_CRBIT), DestReg), - FrameIdx)); - return true; - } else if (PPC::VRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LVX), DestReg), - FrameIdx)); - NonRI = true; - } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) { - unsigned Op = Subtarget.hasP9Vector() ? PPC::LXV : PPC::LXVD2X; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Op), DestReg), - FrameIdx)); - NonRI = true; - } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) { - unsigned Opc = Subtarget.hasP9Vector() ? PPC::DFLOADf64 : PPC::LXSDX; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opc), - DestReg), FrameIdx)); - NonRI = true; - } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) { - unsigned Opc = Subtarget.hasP9Vector() ? PPC::DFLOADf32 : PPC::LXSSPX; - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opc), - DestReg), FrameIdx)); - NonRI = true; - } else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) { - assert(Subtarget.isDarwin() && - "VRSAVE only needs spill/restore on Darwin"); - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, - get(PPC::RESTORE_VRSAVE), - DestReg), - FrameIdx)); - SpillsVRS = true; - } else if (PPC::QFRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVLFDX), DestReg), - FrameIdx)); - NonRI = true; - } else if (PPC::QSRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVLFSXs), DestReg), - FrameIdx)); - NonRI = true; - } else if (PPC::QBRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVLFDXb), DestReg), - FrameIdx)); - NonRI = true; - } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) { - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILLTOVSR_LD), - DestReg), FrameIdx)); - } else { - llvm_unreachable("Unknown regclass!"); - } + if (PPC::CRRCRegClass.hasSubClassEq(RC) || + PPC::CRBITRCRegClass.hasSubClassEq(RC)) + FuncInfo->setSpillsCR(); - return false; + if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) + FuncInfo->setSpillsVRSAVE(); + + if (isXFormMemOp(Opcode)) + FuncInfo->setHasNonRISpills(); } void @@ -1259,16 +1282,7 @@ PPCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, if (Subtarget.hasVSX() && RC == &PPC::VRRCRegClass) RC = &PPC::VSRCRegClass; - bool NonRI = false, SpillsVRS = false; - if (LoadRegFromStackSlot(MF, DL, DestReg, FrameIdx, RC, NewMIs, - NonRI, SpillsVRS)) - FuncInfo->setSpillsCR(); - - if (SpillsVRS) - FuncInfo->setSpillsVRSAVE(); - - if (NonRI) - FuncInfo->setHasNonRISpills(); + LoadRegFromStackSlot(MF, DL, DestReg, FrameIdx, RC, NewMIs); for (unsigned i = 0, e = NewMIs.size(); i != e; ++i) MBB.insert(MI, NewMIs[i]); @@ -1617,7 +1631,7 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg, int OpC = CmpInstr.getOpcode(); unsigned CRReg = CmpInstr.getOperand(0).getReg(); - // FP record forms set CR1 based on the execption status bits, not a + // FP record forms set CR1 based on the exception status bits, not a // comparison with zero. if (OpC == PPC::FCMPUS || OpC == PPC::FCMPUD) return false; @@ -1740,7 +1754,7 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg, unsigned PredHint = PPC::getPredicateHint(Pred); int16_t Immed = (int16_t)Value; - // When modyfing the condition in the predicate, we propagate hint bits + // When modifying the condition in the predicate, we propagate hint bits // from the original predicate to the new one. if (Immed == -1 && PredCond == PPC::PRED_GT) // We convert "greater than -1" into "greater than or equal to 0", @@ -1897,6 +1911,31 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg, // specifically the case if this is the instruction directly after the // compare). + // Rotates are expensive instructions. If we're emitting a record-form + // rotate that can just be an andi, we should just emit the andi. + if ((MIOpC == PPC::RLWINM || MIOpC == PPC::RLWINM8) && + MI->getOperand(2).getImm() == 0) { + int64_t MB = MI->getOperand(3).getImm(); + int64_t ME = MI->getOperand(4).getImm(); + if (MB < ME && MB >= 16) { + uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); + NewOpC = MIOpC == PPC::RLWINM ? PPC::ANDIo : PPC::ANDIo8; + MI->RemoveOperand(4); + MI->RemoveOperand(3); + MI->getOperand(2).setImm(Mask); + NumRcRotatesConvertedToRcAnd++; + } + } else if (MIOpC == PPC::RLDICL && MI->getOperand(2).getImm() == 0) { + int64_t MB = MI->getOperand(3).getImm(); + if (MB >= 48) { + uint64_t Mask = (1LLU << (63 - MB + 1)) - 1; + NewOpC = PPC::ANDIo8; + MI->RemoveOperand(3); + MI->getOperand(2).setImm(Mask); + NumRcRotatesConvertedToRcAnd++; + } + } + const MCInstrDesc &NewDesc = get(NewOpC); MI->setDesc(NewDesc); @@ -2049,6 +2088,12 @@ bool PPCInstrInfo::expandVSXMemPseudo(MachineInstr &MI) const { return true; } +#ifndef NDEBUG +static bool isAnImmediateOperand(const MachineOperand &MO) { + return MO.isCPI() || MO.isGlobal() || MO.isImm(); +} +#endif + bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { auto &MBB = *MI.getParent(); auto DL = MI.getDebugLoc(); @@ -2071,7 +2116,8 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { case PPC::DFSTOREf64: { assert(Subtarget.hasP9Vector() && "Invalid D-Form Pseudo-ops on Pre-P9 target."); - assert(MI.getOperand(2).isReg() && MI.getOperand(1).isImm() && + assert(MI.getOperand(2).isReg() && + isAnImmediateOperand(MI.getOperand(1)) && "D-form op must have register and immediate operands"); return expandVSXMemPseudo(MI); } @@ -2151,28 +2197,6 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { return false; } -unsigned PPCInstrInfo::lookThruCopyLike(unsigned SrcReg, - const MachineRegisterInfo *MRI) { - while (true) { - MachineInstr *MI = MRI->getVRegDef(SrcReg); - if (!MI->isCopyLike()) - return SrcReg; - - unsigned CopySrcReg; - if (MI->isCopy()) - CopySrcReg = MI->getOperand(1).getReg(); - else { - assert(MI->isSubregToReg() && "Bad opcode for lookThruCopyLike"); - CopySrcReg = MI->getOperand(2).getReg(); - } - - if (!TargetRegisterInfo::isVirtualRegister(CopySrcReg)) - return CopySrcReg; - - SrcReg = CopySrcReg; - } -} - // Essentially a compile-time implementation of a compare->isel sequence. // It takes two constants to compare, along with the true/false registers // and the comparison type (as a subreg to a CR field) and returns one @@ -2238,7 +2262,8 @@ MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI, ConstOp = ~0U; MachineInstr *DefMI = nullptr; MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo(); - // If we'ere in SSA, get the defs through the MRI. Otherwise, only look + const TargetRegisterInfo *TRI = &getRegisterInfo(); + // If we're in SSA, get the defs through the MRI. Otherwise, only look // within the basic block to see if the register is defined using an LI/LI8. if (MRI->isSSA()) { for (int i = 1, e = MI.getNumOperands(); i < e; i++) { @@ -2247,7 +2272,7 @@ MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI, unsigned Reg = MI.getOperand(i).getReg(); if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; - unsigned TrueReg = lookThruCopyLike(Reg, MRI); + unsigned TrueReg = TRI->lookThruCopyLike(Reg, MRI); if (TargetRegisterInfo::isVirtualRegister(TrueReg)) { DefMI = MRI->getVRegDef(TrueReg); if (DefMI->getOpcode() == PPC::LI || DefMI->getOpcode() == PPC::LI8) { @@ -2313,6 +2338,38 @@ MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI, return ConstOp == ~0U ? nullptr : DefMI; } +const unsigned *PPCInstrInfo::getStoreOpcodesForSpillArray() const { + static const unsigned OpcodesForSpill[2][SOK_LastOpcodeSpill] = { + // Power 8 + {PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, + PPC::SPILL_CRBIT, PPC::STVX, PPC::STXVD2X, PPC::STXSDX, PPC::STXSSPX, + PPC::SPILL_VRSAVE, PPC::QVSTFDX, PPC::QVSTFSXs, PPC::QVSTFDXb, + PPC::SPILLTOVSR_ST, PPC::EVSTDD, PPC::SPESTW}, + // Power 9 + {PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, + PPC::SPILL_CRBIT, PPC::STVX, PPC::STXV, PPC::DFSTOREf64, PPC::DFSTOREf32, + PPC::SPILL_VRSAVE, PPC::QVSTFDX, PPC::QVSTFSXs, PPC::QVSTFDXb, + PPC::SPILLTOVSR_ST}}; + + return OpcodesForSpill[(Subtarget.hasP9Vector()) ? 1 : 0]; +} + +const unsigned *PPCInstrInfo::getLoadOpcodesForSpillArray() const { + static const unsigned OpcodesForSpill[2][SOK_LastOpcodeSpill] = { + // Power 8 + {PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR, + PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXVD2X, PPC::LXSDX, PPC::LXSSPX, + PPC::RESTORE_VRSAVE, PPC::QVLFDX, PPC::QVLFSXs, PPC::QVLFDXb, + PPC::SPILLTOVSR_LD, PPC::EVLDD, PPC::SPELWZ}, + // Power 9 + {PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR, + PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXV, PPC::DFLOADf64, PPC::DFLOADf32, + PPC::RESTORE_VRSAVE, PPC::QVLFDX, PPC::QVLFSXs, PPC::QVLFDXb, + PPC::SPILLTOVSR_LD}}; + + return OpcodesForSpill[(Subtarget.hasP9Vector()) ? 1 : 0]; +} + // If this instruction has an immediate form and one of its operands is a // result of a load-immediate, convert it to the immediate form if the constant // is in range. @@ -2391,16 +2448,17 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, CompareUseMI.RemoveOperand(2); continue; } - DEBUG(dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n"); - DEBUG(DefMI->dump(); MI.dump(); CompareUseMI.dump()); - DEBUG(dbgs() << "Is converted to:\n"); + LLVM_DEBUG( + dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n"); + LLVM_DEBUG(DefMI->dump(); MI.dump(); CompareUseMI.dump()); + LLVM_DEBUG(dbgs() << "Is converted to:\n"); // Convert to copy and remove unneeded operands. CompareUseMI.setDesc(get(PPC::COPY)); CompareUseMI.RemoveOperand(3); CompareUseMI.RemoveOperand(RegToCopy == TrueReg ? 2 : 1); CmpIselsConverted++; Changed = true; - DEBUG(CompareUseMI.dump()); + LLVM_DEBUG(CompareUseMI.dump()); } if (Changed) return true; @@ -2431,9 +2489,10 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, // Use APInt's rotate function. int64_t SH = MI.getOperand(2).getImm(); int64_t MB = MI.getOperand(3).getImm(); - APInt InVal(Opc == PPC::RLDICL ? 64 : 32, SExtImm, true); + APInt InVal((Opc == PPC::RLDICL || Opc == PPC::RLDICLo) ? + 64 : 32, SExtImm, true); InVal = InVal.rotl(SH); - uint64_t Mask = (1LU << (63 - MB + 1)) - 1; + uint64_t Mask = (1LLU << (63 - MB + 1)) - 1; InVal &= Mask; // Can't replace negative values with an LI as that will sign-extend // and not clear the left bits. If we're setting the CR bit, we will use @@ -2457,8 +2516,8 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, int64_t ME = MI.getOperand(4).getImm(); APInt InVal(32, SExtImm, true); InVal = InVal.rotl(SH); - // Set the bits ( MB + 32 ) to ( ME + 32 ). - uint64_t Mask = ((1 << (32 - MB)) - 1) & ~((1 << (31 - ME)) - 1); + // Set the bits ( MB + 32 ) to ( ME + 32 ). + uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); InVal &= Mask; // Can't replace negative values with an LI as that will sign-extend // and not clear the left bits. If we're setting the CR bit, we will use @@ -2496,10 +2555,37 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, } if (ReplaceWithLI) { - DEBUG(dbgs() << "Replacing instruction:\n"); - DEBUG(MI.dump()); - DEBUG(dbgs() << "Fed by:\n"); - DEBUG(DefMI->dump()); + // We need to be careful with CR-setting instructions we're replacing. + if (SetCR) { + // We don't know anything about uses when we're out of SSA, so only + // replace if the new immediate will be reproduced. + bool ImmChanged = (SExtImm & NewImm) != NewImm; + if (PostRA && ImmChanged) + return false; + + if (!PostRA) { + // If the defining load-immediate has no other uses, we can just replace + // the immediate with the new immediate. + if (MRI->hasOneUse(DefMI->getOperand(0).getReg())) + DefMI->getOperand(1).setImm(NewImm); + + // If we're not using the GPR result of the CR-setting instruction, we + // just need to and with zero/non-zero depending on the new immediate. + else if (MRI->use_empty(MI.getOperand(0).getReg())) { + if (NewImm) { + assert(Immediate && "Transformation converted zero to non-zero?"); + NewImm = Immediate; + } + } + else if (ImmChanged) + return false; + } + } + + LLVM_DEBUG(dbgs() << "Replacing instruction:\n"); + LLVM_DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Fed by:\n"); + LLVM_DEBUG(DefMI->dump()); LoadImmediateInfo LII; LII.Imm = NewImm; LII.Is64Bit = Is64BitLI; @@ -2509,8 +2595,8 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, if (KilledDef && SetCR) *KilledDef = nullptr; replaceInstrWithLI(MI, LII); - DEBUG(dbgs() << "With:\n"); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "With:\n"); + LLVM_DEBUG(MI.dump()); return true; } return false; @@ -2527,6 +2613,7 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, III.ConstantOpNo = 2; III.ImmWidth = 16; III.ImmMustBeMultipleOf = 1; + III.TruncateImmTo = 0; switch (Opc) { default: return false; case PPC::ADD4: @@ -2600,10 +2687,6 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, case PPC::RLWNM8: case PPC::RLWNMo: case PPC::RLWNM8o: - case PPC::RLDCL: - case PPC::RLDCLo: - case PPC::RLDCR: - case PPC::RLDCRo: case PPC::SLW: case PPC::SLW8: case PPC::SLWo: @@ -2614,29 +2697,26 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, case PPC::SRW8o: case PPC::SRAW: case PPC::SRAWo: - case PPC::SLD: - case PPC::SLDo: - case PPC::SRD: - case PPC::SRDo: - case PPC::SRAD: - case PPC::SRADo: III.SignedImm = false; III.ZeroIsSpecialOrig = 0; III.ZeroIsSpecialNew = 0; III.IsCommutative = false; // This isn't actually true, but the instructions ignore any of the // upper bits, so any immediate loaded with an LI is acceptable. + // This does not apply to shift right algebraic because a value + // out of range will produce a -1/0. III.ImmWidth = 16; + if (Opc == PPC::RLWNM || Opc == PPC::RLWNM8 || + Opc == PPC::RLWNMo || Opc == PPC::RLWNM8o) + III.TruncateImmTo = 5; + else + III.TruncateImmTo = 6; switch(Opc) { default: llvm_unreachable("Unknown opcode"); case PPC::RLWNM: III.ImmOpcode = PPC::RLWINM; break; case PPC::RLWNM8: III.ImmOpcode = PPC::RLWINM8; break; case PPC::RLWNMo: III.ImmOpcode = PPC::RLWINMo; break; case PPC::RLWNM8o: III.ImmOpcode = PPC::RLWINM8o; break; - case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break; - case PPC::RLDCLo: III.ImmOpcode = PPC::RLDICLo; break; - case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break; - case PPC::RLDCRo: III.ImmOpcode = PPC::RLDICRo; break; case PPC::SLW: III.ImmOpcode = PPC::RLWINM; break; case PPC::SLW8: III.ImmOpcode = PPC::RLWINM8; break; case PPC::SLWo: III.ImmOpcode = PPC::RLWINMo; break; @@ -2645,14 +2725,62 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI, case PPC::SRW8: III.ImmOpcode = PPC::RLWINM8; break; case PPC::SRWo: III.ImmOpcode = PPC::RLWINMo; break; case PPC::SRW8o: III.ImmOpcode = PPC::RLWINM8o; break; - case PPC::SRAW: III.ImmOpcode = PPC::SRAWI; break; - case PPC::SRAWo: III.ImmOpcode = PPC::SRAWIo; break; + case PPC::SRAW: + III.ImmWidth = 5; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRAWI; + break; + case PPC::SRAWo: + III.ImmWidth = 5; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRAWIo; + break; + } + break; + case PPC::RLDCL: + case PPC::RLDCLo: + case PPC::RLDCR: + case PPC::RLDCRo: + case PPC::SLD: + case PPC::SLDo: + case PPC::SRD: + case PPC::SRDo: + case PPC::SRAD: + case PPC::SRADo: + III.SignedImm = false; + III.ZeroIsSpecialOrig = 0; + III.ZeroIsSpecialNew = 0; + III.IsCommutative = false; + // This isn't actually true, but the instructions ignore any of the + // upper bits, so any immediate loaded with an LI is acceptable. + // This does not apply to shift right algebraic because a value + // out of range will produce a -1/0. + III.ImmWidth = 16; + if (Opc == PPC::RLDCL || Opc == PPC::RLDCLo || + Opc == PPC::RLDCR || Opc == PPC::RLDCRo) + III.TruncateImmTo = 6; + else + III.TruncateImmTo = 7; + switch(Opc) { + default: llvm_unreachable("Unknown opcode"); + case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break; + case PPC::RLDCLo: III.ImmOpcode = PPC::RLDICLo; break; + case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break; + case PPC::RLDCRo: III.ImmOpcode = PPC::RLDICRo; break; case PPC::SLD: III.ImmOpcode = PPC::RLDICR; break; case PPC::SLDo: III.ImmOpcode = PPC::RLDICRo; break; case PPC::SRD: III.ImmOpcode = PPC::RLDICL; break; case PPC::SRDo: III.ImmOpcode = PPC::RLDICLo; break; - case PPC::SRAD: III.ImmOpcode = PPC::SRADI; break; - case PPC::SRADo: III.ImmOpcode = PPC::SRADIo; break; + case PPC::SRAD: + III.ImmWidth = 6; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRADI; + break; + case PPC::SRADo: + III.ImmWidth = 6; + III.TruncateImmTo = 0; + III.ImmOpcode = PPC::SRADIo; + break; } break; // Loads and stores: @@ -2866,6 +2994,8 @@ bool PPCInstrInfo::transformToImmForm(MachineInstr &MI, const ImmInstrInfo &III, return false; if (Imm % III.ImmMustBeMultipleOf) return false; + if (III.TruncateImmTo) + Imm &= ((1 << III.TruncateImmTo) - 1); if (III.SignedImm) { APInt ActualValue(64, Imm, true); if (!ActualValue.isSignedIntN(III.ImmWidth)) @@ -3108,7 +3238,7 @@ bool PPCInstrInfo::isTOCSaveMI(const MachineInstr &MI) const { } // We limit the max depth to track incoming values of PHIs or binary ops -// (e.g. AND) to avoid exsessive cost. +// (e.g. AND) to avoid excessive cost. const unsigned MAX_DEPTH = 1; bool diff --git a/lib/Target/PowerPC/PPCInstrInfo.h b/lib/Target/PowerPC/PPCInstrInfo.h index 4271c50127a1..ba82f56a2464 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.h +++ b/lib/Target/PowerPC/PPCInstrInfo.h @@ -68,7 +68,9 @@ enum { /// The VSX instruction that uses VSX register (vs0-vs63), instead of VMX /// register (v0-v31). - UseVSXReg = 0x1 << NewDef_Shift + UseVSXReg = 0x1 << NewDef_Shift, + /// This instruction is an X-Form memory operation. + XFormMemOp = 0x1 << (NewDef_Shift+1) }; } // end namespace PPCII @@ -97,6 +99,8 @@ struct ImmInstrInfo { uint64_t ImmOpcode : 16; // The size of the immediate. uint64_t ImmWidth : 5; + // The immediate should be truncated to N bits. + uint64_t TruncateImmTo : 5; }; // Information required to convert an instruction to just a materialized @@ -112,20 +116,19 @@ class PPCInstrInfo : public PPCGenInstrInfo { PPCSubtarget &Subtarget; const PPCRegisterInfo RI; - bool StoreRegToStackSlot(MachineFunction &MF, - unsigned SrcReg, bool isKill, int FrameIdx, - const TargetRegisterClass *RC, - SmallVectorImpl<MachineInstr*> &NewMIs, - bool &NonRI, bool &SpillsVRS) const; - bool LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL, + void StoreRegToStackSlot(MachineFunction &MF, unsigned SrcReg, bool isKill, + int FrameIdx, const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr *> &NewMIs) const; + void LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL, unsigned DestReg, int FrameIdx, const TargetRegisterClass *RC, - SmallVectorImpl<MachineInstr *> &NewMIs, - bool &NonRI, bool &SpillsVRS) const; + SmallVectorImpl<MachineInstr *> &NewMIs) const; bool transformToImmForm(MachineInstr &MI, const ImmInstrInfo &III, unsigned ConstantOpNo, int64_t Imm) const; MachineInstr *getConstantDefMI(MachineInstr &MI, unsigned &ConstOp, bool &SeenIntermediateUse) const; + const unsigned *getStoreOpcodesForSpillArray() const; + const unsigned *getLoadOpcodesForSpillArray() const; virtual void anchor(); protected: @@ -152,6 +155,10 @@ public: /// const PPCRegisterInfo &getRegisterInfo() const { return RI; } + bool isXFormMemOp(unsigned Opcode) const { + return get(Opcode).TSFlags & PPCII::XFormMemOp; + } + ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const override; @@ -249,6 +256,12 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override; + unsigned getStoreOpcodeForSpill(unsigned Reg, + const TargetRegisterClass *RC = nullptr) const; + + unsigned getLoadOpcodeForSpill(unsigned Reg, + const TargetRegisterClass *RC = nullptr) const; + bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; @@ -357,13 +370,6 @@ public: MachineInstr **KilledDef = nullptr) const; void replaceInstrWithLI(MachineInstr &MI, const LoadImmediateInfo &LII) const; - // This is used to find the "true" source register for n - // Machine instruction. Returns the original SrcReg unless it is the target - // of a copy-like operation, in which case we chain backwards through all - // such operations to the ultimate source register. If a - // physical register is encountered, we stop the search. - static unsigned lookThruCopyLike(unsigned SrcReg, - const MachineRegisterInfo *MRI); bool instrHasImmForm(const MachineInstr &MI, ImmInstrInfo &III) const; }; diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index a932d05b24ee..1a43037e4a4b 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -29,6 +29,12 @@ def SDT_PPCLxsizx : SDTypeProfile<1, 2, [ def SDT_PPCstxsix : SDTypeProfile<0, 3, [ SDTCisVT<0, f64>, SDTCisPtrTy<1>, SDTCisPtrTy<2> ]>; +def SDT_PPCcv_fp_to_int : SDTypeProfile<1, 1, [ + SDTCisFP<0>, SDTCisFP<1> + ]>; +def SDT_PPCstore_scal_int_from_vsr : SDTypeProfile<0, 3, [ + SDTCisVT<0, f64>, SDTCisPtrTy<1>, SDTCisPtrTy<2> +]>; def SDT_PPCVexts : SDTypeProfile<1, 2, [ SDTCisVT<0, f64>, SDTCisVT<1, f64>, SDTCisPtrTy<2> ]>; @@ -123,6 +129,14 @@ def PPCfctidz : SDNode<"PPCISD::FCTIDZ", SDTFPUnaryOp, []>; def PPCfctiwz : SDNode<"PPCISD::FCTIWZ", SDTFPUnaryOp, []>; def PPCfctiduz: SDNode<"PPCISD::FCTIDUZ",SDTFPUnaryOp, []>; def PPCfctiwuz: SDNode<"PPCISD::FCTIWUZ",SDTFPUnaryOp, []>; + +def PPCcv_fp_to_uint_in_vsr: + SDNode<"PPCISD::FP_TO_UINT_IN_VSR", SDT_PPCcv_fp_to_int, []>; +def PPCcv_fp_to_sint_in_vsr: + SDNode<"PPCISD::FP_TO_SINT_IN_VSR", SDT_PPCcv_fp_to_int, []>; +def PPCstore_scal_int_from_vsr: + SDNode<"PPCISD::ST_VSR_SCAL_INT", SDT_PPCstore_scal_int_from_vsr, + [SDNPHasChain, SDNPMayStore]>; def PPCstfiwx : SDNode<"PPCISD::STFIWX", SDT_PPCstfiwx, [SDNPHasChain, SDNPMayStore]>; def PPClfiwax : SDNode<"PPCISD::LFIWAX", SDT_PPClfiwx, @@ -204,6 +218,13 @@ def PPCsrl : SDNode<"PPCISD::SRL" , SDTIntShiftOp>; def PPCsra : SDNode<"PPCISD::SRA" , SDTIntShiftOp>; def PPCshl : SDNode<"PPCISD::SHL" , SDTIntShiftOp>; +// Move 2 i64 values into a VSX register +def PPCbuild_fp128: SDNode<"PPCISD::BUILD_FP128", + SDTypeProfile<1, 2, + [SDTCisFP<0>, SDTCisSameSizeAs<1,2>, + SDTCisSameAs<1,2>]>, + []>; + // These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeqStart, [SDNPHasChain, SDNPOutGlue]>; @@ -257,6 +278,13 @@ def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutGlue]>; def PPCcondbranch : SDNode<"PPCISD::COND_BRANCH", SDT_PPCcondbr, [SDNPHasChain, SDNPOptInGlue]>; +// PPC-specific atomic operations. +def PPCatomicCmpSwap_8 : + SDNode<"PPCISD::ATOMIC_CMP_SWAP_8", SDTAtomic3, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def PPCatomicCmpSwap_16 : + SDNode<"PPCISD::ATOMIC_CMP_SWAP_16", SDTAtomic3, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; def PPClbrx : SDNode<"PPCISD::LBRX", SDT_PPClbrx, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; def PPCstbrx : SDNode<"PPCISD::STBRX", SDT_PPCstbrx, @@ -301,7 +329,7 @@ def HI16 : SDNodeXForm<imm, [{ def HA16 : SDNodeXForm<imm, [{ // Transformation function: shift the immediate value down into the low bits. - int Val = N->getZExtValue(); + long Val = N->getZExtValue(); return getI32Imm((Val - (signed short)Val) >> 16, SDLoc(N)); }]>; def MB : SDNodeXForm<imm, [{ @@ -516,6 +544,19 @@ def crrc0 : RegisterOperand<CRRC0> { let ParserMatchClass = PPCRegCRRCAsmOperand; } +def PPCRegSPERCAsmOperand : AsmOperandClass { + let Name = "RegSPERC"; let PredicateMethod = "isRegNumber"; +} +def sperc : RegisterOperand<SPERC> { + let ParserMatchClass = PPCRegSPERCAsmOperand; +} +def PPCRegSPE4RCAsmOperand : AsmOperandClass { + let Name = "RegSPE4RC"; let PredicateMethod = "isRegNumber"; +} +def spe4rc : RegisterOperand<SPE4RC> { + let ParserMatchClass = PPCRegSPE4RCAsmOperand; +} + def PPCU1ImmAsmOperand : AsmOperandClass { let Name = "U1Imm"; let PredicateMethod = "isU1Imm"; let RenderMethod = "addImmOperands"; @@ -791,16 +832,19 @@ def spe8dis : Operand<iPTR> { // SPE displacement where the imm is 8-aligned. let PrintMethod = "printMemRegImm"; let MIOperandInfo = (ops dispSPE8:$imm, ptr_rc_nor0:$reg); let EncoderMethod = "getSPE8DisEncoding"; + let DecoderMethod = "decodeSPE8Operands"; } def spe4dis : Operand<iPTR> { // SPE displacement where the imm is 4-aligned. let PrintMethod = "printMemRegImm"; let MIOperandInfo = (ops dispSPE4:$imm, ptr_rc_nor0:$reg); let EncoderMethod = "getSPE4DisEncoding"; + let DecoderMethod = "decodeSPE4Operands"; } def spe2dis : Operand<iPTR> { // SPE displacement where the imm is 2-aligned. let PrintMethod = "printMemRegImm"; let MIOperandInfo = (ops dispSPE2:$imm, ptr_rc_nor0:$reg); let EncoderMethod = "getSPE2DisEncoding"; + let DecoderMethod = "decodeSPE2Operands"; } // A single-register address. This is used with the SjLj @@ -855,7 +899,7 @@ def HasSYNC : Predicate<"!PPCSubTarget->hasOnlyMSYNC()">; def IsPPC4xx : Predicate<"PPCSubTarget->isPPC4xx()">; def IsPPC6xx : Predicate<"PPCSubTarget->isPPC6xx()">; def IsE500 : Predicate<"PPCSubTarget->isE500()">; -def HasSPE : Predicate<"PPCSubTarget->HasSPE()">; +def HasSPE : Predicate<"PPCSubTarget->hasSPE()">; def HasICBT : Predicate<"PPCSubTarget->hasICBT()">; def HasPartwordAtomics : Predicate<"PPCSubTarget->hasPartwordAtomics()">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; @@ -863,6 +907,7 @@ def NaNsFPMath : Predicate<"!TM.Options.NoNaNsFPMath">; def HasBPERMD : Predicate<"PPCSubTarget->hasBPERMD()">; def HasExtDiv : Predicate<"PPCSubTarget->hasExtDiv()">; def IsISA3_0 : Predicate<"PPCSubTarget->isISA3_0()">; +def HasFPU : Predicate<"PPCSubTarget->hasFPU()">; //===----------------------------------------------------------------------===// // PowerPC Multiclass Definitions. @@ -1188,6 +1233,9 @@ let usesCustomInserter = 1, // Expanded after instruction selection. def SELECT_CC_F8 : Pseudo<(outs f8rc:$dst), (ins crrc:$cond, f8rc:$T, f8rc:$F, i32imm:$BROPC), "#SELECT_CC_F8", []>; + def SELECT_CC_F16 : Pseudo<(outs vrrc:$dst), (ins crrc:$cond, vrrc:$T, vrrc:$F, + i32imm:$BROPC), "#SELECT_CC_F16", + []>; def SELECT_CC_VRRC: Pseudo<(outs vrrc:$dst), (ins crrc:$cond, vrrc:$T, vrrc:$F, i32imm:$BROPC), "#SELECT_CC_VRRC", []>; @@ -1200,12 +1248,17 @@ let usesCustomInserter = 1, // Expanded after instruction selection. def SELECT_I8 : Pseudo<(outs g8rc:$dst), (ins crbitrc:$cond, g8rc_nox0:$T, g8rc_nox0:$F), "#SELECT_I8", [(set i64:$dst, (select i1:$cond, i64:$T, i64:$F))]>; +let Predicates = [HasFPU] in { def SELECT_F4 : Pseudo<(outs f4rc:$dst), (ins crbitrc:$cond, f4rc:$T, f4rc:$F), "#SELECT_F4", [(set f32:$dst, (select i1:$cond, f32:$T, f32:$F))]>; def SELECT_F8 : Pseudo<(outs f8rc:$dst), (ins crbitrc:$cond, f8rc:$T, f8rc:$F), "#SELECT_F8", [(set f64:$dst, (select i1:$cond, f64:$T, f64:$F))]>; + def SELECT_F16 : Pseudo<(outs vrrc:$dst), (ins crbitrc:$cond, + vrrc:$T, vrrc:$F), "#SELECT_F16", + [(set f128:$dst, (select i1:$cond, f128:$T, f128:$F))]>; +} def SELECT_VRRC: Pseudo<(outs vrrc:$dst), (ins crbitrc:$cond, vrrc:$T, vrrc:$F), "#SELECT_VRRC", [(set v4i32:$dst, @@ -1710,30 +1763,35 @@ let usesCustomInserter = 1 in { } } +def : Pat<(PPCatomicCmpSwap_8 xoaddr:$ptr, i32:$old, i32:$new), + (ATOMIC_CMP_SWAP_I8 xoaddr:$ptr, i32:$old, i32:$new)>; +def : Pat<(PPCatomicCmpSwap_16 xoaddr:$ptr, i32:$old, i32:$new), + (ATOMIC_CMP_SWAP_I16 xoaddr:$ptr, i32:$old, i32:$new)>; + // Instructions to support atomic operations let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in { -def LBARX : XForm_1<31, 52, (outs gprc:$rD), (ins memrr:$src), +def LBARX : XForm_1_memOp<31, 52, (outs gprc:$rD), (ins memrr:$src), "lbarx $rD, $src", IIC_LdStLWARX, []>, Requires<[HasPartwordAtomics]>; -def LHARX : XForm_1<31, 116, (outs gprc:$rD), (ins memrr:$src), +def LHARX : XForm_1_memOp<31, 116, (outs gprc:$rD), (ins memrr:$src), "lharx $rD, $src", IIC_LdStLWARX, []>, Requires<[HasPartwordAtomics]>; -def LWARX : XForm_1<31, 20, (outs gprc:$rD), (ins memrr:$src), +def LWARX : XForm_1_memOp<31, 20, (outs gprc:$rD), (ins memrr:$src), "lwarx $rD, $src", IIC_LdStLWARX, []>; // Instructions to support lock versions of atomics // (EH=1 - see Power ISA 2.07 Book II 4.4.2) -def LBARXL : XForm_1<31, 52, (outs gprc:$rD), (ins memrr:$src), +def LBARXL : XForm_1_memOp<31, 52, (outs gprc:$rD), (ins memrr:$src), "lbarx $rD, $src, 1", IIC_LdStLWARX, []>, isDOT, Requires<[HasPartwordAtomics]>; -def LHARXL : XForm_1<31, 116, (outs gprc:$rD), (ins memrr:$src), +def LHARXL : XForm_1_memOp<31, 116, (outs gprc:$rD), (ins memrr:$src), "lharx $rD, $src, 1", IIC_LdStLWARX, []>, isDOT, Requires<[HasPartwordAtomics]>; -def LWARXL : XForm_1<31, 20, (outs gprc:$rD), (ins memrr:$src), +def LWARXL : XForm_1_memOp<31, 20, (outs gprc:$rD), (ins memrr:$src), "lwarx $rD, $src, 1", IIC_LdStLWARX, []>, isDOT; // The atomic instructions use the destination register as well as the next one @@ -1745,15 +1803,15 @@ def LWAT : X_RD5_RS5_IM5<31, 582, (outs gprc:$rD), (ins gprc:$rA, u5imm:$FC), } let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in { -def STBCX : XForm_1<31, 694, (outs), (ins gprc:$rS, memrr:$dst), +def STBCX : XForm_1_memOp<31, 694, (outs), (ins gprc:$rS, memrr:$dst), "stbcx. $rS, $dst", IIC_LdStSTWCX, []>, isDOT, Requires<[HasPartwordAtomics]>; -def STHCX : XForm_1<31, 726, (outs), (ins gprc:$rS, memrr:$dst), +def STHCX : XForm_1_memOp<31, 726, (outs), (ins gprc:$rS, memrr:$dst), "sthcx. $rS, $dst", IIC_LdStSTWCX, []>, isDOT, Requires<[HasPartwordAtomics]>; -def STWCX : XForm_1<31, 150, (outs), (ins gprc:$rS, memrr:$dst), +def STWCX : XForm_1_memOp<31, 150, (outs), (ins gprc:$rS, memrr:$dst), "stwcx. $rS, $dst", IIC_LdStSTWCX, []>, isDOT; } @@ -1794,12 +1852,14 @@ def LWZ : DForm_1<32, (outs gprc:$rD), (ins memri:$src), "lwz $rD, $src", IIC_LdStLoad, [(set i32:$rD, (load iaddr:$src))]>; +let Predicates = [HasFPU] in { def LFS : DForm_1<48, (outs f4rc:$rD), (ins memri:$src), "lfs $rD, $src", IIC_LdStLFD, [(set f32:$rD, (load iaddr:$src))]>; def LFD : DForm_1<50, (outs f8rc:$rD), (ins memri:$src), "lfd $rD, $src", IIC_LdStLFD, [(set f64:$rD, (load iaddr:$src))]>; +} // Unindexed (r+i) Loads with Update (preinc). @@ -1824,6 +1884,7 @@ def LWZU : DForm_1<33, (outs gprc:$rD, ptr_rc_nor0:$ea_result), (ins memri:$addr []>, RegConstraint<"$addr.reg = $ea_result">, NoEncode<"$ea_result">; +let Predicates = [HasFPU] in { def LFSU : DForm_1<49, (outs f4rc:$rD, ptr_rc_nor0:$ea_result), (ins memri:$addr), "lfsu $rD, $addr", IIC_LdStLFDU, []>, RegConstraint<"$addr.reg = $ea_result">, @@ -1833,84 +1894,89 @@ def LFDU : DForm_1<51, (outs f8rc:$rD, ptr_rc_nor0:$ea_result), (ins memri:$addr "lfdu $rD, $addr", IIC_LdStLFDU, []>, RegConstraint<"$addr.reg = $ea_result">, NoEncode<"$ea_result">; +} // Indexed (r+r) Loads with Update (preinc). -def LBZUX : XForm_1<31, 119, (outs gprc:$rD, ptr_rc_nor0:$ea_result), +def LBZUX : XForm_1_memOp<31, 119, (outs gprc:$rD, ptr_rc_nor0:$ea_result), (ins memrr:$addr), "lbzux $rD, $addr", IIC_LdStLoadUpdX, []>, RegConstraint<"$addr.ptrreg = $ea_result">, NoEncode<"$ea_result">; -def LHAUX : XForm_1<31, 375, (outs gprc:$rD, ptr_rc_nor0:$ea_result), +def LHAUX : XForm_1_memOp<31, 375, (outs gprc:$rD, ptr_rc_nor0:$ea_result), (ins memrr:$addr), "lhaux $rD, $addr", IIC_LdStLHAUX, []>, RegConstraint<"$addr.ptrreg = $ea_result">, NoEncode<"$ea_result">; -def LHZUX : XForm_1<31, 311, (outs gprc:$rD, ptr_rc_nor0:$ea_result), +def LHZUX : XForm_1_memOp<31, 311, (outs gprc:$rD, ptr_rc_nor0:$ea_result), (ins memrr:$addr), "lhzux $rD, $addr", IIC_LdStLoadUpdX, []>, RegConstraint<"$addr.ptrreg = $ea_result">, NoEncode<"$ea_result">; -def LWZUX : XForm_1<31, 55, (outs gprc:$rD, ptr_rc_nor0:$ea_result), +def LWZUX : XForm_1_memOp<31, 55, (outs gprc:$rD, ptr_rc_nor0:$ea_result), (ins memrr:$addr), "lwzux $rD, $addr", IIC_LdStLoadUpdX, []>, RegConstraint<"$addr.ptrreg = $ea_result">, NoEncode<"$ea_result">; -def LFSUX : XForm_1<31, 567, (outs f4rc:$rD, ptr_rc_nor0:$ea_result), +let Predicates = [HasFPU] in { +def LFSUX : XForm_1_memOp<31, 567, (outs f4rc:$rD, ptr_rc_nor0:$ea_result), (ins memrr:$addr), "lfsux $rD, $addr", IIC_LdStLFDUX, []>, RegConstraint<"$addr.ptrreg = $ea_result">, NoEncode<"$ea_result">; -def LFDUX : XForm_1<31, 631, (outs f8rc:$rD, ptr_rc_nor0:$ea_result), +def LFDUX : XForm_1_memOp<31, 631, (outs f8rc:$rD, ptr_rc_nor0:$ea_result), (ins memrr:$addr), "lfdux $rD, $addr", IIC_LdStLFDUX, []>, RegConstraint<"$addr.ptrreg = $ea_result">, NoEncode<"$ea_result">; } } +} // Indexed (r+r) Loads. // let PPC970_Unit = 2, mayLoad = 1, mayStore = 0 in { -def LBZX : XForm_1<31, 87, (outs gprc:$rD), (ins memrr:$src), +def LBZX : XForm_1_memOp<31, 87, (outs gprc:$rD), (ins memrr:$src), "lbzx $rD, $src", IIC_LdStLoad, [(set i32:$rD, (zextloadi8 xaddr:$src))]>; -def LHAX : XForm_1<31, 343, (outs gprc:$rD), (ins memrr:$src), +def LHAX : XForm_1_memOp<31, 343, (outs gprc:$rD), (ins memrr:$src), "lhax $rD, $src", IIC_LdStLHA, [(set i32:$rD, (sextloadi16 xaddr:$src))]>, PPC970_DGroup_Cracked; -def LHZX : XForm_1<31, 279, (outs gprc:$rD), (ins memrr:$src), +def LHZX : XForm_1_memOp<31, 279, (outs gprc:$rD), (ins memrr:$src), "lhzx $rD, $src", IIC_LdStLoad, [(set i32:$rD, (zextloadi16 xaddr:$src))]>; -def LWZX : XForm_1<31, 23, (outs gprc:$rD), (ins memrr:$src), +def LWZX : XForm_1_memOp<31, 23, (outs gprc:$rD), (ins memrr:$src), "lwzx $rD, $src", IIC_LdStLoad, [(set i32:$rD, (load xaddr:$src))]>; -def LHBRX : XForm_1<31, 790, (outs gprc:$rD), (ins memrr:$src), +def LHBRX : XForm_1_memOp<31, 790, (outs gprc:$rD), (ins memrr:$src), "lhbrx $rD, $src", IIC_LdStLoad, [(set i32:$rD, (PPClbrx xoaddr:$src, i16))]>; -def LWBRX : XForm_1<31, 534, (outs gprc:$rD), (ins memrr:$src), +def LWBRX : XForm_1_memOp<31, 534, (outs gprc:$rD), (ins memrr:$src), "lwbrx $rD, $src", IIC_LdStLoad, [(set i32:$rD, (PPClbrx xoaddr:$src, i32))]>; -def LFSX : XForm_25<31, 535, (outs f4rc:$frD), (ins memrr:$src), +let Predicates = [HasFPU] in { +def LFSX : XForm_25_memOp<31, 535, (outs f4rc:$frD), (ins memrr:$src), "lfsx $frD, $src", IIC_LdStLFD, [(set f32:$frD, (load xaddr:$src))]>; -def LFDX : XForm_25<31, 599, (outs f8rc:$frD), (ins memrr:$src), +def LFDX : XForm_25_memOp<31, 599, (outs f8rc:$frD), (ins memrr:$src), "lfdx $frD, $src", IIC_LdStLFD, [(set f64:$frD, (load xaddr:$src))]>; -def LFIWAX : XForm_25<31, 855, (outs f8rc:$frD), (ins memrr:$src), +def LFIWAX : XForm_25_memOp<31, 855, (outs f8rc:$frD), (ins memrr:$src), "lfiwax $frD, $src", IIC_LdStLFD, [(set f64:$frD, (PPClfiwax xoaddr:$src))]>; -def LFIWZX : XForm_25<31, 887, (outs f8rc:$frD), (ins memrr:$src), +def LFIWZX : XForm_25_memOp<31, 887, (outs f8rc:$frD), (ins memrr:$src), "lfiwzx $frD, $src", IIC_LdStLFD, [(set f64:$frD, (PPClfiwzx xoaddr:$src))]>; } +} // Load Multiple def LMW : DForm_1<46, (outs gprc:$rD), (ins memri:$src), @@ -1931,6 +1997,7 @@ def STH : DForm_1<44, (outs), (ins gprc:$rS, memri:$src), def STW : DForm_1<36, (outs), (ins gprc:$rS, memri:$src), "stw $rS, $src", IIC_LdStStore, [(store i32:$rS, iaddr:$src)]>; +let Predicates = [HasFPU] in { def STFS : DForm_1<52, (outs), (ins f4rc:$rS, memri:$dst), "stfs $rS, $dst", IIC_LdStSTFD, [(store f32:$rS, iaddr:$dst)]>; @@ -1938,6 +2005,7 @@ def STFD : DForm_1<54, (outs), (ins f8rc:$rS, memri:$dst), "stfd $rS, $dst", IIC_LdStSTFD, [(store f64:$rS, iaddr:$dst)]>; } +} // Unindexed (r+i) Stores with Update (preinc). let PPC970_Unit = 2, mayStore = 1, mayLoad = 0 in { @@ -1950,6 +2018,7 @@ def STHU : DForm_1<45, (outs ptr_rc_nor0:$ea_res), (ins gprc:$rS, memri:$dst), def STWU : DForm_1<37, (outs ptr_rc_nor0:$ea_res), (ins gprc:$rS, memri:$dst), "stwu $rS, $dst", IIC_LdStStoreUpd, []>, RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">; +let Predicates = [HasFPU] in { def STFSU : DForm_1<53, (outs ptr_rc_nor0:$ea_res), (ins f4rc:$rS, memri:$dst), "stfsu $rS, $dst", IIC_LdStSTFDU, []>, RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">; @@ -1957,6 +2026,7 @@ def STFDU : DForm_1<55, (outs ptr_rc_nor0:$ea_res), (ins f8rc:$rS, memri:$dst), "stfdu $rS, $dst", IIC_LdStSTFDU, []>, RegConstraint<"$dst.reg = $ea_res">, NoEncode<"$ea_res">; } +} // Patterns to match the pre-inc stores. We can't put the patterns on // the instruction definitions directly as ISel wants the address base @@ -1974,62 +2044,76 @@ def : Pat<(pre_store f64:$rS, iPTR:$ptrreg, iaddroff:$ptroff), // Indexed (r+r) Stores. let PPC970_Unit = 2 in { -def STBX : XForm_8<31, 215, (outs), (ins gprc:$rS, memrr:$dst), +def STBX : XForm_8_memOp<31, 215, (outs), (ins gprc:$rS, memrr:$dst), "stbx $rS, $dst", IIC_LdStStore, [(truncstorei8 i32:$rS, xaddr:$dst)]>, PPC970_DGroup_Cracked; -def STHX : XForm_8<31, 407, (outs), (ins gprc:$rS, memrr:$dst), +def STHX : XForm_8_memOp<31, 407, (outs), (ins gprc:$rS, memrr:$dst), "sthx $rS, $dst", IIC_LdStStore, [(truncstorei16 i32:$rS, xaddr:$dst)]>, PPC970_DGroup_Cracked; -def STWX : XForm_8<31, 151, (outs), (ins gprc:$rS, memrr:$dst), +def STWX : XForm_8_memOp<31, 151, (outs), (ins gprc:$rS, memrr:$dst), "stwx $rS, $dst", IIC_LdStStore, [(store i32:$rS, xaddr:$dst)]>, PPC970_DGroup_Cracked; - -def STHBRX: XForm_8<31, 918, (outs), (ins gprc:$rS, memrr:$dst), + +def STHBRX: XForm_8_memOp<31, 918, (outs), (ins gprc:$rS, memrr:$dst), "sthbrx $rS, $dst", IIC_LdStStore, [(PPCstbrx i32:$rS, xoaddr:$dst, i16)]>, PPC970_DGroup_Cracked; -def STWBRX: XForm_8<31, 662, (outs), (ins gprc:$rS, memrr:$dst), +def STWBRX: XForm_8_memOp<31, 662, (outs), (ins gprc:$rS, memrr:$dst), "stwbrx $rS, $dst", IIC_LdStStore, [(PPCstbrx i32:$rS, xoaddr:$dst, i32)]>, PPC970_DGroup_Cracked; -def STFIWX: XForm_28<31, 983, (outs), (ins f8rc:$frS, memrr:$dst), +let Predicates = [HasFPU] in { +def STFIWX: XForm_28_memOp<31, 983, (outs), (ins f8rc:$frS, memrr:$dst), "stfiwx $frS, $dst", IIC_LdStSTFD, [(PPCstfiwx f64:$frS, xoaddr:$dst)]>; - -def STFSX : XForm_28<31, 663, (outs), (ins f4rc:$frS, memrr:$dst), + +def STFSX : XForm_28_memOp<31, 663, (outs), (ins f4rc:$frS, memrr:$dst), "stfsx $frS, $dst", IIC_LdStSTFD, [(store f32:$frS, xaddr:$dst)]>; -def STFDX : XForm_28<31, 727, (outs), (ins f8rc:$frS, memrr:$dst), +def STFDX : XForm_28_memOp<31, 727, (outs), (ins f8rc:$frS, memrr:$dst), "stfdx $frS, $dst", IIC_LdStSTFD, [(store f64:$frS, xaddr:$dst)]>; } +} // Indexed (r+r) Stores with Update (preinc). let PPC970_Unit = 2, mayStore = 1, mayLoad = 0 in { -def STBUX : XForm_8<31, 247, (outs ptr_rc_nor0:$ea_res), (ins gprc:$rS, memrr:$dst), - "stbux $rS, $dst", IIC_LdStStoreUpd, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; -def STHUX : XForm_8<31, 439, (outs ptr_rc_nor0:$ea_res), (ins gprc:$rS, memrr:$dst), - "sthux $rS, $dst", IIC_LdStStoreUpd, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; -def STWUX : XForm_8<31, 183, (outs ptr_rc_nor0:$ea_res), (ins gprc:$rS, memrr:$dst), - "stwux $rS, $dst", IIC_LdStStoreUpd, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; -def STFSUX: XForm_8<31, 695, (outs ptr_rc_nor0:$ea_res), (ins f4rc:$rS, memrr:$dst), - "stfsux $rS, $dst", IIC_LdStSTFDU, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; -def STFDUX: XForm_8<31, 759, (outs ptr_rc_nor0:$ea_res), (ins f8rc:$rS, memrr:$dst), - "stfdux $rS, $dst", IIC_LdStSTFDU, []>, - RegConstraint<"$dst.ptrreg = $ea_res">, NoEncode<"$ea_res">, - PPC970_DGroup_Cracked; +def STBUX : XForm_8_memOp<31, 247, (outs ptr_rc_nor0:$ea_res), + (ins gprc:$rS, memrr:$dst), + "stbux $rS, $dst", IIC_LdStStoreUpd, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; +def STHUX : XForm_8_memOp<31, 439, (outs ptr_rc_nor0:$ea_res), + (ins gprc:$rS, memrr:$dst), + "sthux $rS, $dst", IIC_LdStStoreUpd, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; +def STWUX : XForm_8_memOp<31, 183, (outs ptr_rc_nor0:$ea_res), + (ins gprc:$rS, memrr:$dst), + "stwux $rS, $dst", IIC_LdStStoreUpd, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; +let Predicates = [HasFPU] in { +def STFSUX: XForm_8_memOp<31, 695, (outs ptr_rc_nor0:$ea_res), + (ins f4rc:$rS, memrr:$dst), + "stfsux $rS, $dst", IIC_LdStSTFDU, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; +def STFDUX: XForm_8_memOp<31, 759, (outs ptr_rc_nor0:$ea_res), + (ins f8rc:$rS, memrr:$dst), + "stfdux $rS, $dst", IIC_LdStSTFDU, []>, + RegConstraint<"$dst.ptrreg = $ea_res">, + NoEncode<"$ea_res">, + PPC970_DGroup_Cracked; +} } // Patterns to match the pre-inc stores. We can't put the patterns on @@ -2041,10 +2125,12 @@ def : Pat<(pre_truncsti16 i32:$rS, iPTR:$ptrreg, iPTR:$ptroff), (STHUX $rS, $ptrreg, $ptroff)>; def : Pat<(pre_store i32:$rS, iPTR:$ptrreg, iPTR:$ptroff), (STWUX $rS, $ptrreg, $ptroff)>; +let Predicates = [HasFPU] in { def : Pat<(pre_store f32:$rS, iPTR:$ptrreg, iPTR:$ptroff), (STFSUX $rS, $ptrreg, $ptroff)>; def : Pat<(pre_store f64:$rS, iPTR:$ptrreg, iPTR:$ptroff), (STFDUX $rS, $ptrreg, $ptroff)>; +} // Store Multiple def STMW : DForm_1<47, (outs), (ins gprc:$rS, memri:$dst), @@ -2228,7 +2314,7 @@ let isCompare = 1, hasSideEffects = 0 in { "cmplw $crD, $rA, $rB", IIC_IntCompare>; } } -let PPC970_Unit = 3 in { // FPU Operations. +let PPC970_Unit = 3, Predicates = [HasFPU] in { // FPU Operations. //def FCMPO : XForm_17<63, 32, (outs CRRC:$crD), (ins FPRC:$fA, FPRC:$fB), // "fcmpo $crD, $fA, $fB", IIC_FPCompare>; let isCompare = 1, hasSideEffects = 0 in { @@ -2306,13 +2392,13 @@ let Uses = [RM] in { /// often coalesced away and we don't want the dispatch group builder to think /// that they will fill slots (which could cause the load of a LSU reject to /// sneak into a d-group with a store). -let hasSideEffects = 0 in +let hasSideEffects = 0, Predicates = [HasFPU] in defm FMR : XForm_26r<63, 72, (outs f4rc:$frD), (ins f4rc:$frB), "fmr", "$frD, $frB", IIC_FPGeneral, []>, // (set f32:$frD, f32:$frB) PPC970_Unit_Pseudo; -let PPC970_Unit = 3, hasSideEffects = 0 in { // FPU Operations. +let PPC970_Unit = 3, hasSideEffects = 0, Predicates = [HasFPU] in { // FPU Operations. // These are artificially split into two different forms, for 4/8 byte FP. defm FABSS : XForm_26r<63, 264, (outs f4rc:$frD), (ins f4rc:$frB), "fabs", "$frD, $frB", IIC_FPGeneral, @@ -2561,6 +2647,7 @@ def MCRXRX : X_BF3<31, 576, (outs crrc:$BF), (ins), "mcrxrx $BF", IIC_BrMCRX>, Requires<[IsISA3_0]>; } // hasSideEffects = 0 +let Predicates = [HasFPU] in { // Pseudo instruction to perform FADD in round-to-zero mode. let usesCustomInserter = 1, Uses = [RM] in { def FADDrtz: Pseudo<(outs f8rc:$FRT), (ins f8rc:$FRA, f8rc:$FRB), "", @@ -2620,6 +2707,7 @@ let Uses = [RM] in { "mffsl $rT", IIC_IntMFFS, []>, PPC970_DGroup_Single, PPC970_Unit_FPU; } +} let Predicates = [IsISA3_0] in { def MODSW : XForm_8<31, 779, (outs gprc:$rT), (ins gprc:$rA, gprc:$rB), @@ -2717,7 +2805,7 @@ defm SUBFZE : XOForm_3rc<31, 200, 0, (outs gprc:$rT), (ins gprc:$rA), // A-Form instructions. Most of the instructions executed in the FPU are of // this type. // -let PPC970_Unit = 3, hasSideEffects = 0 in { // FPU Operations. +let PPC970_Unit = 3, hasSideEffects = 0, Predicates = [HasFPU] in { // FPU Operations. let Uses = [RM] in { let isCommutable = 1 in { defm FMADD : AForm_1r<63, 29, @@ -3043,6 +3131,7 @@ def : Pat<(extloadi16 iaddr:$src), (LHZ iaddr:$src)>; def : Pat<(extloadi16 xaddr:$src), (LHZX xaddr:$src)>; +let Predicates = [HasFPU] in { def : Pat<(f64 (extloadf32 iaddr:$src)), (COPY_TO_REGCLASS (LFS iaddr:$src), F8RC)>; def : Pat<(f64 (extloadf32 xaddr:$src)), @@ -3050,6 +3139,7 @@ def : Pat<(f64 (extloadf32 xaddr:$src)), def : Pat<(f64 (fpextend f32:$src)), (COPY_TO_REGCLASS $src, F8RC)>; +} // Only seq_cst fences require the heavyweight sync (SYNC 0). // All others can use the lightweight sync (SYNC 1). @@ -3061,6 +3151,7 @@ def : Pat<(atomic_fence (i32 7), (imm)), (SYNC 0)>, Requires<[HasSYNC]>; def : Pat<(atomic_fence (imm), (imm)), (SYNC 1)>, Requires<[HasSYNC]>; def : Pat<(atomic_fence (imm), (imm)), (MSYNC)>, Requires<[HasOnlyMSYNC]>; +let Predicates = [HasFPU] in { // Additional FNMSUB patterns: -a*c + b == -(a*c - b) def : Pat<(fma (fneg f64:$A), f64:$C, f64:$B), (FNMSUB $A, $C, $B)>; @@ -3076,6 +3167,7 @@ def : Pat<(fcopysign f64:$frB, f32:$frA), (FCPSGND (COPY_TO_REGCLASS $frA, F8RC), $frB)>; def : Pat<(fcopysign f32:$frB, f64:$frA), (FCPSGNS (COPY_TO_REGCLASS $frA, F4RC), $frB)>; +} include "PPCInstrAltivec.td" include "PPCInstrSPE.td" @@ -3518,6 +3610,7 @@ defm : CRNotPat<(i1 (setcc i64:$s1, i64:$s2, SETNE)), (EXTRACT_SUBREG (CMPD $s1, $s2), sub_eq)>; // SETCC for f32. +let Predicates = [HasFPU] in { def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETOLT)), (EXTRACT_SUBREG (FCMPUS $s1, $s2), sub_lt)>; def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETLT)), @@ -3579,6 +3672,96 @@ defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETNE)), defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETO)), (EXTRACT_SUBREG (FCMPUD $s1, $s2), sub_un)>; +// SETCC for f128. +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETOLT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETLT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETOGT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETGT)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETOEQ)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETEQ)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +def : Pat<(i1 (setcc f128:$s1, f128:$s2, SETUO)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_un)>; + +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETUGE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETGE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_lt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETULE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETLE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETUNE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETNE)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_eq)>; +defm : CRNotPat<(i1 (setcc f128:$s1, f128:$s2, SETO)), + (EXTRACT_SUBREG (XSCMPUQP $s1, $s2), sub_un)>; + +} + +// This must be in this file because it relies on patterns defined in this file +// after the inclusion of the instruction sets. +let Predicates = [HasSPE] in { +// SETCC for f32. +def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETOLT)), + (EXTRACT_SUBREG (EFSCMPLT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETLT)), + (EXTRACT_SUBREG (EFSCMPLT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETOGT)), + (EXTRACT_SUBREG (EFSCMPGT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETGT)), + (EXTRACT_SUBREG (EFSCMPGT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETOEQ)), + (EXTRACT_SUBREG (EFSCMPEQ $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f32:$s1, f32:$s2, SETEQ)), + (EXTRACT_SUBREG (EFSCMPEQ $s1, $s2), sub_gt)>; + +defm : CRNotPat<(i1 (setcc f32:$s1, f32:$s2, SETUGE)), + (EXTRACT_SUBREG (EFSCMPLT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f32:$s1, f32:$s2, SETGE)), + (EXTRACT_SUBREG (EFSCMPLT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f32:$s1, f32:$s2, SETULE)), + (EXTRACT_SUBREG (EFSCMPGT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f32:$s1, f32:$s2, SETLE)), + (EXTRACT_SUBREG (EFSCMPGT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f32:$s1, f32:$s2, SETUNE)), + (EXTRACT_SUBREG (EFSCMPEQ $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f32:$s1, f32:$s2, SETNE)), + (EXTRACT_SUBREG (EFSCMPEQ $s1, $s2), sub_gt)>; + +// SETCC for f64. +def : Pat<(i1 (setcc f64:$s1, f64:$s2, SETOLT)), + (EXTRACT_SUBREG (EFDCMPLT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f64:$s1, f64:$s2, SETLT)), + (EXTRACT_SUBREG (EFDCMPLT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f64:$s1, f64:$s2, SETOGT)), + (EXTRACT_SUBREG (EFDCMPGT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f64:$s1, f64:$s2, SETGT)), + (EXTRACT_SUBREG (EFDCMPGT $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f64:$s1, f64:$s2, SETOEQ)), + (EXTRACT_SUBREG (EFDCMPEQ $s1, $s2), sub_gt)>; +def : Pat<(i1 (setcc f64:$s1, f64:$s2, SETEQ)), + (EXTRACT_SUBREG (EFDCMPEQ $s1, $s2), sub_gt)>; + +defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETUGE)), + (EXTRACT_SUBREG (EFDCMPLT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETGE)), + (EXTRACT_SUBREG (EFDCMPLT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETULE)), + (EXTRACT_SUBREG (EFDCMPGT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETLE)), + (EXTRACT_SUBREG (EFDCMPGT $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETUNE)), + (EXTRACT_SUBREG (EFDCMPEQ $s1, $s2), sub_gt)>; +defm : CRNotPat<(i1 (setcc f64:$s1, f64:$s2, SETNE)), + (EXTRACT_SUBREG (EFDCMPEQ $s1, $s2), sub_gt)>; +} // match select on i1 variables: def : Pat<(i1 (select i1:$cond, i1:$tval, i1:$fval)), (CROR (CRAND $cond , $tval), @@ -3661,6 +3844,7 @@ def : Pat<(i64 (selectcc i1:$lhs, i1:$rhs, i64:$tval, i64:$fval, SETUGT)), def : Pat<(i64 (selectcc i1:$lhs, i1:$rhs, i64:$tval, i64:$fval, SETNE)), (SELECT_I8 (CRXOR $lhs, $rhs), $tval, $fval)>; +let Predicates = [HasFPU] in { def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETLT)), (SELECT_F4 (CRANDC $lhs, $rhs), $tval, $fval)>; def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETULT)), @@ -3702,6 +3886,28 @@ def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETUGT)), (SELECT_F8 (CRANDC $lhs, $rhs), $tval, $fval)>; def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETNE)), (SELECT_F8 (CRXOR $lhs, $rhs), $tval, $fval)>; +} + +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETLT)), + (SELECT_F16 (CRANDC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETULT)), + (SELECT_F16 (CRANDC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETLE)), + (SELECT_F16 (CRORC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETULE)), + (SELECT_F16 (CRORC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETEQ)), + (SELECT_F16 (CREQV $lhs, $rhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETGE)), + (SELECT_F16 (CRORC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETUGE)), + (SELECT_F16 (CRORC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETGT)), + (SELECT_F16 (CRANDC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETUGT)), + (SELECT_F16 (CRANDC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f128 (selectcc i1:$lhs, i1:$rhs, f128:$tval, f128:$fval, SETNE)), + (SELECT_F16 (CRXOR $lhs, $rhs), $tval, $fval)>; def : Pat<(v4i32 (selectcc i1:$lhs, i1:$rhs, v4i32:$tval, v4i32:$fval, SETLT)), (SELECT_VRRC (CRANDC $lhs, $rhs), $tval, $fval)>; @@ -3751,13 +3957,15 @@ def : Pat<(i1 (not (trunc i64:$in))), // FIXME: For B=0 or B > 8, the registers following RT are used. // WARNING: Do not add patterns for this instruction without fixing this. -def LSWI : XForm_base_r3xo<31, 597, (outs gprc:$RT), (ins gprc:$A, u5imm:$B), - "lswi $RT, $A, $B", IIC_LdStLoad, []>; +def LSWI : XForm_base_r3xo_memOp<31, 597, (outs gprc:$RT), + (ins gprc:$A, u5imm:$B), + "lswi $RT, $A, $B", IIC_LdStLoad, []>; // FIXME: For B=0 or B > 8, the registers following RT are used. // WARNING: Do not add patterns for this instruction without fixing this. -def STSWI : XForm_base_r3xo<31, 725, (outs), (ins gprc:$RT, gprc:$A, u5imm:$B), - "stswi $RT, $A, $B", IIC_LdStLoad, []>; +def STSWI : XForm_base_r3xo_memOp<31, 725, (outs), + (ins gprc:$RT, gprc:$A, u5imm:$B), + "stswi $RT, $A, $B", IIC_LdStLoad, []>; def ISYNC : XLForm_2_ext<19, 150, 0, 0, 0, (outs), (ins), "isync", IIC_SprISYNC, []>; @@ -3769,7 +3977,7 @@ def ICBI : XForm_1a<31, 982, (outs), (ins memrr:$src), def EnforceIEIO : XForm_24_eieio<31, 854, (outs), (ins), "eieio", IIC_LdStLoad, []>; -def WAIT : XForm_24_sync<31, 62, (outs), (ins i32imm:$L), +def WAIT : XForm_24_sync<31, 30, (outs), (ins i32imm:$L), "wait $L", IIC_LdStLoad, []>; def MBAR : XForm_mbar<31, 854, (outs), (ins u5imm:$MO), @@ -3831,6 +4039,7 @@ def MTFSFIo : XLForm_4<63, 134, (outs crrc:$BF), (ins i32imm:$U, i32imm:$W), def : InstAlias<"mtfsfi $BF, $U", (MTFSFI crrc:$BF, i32imm:$U, 0)>; def : InstAlias<"mtfsfi. $BF, $U", (MTFSFIo crrc:$BF, i32imm:$U, 0)>; +let Predicates = [HasFPU] in { def MTFSF : XFLForm_1<63, 711, (outs), (ins i32imm:$FLM, f8rc:$FRB, i32imm:$L, i32imm:$W), "mtfsf $FLM, $FRB, $L, $W", IIC_IntMFFS, []>; @@ -3840,6 +4049,7 @@ def MTFSFo : XFLForm_1<63, 711, (outs), def : InstAlias<"mtfsf $FLM, $FRB", (MTFSF i32imm:$FLM, f8rc:$FRB, 0, 0)>; def : InstAlias<"mtfsf. $FLM, $FRB", (MTFSFo i32imm:$FLM, f8rc:$FRB, 0, 0)>; +} def SLBIE : XForm_16b<31, 434, (outs), (ins gprc:$RB), "slbie $RB", IIC_SprSLBIE, []>; @@ -3920,23 +4130,31 @@ def NAP : XLForm_1_np<19, 434, (outs), (ins), "nap", IIC_BrB, []>; def ATTN : XForm_attn<0, 256, (outs), (ins), "attn", IIC_BrB>; -def LBZCIX : XForm_base_r3xo<31, 853, (outs gprc:$RST), (ins gprc:$A, gprc:$B), - "lbzcix $RST, $A, $B", IIC_LdStLoad, []>; -def LHZCIX : XForm_base_r3xo<31, 821, (outs gprc:$RST), (ins gprc:$A, gprc:$B), - "lhzcix $RST, $A, $B", IIC_LdStLoad, []>; -def LWZCIX : XForm_base_r3xo<31, 789, (outs gprc:$RST), (ins gprc:$A, gprc:$B), - "lwzcix $RST, $A, $B", IIC_LdStLoad, []>; -def LDCIX : XForm_base_r3xo<31, 885, (outs gprc:$RST), (ins gprc:$A, gprc:$B), - "ldcix $RST, $A, $B", IIC_LdStLoad, []>; +def LBZCIX : XForm_base_r3xo_memOp<31, 853, (outs gprc:$RST), + (ins gprc:$A, gprc:$B), + "lbzcix $RST, $A, $B", IIC_LdStLoad, []>; +def LHZCIX : XForm_base_r3xo_memOp<31, 821, (outs gprc:$RST), + (ins gprc:$A, gprc:$B), + "lhzcix $RST, $A, $B", IIC_LdStLoad, []>; +def LWZCIX : XForm_base_r3xo_memOp<31, 789, (outs gprc:$RST), + (ins gprc:$A, gprc:$B), + "lwzcix $RST, $A, $B", IIC_LdStLoad, []>; +def LDCIX : XForm_base_r3xo_memOp<31, 885, (outs gprc:$RST), + (ins gprc:$A, gprc:$B), + "ldcix $RST, $A, $B", IIC_LdStLoad, []>; -def STBCIX : XForm_base_r3xo<31, 981, (outs), (ins gprc:$RST, gprc:$A, gprc:$B), - "stbcix $RST, $A, $B", IIC_LdStLoad, []>; -def STHCIX : XForm_base_r3xo<31, 949, (outs), (ins gprc:$RST, gprc:$A, gprc:$B), - "sthcix $RST, $A, $B", IIC_LdStLoad, []>; -def STWCIX : XForm_base_r3xo<31, 917, (outs), (ins gprc:$RST, gprc:$A, gprc:$B), - "stwcix $RST, $A, $B", IIC_LdStLoad, []>; -def STDCIX : XForm_base_r3xo<31, 1013, (outs), (ins gprc:$RST, gprc:$A, gprc:$B), - "stdcix $RST, $A, $B", IIC_LdStLoad, []>; +def STBCIX : XForm_base_r3xo_memOp<31, 981, (outs), + (ins gprc:$RST, gprc:$A, gprc:$B), + "stbcix $RST, $A, $B", IIC_LdStLoad, []>; +def STHCIX : XForm_base_r3xo_memOp<31, 949, (outs), + (ins gprc:$RST, gprc:$A, gprc:$B), + "sthcix $RST, $A, $B", IIC_LdStLoad, []>; +def STWCIX : XForm_base_r3xo_memOp<31, 917, (outs), + (ins gprc:$RST, gprc:$A, gprc:$B), + "stwcix $RST, $A, $B", IIC_LdStLoad, []>; +def STDCIX : XForm_base_r3xo_memOp<31, 1013, (outs), + (ins gprc:$RST, gprc:$A, gprc:$B), + "stdcix $RST, $A, $B", IIC_LdStLoad, []>; // External PID Load Store Instructions @@ -3960,7 +4178,7 @@ def STBEPX : XForm_8<31, 223, (outs), (ins gprc:$rS, memrr:$dst), "stbepx $rS, $dst", IIC_LdStStore, []>, Requires<[IsE500]>; -def STFDEPX : XForm_28<31, 735, (outs), (ins f8rc:$frS, memrr:$dst), +def STFDEPX : XForm_28_memOp<31, 735, (outs), (ins f8rc:$frS, memrr:$dst), "stfdepx $frS, $dst", IIC_LdStSTFD, []>, Requires<[IsE500]>; @@ -4683,10 +4901,10 @@ def DWMaskValues { def DWSwapInByte { dag Swap1 = (OR8 (AND8 (RLDICL $A, 63, 1), DWMaskValues.Lo1), (AND8 (RLDICR $A, 1, 62), DWMaskValues.Hi1)); - dag Swap2 = (OR8 (AND8 (RLDICL DWSwapInByte.Swap1, 62, 2), DWMaskValues.Lo2), - (AND8 (RLDICR DWSwapInByte.Swap1, 2, 61), DWMaskValues.Hi2)); - dag Swap4 = (OR8 (AND8 (RLDICL DWSwapInByte.Swap2, 60, 4), DWMaskValues.Lo4), - (AND8 (RLDICR DWSwapInByte.Swap2, 4, 59), DWMaskValues.Hi4)); + dag Swap2 = (OR8 (AND8 (RLDICL Swap1, 62, 2), DWMaskValues.Lo2), + (AND8 (RLDICR Swap1, 2, 61), DWMaskValues.Hi2)); + dag Swap4 = (OR8 (AND8 (RLDICL Swap2, 60, 4), DWMaskValues.Lo4), + (AND8 (RLDICR Swap2, 4, 59), DWMaskValues.Hi4)); } // Intra-byte swap is done, now start inter-byte swap. @@ -4706,7 +4924,7 @@ def DWBytes7656 { def DWBytes7654 { dag Word = (RLWIMI DWBytes7656.Word, DWBytes4567.Word, 8, 24, 31); dag DWord = - (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), DWBytes7654.Word, sub_32)); + (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), Word, sub_32)); } def DWBytes0123 { @@ -4725,7 +4943,7 @@ def DWBytes3212 { def DWBytes3210 { dag Word = (RLWIMI DWBytes3212.Word, DWBytes0123.Word, 8, 24, 31); dag DWord = - (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), DWBytes3210.Word, sub_32)); + (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), Word, sub_32)); } // Now both high word and low word are reversed, next diff --git a/lib/Target/PowerPC/PPCInstrQPX.td b/lib/Target/PowerPC/PPCInstrQPX.td index 4940c77c7ae5..c4bb02695b36 100644 --- a/lib/Target/PowerPC/PPCInstrQPX.td +++ b/lib/Target/PowerPC/PPCInstrQPX.td @@ -502,14 +502,14 @@ let Uses = [RM] in { // Load indexed instructions let mayLoad = 1 in { - def QVLFDX : XForm_1<31, 583, - (outs qfrc:$FRT), (ins memrr:$src), - "qvlfdx $FRT, $src", IIC_LdStLFD, - [(set v4f64:$FRT, (load xoaddr:$src))]>; + def QVLFDX : XForm_1_memOp<31, 583, + (outs qfrc:$FRT), (ins memrr:$src), + "qvlfdx $FRT, $src", IIC_LdStLFD, + [(set v4f64:$FRT, (load xoaddr:$src))]>; let isCodeGenOnly = 1 in - def QVLFDXb : XForm_1<31, 583, - (outs qbrc:$FRT), (ins memrr:$src), - "qvlfdx $FRT, $src", IIC_LdStLFD, []>; + def QVLFDXb : XForm_1_memOp<31, 583, + (outs qbrc:$FRT), (ins memrr:$src), + "qvlfdx $FRT, $src", IIC_LdStLFD, []>; let RC = 1 in def QVLFDXA : XForm_1<31, 583, @@ -527,10 +527,10 @@ let Uses = [RM] in { (outs qfrc:$FRT), (ins memrr:$src), "qvlfduxa $FRT, $src", IIC_LdStLFD, []>; - def QVLFSX : XForm_1<31, 519, - (outs qfrc:$FRT), (ins memrr:$src), - "qvlfsx $FRT, $src", IIC_LdStLFD, - [(set v4f64:$FRT, (extloadv4f32 xoaddr:$src))]>; + def QVLFSX : XForm_1_memOp<31, 519, + (outs qfrc:$FRT), (ins memrr:$src), + "qvlfsx $FRT, $src", IIC_LdStLFD, + [(set v4f64:$FRT, (extloadv4f32 xoaddr:$src))]>; let isCodeGenOnly = 1 in def QVLFSXb : XForm_1<31, 519, @@ -538,10 +538,10 @@ let Uses = [RM] in { "qvlfsx $FRT, $src", IIC_LdStLFD, [(set v4i1:$FRT, (PPCqvlfsb xoaddr:$src))]>; let isCodeGenOnly = 1 in - def QVLFSXs : XForm_1<31, 519, - (outs qsrc:$FRT), (ins memrr:$src), - "qvlfsx $FRT, $src", IIC_LdStLFD, - [(set v4f32:$FRT, (load xoaddr:$src))]>; + def QVLFSXs : XForm_1_memOp<31, 519, + (outs qsrc:$FRT), (ins memrr:$src), + "qvlfsx $FRT, $src", IIC_LdStLFD, + [(set v4f32:$FRT, (load xoaddr:$src))]>; let RC = 1 in def QVLFSXA : XForm_1<31, 519, @@ -634,12 +634,12 @@ let Uses = [RM] in { // Store indexed instructions let mayStore = 1 in { - def QVSTFDX : XForm_8<31, 711, + def QVSTFDX : XForm_8_memOp<31, 711, (outs), (ins qfrc:$FRT, memrr:$dst), "qvstfdx $FRT, $dst", IIC_LdStSTFD, [(store qfrc:$FRT, xoaddr:$dst)]>; let isCodeGenOnly = 1 in - def QVSTFDXb : XForm_8<31, 711, + def QVSTFDXb : XForm_8_memOp<31, 711, (outs), (ins qbrc:$FRT, memrr:$dst), "qvstfdx $FRT, $dst", IIC_LdStSTFD, []>; @@ -675,12 +675,12 @@ let Uses = [RM] in { (outs), (ins qfrc:$FRT, memrr:$dst), "qvstfduxia $FRT, $dst", IIC_LdStSTFD, []>; - def QVSTFSX : XForm_8<31, 647, + def QVSTFSX : XForm_8_memOp<31, 647, (outs), (ins qfrc:$FRT, memrr:$dst), "qvstfsx $FRT, $dst", IIC_LdStSTFD, [(truncstorev4f32 qfrc:$FRT, xoaddr:$dst)]>; let isCodeGenOnly = 1 in - def QVSTFSXs : XForm_8<31, 647, + def QVSTFSXs : XForm_8_memOp<31, 647, (outs), (ins qsrc:$FRT, memrr:$dst), "qvstfsx $FRT, $dst", IIC_LdStSTFD, [(store qsrc:$FRT, xoaddr:$dst)]>; diff --git a/lib/Target/PowerPC/PPCInstrSPE.td b/lib/Target/PowerPC/PPCInstrSPE.td index cc3a4d20a9b2..96649efdc1bc 100644 --- a/lib/Target/PowerPC/PPCInstrSPE.td +++ b/lib/Target/PowerPC/PPCInstrSPE.td @@ -12,14 +12,56 @@ // //===----------------------------------------------------------------------===// +class EFXForm_1<bits<11> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> : + I<4, OOL, IOL, asmstr, itin> { + bits<5> RT; + bits<5> RA; + bits<5> RB; + + let Pattern = pattern; + + let Inst{6-10} = RT; + let Inst{11-15} = RA; + let Inst{16-20} = RB; + let Inst{21-31} = xo; +} + +class EFXForm_2<bits<11> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> : + EFXForm_1<xo, OOL, IOL, asmstr, itin, pattern> { + let RB = 0; +} + +class EFXForm_2a<bits<11> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> : + EFXForm_1<xo, OOL, IOL, asmstr, itin, pattern> { + let RA = 0; +} + +class EFXForm_3<bits<11> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin> : + I<4, OOL, IOL, asmstr, itin> { + bits<3> crD; + bits<5> RA; + bits<5> RB; + + let Inst{6-8} = crD; + let Inst{9-10} = 0; + let Inst{11-15} = RA; + let Inst{16-20} = RB; + let Inst{21-31} = xo; +} + class EVXForm_1<bits<11> xo, dag OOL, dag IOL, string asmstr, - InstrItinClass itin> : I<4, OOL, IOL, asmstr, itin> { + InstrItinClass itin, list<dag> pattern> : + I<4, OOL, IOL, asmstr, itin> { bits<5> RT; bits<5> RA; bits<5> RB; - let Pattern = []; - + let Pattern = pattern; + let Inst{6-10} = RT; let Inst{11-15} = RA; let Inst{16-20} = RB; @@ -27,18 +69,26 @@ class EVXForm_1<bits<11> xo, dag OOL, dag IOL, string asmstr, } class EVXForm_2<bits<11> xo, dag OOL, dag IOL, string asmstr, - InstrItinClass itin> : EVXForm_1<xo, OOL, IOL, asmstr, itin> { + InstrItinClass itin, list<dag> pattern> : + EVXForm_1<xo, OOL, IOL, asmstr, itin, pattern> { let RB = 0; } +class EVXForm_2a<bits<11> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> : + EVXForm_1<xo, OOL, IOL, asmstr, itin, pattern> { + let RA = 0; +} + class EVXForm_3<bits<11> xo, dag OOL, dag IOL, string asmstr, - InstrItinClass itin> : I<4, OOL, IOL, asmstr, itin> { + InstrItinClass itin, list<dag> pattern> : + I<4, OOL, IOL, asmstr, itin> { bits<3> crD; bits<5> RA; bits<5> RB; - let Pattern = []; - + let Pattern = pattern; + let Inst{6-8} = crD; let Inst{9-10} = 0; let Inst{11-15} = RA; @@ -46,12 +96,30 @@ class EVXForm_3<bits<11> xo, dag OOL, dag IOL, string asmstr, let Inst{21-31} = xo; } +class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list<dag> pattern> : + I<4, OOL, IOL, asmstr, itin> { + bits<3> crD; + bits<5> RA; + bits<5> RB; + bits<5> RT; + + let Pattern = pattern; + + let Inst{6-10} = RT; + let Inst{11-15} = RA; + let Inst{16-20} = RB; + let Inst{21-28} = xo; + let Inst{29-31} = crD; +} + class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr, - InstrItinClass itin> : I<4, OOL, IOL, asmstr, itin> { + InstrItinClass itin, list<dag> pattern> : + I<4, OOL, IOL, asmstr, itin> { bits<5> RT; bits<21> D; - let Pattern = []; + let Pattern = pattern; let Inst{6-10} = RT; let Inst{20} = D{0}; @@ -68,380 +136,757 @@ class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr, let Inst{21-31} = xo; } -let Predicates = [HasSPE], isAsmParserOnly = 1 in { +let DecoderNamespace = "SPE", Predicates = [HasSPE] in { + +def BRINC : EVXForm_1<527, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), + "brinc $RT, $RA, $RB", IIC_IntSimple, []>; -def EVLDD : EVXForm_D<769, (outs gprc:$RT), (ins spe8dis:$dst), - "evldd $RT, $dst", IIC_VecFP>; -def EVLDW : EVXForm_D<771, (outs gprc:$RT), (ins spe8dis:$dst), - "evldw $RT, $dst", IIC_VecFP>; -def EVLDH : EVXForm_D<773, (outs gprc:$RT), (ins spe8dis:$dst), - "evldh $RT, $dst", IIC_VecFP>; -def EVLHHESPLAT : EVXForm_D<777, (outs gprc:$RT), (ins spe2dis:$dst), - "evlhhesplat $RT, $dst", IIC_VecFP>; -def EVLHHOUSPLAT : EVXForm_D<781, (outs gprc:$RT), (ins spe2dis:$dst), - "evlhhousplat $RT, $dst", IIC_VecFP>; -def EVLHHOSSPLAT : EVXForm_D<783, (outs gprc:$RT), (ins spe2dis:$dst), - "evlhhossplat $RT, $dst", IIC_VecFP>; -def EVLWHE : EVXForm_D<785, (outs gprc:$RT), (ins spe4dis:$dst), - "evlwhe $RT, $dst", IIC_VecFP>; -def EVLWHOU : EVXForm_D<789, (outs gprc:$RT), (ins spe4dis:$dst), - "evlwhou $RT, $dst", IIC_VecFP>; -def EVLWHOS : EVXForm_D<791, (outs gprc:$RT), (ins spe4dis:$dst), - "evlwhos $RT, $dst", IIC_VecFP>; -def EVLWWSPLAT : EVXForm_D<793, (outs gprc:$RT), (ins spe4dis:$dst), - "evlwwsplat $RT, $dst", IIC_VecFP>; -def EVLWHSPLAT : EVXForm_D<797, (outs gprc:$RT), (ins spe4dis:$dst), - "evlwhsplat $RT, $dst", IIC_VecFP>; +// Double-precision floating point +def EFDABS : EFXForm_2<740, (outs sperc:$RT), (ins sperc:$RA), + "efdabs $RT, $RA", IIC_FPDGeneral, + [(set f64:$RT, (fabs f64:$RA))]>; -def EVSTDD : EVXForm_D<801, (outs), (ins gprc:$RT, spe8dis:$dst), - "evstdd $RT, $dst", IIC_VecFP>; -def EVSTDH : EVXForm_D<805, (outs), (ins gprc:$RT, spe8dis:$dst), - "evstdh $RT, $dst", IIC_VecFP>; -def EVSTDW : EVXForm_D<803, (outs), (ins gprc:$RT, spe8dis:$dst), - "evstdw $RT, $dst", IIC_VecFP>; -def EVSTWHE : EVXForm_D<817, (outs), (ins gprc:$RT, spe4dis:$dst), - "evstwhe $RT, $dst", IIC_VecFP>; -def EVSTWHO : EVXForm_D<821, (outs), (ins gprc:$RT, spe4dis:$dst), - "evstwho $RT, $dst", IIC_VecFP>; -def EVSTWWE : EVXForm_D<825, (outs), (ins gprc:$RT, spe4dis:$dst), - "evstwwe $RT, $dst", IIC_VecFP>; -def EVSTWWO : EVXForm_D<829, (outs), (ins gprc:$RT, spe4dis:$dst), - "evstwwo $RT, $dst", IIC_VecFP>; +def EFDADD : EFXForm_1<736, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "efdadd $RT, $RA, $RB", IIC_FPAddSub, + [(set f64:$RT, (fadd f64:$RA, f64:$RB))]>; -def EVMRA : EVXForm_1<1220, (outs gprc:$RT), (ins gprc:$RA), - "evmra $RT, $RA", IIC_VecFP> { - let RB = 0; +def EFDCFS : EFXForm_2a<751, (outs sperc:$RT), (ins spe4rc:$RB), + "efdcfs $RT, $RB", IIC_FPDGeneral, + [(set f64:$RT, (fpextend f32:$RB))]>; + +def EFDCFSF : EFXForm_2a<755, (outs sperc:$RT), (ins spe4rc:$RB), + "efdcfsf $RT, $RB", IIC_FPDGeneral, []>; + +def EFDCFSI : EFXForm_2a<753, (outs sperc:$RT), (ins gprc:$RB), + "efdcfsi $RT, $RB", IIC_FPDGeneral, + [(set f64:$RT, (sint_to_fp i32:$RB))]>; + +def EFDCFSID : EFXForm_2a<739, (outs sperc:$RT), (ins gprc:$RB), + "efdcfsid $RT, $RB", IIC_FPDGeneral, + []>; + +def EFDCFUF : EFXForm_2a<754, (outs sperc:$RT), (ins spe4rc:$RB), + "efdcfuf $RT, $RB", IIC_FPDGeneral, []>; + +def EFDCFUI : EFXForm_2a<752, (outs sperc:$RT), (ins gprc:$RB), + "efdcfui $RT, $RB", IIC_FPDGeneral, + [(set f64:$RT, (uint_to_fp i32:$RB))]>; + +def EFDCFUID : EFXForm_2a<738, (outs sperc:$RT), (ins gprc:$RB), + "efdcfuid $RT, $RB", IIC_FPDGeneral, + []>; + +let isCompare = 1 in { +def EFDCMPEQ : EFXForm_3<750, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efdcmpeq $crD, $RA, $RB", IIC_FPDGeneral>; +def EFDCMPGT : EFXForm_3<748, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efdcmpgt $crD, $RA, $RB", IIC_FPDGeneral>; +def EFDCMPLT : EFXForm_3<749, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efdcmplt $crD, $RA, $RB", IIC_FPDGeneral>; } -def BRINC : EVXForm_1<527, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "brinc $RT, $RA, $RB", IIC_VecFP>; -def EVABS : EVXForm_2<520, (outs gprc:$RT), (ins gprc:$RA), - "evabs $RT, $RA", IIC_VecFP>; +def EFDCTSF : EFXForm_2a<759, (outs sperc:$RT), (ins spe4rc:$RB), + "efdctsf $RT, $RB", IIC_FPDGeneral, []>; -def EVADDIW : EVXForm_1<514, (outs gprc:$RT), (ins gprc:$RA, u5imm:$RB), - "evaddiw $RT, $RB, $RA", IIC_VecFP>; -def EVADDSMIAAW : EVXForm_2<1225, (outs gprc:$RT), (ins gprc:$RA), - "evaddsmiaaw $RT, $RA", IIC_VecFP>; -def EVADDSSIAAW : EVXForm_2<1217, (outs gprc:$RT), (ins gprc:$RA), - "evaddssiaaw $RT, $RA", IIC_VecFP>; -def EVADDUSIAAW : EVXForm_2<1216, (outs gprc:$RT), (ins gprc:$RA), - "evaddusiaaw $RT, $RA", IIC_VecFP>; -def EVADDUMIAAW : EVXForm_2<1224, (outs gprc:$RT), (ins gprc:$RA), - "evaddumiaaw $RT, $RA", IIC_VecFP>; -def EVADDW : EVXForm_1<512, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evaddw $RT, $RA, $RB", IIC_VecFP>; +def EFDCTSI : EFXForm_2a<757, (outs gprc:$RT), (ins sperc:$RB), + "efdctsi $RT, $RB", IIC_FPDGeneral, + []>; -def EVAND : EVXForm_1<529, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evand $RT, $RA, $RB", IIC_VecFP>; -def EVANDC : EVXForm_1<530, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evandc $RT, $RA, $RB", IIC_VecFP>; +def EFDCTSIDZ : EFXForm_2a<747, (outs gprc:$RT), (ins sperc:$RB), + "efdctsidz $RT, $RB", IIC_FPDGeneral, + []>; -def EVCMPEQ : EVXForm_3<564, (outs crrc:$crD), (ins gprc:$RA, gprc:$RB), - "evcmpeq $crD, $RA, $RB", IIC_VecFP>; -def EVCMPGTS : EVXForm_3<561, (outs crrc:$crD), (ins gprc:$RA, gprc:$RB), - "evcmpgts $crD, $RA, $RB", IIC_VecFP>; -def EVCMPGTU : EVXForm_3<560, (outs crrc:$crD), (ins gprc:$RA, gprc:$RB), - "evcmpgtu $crD, $RA, $RB", IIC_VecFP>; -def EVCMPLTS : EVXForm_3<563, (outs crrc:$crD), (ins gprc:$RA, gprc:$RB), - "evcmplts $crD, $RA, $RB", IIC_VecFP>; -def EVCMPLTU : EVXForm_3<562, (outs crrc:$crD), (ins gprc:$RA, gprc:$RB), - "evcmpltu $crD, $RA, $RB", IIC_VecFP>; +def EFDCTSIZ : EFXForm_2a<762, (outs gprc:$RT), (ins sperc:$RB), + "efdctsiz $RT, $RB", IIC_FPDGeneral, + [(set i32:$RT, (fp_to_sint f64:$RB))]>; -def EVCNTLSW : EVXForm_2<526, (outs gprc:$RT), (ins gprc:$RA), - "evcntlsw $RT, $RA", IIC_VecFP>; -def EVCNTLZW : EVXForm_2<525, (outs gprc:$RT), (ins gprc:$RA), - "evcntlzw $RT, $RA", IIC_VecFP>; +def EFDCTUF : EFXForm_2a<758, (outs sperc:$RT), (ins spe4rc:$RB), + "efdctuf $RT, $RB", IIC_FPDGeneral, []>; -def EVDIVWS : EVXForm_1<1222, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evdivws $RT, $RA, $RB", IIC_VecFP>; -def EVDIVWU : EVXForm_1<1223, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evdivwu $RT, $RA, $RB", IIC_VecFP>; +def EFDCTUI : EFXForm_2a<756, (outs gprc:$RT), (ins sperc:$RB), + "efdctui $RT, $RB", IIC_FPDGeneral, + []>; -def EVEQV : EVXForm_1<537, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "eveqv $RT, $RA, $RB", IIC_VecFP>; +def EFDCTUIDZ : EFXForm_2a<746, (outs gprc:$RT), (ins sperc:$RB), + "efdctuidz $RT, $RB", IIC_FPDGeneral, + []>; -def EVEXTSB : EVXForm_2<522, (outs gprc:$RT), (ins gprc:$RA), - "evextsb $RT, $RA", IIC_VecFP>; -def EVEXTSH : EVXForm_2<523, (outs gprc:$RT), (ins gprc:$RA), - "evextsh $RT, $RA", IIC_VecFP>; +def EFDCTUIZ : EFXForm_2a<760, (outs gprc:$RT), (ins sperc:$RB), + "efdctuiz $RT, $RB", IIC_FPDGeneral, + [(set i32:$RT, (fp_to_uint f64:$RB))]>; -def EVLDDX : EVXForm_1<768, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlddx $RT, $RA, $RB", IIC_VecFP>; -def EVLDWX : EVXForm_1<770, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evldwx $RT, $RA, $RB", IIC_VecFP>; -def EVLDHX : EVXForm_1<772, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evldhx $RT, $RA, $RB", IIC_VecFP>; -def EVLHHESPLATX : EVXForm_1<776, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlhhesplatx $RT, $RA, $RB", IIC_VecFP>; -def EVLHHOUSPLATX : EVXForm_1<780, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlhhousplatx $RT, $RA, $RB", IIC_VecFP>; -def EVLHHOSSPLATX : EVXForm_1<782, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlhhossplatx $RT, $RA, $RB", IIC_VecFP>; -def EVLWHEX : EVXForm_1<784, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlwhex $RT, $RA, $RB", IIC_VecFP>; -def EVLWHOUX : EVXForm_1<788, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlwhoux $RT, $RA, $RB", IIC_VecFP>; -def EVLWHOSX : EVXForm_1<790, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlwhosx $RT, $RA, $RB", IIC_VecFP>; -def EVLWWSPLATX : EVXForm_1<792, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlwwsplatx $RT, $RA, $RB", IIC_VecFP>; -def EVLWHSPLATX : EVXForm_1<796, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evlwhsplatx $RT, $RA, $RB", IIC_VecFP>; +def EFDDIV : EFXForm_1<745, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "efddiv $RT, $RA, $RB", IIC_FPDivD, + [(set f64:$RT, (fdiv f64:$RA, f64:$RB))]>; -def EVMERGEHI : EVXForm_1<556, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmergehi $RT, $RA, $RB", IIC_VecFP>; -def EVMERGELO : EVXForm_1<557, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmergelo $RT, $RA, $RB", IIC_VecFP>; -def EVMERGEHILO : EVXForm_1<558, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmergehilo $RT, $RA, $RB", IIC_VecFP>; -def EVMERGELOHI : EVXForm_1<559, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmergelohi $RT, $RA, $RB", IIC_VecFP>; +def EFDMUL : EFXForm_1<744, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "efdmul $RT, $RA, $RB", IIC_FPDGeneral, + [(set f64:$RT, (fmul f64:$RA, f64:$RB))]>; -def EVMHEGSMFAA : EVXForm_1<1323, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhegsmfaa $RT, $RA, $RB", IIC_VecFP>; -def EVMHEGSMFAN : EVXForm_1<1451, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhegsmfan $RT, $RA, $RB", IIC_VecFP>; -def EVMHEGSMIAA : EVXForm_1<1321, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhegsmiaa $RT, $RA, $RB", IIC_VecFP>; -def EVMHEGSMIAN : EVXForm_1<1449, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhegsmian $RT, $RA, $RB", IIC_VecFP>; -def EVMHEGUMIAA : EVXForm_1<1320, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhegumiaa $RT, $RA, $RB", IIC_VecFP>; -def EVMHEGUMIAN : EVXForm_1<1448, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhegumian $RT, $RA, $RB", IIC_VecFP>; +def EFDNABS : EFXForm_2<741, (outs sperc:$RT), (ins sperc:$RA), + "efdnabs $RT, $RA", IIC_FPDGeneral, + [(set f64:$RT, (fneg (fabs f64:$RA)))]>; -def EVMHESMF : EVXForm_1<1035, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmf $RT, $RA, $RB", IIC_VecFP>; -def EVMHESMFA : EVXForm_1<1067, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmfa $RT, $RA, $RB", IIC_VecFP>; -def EVMHESMFAAW : EVXForm_1<1291, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmfaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHESMFANW : EVXForm_1<1419, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmfanw $RT, $RA, $RB", IIC_VecFP>; -def EVMHESMI : EVXForm_1<1033, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmi $RT, $RA, $RB", IIC_VecFP>; -def EVMHESMIA : EVXForm_1<1065, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmia $RT, $RA, $RB", IIC_VecFP>; -def EVMHESMIAAW : EVXForm_1<1289, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHESMIANW : EVXForm_1<1417, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhesmianw $RT, $RA, $RB", IIC_VecFP>; -def EVMHESSF : EVXForm_1<1027, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhessf $RT, $RA, $RB", IIC_VecFP>; -def EVMHESSFA : EVXForm_1<1059, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhessfa $RT, $RA, $RB", IIC_VecFP>; -def EVMHESSFAAW : EVXForm_1<1283, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhessfaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHESSFANW : EVXForm_1<1411, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhessfanw $RT, $RA, $RB", IIC_VecFP>; -def EVMHESSIAAW : EVXForm_1<1281, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhessiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHESSIANW : EVXForm_1<1409, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhessianw $RT, $RA, $RB", IIC_VecFP>; -def EVMHEUMI : EVXForm_1<1032, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmheumi $RT, $RA, $RB", IIC_VecFP>; -def EVMHEUMIA : EVXForm_1<1064, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmheumia $RT, $RA, $RB", IIC_VecFP>; -def EVMHEUMIAAW : EVXForm_1<1288, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmheumiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHEUMIANW : EVXForm_1<1416, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmheumianw $RT, $RA, $RB", IIC_VecFP>; -def EVMHEUSIAAW : EVXForm_1<1280, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmheusiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHEUSIANW : EVXForm_1<1408, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmheusianw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOGSMFAA : EVXForm_1<1327, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhogsmfaa $RT, $RA, $RB", IIC_VecFP>; -def EVMHOGSMFAN : EVXForm_1<1455, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhogsmfan $RT, $RA, $RB", IIC_VecFP>; -def EVMHOGSMIAA : EVXForm_1<1325, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhogsmiaa $RT, $RA, $RB", IIC_VecFP>; -def EVMHOGSMIAN : EVXForm_1<1453, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhogsmian $RT, $RA, $RB", IIC_VecFP>; -def EVMHOGUMIAA : EVXForm_1<1324, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhogumiaa $RT, $RA, $RB", IIC_VecFP>; -def EVMHOGUMIAN : EVXForm_1<1452, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhogumian $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMF : EVXForm_1<1039, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmf $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMFA : EVXForm_1<1071, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmfa $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMFAAW : EVXForm_1<1295, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmfaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMFANW : EVXForm_1<1423, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmfanw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMI : EVXForm_1<1037, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmi $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMIA : EVXForm_1<1069, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmia $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMIAAW : EVXForm_1<1293, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSMIANW : EVXForm_1<1421, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhosmianw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSSF : EVXForm_1<1031, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhossf $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSSFA : EVXForm_1<1063, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhossfa $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSSFAAW : EVXForm_1<1287, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhossfaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSSFANW : EVXForm_1<1415, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhossfanw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSSIAAW : EVXForm_1<1285, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhossiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOSSIANW : EVXForm_1<1413, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhossianw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOUMI : EVXForm_1<1036, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhoumi $RT, $RA, $RB", IIC_VecFP>; -def EVMHOUMIA : EVXForm_1<1068, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhoumia $RT, $RA, $RB", IIC_VecFP>; -def EVMHOUMIAAW : EVXForm_1<1292, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhoumiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOUMIANW : EVXForm_1<1420, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhoumianw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOUSIAAW : EVXForm_1<1284, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhousiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMHOUSIANW : EVXForm_1<1412, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmhousianw $RT, $RA, $RB", IIC_VecFP>; +def EFDNEG : EFXForm_2<742, (outs sperc:$RT), (ins sperc:$RA), + "efdneg $RT, $RA", IIC_FPDGeneral, + [(set f64:$RT, (fneg f64:$RA))]>; +def EFDSUB : EFXForm_1<737, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "efdsub $RT, $RA, $RB", IIC_FPDGeneral, + [(set f64:$RT, (fsub f64:$RA, f64:$RB))]>; -def EVMWHSMF : EVXForm_1<1103, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhsmf $RT, $RA, $RB", IIC_VecFP>; -def EVMWHSMFA : EVXForm_1<1135, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhsmfa $RT, $RA, $RB", IIC_VecFP>; -def EVMWHSMI : EVXForm_1<1101, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhsmi $RT, $RA, $RB", IIC_VecFP>; -def EVMWHSMIA : EVXForm_1<1133, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhsmia $RT, $RA, $RB", IIC_VecFP>; -def EVMWHSSF : EVXForm_1<1095, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhssf $RT, $RA, $RB", IIC_VecFP>; -def EVMWHSSFA : EVXForm_1<1127, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhssfa $RT, $RA, $RB", IIC_VecFP>; -def EVMWHUMI : EVXForm_1<1100, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhumi $RT, $RA, $RB", IIC_VecFP>; -def EVMWHUMIA : EVXForm_1<1132, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwhumia $RT, $RA, $RB", IIC_VecFP>; -def EVMWLSMIAAW : EVXForm_1<1353, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlsmiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMWLSMIANW : EVXForm_1<1481, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlsmianw $RT, $RA, $RB", IIC_VecFP>; -def EVMWLSSIAAW : EVXForm_1<1345, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlssiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMWLSSIANW : EVXForm_1<1473, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlssianw $RT, $RA, $RB", IIC_VecFP>; -def EVMWLUMI : EVXForm_1<1096, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlumi $RT, $RA, $RB", IIC_VecFP>; -def EVMWLUMIA : EVXForm_1<1128, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlumia $RT, $RA, $RB", IIC_VecFP>; -def EVMWLUMIAAW : EVXForm_1<1352, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlumiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMWLUMIANW : EVXForm_1<1480, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlumianw $RT, $RA, $RB", IIC_VecFP>; -def EVMWLUSIAAW : EVXForm_1<1344, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlusiaaw $RT, $RA, $RB", IIC_VecFP>; -def EVMWLUSIANW : EVXForm_1<1472, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwlusianw $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMF : EVXForm_1<1115, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmf $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMFA : EVXForm_1<1147, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmfa $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMFAA : EVXForm_1<1371, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmfaa $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMFAN : EVXForm_1<1499, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmfan $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMI : EVXForm_1<1113, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmi $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMIA : EVXForm_1<1145, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmia $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMIAA : EVXForm_1<1369, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmiaa $RT, $RA, $RB", IIC_VecFP>; -def EVMWSMIAN : EVXForm_1<1497, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwsmian $RT, $RA, $RB", IIC_VecFP>; -def EVMWSSF : EVXForm_1<1107, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwssf $RT, $RA, $RB", IIC_VecFP>; -def EVMWSSFA : EVXForm_1<1139, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwssfa $RT, $RA, $RB", IIC_VecFP>; -def EVMWSSFAA : EVXForm_1<1363, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwssfaa $RT, $RA, $RB", IIC_VecFP>; -def EVMWSSFAN : EVXForm_1<1491, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwssfan $RT, $RA, $RB", IIC_VecFP>; -def EVMWUMI : EVXForm_1<1112, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwumi $RT, $RA, $RB", IIC_VecFP>; -def EVMWUMIA : EVXForm_1<1144, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwumia $RT, $RA, $RB", IIC_VecFP>; -def EVMWUMIAA : EVXForm_1<1368, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwumiaa $RT, $RA, $RB", IIC_VecFP>; -def EVMWUMIAN : EVXForm_1<1496, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evmwumian $RT, $RA, $RB", IIC_VecFP>; +let isCompare = 1 in { +def EFDTSTEQ : EFXForm_3<766, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efdtsteq $crD, $RA, $RB", IIC_FPDGeneral>; +def EFDTSTGT : EFXForm_3<764, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efdtstgt $crD, $RA, $RB", IIC_FPDGeneral>; +def EFDTSTLT : EFXForm_3<765, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efdtstlt $crD, $RA, $RB", IIC_FPDGeneral>; +} +// Single-precision floating point +def EFSABS : EFXForm_2<708, (outs spe4rc:$RT), (ins spe4rc:$RA), + "efsabs $RT, $RA", IIC_FPSGeneral, + [(set f32:$RT, (fabs f32:$RA))]>; -def EVNAND : EVXForm_1<542, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evnand $RT, $RA, $RB", IIC_VecFP>; +def EFSADD : EFXForm_1<704, (outs spe4rc:$RT), (ins spe4rc:$RA, spe4rc:$RB), + "efsadd $RT, $RA, $RB", IIC_FPAddSub, + [(set f32:$RT, (fadd f32:$RA, f32:$RB))]>; -def EVNEG : EVXForm_2<521, (outs gprc:$RT), (ins gprc:$RA), - "evneg $RT, $RA", IIC_VecFP>; +def EFSCFD : EFXForm_2a<719, (outs spe4rc:$RT), (ins sperc:$RB), + "efscfd $RT, $RB", IIC_FPSGeneral, + [(set f32:$RT, (fpround f64:$RB))]>; -def EVNOR : EVXForm_1<536, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evnor $RT, $RA, $RB", IIC_VecFP>; -def EVOR : EVXForm_1<535, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evor $RT, $RA, $RB", IIC_VecFP>; -def EVORC : EVXForm_1<539, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evorc $RT, $RA, $RB", IIC_VecFP>; +def EFSCFSF : EFXForm_2a<723, (outs spe4rc:$RT), (ins spe4rc:$RB), + "efscfsf $RT, $RB", IIC_FPSGeneral, []>; -def EVRLWI : EVXForm_1<554, (outs gprc:$RT), (ins gprc:$RA, u5imm:$RB), - "evrlwi $RT, $RA, $RB", IIC_VecFP>; -def EVRLW : EVXForm_1<552, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evrlw $RT, $RA, $RB", IIC_VecFP>; +def EFSCFSI : EFXForm_2a<721, (outs spe4rc:$RT), (ins gprc:$RB), + "efscfsi $RT, $RB", IIC_FPSGeneral, + [(set f32:$RT, (sint_to_fp i32:$RB))]>; -def EVRNDW : EVXForm_2<524, (outs gprc:$RT), (ins gprc:$RA), - "evrndw $RT, $RA", IIC_VecFP>; +def EFSCFUF : EFXForm_2a<722, (outs spe4rc:$RT), (ins spe4rc:$RB), + "efscfuf $RT, $RB", IIC_FPSGeneral, []>; -def EVSLWI : EVXForm_1<550, (outs gprc:$RT), (ins gprc:$RA, u5imm:$RB), - "evslwi $RT, $RA, $RB", IIC_VecFP>; -def EVSLW : EVXForm_1<548, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evslw $RT, $RA, $RB", IIC_VecFP>; +def EFSCFUI : EFXForm_2a<720, (outs spe4rc:$RT), (ins gprc:$RB), + "efscfui $RT, $RB", IIC_FPSGeneral, + [(set f32:$RT, (uint_to_fp i32:$RB))]>; -def EVSPLATFI : EVXForm_2<555, (outs gprc:$RT), (ins i32imm:$RA), - "evsplatfi $RT, $RA", IIC_VecFP>; -def EVSPLATI : EVXForm_2<553, (outs gprc:$RT), (ins i32imm:$RA), - "evsplati $RT, $RA", IIC_VecFP>; +let isCompare = 1 in { +def EFSCMPEQ : EFXForm_3<718, (outs crrc:$crD), (ins spe4rc:$RA, spe4rc:$RB), + "efscmpeq $crD, $RA, $RB", IIC_FPCompare>; +def EFSCMPGT : EFXForm_3<716, (outs crrc:$crD), (ins spe4rc:$RA, spe4rc:$RB), + "efscmpgt $crD, $RA, $RB", IIC_FPCompare>; +def EFSCMPLT : EFXForm_3<717, (outs crrc:$crD), (ins spe4rc:$RA, spe4rc:$RB), + "efscmplt $crD, $RA, $RB", IIC_FPCompare>; +} + +def EFSCTSF : EFXForm_2a<727, (outs spe4rc:$RT), (ins spe4rc:$RB), + "efsctsf $RT, $RB", IIC_FPSGeneral, []>; + +def EFSCTSI : EFXForm_2a<725, (outs gprc:$RT), (ins spe4rc:$RB), + "efsctsi $RT, $RB", IIC_FPSGeneral, + []>; + +def EFSCTSIZ : EFXForm_2a<730, (outs gprc:$RT), (ins spe4rc:$RB), + "efsctsiz $RT, $RB", IIC_FPSGeneral, + [(set i32:$RT, (fp_to_sint f32:$RB))]>; + +def EFSCTUF : EFXForm_2a<726, (outs sperc:$RT), (ins spe4rc:$RB), + "efsctuf $RT, $RB", IIC_FPSGeneral, []>; + +def EFSCTUI : EFXForm_2a<724, (outs gprc:$RT), (ins spe4rc:$RB), + "efsctui $RT, $RB", IIC_FPSGeneral, + []>; + +def EFSCTUIZ : EFXForm_2a<728, (outs gprc:$RT), (ins spe4rc:$RB), + "efsctuiz $RT, $RB", IIC_FPSGeneral, + [(set i32:$RT, (fp_to_uint f32:$RB))]>; + +def EFSDIV : EFXForm_1<713, (outs spe4rc:$RT), (ins spe4rc:$RA, spe4rc:$RB), + "efsdiv $RT, $RA, $RB", IIC_FPDivD, + [(set f32:$RT, (fdiv f32:$RA, f32:$RB))]>; + +def EFSMUL : EFXForm_1<712, (outs spe4rc:$RT), (ins spe4rc:$RA, spe4rc:$RB), + "efsmul $RT, $RA, $RB", IIC_FPGeneral, + [(set f32:$RT, (fmul f32:$RA, f32:$RB))]>; + +def EFSNABS : EFXForm_2<709, (outs spe4rc:$RT), (ins spe4rc:$RA), + "efsnabs $RT, $RA", IIC_FPGeneral, + [(set f32:$RT, (fneg (fabs f32:$RA)))]>; + +def EFSNEG : EFXForm_2<710, (outs spe4rc:$RT), (ins spe4rc:$RA), + "efsneg $RT, $RA", IIC_FPGeneral, + [(set f32:$RT, (fneg f32:$RA))]>; + +def EFSSUB : EFXForm_1<705, (outs spe4rc:$RT), (ins spe4rc:$RA, spe4rc:$RB), + "efssub $RT, $RA, $RB", IIC_FPSGeneral, + [(set f32:$RT, (fsub f32:$RA, f32:$RB))]>; + +let isCompare = 1 in { +def EFSTSTEQ : EFXForm_3<734, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efststeq $crD, $RA, $RB", IIC_FPCompare>; +def EFSTSTGT : EFXForm_3<732, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efststgt $crD, $RA, $RB", IIC_FPCompare>; +def EFSTSTLT : EFXForm_3<733, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "efststlt $crD, $RA, $RB", IIC_FPCompare>; +} -def EVSRWIS : EVXForm_1<547, (outs gprc:$RT), (ins gprc:$RA, u5imm:$RB), - "evsrwis $RT, $RA, $RB", IIC_VecFP>; -def EVSRWIU : EVXForm_1<546, (outs gprc:$RT), (ins gprc:$RA, u5imm:$RB), - "evsrwiu $RT, $RA, $RB", IIC_VecFP>; -def EVSRWS : EVXForm_1<545, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evsrws $RT, $RA, $RB", IIC_VecFP>; -def EVSRWU : EVXForm_1<544, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evsrwu $RT, $RA, $RB", IIC_VecFP>; +// SPE Vector operations -def EVSTDDX : EVXForm_1<800, (outs), (ins gprc:$RT, gprc:$RA, gprc:$RB), - "evstddx $RT, $RA, $RB", IIC_VecFP>; -def EVSTDHX : EVXForm_1<804, (outs), (ins gprc:$RT, gprc:$RA, gprc:$RB), - "evstdhx $RT, $RA, $RB", IIC_VecFP>; -def EVSTDWX : EVXForm_1<802, (outs), (ins gprc:$RT, gprc:$RA, gprc:$RB), - "evstdwx $RT, $RA, $RB", IIC_VecFP>; -def EVSTWHEX : EVXForm_1<816, (outs), (ins gprc:$RT, gprc:$RA, gprc:$RB), - "evstwhex $RT, $RA, $RB", IIC_VecFP>; -def EVSTWHOX : EVXForm_1<820, (outs), (ins gprc:$RT, gprc:$RA, gprc:$RB), - "evstwhox $RT, $RA, $RB", IIC_VecFP>; -def EVSTWWEX : EVXForm_1<824, (outs), (ins gprc:$RT, gprc:$RA, gprc:$RB), - "evstwwex $RT, $RA, $RB", IIC_VecFP>; -def EVSTWWOX : EVXForm_1<828, (outs), (ins gprc:$RT, gprc:$RA, gprc:$RB), - "evstwwox $RT, $RA, $RB", IIC_VecFP>; +def EVABS : EVXForm_2<520, (outs sperc:$RT), (ins sperc:$RA), + "evabs $RT, $RA", IIC_VecGeneral, + []>; + +def EVADDIW : EVXForm_1<514, (outs sperc:$RT), (ins sperc:$RA, u5imm:$RB), + "evaddiw $RT, $RB, $RA", IIC_VecGeneral, []>; +def EVADDSMIAAW : EVXForm_2<1225, (outs sperc:$RT), (ins sperc:$RA), + "evaddsmiaaw $RT, $RA", IIC_VecComplex, []>; +def EVADDSSIAAW : EVXForm_2<1217, (outs sperc:$RT), (ins sperc:$RA), + "evaddssiaaw $RT, $RA", IIC_VecComplex, []>; +def EVADDUSIAAW : EVXForm_2<1216, (outs sperc:$RT), (ins sperc:$RA), + "evaddusiaaw $RT, $RA", IIC_VecComplex, []>; +def EVADDUMIAAW : EVXForm_2<1224, (outs sperc:$RT), (ins sperc:$RA), + "evaddumiaaw $RT, $RA", IIC_VecComplex, []>; +def EVADDW : EVXForm_1<512, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evaddw $RT, $RA, $RB", IIC_VecGeneral, + []>; + +def EVAND : EVXForm_1<529, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evand $RT, $RA, $RB", IIC_VecGeneral, + []>; +def EVANDC : EVXForm_1<530, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evandc $RT, $RA, $RB", IIC_VecGeneral, + []>; + +let isCompare = 1 in { +def EVCMPEQ : EVXForm_3<564, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evcmpeq $crD, $RA, $RB", IIC_VecGeneral, []>; +def EVCMPGTS : EVXForm_3<561, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evcmpgts $crD, $RA, $RB", IIC_VecGeneral, []>; +def EVCMPGTU : EVXForm_3<560, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evcmpgtu $crD, $RA, $RB", IIC_VecGeneral, []>; +def EVCMPLTS : EVXForm_3<563, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evcmplts $crD, $RA, $RB", IIC_VecGeneral, []>; +def EVCMPLTU : EVXForm_3<562, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evcmpltu $crD, $RA, $RB", IIC_VecGeneral, []>; +} + +def EVCNTLSW : EVXForm_2<526, (outs sperc:$RT), (ins sperc:$RA), + "evcntlsw $RT, $RA", IIC_VecGeneral, []>; +def EVCNTLZW : EVXForm_2<525, (outs sperc:$RT), (ins sperc:$RA), + "evcntlzw $RT, $RA", IIC_VecGeneral, + []>; + +def EVDIVWS : EVXForm_1<1222, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evdivws $RT, $RA, $RB", IIC_VecComplex, + []>; +def EVDIVWU : EVXForm_1<1223, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evdivwu $RT, $RA, $RB", IIC_VecComplex, + []>; + +def EVEQV : EVXForm_1<537, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "eveqv $RT, $RA, $RB", IIC_VecGeneral, + []>; + +def EVEXTSB : EVXForm_2<522, (outs sperc:$RT), (ins sperc:$RA), + "evextsb $RT, $RA", IIC_VecGeneral, + []>; +def EVEXTSH : EVXForm_2<523, (outs sperc:$RT), (ins sperc:$RA), + "evextsh $RT, $RA", IIC_VecGeneral, + []>; + +def EVFSABS : EVXForm_2<644, (outs sperc:$RT), (ins sperc:$RA), + "evfsabs $RT, $RA", IIC_VecGeneral, + []>; +def EVFSADD : EVXForm_1<640, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evfsadd $RT, $RA, $RB", IIC_VecComplex, + []>; +def EVFSCFSF : EVXForm_2a<659, (outs sperc:$RT), (ins sperc:$RB), + "evfscfsf $RT, $RB", IIC_VecComplex, []>; +def EVFSCFSI : EVXForm_2a<657, (outs sperc:$RT), (ins sperc:$RB), + "evfscfsi $RT, $RB", IIC_VecComplex, + []>; +def EVFSCFUF : EVXForm_2a<658, (outs sperc:$RT), (ins sperc:$RB), + "evfscfuf $RT, $RB", IIC_VecComplex, []>; +def EVFSCFUI : EVXForm_2a<650, (outs sperc:$RT), (ins sperc:$RB), + "evfscfui $RT, $RB", IIC_VecComplex, + []>; +let isCompare = 1 in { +def EVFSCMPEQ : EVXForm_3<654, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evfscmpeq $crD, $RA, $RB", IIC_FPSGeneral, []>; +def EVFSCMPGT : EVXForm_3<652, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evfscmpgt $crD, $RA, $RB", IIC_FPSGeneral, []>; +def EVFSCMPLT : EVXForm_3<653, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evfscmplt $crD, $RA, $RB", IIC_FPSGeneral, []>; +} + +def EVFSCTSF : EVXForm_2a<663, (outs sperc:$RT), (ins sperc:$RB), + "evfsctsf $RT, $RB", IIC_VecComplex, []>; +def EVFSCTSI : EVXForm_2a<661, (outs sperc:$RT), (ins sperc:$RB), + "evfsctsi $RT, $RB", IIC_VecComplex, + []>; +def EVFSCTSIZ : EVXForm_2a<666, (outs sperc:$RT), (ins sperc:$RB), + "evfsctsiz $RT, $RB", IIC_VecComplex, + []>; +def EVFSCTUF : EVXForm_2a<662, (outs sperc:$RT), (ins sperc:$RB), + "evfsctsf $RT, $RB", IIC_VecComplex, []>; +def EVFSCTUI : EVXForm_2a<660, (outs sperc:$RT), (ins sperc:$RB), + "evfsctui $RT, $RB", IIC_VecComplex, + []>; +def EVFSCTUIZ : EVXForm_2a<664, (outs sperc:$RT), (ins sperc:$RB), + "evfsctsiz $RT, $RB", IIC_VecComplex, + []>; +def EVFSDIV : EVXForm_1<649, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evfsdiv $RT, $RA, $RB", IIC_FPDivD, + []>; +def EVFSMUL : EVXForm_1<648, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evfsmul $RT, $RA, $RB", IIC_VecComplex, + []>; +def EVFSNABS : EVXForm_2<645, (outs sperc:$RT), (ins sperc:$RA), + "evfsnabs $RT, $RA", IIC_VecGeneral, + []>; +def EVFSNEG : EVXForm_2<646, (outs sperc:$RT), (ins sperc:$RA), + "evfsneg $RT, $RA", IIC_VecGeneral, + []>; +def EVFSSUB : EVXForm_1<641, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evfssub $RT, $RA, $RB", IIC_VecComplex, + []>; + +let isCompare = 1 in { +def EVFSTSTEQ : EVXForm_3<670, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evfststeq $crD, $RA, $RB", IIC_VecGeneral, []>; +def EVFSTSTGT : EVXForm_3<668, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evfststgt $crD, $RA, $RB", IIC_VecGeneral, []>; +def EVFSTSTLT : EVXForm_3<669, (outs crrc:$crD), (ins sperc:$RA, sperc:$RB), + "evfststlt $crD, $RA, $RB", IIC_VecGeneral, []>; +} -def EVSUBFSSIAAW : EVXForm_2<1219, (outs gprc:$RT), (ins gprc:$RA), - "evsubfssiaaw $RT, $RA", IIC_VecFP>; -def EVSUBFSMIAAW : EVXForm_2<1227, (outs gprc:$RT), (ins gprc:$RA), - "evsubfsmiaaw $RT, $RA", IIC_VecFP>; -def EVSUBFUMIAAW : EVXForm_2<1226, (outs gprc:$RT), (ins gprc:$RA), - "evsubfumiaaw $RT, $RA", IIC_VecFP>; -def EVSUBFUSIAAW : EVXForm_2<1218, (outs gprc:$RT), (ins gprc:$RA), - "evsubfusiaaw $RT, $RA", IIC_VecFP>; -def EVSUBFW : EVXForm_1<516, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evsubfw $RT, $RA, $RB", IIC_VecFP>; -def EVSUBIFW : EVXForm_1<518, (outs gprc:$RT), (ins u5imm:$RA, gprc:$RB), - "evsubifw $RT, $RA, $RB", IIC_VecFP>; -def EVXOR : EVXForm_1<534, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), - "evxor $RT, $RA, $RB", IIC_VecFP>; +def EVLDD : EVXForm_D<769, (outs sperc:$RT), (ins spe8dis:$dst), + "evldd $RT, $dst", IIC_LdStLoad, + [(set f64:$RT, (load iaddr:$dst))]>; +def EVLDDX : EVXForm_1<768, (outs sperc:$RT), (ins memrr:$src), + "evlddx $RT, $src", IIC_LdStLoad, + [(set f64:$RT, (load xaddr:$src))]>; +def EVLDH : EVXForm_D<773, (outs sperc:$RT), (ins spe8dis:$dst), + "evldh $RT, $dst", IIC_LdStLoad, []>; +def EVLDHX : EVXForm_1<772, (outs sperc:$RT), (ins memrr:$src), + "evldhx $RT, $src", IIC_LdStLoad, []>; +def EVLDW : EVXForm_D<771, (outs sperc:$RT), (ins spe8dis:$dst), + "evldw $RT, $dst", IIC_LdStLoad, + []>; +def EVLDWX : EVXForm_1<770, (outs sperc:$RT), (ins memrr:$src), + "evldwx $RT, $src", IIC_LdStLoad, + []>; +def EVLHHESPLAT : EVXForm_D<777, (outs sperc:$RT), (ins spe2dis:$dst), + "evlhhesplat $RT, $dst", IIC_LdStLoad, []>; +def EVLHHESPLATX : EVXForm_1<776, (outs sperc:$RT), (ins memrr:$src), + "evlhhesplatx $RT, $src", IIC_LdStLoad, []>; +def EVLHHOUSPLAT : EVXForm_D<781, (outs sperc:$RT), (ins spe2dis:$dst), + "evlhhousplat $RT, $dst", IIC_LdStLoad, []>; +def EVLHHOUSPLATX : EVXForm_1<780, (outs sperc:$RT), (ins memrr:$src), + "evlhhousplatx $RT, $src", IIC_LdStLoad, []>; +def EVLHHOSSPLAT : EVXForm_D<783, (outs sperc:$RT), (ins spe2dis:$dst), + "evlhhossplat $RT, $dst", IIC_LdStLoad, []>; +def EVLHHOSSPLATX : EVXForm_1<782, (outs sperc:$RT), (ins memrr:$src), + "evlhhossplatx $RT, $src", IIC_LdStLoad, []>; +def EVLWHE : EVXForm_D<785, (outs sperc:$RT), (ins spe4dis:$dst), + "evlwhe $RT, $dst", IIC_LdStLoad, []>; +def EVLWHEX : EVXForm_1<784, (outs sperc:$RT), (ins memrr:$src), + "evlwhex $RT, $src", IIC_LdStLoad, []>; +def EVLWHOS : EVXForm_D<791, (outs sperc:$RT), (ins spe4dis:$dst), + "evlwhos $RT, $dst", IIC_LdStLoad, []>; +def EVLWHOSX : EVXForm_1<790, (outs sperc:$RT), (ins memrr:$src), + "evlwhosx $RT, $src", IIC_LdStLoad, []>; +def EVLWHOU : EVXForm_D<789, (outs sperc:$RT), (ins spe4dis:$dst), + "evlwhou $RT, $dst", IIC_LdStLoad, []>; +def EVLWHOUX : EVXForm_1<788, (outs sperc:$RT), (ins memrr:$src), + "evlwhoux $RT, $src", IIC_LdStLoad, []>; +def EVLWHSPLAT : EVXForm_D<797, (outs sperc:$RT), (ins spe4dis:$dst), + "evlwhsplat $RT, $dst", IIC_LdStLoad, []>; +def EVLWHSPLATX : EVXForm_1<796, (outs sperc:$RT), (ins memrr:$src), + "evlwhsplatx $RT, $src", IIC_LdStLoad, []>; +def EVLWWSPLAT : EVXForm_D<793, (outs sperc:$RT), (ins spe4dis:$dst), + "evlwwsplat $RT, $dst", IIC_LdStLoad, []>; +def EVLWWSPLATX : EVXForm_1<792, (outs sperc:$RT), (ins memrr:$src), + "evlwwsplatx $RT, $src", IIC_LdStLoad, []>; + +def EVMERGEHI : EVXForm_1<556, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmergehi $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVMERGELO : EVXForm_1<557, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmergelo $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVMERGEHILO : EVXForm_1<558, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmergehilo $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVMERGELOHI : EVXForm_1<559, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmergelohi $RT, $RA, $RB", IIC_VecGeneral, []>; + +def EVMHEGSMFAA : EVXForm_1<1323, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhegsmfaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEGSMFAN : EVXForm_1<1451, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhegsmfan $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEGSMIAA : EVXForm_1<1321, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhegsmiaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEGSMIAN : EVXForm_1<1449, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhegsmian $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEGUMIAA : EVXForm_1<1320, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhegumiaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEGUMIAN : EVXForm_1<1448, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhegumian $RT, $RA, $RB", IIC_VecComplex, []>; + +def EVMHESMF : EVXForm_1<1035, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESMFA : EVXForm_1<1067, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESMFAAW : EVXForm_1<1291, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmfaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESMFANW : EVXForm_1<1419, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmfanw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESMI : EVXForm_1<1033, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESMIA : EVXForm_1<1065, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESMIAAW : EVXForm_1<1289, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESMIANW : EVXForm_1<1417, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhesmianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESSF : EVXForm_1<1027, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhessf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESSFA : EVXForm_1<1059, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhessfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESSFAAW : EVXForm_1<1283, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhessfaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESSFANW : EVXForm_1<1411, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhessfanw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESSIAAW : EVXForm_1<1281, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhessiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHESSIANW : EVXForm_1<1409, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhessianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEUMI : EVXForm_1<1032, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmheumi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEUMIA : EVXForm_1<1064, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmheumia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEUMIAAW : EVXForm_1<1288, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmheumiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEUMIANW : EVXForm_1<1416, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmheumianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEUSIAAW : EVXForm_1<1280, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmheusiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHEUSIANW : EVXForm_1<1408, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmheusianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOGSMFAA : EVXForm_1<1327, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhogsmfaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOGSMFAN : EVXForm_1<1455, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhogsmfan $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOGSMIAA : EVXForm_1<1325, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhogsmiaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOGSMIAN : EVXForm_1<1453, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhogsmian $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOGUMIAA : EVXForm_1<1324, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhogumiaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOGUMIAN : EVXForm_1<1452, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhogumian $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMF : EVXForm_1<1039, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMFA : EVXForm_1<1071, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMFAAW : EVXForm_1<1295, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmfaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMFANW : EVXForm_1<1423, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmfanw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMI : EVXForm_1<1037, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMIA : EVXForm_1<1069, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMIAAW : EVXForm_1<1293, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSMIANW : EVXForm_1<1421, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhosmianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSSF : EVXForm_1<1031, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhossf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSSFA : EVXForm_1<1063, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhossfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSSFAAW : EVXForm_1<1287, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhossfaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSSFANW : EVXForm_1<1415, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhossfanw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSSIAAW : EVXForm_1<1285, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhossiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOSSIANW : EVXForm_1<1413, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhossianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOUMI : EVXForm_1<1036, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhoumi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOUMIA : EVXForm_1<1068, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhoumia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOUMIAAW : EVXForm_1<1292, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhoumiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOUMIANW : EVXForm_1<1420, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhoumianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOUSIAAW : EVXForm_1<1284, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhousiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMHOUSIANW : EVXForm_1<1412, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmhousianw $RT, $RA, $RB", IIC_VecComplex, []>; + +def EVMRA : EVXForm_2<1220, (outs sperc:$RT), (ins sperc:$RA), + "evmra $RT, $RA", IIC_VecComplex, []>; + +def EVMWHSMF : EVXForm_1<1103, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhsmf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWHSMFA : EVXForm_1<1135, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhsmfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWHSMI : EVXForm_1<1101, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhsmi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWHSMIA : EVXForm_1<1133, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhsmia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWHSSF : EVXForm_1<1095, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhssf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWHSSFA : EVXForm_1<1127, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhssfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWHUMI : EVXForm_1<1100, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhumi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWHUMIA : EVXForm_1<1132, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwhumia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLSMIAAW : EVXForm_1<1353, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlsmiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLSMIANW : EVXForm_1<1481, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlsmianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLSSIAAW : EVXForm_1<1345, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlssiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLSSIANW : EVXForm_1<1473, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlssianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLUMI : EVXForm_1<1096, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlumi $RT, $RA, $RB", IIC_VecComplex, + []>; +def EVMWLUMIA : EVXForm_1<1128, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlumia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLUMIAAW : EVXForm_1<1352, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlumiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLUMIANW : EVXForm_1<1480, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlumianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLUSIAAW : EVXForm_1<1344, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlusiaaw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWLUSIANW : EVXForm_1<1472, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwlusianw $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMF : EVXForm_1<1115, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMFA : EVXForm_1<1147, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMFAA : EVXForm_1<1371, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmfaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMFAN : EVXForm_1<1499, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmfan $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMI : EVXForm_1<1113, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMIA : EVXForm_1<1145, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMIAA : EVXForm_1<1369, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmiaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSMIAN : EVXForm_1<1497, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwsmian $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSSF : EVXForm_1<1107, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwssf $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSSFA : EVXForm_1<1139, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwssfa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSSFAA : EVXForm_1<1363, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwssfaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWSSFAN : EVXForm_1<1491, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwssfan $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWUMI : EVXForm_1<1112, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwumi $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWUMIA : EVXForm_1<1144, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwumia $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWUMIAA : EVXForm_1<1368, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwumiaa $RT, $RA, $RB", IIC_VecComplex, []>; +def EVMWUMIAN : EVXForm_1<1496, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evmwumian $RT, $RA, $RB", IIC_VecComplex, []>; + + +def EVNAND : EVXForm_1<542, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evnand $RT, $RA, $RB", IIC_VecGeneral, + []>; + +def EVNEG : EVXForm_2<521, (outs sperc:$RT), (ins sperc:$RA), + "evneg $RT, $RA", IIC_VecGeneral, + []>; + +def EVNOR : EVXForm_1<536, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evnor $RT, $RA, $RB", IIC_VecGeneral, + []>; +def EVOR : EVXForm_1<535, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evor $RT, $RA, $RB", IIC_VecGeneral, + []>; +def EVORC : EVXForm_1<539, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evorc $RT, $RA, $RB", IIC_VecGeneral, + []>; + +def EVRLWI : EVXForm_1<554, (outs sperc:$RT), (ins sperc:$RA, u5imm:$RB), + "evrlwi $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVRLW : EVXForm_1<552, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evrlw $RT, $RA, $RB", IIC_VecGeneral, + []>; + +def EVRNDW : EVXForm_2<524, (outs sperc:$RT), (ins sperc:$RA), + "evrndw $RT, $RA", IIC_VecGeneral, []>; + +def EVSEL : EVXForm_4<79, (outs sperc:$RT), + (ins sperc:$RA, sperc:$RB, crrc:$crD), + "evsel crD,$RT,$RA,$RB", IIC_VecGeneral, []>; + +def EVSLWI : EVXForm_1<550, (outs sperc:$RT), (ins sperc:$RA, u5imm:$RB), + "evslwi $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVSLW : EVXForm_1<548, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evslw $RT, $RA, $RB", IIC_VecGeneral, + []>; + +def EVSPLATFI : EVXForm_2<555, (outs sperc:$RT), (ins s5imm:$RA), + "evsplatfi $RT, $RA", IIC_VecGeneral, []>; +def EVSPLATI : EVXForm_2<553, (outs sperc:$RT), (ins s5imm:$RA), + "evsplati $RT, $RA", IIC_VecGeneral, []>; + +def EVSRWIS : EVXForm_1<547, (outs sperc:$RT), (ins sperc:$RA, u5imm:$RB), + "evsrwis $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVSRWIU : EVXForm_1<546, (outs sperc:$RT), (ins sperc:$RA, u5imm:$RB), + "evsrwiu $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVSRWS : EVXForm_1<545, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evsrws $RT, $RA, $RB", IIC_VecGeneral, + []>; +def EVSRWU : EVXForm_1<544, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evsrwu $RT, $RA, $RB", IIC_VecGeneral, + []>; + +def EVSTDD : EVXForm_D<801, (outs), (ins sperc:$RT, spe8dis:$dst), + "evstdd $RT, $dst", IIC_LdStStore, + [(store f64:$RT, iaddr:$dst)]>; +def EVSTDDX : EVXForm_1<800, (outs), (ins sperc:$RT, memrr:$dst), + "evstddx $RT, $dst", IIC_LdStStore, + [(store f64:$RT, xaddr:$dst)]>; +def EVSTDH : EVXForm_D<805, (outs), (ins sperc:$RT, spe8dis:$dst), + "evstdh $RT, $dst", IIC_LdStStore, []>; +def EVSTDHX : EVXForm_1<804, (outs), (ins sperc:$RT, memrr:$dst), + "evstdhx $RT, $dst", IIC_LdStStore, []>; +def EVSTDW : EVXForm_D<803, (outs), (ins sperc:$RT, spe8dis:$dst), + "evstdw $RT, $dst", IIC_LdStStore, + []>; +def EVSTDWX : EVXForm_1<802, (outs), (ins sperc:$RT, memrr:$dst), + "evstdwx $RT, $dst", IIC_LdStStore, + []>; +def EVSTWHE : EVXForm_D<817, (outs), (ins sperc:$RT, spe4dis:$dst), + "evstwhe $RT, $dst", IIC_LdStStore, []>; +def EVSTWHEX : EVXForm_1<816, (outs), (ins sperc:$RT, memrr:$dst), + "evstwhex $RT, $dst", IIC_LdStStore, []>; +def EVSTWHO : EVXForm_D<821, (outs), (ins sperc:$RT, spe4dis:$dst), + "evstwho $RT, $dst", IIC_LdStStore, []>; +def EVSTWHOX : EVXForm_1<820, (outs), (ins sperc:$RT, memrr:$dst), + "evstwhox $RT, $dst", IIC_LdStStore, []>; +def EVSTWWE : EVXForm_D<825, (outs), (ins sperc:$RT, spe4dis:$dst), + "evstwwe $RT, $dst", IIC_LdStStore, []>; +def EVSTWWEX : EVXForm_1<824, (outs), (ins sperc:$RT, memrr:$dst), + "evstwwex $RT, $dst", IIC_LdStStore, []>; +def EVSTWWO : EVXForm_D<829, (outs), (ins sperc:$RT, spe4dis:$dst), + "evstwwo $RT, $dst", IIC_LdStStore, []>; +def EVSTWWOX : EVXForm_1<828, (outs), (ins sperc:$RT, memrr:$dst), + "evstwwox $RT, $dst", IIC_LdStStore, []>; + +def EVSUBFSSIAAW : EVXForm_2<1219, (outs sperc:$RT), (ins sperc:$RA), + "evsubfssiaaw $RT, $RA", IIC_VecComplex, []>; +def EVSUBFSMIAAW : EVXForm_2<1227, (outs sperc:$RT), (ins sperc:$RA), + "evsubfsmiaaw $RT, $RA", IIC_VecComplex, []>; +def EVSUBFUMIAAW : EVXForm_2<1226, (outs sperc:$RT), (ins sperc:$RA), + "evsubfumiaaw $RT, $RA", IIC_VecComplex, []>; +def EVSUBFUSIAAW : EVXForm_2<1218, (outs sperc:$RT), (ins sperc:$RA), + "evsubfusiaaw $RT, $RA", IIC_VecComplex, []>; +def EVSUBFW : EVXForm_1<516, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evsubfw $RT, $RA, $RB", IIC_VecGeneral, + []>; +def EVSUBIFW : EVXForm_1<518, (outs sperc:$RT), (ins u5imm:$RA, sperc:$RB), + "evsubifw $RT, $RA, $RB", IIC_VecGeneral, []>; +def EVXOR : EVXForm_1<534, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB), + "evxor $RT, $RA, $RB", IIC_VecGeneral, + []>; + +let isAsmParserOnly = 1 in { +// Identical to the integer Load/Stores, but to handle floats +def SPELWZ : DForm_1<32, (outs spe4rc:$rD), (ins memri:$src), + "lwz $rD, $src", IIC_LdStLoad, + [(set f32:$rD, (load iaddr:$src))]>; +def SPELWZX : XForm_1<31, 23, (outs spe4rc:$rD), (ins memrr:$src), + "lwzx $rD, $src", IIC_LdStLoad, + [(set f32:$rD, (load xaddr:$src))]>; +def SPESTW : DForm_1<36, (outs), (ins spe4rc:$rS, memri:$src), + "stw $rS, $src", IIC_LdStStore, + [(store f32:$rS, iaddr:$src)]>; +def SPESTWX : XForm_8<31, 151, (outs), (ins spe4rc:$rS, memrr:$dst), + "stwx $rS, $dst", IIC_LdStStore, + [(store f32:$rS, xaddr:$dst)]>; +} } // HasSPE + +let Predicates = [HasSPE] in { +def : Pat<(f64 (extloadf32 iaddr:$src)), + (COPY_TO_REGCLASS (SPELWZ iaddr:$src), SPERC)>; +def : Pat<(f64 (extloadf32 xaddr:$src)), + (COPY_TO_REGCLASS (SPELWZX xaddr:$src), SPERC)>; + +def : Pat<(f64 (fpextend f32:$src)), + (COPY_TO_REGCLASS $src, SPERC)>; +} + +let Predicates = [HasSPE] in { + let usesCustomInserter = 1 in { +def SELECT_CC_SPE4 : Pseudo<(outs spe4rc:$dst), + (ins crrc:$cond, spe4rc:$T, spe4rc:$F, + i32imm:$BROPC), "#SELECT_CC_SPE4", + []>; +def SELECT_CC_SPE : Pseudo<(outs sperc:$dst), + (ins crrc:$cond, sperc:$T, sperc:$F, i32imm:$BROPC), + "#SELECT_CC_SPE", + []>; +def SELECT_SPE4 : Pseudo<(outs spe4rc:$dst), (ins crbitrc:$cond, + spe4rc:$T, spe4rc:$F), "#SELECT_SPE4", + [(set f32:$dst, (select i1:$cond, f32:$T, f32:$F))]>; +def SELECT_SPE : Pseudo<(outs sperc:$dst), (ins crbitrc:$cond, + sperc:$T, sperc:$F), "#SELECT_SPE", + [(set f64:$dst, (select i1:$cond, f64:$T, f64:$F))]>; + } + +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETLT)), + (SELECT_SPE4 (CRANDC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETULT)), + (SELECT_SPE4 (CRANDC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETLE)), + (SELECT_SPE4 (CRORC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETULE)), + (SELECT_SPE4 (CRORC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETEQ)), + (SELECT_SPE4 (CREQV $lhs, $rhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETGE)), + (SELECT_SPE4 (CRORC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETUGE)), + (SELECT_SPE4 (CRORC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETGT)), + (SELECT_SPE4 (CRANDC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETUGT)), + (SELECT_SPE4 (CRANDC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f32 (selectcc i1:$lhs, i1:$rhs, f32:$tval, f32:$fval, SETNE)), + (SELECT_SPE4 (CRXOR $lhs, $rhs), $tval, $fval)>; + +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETLT)), + (SELECT_SPE (CRANDC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETULT)), + (SELECT_SPE (CRANDC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETLE)), + (SELECT_SPE (CRORC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETULE)), + (SELECT_SPE (CRORC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETEQ)), + (SELECT_SPE (CREQV $lhs, $rhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETGE)), + (SELECT_SPE (CRORC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETUGE)), + (SELECT_SPE (CRORC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETGT)), + (SELECT_SPE (CRANDC $rhs, $lhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETUGT)), + (SELECT_SPE (CRANDC $lhs, $rhs), $tval, $fval)>; +def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETNE)), + (SELECT_SPE (CRXOR $lhs, $rhs), $tval, $fval)>; +} diff --git a/lib/Target/PowerPC/PPCInstrVSX.td b/lib/Target/PowerPC/PPCInstrVSX.td index 6f719784eb7c..ffba0e5aadb5 100644 --- a/lib/Target/PowerPC/PPCInstrVSX.td +++ b/lib/Target/PowerPC/PPCInstrVSX.td @@ -126,29 +126,29 @@ let Uses = [RM] in { // Load indexed instructions let mayLoad = 1, mayStore = 0 in { let CodeSize = 3 in - def LXSDX : XX1Form<31, 588, + def LXSDX : XX1Form_memOp<31, 588, (outs vsfrc:$XT), (ins memrr:$src), "lxsdx $XT, $src", IIC_LdStLFD, - [(set f64:$XT, (load xoaddr:$src))]>; + []>; // Pseudo instruction XFLOADf64 will be expanded to LXSDX or LFDX later let isPseudo = 1, CodeSize = 3 in - def XFLOADf64 : Pseudo<(outs vsfrc:$XT), (ins memrr:$src), + def XFLOADf64 : PseudoXFormMemOp<(outs vsfrc:$XT), (ins memrr:$src), "#XFLOADf64", [(set f64:$XT, (load xoaddr:$src))]>; let Predicates = [HasVSX, HasOnlySwappingMemOps] in - def LXVD2X : XX1Form<31, 844, + def LXVD2X : XX1Form_memOp<31, 844, (outs vsrc:$XT), (ins memrr:$src), "lxvd2x $XT, $src", IIC_LdStLFD, [(set v2f64:$XT, (int_ppc_vsx_lxvd2x xoaddr:$src))]>; - def LXVDSX : XX1Form<31, 332, + def LXVDSX : XX1Form_memOp<31, 332, (outs vsrc:$XT), (ins memrr:$src), "lxvdsx $XT, $src", IIC_LdStLFD, []>; let Predicates = [HasVSX, HasOnlySwappingMemOps] in - def LXVW4X : XX1Form<31, 780, + def LXVW4X : XX1Form_memOp<31, 780, (outs vsrc:$XT), (ins memrr:$src), "lxvw4x $XT, $src", IIC_LdStLFD, []>; @@ -157,26 +157,26 @@ let Uses = [RM] in { // Store indexed instructions let mayStore = 1, mayLoad = 0 in { let CodeSize = 3 in - def STXSDX : XX1Form<31, 716, + def STXSDX : XX1Form_memOp<31, 716, (outs), (ins vsfrc:$XT, memrr:$dst), "stxsdx $XT, $dst", IIC_LdStSTFD, - [(store f64:$XT, xoaddr:$dst)]>; + []>; // Pseudo instruction XFSTOREf64 will be expanded to STXSDX or STFDX later let isPseudo = 1, CodeSize = 3 in - def XFSTOREf64 : Pseudo<(outs), (ins vsfrc:$XT, memrr:$dst), + def XFSTOREf64 : PseudoXFormMemOp<(outs), (ins vsfrc:$XT, memrr:$dst), "#XFSTOREf64", [(store f64:$XT, xoaddr:$dst)]>; let Predicates = [HasVSX, HasOnlySwappingMemOps] in { // The behaviour of this instruction is endianness-specific so we provide no // pattern to match it without considering endianness. - def STXVD2X : XX1Form<31, 972, + def STXVD2X : XX1Form_memOp<31, 972, (outs), (ins vsrc:$XT, memrr:$dst), "stxvd2x $XT, $dst", IIC_LdStSTFD, []>; - def STXVW4X : XX1Form<31, 908, + def STXVW4X : XX1Form_memOp<31, 908, (outs), (ins vsrc:$XT, memrr:$dst), "stxvw4x $XT, $dst", IIC_LdStSTFD, []>; @@ -1200,6 +1200,7 @@ def ScalarLoads { */ def HasP8Vector : Predicate<"PPCSubTarget->hasP8Vector()">; def HasDirectMove : Predicate<"PPCSubTarget->hasDirectMove()">; +def NoP9Vector : Predicate<"!PPCSubTarget->hasP9Vector()">; let Predicates = [HasP8Vector] in { let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. let isCommutable = 1, UseVSXReg = 1 in { @@ -1226,11 +1227,11 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. // VSX scalar loads introduced in ISA 2.07 let mayLoad = 1, mayStore = 0 in { let CodeSize = 3 in - def LXSSPX : XX1Form<31, 524, (outs vssrc:$XT), (ins memrr:$src), + def LXSSPX : XX1Form_memOp<31, 524, (outs vssrc:$XT), (ins memrr:$src), "lxsspx $XT, $src", IIC_LdStLFD, []>; - def LXSIWAX : XX1Form<31, 76, (outs vsfrc:$XT), (ins memrr:$src), + def LXSIWAX : XX1Form_memOp<31, 76, (outs vsfrc:$XT), (ins memrr:$src), "lxsiwax $XT, $src", IIC_LdStLFD, []>; - def LXSIWZX : XX1Form<31, 12, (outs vsfrc:$XT), (ins memrr:$src), + def LXSIWZX : XX1Form_memOp<31, 12, (outs vsfrc:$XT), (ins memrr:$src), "lxsiwzx $XT, $src", IIC_LdStLFD, []>; // Please note let isPseudo = 1 is not part of class Pseudo<>. Missing it @@ -1238,15 +1239,15 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. let isPseudo = 1 in { // Pseudo instruction XFLOADf32 will be expanded to LXSSPX or LFSX later let CodeSize = 3 in - def XFLOADf32 : Pseudo<(outs vssrc:$XT), (ins memrr:$src), + def XFLOADf32 : PseudoXFormMemOp<(outs vssrc:$XT), (ins memrr:$src), "#XFLOADf32", [(set f32:$XT, (load xoaddr:$src))]>; // Pseudo instruction LIWAX will be expanded to LXSIWAX or LFIWAX later - def LIWAX : Pseudo<(outs vsfrc:$XT), (ins memrr:$src), + def LIWAX : PseudoXFormMemOp<(outs vsfrc:$XT), (ins memrr:$src), "#LIWAX", [(set f64:$XT, (PPClfiwax xoaddr:$src))]>; // Pseudo instruction LIWZX will be expanded to LXSIWZX or LFIWZX later - def LIWZX : Pseudo<(outs vsfrc:$XT), (ins memrr:$src), + def LIWZX : PseudoXFormMemOp<(outs vsfrc:$XT), (ins memrr:$src), "#LIWZX", [(set f64:$XT, (PPClfiwzx xoaddr:$src))]>; } @@ -1255,9 +1256,9 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. // VSX scalar stores introduced in ISA 2.07 let mayStore = 1, mayLoad = 0 in { let CodeSize = 3 in - def STXSSPX : XX1Form<31, 652, (outs), (ins vssrc:$XT, memrr:$dst), + def STXSSPX : XX1Form_memOp<31, 652, (outs), (ins vssrc:$XT, memrr:$dst), "stxsspx $XT, $dst", IIC_LdStSTFD, []>; - def STXSIWX : XX1Form<31, 140, (outs), (ins vsfrc:$XT, memrr:$dst), + def STXSIWX : XX1Form_memOp<31, 140, (outs), (ins vsfrc:$XT, memrr:$dst), "stxsiwx $XT, $dst", IIC_LdStSTFD, []>; // Please note let isPseudo = 1 is not part of class Pseudo<>. Missing it @@ -1265,11 +1266,11 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. let isPseudo = 1 in { // Pseudo instruction XFSTOREf32 will be expanded to STXSSPX or STFSX later let CodeSize = 3 in - def XFSTOREf32 : Pseudo<(outs), (ins vssrc:$XT, memrr:$dst), + def XFSTOREf32 : PseudoXFormMemOp<(outs), (ins vssrc:$XT, memrr:$dst), "#XFSTOREf32", [(store f32:$XT, xoaddr:$dst)]>; // Pseudo instruction STIWX will be expanded to STXSIWX or STFIWX later - def STIWX : Pseudo<(outs), (ins vsfrc:$XT, memrr:$dst), + def STIWX : PseudoXFormMemOp<(outs), (ins vsfrc:$XT, memrr:$dst), "#STIWX", [(PPCstfiwx f64:$XT, xoaddr:$dst)]>; } @@ -1278,7 +1279,7 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. def : Pat<(f64 (extloadf32 xoaddr:$src)), (COPY_TO_REGCLASS (XFLOADf32 xoaddr:$src), VSFRC)>; - def : Pat<(f32 (fpround (extloadf32 xoaddr:$src))), + def : Pat<(f32 (fpround (f64 (extloadf32 xoaddr:$src)))), (f32 (XFLOADf32 xoaddr:$src))>; def : Pat<(f64 (fpextend f32:$src)), (COPY_TO_REGCLASS $src, VSFRC)>; @@ -1325,6 +1326,9 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. (outs vssrc:$XT), (ins vssrc:$XB), "xsresp $XT, $XB", IIC_VecFP, [(set f32:$XT, (PPCfre f32:$XB))]>; + def XSRSP : XX2Form<60, 281, + (outs vssrc:$XT), (ins vsfrc:$XB), + "xsrsp $XT, $XB", IIC_VecFP, []>; def XSSQRTSP : XX2Form<60, 11, (outs vssrc:$XT), (ins vssrc:$XB), "xssqrtsp $XT, $XB", IIC_FPSqrtS, @@ -1432,28 +1436,57 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. } // UseVSXReg = 1 let Predicates = [IsLittleEndian] in { - def : Pat<(f32 (PPCfcfids (PPCmtvsra (i64 (vector_extract v2i64:$S, 0))))), + def : Pat<(f32 (PPCfcfids + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 0)))))), (f32 (XSCVSXDSP (COPY_TO_REGCLASS (XXPERMDI $S, $S, 2), VSFRC)))>; - def : Pat<(f32 (PPCfcfids (PPCmtvsra (i64 (vector_extract v2i64:$S, 1))))), - (f32 (XSCVSXDSP (COPY_TO_REGCLASS (f64 (COPY_TO_REGCLASS $S, VSRC)), VSFRC)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsra (i64 (vector_extract v2i64:$S, 0))))), + def : Pat<(f32 (PPCfcfids + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 1)))))), + (f32 (XSCVSXDSP (COPY_TO_REGCLASS + (f64 (COPY_TO_REGCLASS $S, VSRC)), VSFRC)))>; + def : Pat<(f32 (PPCfcfidus + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 0)))))), (f32 (XSCVUXDSP (COPY_TO_REGCLASS (XXPERMDI $S, $S, 2), VSFRC)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsra (i64 (vector_extract v2i64:$S, 1))))), - (f32 (XSCVUXDSP (COPY_TO_REGCLASS (f64 (COPY_TO_REGCLASS $S, VSRC)), VSFRC)))>; + def : Pat<(f32 (PPCfcfidus + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 1)))))), + (f32 (XSCVUXDSP (COPY_TO_REGCLASS + (f64 (COPY_TO_REGCLASS $S, VSRC)), VSFRC)))>; } let Predicates = [IsBigEndian] in { - def : Pat<(f32 (PPCfcfids (PPCmtvsra (i64 (vector_extract v2i64:$S, 0))))), + def : Pat<(f32 (PPCfcfids + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 0)))))), (f32 (XSCVSXDSP (COPY_TO_REGCLASS $S, VSFRC)))>; - def : Pat<(f32 (PPCfcfids (PPCmtvsra (i64 (vector_extract v2i64:$S, 1))))), + def : Pat<(f32 (PPCfcfids + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 1)))))), (f32 (XSCVSXDSP (COPY_TO_REGCLASS (XXPERMDI $S, $S, 2), VSFRC)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsra (i64 (vector_extract v2i64:$S, 0))))), + def : Pat<(f32 (PPCfcfidus + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 0)))))), (f32 (XSCVUXDSP (COPY_TO_REGCLASS $S, VSFRC)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsra (i64 (vector_extract v2i64:$S, 1))))), + def : Pat<(f32 (PPCfcfidus + (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 1)))))), (f32 (XSCVUXDSP (COPY_TO_REGCLASS (XXPERMDI $S, $S, 2), VSFRC)))>; } def : Pat<(v4i32 (scalar_to_vector ScalarLoads.Li32)), (v4i32 (XXSPLTWs (LIWAX xoaddr:$src), 1))>; + + // Instructions for converting float to i64 feeding a store. + let Predicates = [NoP9Vector] in { + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 8), + (STXSDX (XSCVDPSXDS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 8), + (STXSDX (XSCVDPUXDS f64:$src), xoaddr:$dst)>; + } + + // Instructions for converting float to i32 feeding a store. + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 4), + (STIWX (XSCVDPSXWS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 4), + (STIWX (XSCVDPUXWS f64:$src), xoaddr:$dst)>; + } // AddedComplexity = 400 } // HasP8Vector @@ -1614,11 +1647,11 @@ def VectorExtractions { This is accomplished by inverting the bits of the index and AND-ing with 0x8 (i.e. clearing all bits of the index and inverting bit 60). */ - dag LE_VBYTE_PERM_VEC = (LVSL ZERO8, (ANDC8 (LI8 8), $Idx)); + dag LE_VBYTE_PERM_VEC = (v16i8 (LVSL ZERO8, (ANDC8 (LI8 8), $Idx))); // Number 2. above: // - Now that we set up the shift amount, we shift in the VMX register - dag LE_VBYTE_PERMUTE = (VPERM $S, $S, LE_VBYTE_PERM_VEC); + dag LE_VBYTE_PERMUTE = (v16i8 (VPERM $S, $S, LE_VBYTE_PERM_VEC)); // Number 3. above: // - The doubleword containing our element is moved to a GPR @@ -1646,11 +1679,12 @@ def VectorExtractions { AND with 0x4 (i.e. clear all bits of the index and invert bit 61). Of course, the shift is still by 8 bytes, so we must multiply by 2. */ - dag LE_VHALF_PERM_VEC = (LVSL ZERO8, (RLDICR (ANDC8 (LI8 4), $Idx), 1, 62)); + dag LE_VHALF_PERM_VEC = + (v16i8 (LVSL ZERO8, (RLDICR (ANDC8 (LI8 4), $Idx), 1, 62))); // Number 2. above: // - Now that we set up the shift amount, we shift in the VMX register - dag LE_VHALF_PERMUTE = (VPERM $S, $S, LE_VHALF_PERM_VEC); + dag LE_VHALF_PERMUTE = (v16i8 (VPERM $S, $S, LE_VHALF_PERM_VEC)); // Number 3. above: // - The doubleword containing our element is moved to a GPR @@ -1675,11 +1709,12 @@ def VectorExtractions { - For elements 0-1, we shift left by 8 since they're on the right - For elements 2-3, we need not shift */ - dag LE_VWORD_PERM_VEC = (LVSL ZERO8, (RLDICR (ANDC8 (LI8 2), $Idx), 2, 61)); + dag LE_VWORD_PERM_VEC = (v16i8 (LVSL ZERO8, + (RLDICR (ANDC8 (LI8 2), $Idx), 2, 61))); // Number 2. above: // - Now that we set up the shift amount, we shift in the VMX register - dag LE_VWORD_PERMUTE = (VPERM $S, $S, LE_VWORD_PERM_VEC); + dag LE_VWORD_PERMUTE = (v16i8 (VPERM $S, $S, LE_VWORD_PERM_VEC)); // Number 3. above: // - The doubleword containing our element is moved to a GPR @@ -1704,11 +1739,12 @@ def VectorExtractions { - For element 0, we shift left by 8 since it's on the right - For element 1, we need not shift */ - dag LE_VDWORD_PERM_VEC = (LVSL ZERO8, (RLDICR (ANDC8 (LI8 1), $Idx), 3, 60)); + dag LE_VDWORD_PERM_VEC = (v16i8 (LVSL ZERO8, + (RLDICR (ANDC8 (LI8 1), $Idx), 3, 60))); // Number 2. above: // - Now that we set up the shift amount, we shift in the VMX register - dag LE_VDWORD_PERMUTE = (VPERM $S, $S, LE_VDWORD_PERM_VEC); + dag LE_VDWORD_PERMUTE = (v16i8 (VPERM $S, $S, LE_VDWORD_PERM_VEC)); // Number 3. above: // - The doubleword containing our element is moved to a GPR @@ -1722,16 +1758,17 @@ def VectorExtractions { - Shift the vector to line up the desired element to BE Word 0 - Convert 32-bit float to a 64-bit single precision float */ - dag LE_VFLOAT_PERM_VEC = (LVSL ZERO8, (RLDICR (XOR8 (LI8 3), $Idx), 2, 61)); + dag LE_VFLOAT_PERM_VEC = (v16i8 (LVSL ZERO8, + (RLDICR (XOR8 (LI8 3), $Idx), 2, 61))); dag LE_VFLOAT_PERMUTE = (VPERM $S, $S, LE_VFLOAT_PERM_VEC); dag LE_VARIABLE_FLOAT = (XSCVSPDPN LE_VFLOAT_PERMUTE); /* LE variable double Same as the LE doubleword except there is no move. */ - dag LE_VDOUBLE_PERMUTE = (VPERM (COPY_TO_REGCLASS $S, VRRC), - (COPY_TO_REGCLASS $S, VRRC), - LE_VDWORD_PERM_VEC); + dag LE_VDOUBLE_PERMUTE = (v16i8 (VPERM (v16i8 (COPY_TO_REGCLASS $S, VRRC)), + (v16i8 (COPY_TO_REGCLASS $S, VRRC)), + LE_VDWORD_PERM_VEC)); dag LE_VARIABLE_DOUBLE = (COPY_TO_REGCLASS LE_VDOUBLE_PERMUTE, VSRC); /* BE variable byte @@ -1741,8 +1778,8 @@ def VectorExtractions { - The order of elements after the move to GPR is reversed, so we invert the bits of the index prior to truncating to the range 0-7 */ - dag BE_VBYTE_PERM_VEC = (LVSL ZERO8, (ANDIo8 $Idx, 8)); - dag BE_VBYTE_PERMUTE = (VPERM $S, $S, BE_VBYTE_PERM_VEC); + dag BE_VBYTE_PERM_VEC = (v16i8 (LVSL ZERO8, (ANDIo8 $Idx, 8))); + dag BE_VBYTE_PERMUTE = (v16i8 (VPERM $S, $S, BE_VBYTE_PERM_VEC)); dag BE_MV_VBYTE = (MFVSRD (EXTRACT_SUBREG (v2i64 (COPY_TO_REGCLASS BE_VBYTE_PERMUTE, VSRC)), @@ -1759,8 +1796,9 @@ def VectorExtractions { - The order of elements after the move to GPR is reversed, so we invert the bits of the index prior to truncating to the range 0-3 */ - dag BE_VHALF_PERM_VEC = (LVSL ZERO8, (RLDICR (ANDIo8 $Idx, 4), 1, 62)); - dag BE_VHALF_PERMUTE = (VPERM $S, $S, BE_VHALF_PERM_VEC); + dag BE_VHALF_PERM_VEC = (v16i8 (LVSL ZERO8, + (RLDICR (ANDIo8 $Idx, 4), 1, 62))); + dag BE_VHALF_PERMUTE = (v16i8 (VPERM $S, $S, BE_VHALF_PERM_VEC)); dag BE_MV_VHALF = (MFVSRD (EXTRACT_SUBREG (v2i64 (COPY_TO_REGCLASS BE_VHALF_PERMUTE, VSRC)), @@ -1776,8 +1814,9 @@ def VectorExtractions { - The order of elements after the move to GPR is reversed, so we invert the bits of the index prior to truncating to the range 0-1 */ - dag BE_VWORD_PERM_VEC = (LVSL ZERO8, (RLDICR (ANDIo8 $Idx, 2), 2, 61)); - dag BE_VWORD_PERMUTE = (VPERM $S, $S, BE_VWORD_PERM_VEC); + dag BE_VWORD_PERM_VEC = (v16i8 (LVSL ZERO8, + (RLDICR (ANDIo8 $Idx, 2), 2, 61))); + dag BE_VWORD_PERMUTE = (v16i8 (VPERM $S, $S, BE_VWORD_PERM_VEC)); dag BE_MV_VWORD = (MFVSRD (EXTRACT_SUBREG (v2i64 (COPY_TO_REGCLASS BE_VWORD_PERMUTE, VSRC)), @@ -1791,8 +1830,9 @@ def VectorExtractions { Same as the LE doubleword except we shift in the VMX register for opposite element indices. */ - dag BE_VDWORD_PERM_VEC = (LVSL ZERO8, (RLDICR (ANDIo8 $Idx, 1), 3, 60)); - dag BE_VDWORD_PERMUTE = (VPERM $S, $S, BE_VDWORD_PERM_VEC); + dag BE_VDWORD_PERM_VEC = (v16i8 (LVSL ZERO8, + (RLDICR (ANDIo8 $Idx, 1), 3, 60))); + dag BE_VDWORD_PERMUTE = (v16i8 (VPERM $S, $S, BE_VDWORD_PERM_VEC)); dag BE_VARIABLE_DWORD = (MFVSRD (EXTRACT_SUBREG (v2i64 (COPY_TO_REGCLASS BE_VDWORD_PERMUTE, VSRC)), @@ -1802,16 +1842,16 @@ def VectorExtractions { - Shift the vector to line up the desired element to BE Word 0 - Convert 32-bit float to a 64-bit single precision float */ - dag BE_VFLOAT_PERM_VEC = (LVSL ZERO8, (RLDICR $Idx, 2, 61)); + dag BE_VFLOAT_PERM_VEC = (v16i8 (LVSL ZERO8, (RLDICR $Idx, 2, 61))); dag BE_VFLOAT_PERMUTE = (VPERM $S, $S, BE_VFLOAT_PERM_VEC); dag BE_VARIABLE_FLOAT = (XSCVSPDPN BE_VFLOAT_PERMUTE); /* BE variable double Same as the BE doubleword except there is no move. */ - dag BE_VDOUBLE_PERMUTE = (VPERM (COPY_TO_REGCLASS $S, VRRC), - (COPY_TO_REGCLASS $S, VRRC), - BE_VDWORD_PERM_VEC); + dag BE_VDOUBLE_PERMUTE = (v16i8 (VPERM (v16i8 (COPY_TO_REGCLASS $S, VRRC)), + (v16i8 (COPY_TO_REGCLASS $S, VRRC)), + BE_VDWORD_PERM_VEC)); dag BE_VARIABLE_DOUBLE = (COPY_TO_REGCLASS BE_VDOUBLE_PERMUTE, VSRC); } @@ -2282,7 +2322,7 @@ let Predicates = [HasDirectMove, HasVSX] in { // (convert to 32-bit fp single, shift right 1 word, move to GPR) def : Pat<(i32 (bitconvert f32:$S)), (i32 (MFVSRWZ (EXTRACT_SUBREG - (XXSLDWI (XSCVDPSPN $S),(XSCVDPSPN $S), 3), + (XXSLDWI (XSCVDPSPN $S), (XSCVDPSPN $S), 3), sub_64)))>; // bitconvert i32 -> f32 // (move to FPR, shift left 1 word, convert to 64-bit fp single) @@ -2333,6 +2373,17 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { : X_RD5_XO5_RS5<opcode, xo2, xo, (outs vrrc:$vT), (ins vbtype:$vB), !strconcat(opc, " $vT, $vB"), IIC_VecFP, pattern>; + // [PO VRT XO VRB XO /] + class X_VT5_XO5_VB5_VSFR<bits<6> opcode, bits<5> xo2, bits<10> xo, string opc, + list<dag> pattern> + : X_RD5_XO5_RS5<opcode, xo2, xo, (outs vfrc:$vT), (ins vrrc:$vB), + !strconcat(opc, " $vT, $vB"), IIC_VecFP, pattern>; + + // [PO VRT XO VRB XO RO], Round to Odd version of [PO VRT XO VRB XO /] + class X_VT5_XO5_VB5_VSFR_Ro<bits<6> opcode, bits<5> xo2, bits<10> xo, string opc, + list<dag> pattern> + : X_VT5_XO5_VB5_VSFR<opcode, xo2, xo, opc, pattern>, isDOT; + let UseVSXReg = 1 in { // [PO T XO B XO BX /] class XX2_RT5_XO5_XB6<bits<6> opcode, bits<5> xo2, bits<9> xo, string opc, @@ -2365,43 +2416,112 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { list<dag> pattern> : X_VT5_VA5_VB5<opcode, xo, opc, pattern>, isDOT; + // [PO VRT VRA VRB XO /] + class X_VT5_VA5_VB5_FMA<bits<6> opcode, bits<10> xo, string opc, + list<dag> pattern> + : XForm_1<opcode, xo, (outs vrrc:$vT), (ins vrrc:$vTi, vrrc:$vA, vrrc:$vB), + !strconcat(opc, " $vT, $vA, $vB"), IIC_VecFP, pattern>, + RegConstraint<"$vTi = $vT">, NoEncode<"$vTi">; + + // [PO VRT VRA VRB XO RO], Round to Odd version of [PO VRT VRA VRB XO /] + class X_VT5_VA5_VB5_FMA_Ro<bits<6> opcode, bits<10> xo, string opc, + list<dag> pattern> + : X_VT5_VA5_VB5_FMA<opcode, xo, opc, pattern>, isDOT; + //===--------------------------------------------------------------------===// // Quad-Precision Scalar Move Instructions: // Copy Sign - def XSCPSGNQP : X_VT5_VA5_VB5<63, 100, "xscpsgnqp", []>; + def XSCPSGNQP : X_VT5_VA5_VB5<63, 100, "xscpsgnqp", + [(set f128:$vT, + (fcopysign f128:$vB, f128:$vA))]>; // Absolute/Negative-Absolute/Negate - def XSABSQP : X_VT5_XO5_VB5<63, 0, 804, "xsabsqp" , []>; - def XSNABSQP : X_VT5_XO5_VB5<63, 8, 804, "xsnabsqp", []>; - def XSNEGQP : X_VT5_XO5_VB5<63, 16, 804, "xsnegqp" , []>; + def XSABSQP : X_VT5_XO5_VB5<63, 0, 804, "xsabsqp", + [(set f128:$vT, (fabs f128:$vB))]>; + def XSNABSQP : X_VT5_XO5_VB5<63, 8, 804, "xsnabsqp", + [(set f128:$vT, (fneg (fabs f128:$vB)))]>; + def XSNEGQP : X_VT5_XO5_VB5<63, 16, 804, "xsnegqp", + [(set f128:$vT, (fneg f128:$vB))]>; //===--------------------------------------------------------------------===// // Quad-Precision Scalar Floating-Point Arithmetic Instructions: // Add/Divide/Multiply/Subtract - def XSADDQP : X_VT5_VA5_VB5 <63, 4, "xsaddqp" , []>; - def XSADDQPO : X_VT5_VA5_VB5_Ro<63, 4, "xsaddqpo", []>; - def XSDIVQP : X_VT5_VA5_VB5 <63, 548, "xsdivqp" , []>; - def XSDIVQPO : X_VT5_VA5_VB5_Ro<63, 548, "xsdivqpo", []>; - def XSMULQP : X_VT5_VA5_VB5 <63, 36, "xsmulqp" , []>; - def XSMULQPO : X_VT5_VA5_VB5_Ro<63, 36, "xsmulqpo", []>; - def XSSUBQP : X_VT5_VA5_VB5 <63, 516, "xssubqp" , []>; - def XSSUBQPO : X_VT5_VA5_VB5_Ro<63, 516, "xssubqpo", []>; + let isCommutable = 1 in { + def XSADDQP : X_VT5_VA5_VB5 <63, 4, "xsaddqp", + [(set f128:$vT, (fadd f128:$vA, f128:$vB))]>; + def XSADDQPO : X_VT5_VA5_VB5_Ro<63, 4, "xsaddqpo", + [(set f128:$vT, + (int_ppc_addf128_round_to_odd + f128:$vA, f128:$vB))]>; + def XSMULQP : X_VT5_VA5_VB5 <63, 36, "xsmulqp", + [(set f128:$vT, (fmul f128:$vA, f128:$vB))]>; + def XSMULQPO : X_VT5_VA5_VB5_Ro<63, 36, "xsmulqpo", + [(set f128:$vT, + (int_ppc_mulf128_round_to_odd + f128:$vA, f128:$vB))]>; + } + + def XSSUBQP : X_VT5_VA5_VB5 <63, 516, "xssubqp" , + [(set f128:$vT, (fsub f128:$vA, f128:$vB))]>; + def XSSUBQPO : X_VT5_VA5_VB5_Ro<63, 516, "xssubqpo", + [(set f128:$vT, + (int_ppc_subf128_round_to_odd + f128:$vA, f128:$vB))]>; + def XSDIVQP : X_VT5_VA5_VB5 <63, 548, "xsdivqp", + [(set f128:$vT, (fdiv f128:$vA, f128:$vB))]>; + def XSDIVQPO : X_VT5_VA5_VB5_Ro<63, 548, "xsdivqpo", + [(set f128:$vT, + (int_ppc_divf128_round_to_odd + f128:$vA, f128:$vB))]>; // Square-Root - def XSSQRTQP : X_VT5_XO5_VB5 <63, 27, 804, "xssqrtqp" , []>; - def XSSQRTQPO : X_VT5_XO5_VB5_Ro<63, 27, 804, "xssqrtqpo", []>; + def XSSQRTQP : X_VT5_XO5_VB5 <63, 27, 804, "xssqrtqp", + [(set f128:$vT, (fsqrt f128:$vB))]>; + def XSSQRTQPO : X_VT5_XO5_VB5_Ro<63, 27, 804, "xssqrtqpo", + [(set f128:$vT, + (int_ppc_sqrtf128_round_to_odd f128:$vB))]>; // (Negative) Multiply-{Add/Subtract} - def XSMADDQP : X_VT5_VA5_VB5 <63, 388, "xsmaddqp" , []>; - def XSMADDQPO : X_VT5_VA5_VB5_Ro<63, 388, "xsmaddqpo" , []>; - def XSMSUBQP : X_VT5_VA5_VB5 <63, 420, "xsmsubqp" , []>; - def XSMSUBQPO : X_VT5_VA5_VB5_Ro<63, 420, "xsmsubqpo" , []>; - def XSNMADDQP : X_VT5_VA5_VB5 <63, 452, "xsnmaddqp" , []>; - def XSNMADDQPO: X_VT5_VA5_VB5_Ro<63, 452, "xsnmaddqpo", []>; - def XSNMSUBQP : X_VT5_VA5_VB5 <63, 484, "xsnmsubqp" , []>; - def XSNMSUBQPO: X_VT5_VA5_VB5_Ro<63, 484, "xsnmsubqpo", []>; + def XSMADDQP : X_VT5_VA5_VB5_FMA <63, 388, "xsmaddqp", + [(set f128:$vT, + (fma f128:$vA, f128:$vB, + f128:$vTi))]>; + + def XSMADDQPO : X_VT5_VA5_VB5_FMA_Ro<63, 388, "xsmaddqpo", + [(set f128:$vT, + (int_ppc_fmaf128_round_to_odd + f128:$vA,f128:$vB,f128:$vTi))]>; + + def XSMSUBQP : X_VT5_VA5_VB5_FMA <63, 420, "xsmsubqp" , + [(set f128:$vT, + (fma f128:$vA, f128:$vB, + (fneg f128:$vTi)))]>; + def XSMSUBQPO : X_VT5_VA5_VB5_FMA_Ro<63, 420, "xsmsubqpo" , + [(set f128:$vT, + (int_ppc_fmaf128_round_to_odd + f128:$vA, f128:$vB, (fneg f128:$vTi)))]>; + def XSNMADDQP : X_VT5_VA5_VB5_FMA <63, 452, "xsnmaddqp", + [(set f128:$vT, + (fneg (fma f128:$vA, f128:$vB, + f128:$vTi)))]>; + def XSNMADDQPO: X_VT5_VA5_VB5_FMA_Ro<63, 452, "xsnmaddqpo", + [(set f128:$vT, + (fneg (int_ppc_fmaf128_round_to_odd + f128:$vA, f128:$vB, f128:$vTi)))]>; + def XSNMSUBQP : X_VT5_VA5_VB5_FMA <63, 484, "xsnmsubqp", + [(set f128:$vT, + (fneg (fma f128:$vA, f128:$vB, + (fneg f128:$vTi))))]>; + def XSNMSUBQPO: X_VT5_VA5_VB5_FMA_Ro<63, 484, "xsnmsubqpo", + [(set f128:$vT, + (fneg (int_ppc_fmaf128_round_to_odd + f128:$vA, f128:$vB, (fneg f128:$vTi))))]>; + + // Additional fnmsub patterns: -a*c + b == -(a*c - b) + def : Pat<(fma (fneg f128:$A), f128:$C, f128:$B), (XSNMSUBQP $B, $C, $A)>; + def : Pat<(fma f128:$A, (fneg f128:$C), f128:$B), (XSNMSUBQP $B, $C, $A)>; //===--------------------------------------------------------------------===// // Quad/Double-Precision Compare Instructions: @@ -2434,37 +2554,20 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { IIC_FPCompare, []>; def XSCMPGTDP : XX3_XT5_XA5_XB5<60, 11, "xscmpgtdp", vsrc, vsfrc, vsfrc, IIC_FPCompare, []>; - def XSCMPNEDP : XX3_XT5_XA5_XB5<60, 27, "xscmpnedp", vsrc, vsfrc, vsfrc, - IIC_FPCompare, []>; - let UseVSXReg = 1 in { - // Vector Compare Not Equal - def XVCMPNEDP : XX3Form_Rc<60, 123, - (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), - "xvcmpnedp $XT, $XA, $XB", IIC_VecFPCompare, []>; - let Defs = [CR6] in - def XVCMPNEDPo : XX3Form_Rc<60, 123, - (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), - "xvcmpnedp. $XT, $XA, $XB", IIC_VecFPCompare, []>, - isDOT; - def XVCMPNESP : XX3Form_Rc<60, 91, - (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), - "xvcmpnesp $XT, $XA, $XB", IIC_VecFPCompare, []>; - let Defs = [CR6] in - def XVCMPNESPo : XX3Form_Rc<60, 91, - (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), - "xvcmpnesp. $XT, $XA, $XB", IIC_VecFPCompare, []>, - isDOT; - } // UseVSXReg = 1 //===--------------------------------------------------------------------===// // Quad-Precision Floating-Point Conversion Instructions: // Convert DP -> QP - def XSCVDPQP : X_VT5_XO5_VB5_TyVB<63, 22, 836, "xscvdpqp", vfrc, []>; + def XSCVDPQP : X_VT5_XO5_VB5_TyVB<63, 22, 836, "xscvdpqp", vfrc, + [(set f128:$vT, (fpextend f64:$vB))]>; // Round & Convert QP -> DP (dword[1] is set to zero) - def XSCVQPDP : X_VT5_XO5_VB5 <63, 20, 836, "xscvqpdp" , []>; - def XSCVQPDPO : X_VT5_XO5_VB5_Ro<63, 20, 836, "xscvqpdpo", []>; + def XSCVQPDP : X_VT5_XO5_VB5_VSFR<63, 20, 836, "xscvqpdp" , []>; + def XSCVQPDPO : X_VT5_XO5_VB5_VSFR_Ro<63, 20, 836, "xscvqpdpo", + [(set f64:$vT, + (int_ppc_truncf128_round_to_odd + f128:$vB))]>; // Truncate & Convert QP -> (Un)Signed (D)Word (dword[1] is set to zero) def XSCVQPSDZ : X_VT5_XO5_VB5<63, 25, 836, "xscvqpsdz", []>; @@ -2472,9 +2575,30 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def XSCVQPUDZ : X_VT5_XO5_VB5<63, 17, 836, "xscvqpudz", []>; def XSCVQPUWZ : X_VT5_XO5_VB5<63, 1, 836, "xscvqpuwz", []>; - // Convert (Un)Signed DWord -> QP + // Convert (Un)Signed DWord -> QP. def XSCVSDQP : X_VT5_XO5_VB5_TyVB<63, 10, 836, "xscvsdqp", vfrc, []>; + def : Pat<(f128 (sint_to_fp i64:$src)), + (f128 (XSCVSDQP (COPY_TO_REGCLASS $src, VFRC)))>; + def : Pat<(f128 (sint_to_fp (i64 (PPCmfvsr f64:$src)))), + (f128 (XSCVSDQP $src))>; + def : Pat<(f128 (sint_to_fp (i32 (PPCmfvsr f64:$src)))), + (f128 (XSCVSDQP (VEXTSW2Ds $src)))>; + def XSCVUDQP : X_VT5_XO5_VB5_TyVB<63, 2, 836, "xscvudqp", vfrc, []>; + def : Pat<(f128 (uint_to_fp i64:$src)), + (f128 (XSCVUDQP (COPY_TO_REGCLASS $src, VFRC)))>; + def : Pat<(f128 (uint_to_fp (i64 (PPCmfvsr f64:$src)))), + (f128 (XSCVUDQP $src))>; + + // Convert (Un)Signed Word -> QP. + def : Pat<(f128 (sint_to_fp i32:$src)), + (f128 (XSCVSDQP (MTVSRWA $src)))>; + def : Pat<(f128 (sint_to_fp (i32 (load xoaddr:$src)))), + (f128 (XSCVSDQP (LIWAX xoaddr:$src)))>; + def : Pat<(f128 (uint_to_fp i32:$src)), + (f128 (XSCVUDQP (MTVSRWZ $src)))>; + def : Pat<(f128 (uint_to_fp (i32 (load xoaddr:$src)))), + (f128 (XSCVUDQP (LIWZX xoaddr:$src)))>; let UseVSXReg = 1 in { //===--------------------------------------------------------------------===// @@ -2503,7 +2627,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { class Z23_VT5_R1_VB5_RMC2_EX1<bits<6> opcode, bits<8> xo, bit ex, string opc, list<dag> pattern> - : Z23Form_1<opcode, xo, + : Z23Form_8<opcode, xo, (outs vrrc:$vT), (ins u1imm:$r, vrrc:$vB, u2imm:$rmc), !strconcat(opc, " $r, $vT, $vB, $rmc"), IIC_VecFP, pattern> { let RC = ex; @@ -2513,6 +2637,20 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def XSRQPI : Z23_VT5_R1_VB5_RMC2_EX1<63, 5, 0, "xsrqpi" , []>; def XSRQPIX : Z23_VT5_R1_VB5_RMC2_EX1<63, 5, 1, "xsrqpix", []>; + // Use current rounding mode + def : Pat<(f128 (fnearbyint f128:$vB)), (f128 (XSRQPI 0, $vB, 3))>; + // Round to nearest, ties away from zero + def : Pat<(f128 (fround f128:$vB)), (f128 (XSRQPI 0, $vB, 0))>; + // Round towards Zero + def : Pat<(f128 (ftrunc f128:$vB)), (f128 (XSRQPI 1, $vB, 1))>; + // Round towards +Inf + def : Pat<(f128 (fceil f128:$vB)), (f128 (XSRQPI 1, $vB, 2))>; + // Round towards -Inf + def : Pat<(f128 (ffloor f128:$vB)), (f128 (XSRQPI 1, $vB, 3))>; + + // Use current rounding mode, [with Inexact] + def : Pat<(f128 (frint f128:$vB)), (f128 (XSRQPIX 0, $vB, 3))>; + // Round Quad-Precision to Double-Extended Precision (fp80) def XSRQPXP : Z23_VT5_R1_VB5_RMC2_EX1<63, 37, 0, "xsrqpxp", []>; @@ -2670,7 +2808,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // "out" and "in" dag class X_XT6_RA5_RB5<bits<6> opcode, bits<10> xo, string opc, RegisterOperand vtype, list<dag> pattern> - : XX1Form<opcode, xo, (outs vtype:$XT), (ins memrr:$src), + : XX1Form_memOp<opcode, xo, (outs vtype:$XT), (ins memrr:$src), !strconcat(opc, " $XT, $src"), IIC_LdStLFD, pattern>, UseVSXReg; // Load as Integer Byte/Halfword & Zero Indexed @@ -2687,11 +2825,11 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def LXVX : X_XT6_RA5_RB5<31, 268, "lxvx" , vsrc, [(set v2f64:$XT, (load xaddr:$src))]>; // Load Vector (Left-justified) with Length - def LXVL : XX1Form<31, 269, (outs vsrc:$XT), (ins memr:$src, g8rc:$rB), + def LXVL : XX1Form_memOp<31, 269, (outs vsrc:$XT), (ins memr:$src, g8rc:$rB), "lxvl $XT, $src, $rB", IIC_LdStLoad, [(set v4i32:$XT, (int_ppc_vsx_lxvl addr:$src, i64:$rB))]>, UseVSXReg; - def LXVLL : XX1Form<31,301, (outs vsrc:$XT), (ins memr:$src, g8rc:$rB), + def LXVLL : XX1Form_memOp<31,301, (outs vsrc:$XT), (ins memr:$src, g8rc:$rB), "lxvll $XT, $src, $rB", IIC_LdStLoad, [(set v4i32:$XT, (int_ppc_vsx_lxvll addr:$src, i64:$rB))]>, UseVSXReg; @@ -2716,7 +2854,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // [PO S RA RB XO SX] class X_XS6_RA5_RB5<bits<6> opcode, bits<10> xo, string opc, RegisterOperand vtype, list<dag> pattern> - : XX1Form<opcode, xo, (outs), (ins vtype:$XT, memrr:$dst), + : XX1Form_memOp<opcode, xo, (outs), (ins vtype:$XT, memrr:$dst), !strconcat(opc, " $XT, $dst"), IIC_LdStSTFD, pattern>, UseVSXReg; // Store as Integer Byte/Halfword Indexed @@ -2738,51 +2876,55 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { [(store v2f64:$XT, xaddr:$dst)]>; // Store Vector (Left-justified) with Length - def STXVL : XX1Form<31, 397, (outs), (ins vsrc:$XT, memr:$dst, g8rc:$rB), - "stxvl $XT, $dst, $rB", IIC_LdStLoad, - [(int_ppc_vsx_stxvl v4i32:$XT, addr:$dst, i64:$rB)]>, - UseVSXReg; - def STXVLL : XX1Form<31, 429, (outs), (ins vsrc:$XT, memr:$dst, g8rc:$rB), - "stxvll $XT, $dst, $rB", IIC_LdStLoad, - [(int_ppc_vsx_stxvll v4i32:$XT, addr:$dst, i64:$rB)]>, - UseVSXReg; + def STXVL : XX1Form_memOp<31, 397, (outs), + (ins vsrc:$XT, memr:$dst, g8rc:$rB), + "stxvl $XT, $dst, $rB", IIC_LdStLoad, + [(int_ppc_vsx_stxvl v4i32:$XT, addr:$dst, + i64:$rB)]>, + UseVSXReg; + def STXVLL : XX1Form_memOp<31, 429, (outs), + (ins vsrc:$XT, memr:$dst, g8rc:$rB), + "stxvll $XT, $dst, $rB", IIC_LdStLoad, + [(int_ppc_vsx_stxvll v4i32:$XT, addr:$dst, + i64:$rB)]>, + UseVSXReg; } // mayStore let Predicates = [IsLittleEndian] in { - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 0))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 0)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 3))))>; - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 1))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 1)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 2))))>; - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 2))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 2)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 1))))>; - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 3))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 3)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 0))))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 0))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 0)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 3)), VSFRC))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 1))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 1)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 2)), VSFRC))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 2))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 2)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 1)), VSFRC))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 3))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 3)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 0)), VSFRC))>; } let Predicates = [IsBigEndian] in { - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 0))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 0)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 0))))>; - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 1))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 1)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 1))))>; - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 2))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 2)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 2))))>; - def: Pat<(f32 (PPCfcfids (PPCmtvsra (i32 (extractelt v4i32:$A, 3))))), + def: Pat<(f32 (PPCfcfids (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 3)))))), (f32 (XSCVSPDPN (XVCVSXWSP (XXSPLTW $A, 3))))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 0))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 0)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 0)), VSFRC))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 1))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 1)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 1)), VSFRC))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 2))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 2)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 2)), VSFRC))>; - def: Pat<(f64 (PPCfcfid (PPCmtvsra (i32 (extractelt v4i32:$A, 3))))), + def: Pat<(f64 (PPCfcfid (f64 (PPCmtvsra (i32 (extractelt v4i32:$A, 3)))))), (f64 (COPY_TO_REGCLASS (XVCVSXWDP (XXSPLTW $A, 3)), VSFRC))>; } @@ -2795,21 +2937,21 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // Patterns for which instructions from ISA 3.0 are a better match let Predicates = [IsLittleEndian, HasP9Vector] in { - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 0))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 0)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 12)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 1))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 1)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 8)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 2))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 2)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 4)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 3))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 3)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 0)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 0))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 0)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 12)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 1))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 1)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 8)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 2))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 2)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 4)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 3))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 3)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 0)))>; def : Pat<(v4i32 (insertelt v4i32:$A, i32:$B, 0)), (v4i32 (XXINSERTW v4i32:$A, AlignValues.I32_TO_BE_WORD1, 12))>; @@ -2830,21 +2972,21 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { } // IsLittleEndian, HasP9Vector let Predicates = [IsBigEndian, HasP9Vector] in { - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 0))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 0)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 0)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 1))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 1)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 4)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 2))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 2)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 8)))>; - def : Pat<(f32 (PPCfcfidus (PPCmtvsrz (i32 (extractelt v4i32:$A, 3))))), + def : Pat<(f32 (PPCfcfidus (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 3)))))), (f32 (XSCVUXDSP (XXEXTRACTUW $A, 12)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 0))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 0)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 0)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 1))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 1)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 4)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 2))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 2)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 8)))>; - def : Pat<(f64 (PPCfcfidu (PPCmtvsrz (i32 (extractelt v4i32:$A, 3))))), + def : Pat<(f64 (PPCfcfidu (f64 (PPCmtvsrz (i32 (extractelt v4i32:$A, 3)))))), (f64 (XSCVUXDDP (XXEXTRACTUW $A, 12)))>; def : Pat<(v4i32 (insertelt v4i32:$A, i32:$B, 0)), (v4i32 (XXINSERTW v4i32:$A, AlignValues.I32_TO_BE_WORD1, 0))>; @@ -2869,12 +3011,16 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def : Pat<(v4f32 (quadwOffsetLoad iqaddr:$src)), (LXV memrix16:$src)>; def : Pat<(v2i64 (quadwOffsetLoad iqaddr:$src)), (LXV memrix16:$src)>; def : Pat<(v2f64 (quadwOffsetLoad iqaddr:$src)), (LXV memrix16:$src)>; + def : Pat<(f128 (quadwOffsetLoad iqaddr:$src)), + (COPY_TO_REGCLASS (LXV memrix16:$src), VRRC)>; def : Pat<(v4i32 (int_ppc_vsx_lxvw4x iqaddr:$src)), (LXV memrix16:$src)>; def : Pat<(v2f64 (int_ppc_vsx_lxvd2x iqaddr:$src)), (LXV memrix16:$src)>; def : Pat<(quadwOffsetStore v4f32:$rS, iqaddr:$dst), (STXV $rS, memrix16:$dst)>; def : Pat<(quadwOffsetStore v4i32:$rS, iqaddr:$dst), (STXV $rS, memrix16:$dst)>; def : Pat<(quadwOffsetStore v2f64:$rS, iqaddr:$dst), (STXV $rS, memrix16:$dst)>; + def : Pat<(quadwOffsetStore f128:$rS, iqaddr:$dst), + (STXV (COPY_TO_REGCLASS $rS, VSRC), memrix16:$dst)>; def : Pat<(quadwOffsetStore v2i64:$rS, iqaddr:$dst), (STXV $rS, memrix16:$dst)>; def : Pat<(int_ppc_vsx_stxvw4x v4i32:$rS, iqaddr:$dst), (STXV $rS, memrix16:$dst)>; @@ -2888,6 +3034,10 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def : Pat<(v4i32 (nonQuadwOffsetLoad xoaddr:$src)), (LXVX xoaddr:$src)>; def : Pat<(v4i32 (int_ppc_vsx_lxvw4x xoaddr:$src)), (LXVX xoaddr:$src)>; def : Pat<(v2f64 (int_ppc_vsx_lxvd2x xoaddr:$src)), (LXVX xoaddr:$src)>; + def : Pat<(f128 (nonQuadwOffsetLoad xoaddr:$src)), + (COPY_TO_REGCLASS (LXVX xoaddr:$src), VRRC)>; + def : Pat<(nonQuadwOffsetStore f128:$rS, xoaddr:$dst), + (STXVX (COPY_TO_REGCLASS $rS, VSRC), xoaddr:$dst)>; def : Pat<(nonQuadwOffsetStore v2f64:$rS, xoaddr:$dst), (STXVX $rS, xoaddr:$dst)>; def : Pat<(nonQuadwOffsetStore v2i64:$rS, xoaddr:$dst), @@ -2904,7 +3054,8 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { (v4i32 (LXVWSX xoaddr:$src))>; def : Pat<(v4f32 (scalar_to_vector (f32 (load xoaddr:$src)))), (v4f32 (LXVWSX xoaddr:$src))>; - def : Pat<(v4f32 (scalar_to_vector (f32 (fpround (extloadf32 xoaddr:$src))))), + def : Pat<(v4f32 (scalar_to_vector + (f32 (fpround (f64 (extloadf32 xoaddr:$src)))))), (v4f32 (LXVWSX xoaddr:$src))>; // Build vectors from i8 loads @@ -2936,109 +3087,109 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { let Predicates = [IsBigEndian, HasP9Vector] in { // Scalar stores of i8 def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 0)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 9), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 9)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 1)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 10), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 10)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 2)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 11), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 11)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 3)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 12), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 12)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 4)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 13), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 13)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 5)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 14), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 14)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 6)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 15), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 15)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 7)), xoaddr:$dst), (STXSIBXv $S, xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 8)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 1), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 1)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 9)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 2), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 2)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 10)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 3), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 3)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 11)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 4), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 4)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 12)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 5), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 5)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 13)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 6), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 6)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 14)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 7), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 7)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 15)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 8), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 8)), xoaddr:$dst)>; // Scalar stores of i16 def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 0)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 10), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 10)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 1)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 12), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 12)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 2)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 14), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 14)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 3)), xoaddr:$dst), (STXSIHXv $S, xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 4)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 2), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 2)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 5)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 4), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 4)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 6)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 6), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 6)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 7)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 8), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 8)), xoaddr:$dst)>; } // IsBigEndian, HasP9Vector let Predicates = [IsLittleEndian, HasP9Vector] in { // Scalar stores of i8 def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 0)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 8), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 8)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 1)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 7), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 7)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 2)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 6), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 6)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 3)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 5), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 5)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 4)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 4), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 4)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 5)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 3), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 3)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 6)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 2), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 2)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 7)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 1), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 1)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 8)), xoaddr:$dst), (STXSIBXv $S, xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 9)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 15), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 15)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 10)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 14), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 14)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 11)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 13), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 13)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 12)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 12), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 12)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 13)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 11), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 11)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 14)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 10), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 10)), xoaddr:$dst)>; def : Pat<(truncstorei8 (i32 (vector_extract v16i8:$S, 15)), xoaddr:$dst), - (STXSIBXv (VSLDOI $S, $S, 9), xoaddr:$dst)>; + (STXSIBXv (v16i8 (VSLDOI $S, $S, 9)), xoaddr:$dst)>; // Scalar stores of i16 def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 0)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 8), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 8)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 1)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 6), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 6)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 2)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 4), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 4)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 3)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 2), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 2)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 4)), xoaddr:$dst), (STXSIHXv $S, xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 5)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 14), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 14)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 6)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 12), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 12)), xoaddr:$dst)>; def : Pat<(truncstorei16 (i32 (vector_extract v8i16:$S, 7)), xoaddr:$dst), - (STXSIHXv (VSLDOI $S, $S, 10), xoaddr:$dst)>; + (STXSIHXv (v16i8 (VSLDOI $S, $S, 10)), xoaddr:$dst)>; } // IsLittleEndian, HasP9Vector @@ -3064,21 +3215,264 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { } def : Pat<(f64 (extloadf32 ixaddr:$src)), (COPY_TO_REGCLASS (DFLOADf32 ixaddr:$src), VSFRC)>; - def : Pat<(f32 (fpround (extloadf32 ixaddr:$src))), + def : Pat<(f32 (fpround (f64 (extloadf32 ixaddr:$src)))), (f32 (DFLOADf32 ixaddr:$src))>; + + let Predicates = [IsBigEndian, HasP9Vector] in { + + // (Un)Signed DWord vector extract -> QP + def : Pat<(f128 (sint_to_fp (i64 (extractelt v2i64:$src, 0)))), + (f128 (XSCVSDQP (COPY_TO_REGCLASS $src, VFRC)))>; + def : Pat<(f128 (sint_to_fp (i64 (extractelt v2i64:$src, 1)))), + (f128 (XSCVSDQP + (EXTRACT_SUBREG (XXPERMDI $src, $src, 3), sub_64)))>; + def : Pat<(f128 (uint_to_fp (i64 (extractelt v2i64:$src, 0)))), + (f128 (XSCVUDQP (COPY_TO_REGCLASS $src, VFRC)))>; + def : Pat<(f128 (uint_to_fp (i64 (extractelt v2i64:$src, 1)))), + (f128 (XSCVUDQP + (EXTRACT_SUBREG (XXPERMDI $src, $src, 3), sub_64)))>; + + // (Un)Signed Word vector extract -> QP + def : Pat<(f128 (sint_to_fp (i32 (extractelt v4i32:$src, 1)))), + (f128 (XSCVSDQP (EXTRACT_SUBREG (VEXTSW2D $src), sub_64)))>; + foreach Idx = [0,2,3] in { + def : Pat<(f128 (sint_to_fp (i32 (extractelt v4i32:$src, Idx)))), + (f128 (XSCVSDQP (EXTRACT_SUBREG + (VEXTSW2D (VSPLTW Idx, $src)), sub_64)))>; + } + foreach Idx = 0-3 in { + def : Pat<(f128 (uint_to_fp (i32 (extractelt v4i32:$src, Idx)))), + (f128 (XSCVUDQP (XXEXTRACTUW $src, !shl(Idx, 2))))>; + } + + // (Un)Signed HWord vector extract -> QP + foreach Idx = 0-7 in { + def : Pat<(f128 (sint_to_fp + (i32 (sext_inreg + (vector_extract v8i16:$src, Idx), i16)))), + (f128 (XSCVSDQP (EXTRACT_SUBREG + (VEXTSH2D (VEXTRACTUH !add(Idx, Idx), $src)), + sub_64)))>; + // The SDAG adds the `and` since an `i16` is being extracted as an `i32`. + def : Pat<(f128 (uint_to_fp + (and (i32 (vector_extract v8i16:$src, Idx)), 65535))), + (f128 (XSCVUDQP (EXTRACT_SUBREG + (VEXTRACTUH !add(Idx, Idx), $src), sub_64)))>; + } + + // (Un)Signed Byte vector extract -> QP + foreach Idx = 0-15 in { + def : Pat<(f128 (sint_to_fp + (i32 (sext_inreg (vector_extract v16i8:$src, Idx), + i8)))), + (f128 (XSCVSDQP (EXTRACT_SUBREG + (VEXTSB2D (VEXTRACTUB Idx, $src)), sub_64)))>; + def : Pat<(f128 (uint_to_fp + (and (i32 (vector_extract v16i8:$src, Idx)), 255))), + (f128 (XSCVUDQP + (EXTRACT_SUBREG (VEXTRACTUB Idx, $src), sub_64)))>; + } + + // Unsiged int in vsx register -> QP + def : Pat<(f128 (uint_to_fp (i32 (PPCmfvsr f64:$src)))), + (f128 (XSCVUDQP + (XXEXTRACTUW (SUBREG_TO_REG (i64 1), $src, sub_64), 4)))>; + } // IsBigEndian, HasP9Vector + + let Predicates = [IsLittleEndian, HasP9Vector] in { + + // (Un)Signed DWord vector extract -> QP + def : Pat<(f128 (sint_to_fp (i64 (extractelt v2i64:$src, 0)))), + (f128 (XSCVSDQP + (EXTRACT_SUBREG (XXPERMDI $src, $src, 3), sub_64)))>; + def : Pat<(f128 (sint_to_fp (i64 (extractelt v2i64:$src, 1)))), + (f128 (XSCVSDQP (COPY_TO_REGCLASS $src, VFRC)))>; + def : Pat<(f128 (uint_to_fp (i64 (extractelt v2i64:$src, 0)))), + (f128 (XSCVUDQP + (EXTRACT_SUBREG (XXPERMDI $src, $src, 3), sub_64)))>; + def : Pat<(f128 (uint_to_fp (i64 (extractelt v2i64:$src, 1)))), + (f128 (XSCVUDQP (COPY_TO_REGCLASS $src, VFRC)))>; + + // (Un)Signed Word vector extract -> QP + foreach Idx = [[0,3],[1,2],[3,0]] in { + def : Pat<(f128 (sint_to_fp (i32 (extractelt v4i32:$src, !head(Idx))))), + (f128 (XSCVSDQP (EXTRACT_SUBREG + (VEXTSW2D (VSPLTW !head(!tail(Idx)), $src)), + sub_64)))>; + } + def : Pat<(f128 (sint_to_fp (i32 (extractelt v4i32:$src, 2)))), + (f128 (XSCVSDQP (EXTRACT_SUBREG (VEXTSW2D $src), sub_64)))>; + + foreach Idx = [[0,12],[1,8],[2,4],[3,0]] in { + def : Pat<(f128 (uint_to_fp (i32 (extractelt v4i32:$src, !head(Idx))))), + (f128 (XSCVUDQP (XXEXTRACTUW $src, !head(!tail(Idx)))))>; + } + + // (Un)Signed HWord vector extract -> QP + // The Nested foreach lists identifies the vector element and corresponding + // register byte location. + foreach Idx = [[0,14],[1,12],[2,10],[3,8],[4,6],[5,4],[6,2],[7,0]] in { + def : Pat<(f128 (sint_to_fp + (i32 (sext_inreg + (vector_extract v8i16:$src, !head(Idx)), i16)))), + (f128 (XSCVSDQP + (EXTRACT_SUBREG (VEXTSH2D + (VEXTRACTUH !head(!tail(Idx)), $src)), + sub_64)))>; + def : Pat<(f128 (uint_to_fp + (and (i32 (vector_extract v8i16:$src, !head(Idx))), + 65535))), + (f128 (XSCVUDQP (EXTRACT_SUBREG + (VEXTRACTUH !head(!tail(Idx)), $src), sub_64)))>; + } + + // (Un)Signed Byte vector extract -> QP + foreach Idx = [[0,15],[1,14],[2,13],[3,12],[4,11],[5,10],[6,9],[7,8],[8,7], + [9,6],[10,5],[11,4],[12,3],[13,2],[14,1],[15,0]] in { + def : Pat<(f128 (sint_to_fp + (i32 (sext_inreg + (vector_extract v16i8:$src, !head(Idx)), i8)))), + (f128 (XSCVSDQP + (EXTRACT_SUBREG + (VEXTSB2D (VEXTRACTUB !head(!tail(Idx)), $src)), + sub_64)))>; + def : Pat<(f128 (uint_to_fp + (and (i32 (vector_extract v16i8:$src, !head(Idx))), + 255))), + (f128 (XSCVUDQP + (EXTRACT_SUBREG + (VEXTRACTUB !head(!tail(Idx)), $src), sub_64)))>; + } + + // Unsiged int in vsx register -> QP + def : Pat<(f128 (uint_to_fp (i32 (PPCmfvsr f64:$src)))), + (f128 (XSCVUDQP + (XXEXTRACTUW (SUBREG_TO_REG (i64 1), $src, sub_64), 8)))>; + } // IsLittleEndian, HasP9Vector + + // Convert (Un)Signed DWord in memory -> QP + def : Pat<(f128 (sint_to_fp (i64 (load xaddr:$src)))), + (f128 (XSCVSDQP (LXSDX xaddr:$src)))>; + def : Pat<(f128 (sint_to_fp (i64 (load ixaddr:$src)))), + (f128 (XSCVSDQP (LXSD ixaddr:$src)))>; + def : Pat<(f128 (uint_to_fp (i64 (load xaddr:$src)))), + (f128 (XSCVUDQP (LXSDX xaddr:$src)))>; + def : Pat<(f128 (uint_to_fp (i64 (load ixaddr:$src)))), + (f128 (XSCVUDQP (LXSD ixaddr:$src)))>; + + // Convert Unsigned HWord in memory -> QP + def : Pat<(f128 (uint_to_fp ScalarLoads.ZELi16)), + (f128 (XSCVUDQP (LXSIHZX xaddr:$src)))>; + + // Convert Unsigned Byte in memory -> QP + def : Pat<(f128 (uint_to_fp ScalarLoads.ZELi8)), + (f128 (XSCVUDQP (LXSIBZX xoaddr:$src)))>; + + // Truncate & Convert QP -> (Un)Signed (D)Word. + def : Pat<(i64 (fp_to_sint f128:$src)), (i64 (MFVRD (XSCVQPSDZ $src)))>; + def : Pat<(i64 (fp_to_uint f128:$src)), (i64 (MFVRD (XSCVQPUDZ $src)))>; + def : Pat<(i32 (fp_to_sint f128:$src)), + (i32 (MFVSRWZ (COPY_TO_REGCLASS (XSCVQPSWZ $src), VFRC)))>; + def : Pat<(i32 (fp_to_uint f128:$src)), + (i32 (MFVSRWZ (COPY_TO_REGCLASS (XSCVQPUWZ $src), VFRC)))>; + + // Instructions for store(fptosi). + // The 8-byte version is repeated here due to availability of D-Form STXSD. + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f128:$src)), xaddr:$dst, 8), + (STXSDX (COPY_TO_REGCLASS (XSCVQPSDZ f128:$src), VFRC), + xaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f128:$src)), ixaddr:$dst, 8), + (STXSD (COPY_TO_REGCLASS (XSCVQPSDZ f128:$src), VFRC), + ixaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f128:$src)), xoaddr:$dst, 4), + (STXSIWX (COPY_TO_REGCLASS (XSCVQPSWZ $src), VFRC), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f128:$src)), xoaddr:$dst, 2), + (STXSIHX (COPY_TO_REGCLASS (XSCVQPSWZ $src), VFRC), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f128:$src)), xoaddr:$dst, 1), + (STXSIBX (COPY_TO_REGCLASS (XSCVQPSWZ $src), VFRC), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xaddr:$dst, 8), + (STXSDX (XSCVDPSXDS f64:$src), xaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), ixaddr:$dst, 8), + (STXSD (XSCVDPSXDS f64:$src), ixaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 2), + (STXSIHX (XSCVDPSXWS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 1), + (STXSIBX (XSCVDPSXWS f64:$src), xoaddr:$dst)>; + + // Instructions for store(fptoui). + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f128:$src)), xaddr:$dst, 8), + (STXSDX (COPY_TO_REGCLASS (XSCVQPUDZ f128:$src), VFRC), + xaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f128:$src)), ixaddr:$dst, 8), + (STXSD (COPY_TO_REGCLASS (XSCVQPUDZ f128:$src), VFRC), + ixaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f128:$src)), xoaddr:$dst, 4), + (STXSIWX (COPY_TO_REGCLASS (XSCVQPUWZ $src), VFRC), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f128:$src)), xoaddr:$dst, 2), + (STXSIHX (COPY_TO_REGCLASS (XSCVQPUWZ $src), VFRC), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f128:$src)), xoaddr:$dst, 1), + (STXSIBX (COPY_TO_REGCLASS (XSCVQPUWZ $src), VFRC), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xaddr:$dst, 8), + (STXSDX (XSCVDPUXDS f64:$src), xaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), ixaddr:$dst, 8), + (STXSD (XSCVDPUXDS f64:$src), ixaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 2), + (STXSIHX (XSCVDPUXWS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 1), + (STXSIBX (XSCVDPUXWS f64:$src), xoaddr:$dst)>; + + // Round & Convert QP -> DP/SP + def : Pat<(f64 (fpround f128:$src)), (f64 (XSCVQPDP $src))>; + def : Pat<(f32 (fpround f128:$src)), (f32 (XSRSP (XSCVQPDPO $src)))>; + + // Convert SP -> QP + def : Pat<(f128 (fpextend f32:$src)), + (f128 (XSCVDPQP (COPY_TO_REGCLASS $src, VFRC)))>; + } // end HasP9Vector, AddedComplexity +let AddedComplexity = 400 in { + let Predicates = [IsISA3_0, HasP9Vector, HasDirectMove, IsBigEndian] in { + def : Pat<(f128 (PPCbuild_fp128 i64:$rB, i64:$rA)), + (f128 (COPY_TO_REGCLASS (MTVSRDD $rB, $rA), VRRC))>; + } + let Predicates = [IsISA3_0, HasP9Vector, HasDirectMove, IsLittleEndian] in { + def : Pat<(f128 (PPCbuild_fp128 i64:$rA, i64:$rB)), + (f128 (COPY_TO_REGCLASS (MTVSRDD $rB, $rA), VRRC))>; + } +} + let Predicates = [HasP9Vector] in { let isPseudo = 1 in { let mayStore = 1 in { - def SPILLTOVSR_STX : Pseudo<(outs), (ins spilltovsrrc:$XT, memrr:$dst), - "#SPILLTOVSR_STX", []>; + def SPILLTOVSR_STX : PseudoXFormMemOp<(outs), + (ins spilltovsrrc:$XT, memrr:$dst), + "#SPILLTOVSR_STX", []>; def SPILLTOVSR_ST : Pseudo<(outs), (ins spilltovsrrc:$XT, memrix:$dst), "#SPILLTOVSR_ST", []>; } let mayLoad = 1 in { - def SPILLTOVSR_LDX : Pseudo<(outs spilltovsrrc:$XT), (ins memrr:$src), - "#SPILLTOVSR_LDX", []>; + def SPILLTOVSR_LDX : PseudoXFormMemOp<(outs spilltovsrrc:$XT), + (ins memrr:$src), + "#SPILLTOVSR_LDX", []>; def SPILLTOVSR_LD : Pseudo<(outs spilltovsrrc:$XT), (ins memrix:$src), "#SPILLTOVSR_LD", []>; @@ -3170,10 +3564,10 @@ def FltToULongLoadP9 { dag A = (i64 (PPCmfvsr (PPCfctiduz (f64 (extloadf32 ixaddr:$A))))); } def FltToLong { - dag A = (i64 (PPCmfvsr (PPCfctidz (fpextend f32:$A)))); + dag A = (i64 (PPCmfvsr (f64 (PPCfctidz (fpextend f32:$A))))); } def FltToULong { - dag A = (i64 (PPCmfvsr (PPCfctiduz (fpextend f32:$A)))); + dag A = (i64 (PPCmfvsr (f64 (PPCfctiduz (fpextend f32:$A))))); } def DblToInt { dag A = (i32 (PPCmfvsr (f64 (PPCfctiwz f64:$A)))); @@ -3219,7 +3613,6 @@ def MrgFP { } // Patterns for BUILD_VECTOR nodes. -def NoP9Vector : Predicate<"!PPCSubTarget->hasP9Vector()">; let AddedComplexity = 400 in { let Predicates = [HasVSX] in { @@ -3389,8 +3782,10 @@ let AddedComplexity = 400 in { def : Pat<(v2i64 (build_vector i64:$rB, i64:$rA)), (v2i64 (MTVSRDD $rB, $rA))>; def : Pat<(v4i32 (build_vector i32:$A, i32:$B, i32:$C, i32:$D)), - (VMRGOW (COPY_TO_REGCLASS (MTVSRDD AnyExts.A, AnyExts.C), VSRC), - (COPY_TO_REGCLASS (MTVSRDD AnyExts.B, AnyExts.D), VSRC))>; + (VMRGOW + (v4i32 (COPY_TO_REGCLASS (MTVSRDD AnyExts.A, AnyExts.C), VSRC)), + (v4i32 + (COPY_TO_REGCLASS (MTVSRDD AnyExts.B, AnyExts.D), VSRC)))>; } let Predicates = [IsISA3_0, HasDirectMove, IsLittleEndian] in { @@ -3400,8 +3795,10 @@ let AddedComplexity = 400 in { def : Pat<(v2i64 (build_vector i64:$rA, i64:$rB)), (v2i64 (MTVSRDD $rB, $rA))>; def : Pat<(v4i32 (build_vector i32:$A, i32:$B, i32:$C, i32:$D)), - (VMRGOW (COPY_TO_REGCLASS (MTVSRDD AnyExts.D, AnyExts.B), VSRC), - (COPY_TO_REGCLASS (MTVSRDD AnyExts.C, AnyExts.A), VSRC))>; + (VMRGOW + (v4i32 (COPY_TO_REGCLASS (MTVSRDD AnyExts.D, AnyExts.B), VSRC)), + (v4i32 + (COPY_TO_REGCLASS (MTVSRDD AnyExts.C, AnyExts.A), VSRC)))>; } // P9 Altivec instructions that can be used to build vectors. // Adding them to PPCInstrVSX.td rather than PPCAltivecVSX.td to compete diff --git a/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp b/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp index cdf544bdfac3..2217fa4693ce 100644 --- a/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp +++ b/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp @@ -33,6 +33,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionExpander.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Dominators.h" @@ -47,8 +48,8 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/LoopUtils.h" #include <cassert> #include <iterator> @@ -246,15 +247,14 @@ bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { if (!L->empty()) return MadeChange; - DEBUG(dbgs() << "PIP: Examining: " << *L << "\n"); + LLVM_DEBUG(dbgs() << "PIP: Examining: " << *L << "\n"); BasicBlock *Header = L->getHeader(); const PPCSubtarget *ST = TM ? TM->getSubtargetImpl(*Header->getParent()) : nullptr; - unsigned HeaderLoopPredCount = - std::distance(pred_begin(Header), pred_end(Header)); + unsigned HeaderLoopPredCount = pred_size(Header); // Collect buckets of comparable addresses used by loads and stores. SmallVector<Bucket, 16> Buckets; @@ -294,6 +294,19 @@ bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { if (const SCEVAddRecExpr *LARSCEV = dyn_cast<SCEVAddRecExpr>(LSCEV)) { if (LARSCEV->getLoop() != L) continue; + // See getPreIndexedAddressParts, the displacement for LDU/STDU has to + // be 4's multiple (DS-form). For i64 loads/stores when the displacement + // fits in a 16-bit signed field but isn't a multiple of 4, it will be + // useless and possible to break some original well-form addressing mode + // to make this pre-inc prep for it. + if (PtrValue->getType()->getPointerElementType()->isIntegerTy(64)) { + if (const SCEVConstant *StepConst = + dyn_cast<SCEVConstant>(LARSCEV->getStepRecurrence(*SE))) { + const APInt &ConstInt = StepConst->getValue()->getValue(); + if (ConstInt.isSignedIntN(16) && ConstInt.srem(4) != 0) + continue; + } + } } else { continue; } @@ -332,7 +345,7 @@ bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { if (!LoopPredecessor) return MadeChange; - DEBUG(dbgs() << "PIP: Found " << Buckets.size() << " buckets\n"); + LLVM_DEBUG(dbgs() << "PIP: Found " << Buckets.size() << " buckets\n"); SmallSet<BasicBlock *, 16> BBChanged; for (unsigned i = 0, e = Buckets.size(); i != e; ++i) { @@ -381,7 +394,7 @@ bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { if (!BasePtrSCEV->isAffine()) continue; - DEBUG(dbgs() << "PIP: Transforming: " << *BasePtrSCEV << "\n"); + LLVM_DEBUG(dbgs() << "PIP: Transforming: " << *BasePtrSCEV << "\n"); assert(BasePtrSCEV->getLoop() == L && "AddRec for the wrong loop?"); @@ -407,7 +420,7 @@ bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { if (!isSafeToExpand(BasePtrStartSCEV, *SE)) continue; - DEBUG(dbgs() << "PIP: New start is: " << *BasePtrStartSCEV << "\n"); + LLVM_DEBUG(dbgs() << "PIP: New start is: " << *BasePtrStartSCEV << "\n"); if (alreadyPrepared(L, MemI, BasePtrStartSCEV, BasePtrIncSCEV)) continue; diff --git a/lib/Target/PowerPC/PPCMCInstLower.cpp b/lib/Target/PowerPC/PPCMCInstLower.cpp index 1e40711328ec..62a612feb55c 100644 --- a/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -21,13 +21,13 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/TargetLowering.h" -#include "llvm/CodeGen/TargetLoweringObjectFile.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Mangler.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/Target/TargetLoweringObjectFile.h" using namespace llvm; static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) { @@ -107,10 +107,20 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, break; } - if (MO.getTargetFlags() == PPCII::MO_PLT) + if (MO.getTargetFlags() == PPCII::MO_PLT) RefKind = MCSymbolRefExpr::VK_PLT; + const MachineFunction *MF = MO.getParent()->getParent()->getParent(); + const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); + const TargetMachine &TM = Printer.TM; const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); + // -msecure-plt option works only in PIC mode. If secure plt mode + // is on add 32768 to symbol. + if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && + MO.getTargetFlags() == PPCII::MO_PLT) + Expr = MCBinaryExpr::createAdd(Expr, + MCConstantExpr::create(32768, Ctx), + Ctx); if (!MO.isJTI() && MO.getOffset()) Expr = MCBinaryExpr::createAdd(Expr, diff --git a/lib/Target/PowerPC/PPCMIPeephole.cpp b/lib/Target/PowerPC/PPCMIPeephole.cpp index 474661aaaee8..dbe1fe37ddf8 100644 --- a/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -55,7 +55,7 @@ FixedPointRegToImm("ppc-reg-to-imm-fixed-point", cl::Hidden, cl::init(true), "convert reg-reg instructions to reg-imm")); static cl::opt<bool> -ConvertRegReg("ppc-convert-rr-to-ri", cl::Hidden, cl::init(false), +ConvertRegReg("ppc-convert-rr-to-ri", cl::Hidden, cl::init(true), cl::desc("Convert eligible reg+reg instructions to reg+imm")); static cl::opt<bool> @@ -119,8 +119,8 @@ void PPCMIPeephole::initialize(MachineFunction &MFParm) { MRI = &MF->getRegInfo(); MDT = &getAnalysis<MachineDominatorTree>(); TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo(); - DEBUG(dbgs() << "*** PowerPC MI peephole pass ***\n\n"); - DEBUG(MF->dump()); + LLVM_DEBUG(dbgs() << "*** PowerPC MI peephole pass ***\n\n"); + LLVM_DEBUG(MF->dump()); } static MachineInstr *getVRegDefOrNull(MachineOperand *Op, @@ -190,18 +190,18 @@ getKnownLeadingZeroCount(MachineInstr *MI, const PPCInstrInfo *TII) { } // This function maintains a map for the pairs <TOC Save Instr, Keep> -// Each time a new TOC save is encountered, it checks if any of the exisiting -// ones are dominated by the new one. If so, it marks the exisiting one as +// Each time a new TOC save is encountered, it checks if any of the existing +// ones are dominated by the new one. If so, it marks the existing one as // redundant by setting it's entry in the map as false. It then adds the new // instruction to the map with either true or false depending on if any -// exisiting instructions dominated the new one. +// existing instructions dominated the new one. void PPCMIPeephole::UpdateTOCSaves( std::map<MachineInstr *, bool> &TOCSaves, MachineInstr *MI) { assert(TII->isTOCSaveMI(*MI) && "Expecting a TOC save instruction here"); bool Keep = true; for (auto It = TOCSaves.begin(); It != TOCSaves.end(); It++ ) { MachineInstr *CurrInst = It->first; - // If new instruction dominates an exisiting one, mark exisiting one as + // If new instruction dominates an existing one, mark existing one as // redundant. if (It->second && MDT->dominates(MI, CurrInst)) It->second = false; @@ -220,7 +220,7 @@ bool PPCMIPeephole::simplifyCode(void) { bool Simplified = false; MachineInstr* ToErase = nullptr; std::map<MachineInstr *, bool> TOCSaves; - + const TargetRegisterInfo *TRI = &TII->getRegisterInfo(); NumFunctionsEnteredInMIPeephole++; if (ConvertRegReg) { // Fixed-point conversion of reg/reg instructions fed by load-immediate @@ -232,14 +232,14 @@ bool PPCMIPeephole::simplifyCode(void) { SomethingChanged = false; for (MachineBasicBlock &MBB : *MF) { for (MachineInstr &MI : MBB) { - if (MI.isDebugValue()) + 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. - DEBUG(dbgs() << "Converted instruction to imm form: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); + LLVM_DEBUG(MI.dump()); NumConvertedToImmediateForm++; SomethingChanged = true; Simplified = true; @@ -261,7 +261,7 @@ bool PPCMIPeephole::simplifyCode(void) { } // Ignore debug instructions. - if (MI.isDebugValue()) + if (MI.isDebugInstr()) continue; // Per-opcode peepholes. @@ -276,7 +276,7 @@ bool PPCMIPeephole::simplifyCode(void) { !MF->getSubtarget<PPCSubtarget>().isELFv2ABI()) break; // When encountering a TOC save instruction, call UpdateTOCSaves - // to add it to the TOCSaves map and mark any exisiting TOC saves + // to add it to the TOCSaves map and mark any existing TOC saves // it dominates as redundant. if (TII->isTOCSaveMI(MI)) UpdateTOCSaves(TOCSaves, &MI); @@ -297,9 +297,9 @@ bool PPCMIPeephole::simplifyCode(void) { // We have to look through chains of COPY and SUBREG_TO_REG // to find the real source values for comparison. unsigned TrueReg1 = - TII->lookThruCopyLike(MI.getOperand(1).getReg(), MRI); + TRI->lookThruCopyLike(MI.getOperand(1).getReg(), MRI); unsigned TrueReg2 = - TII->lookThruCopyLike(MI.getOperand(2).getReg(), MRI); + TRI->lookThruCopyLike(MI.getOperand(2).getReg(), MRI); if (TrueReg1 == TrueReg2 && TargetRegisterInfo::isVirtualRegister(TrueReg1)) { @@ -314,7 +314,7 @@ bool PPCMIPeephole::simplifyCode(void) { if (DefOpc != PPC::XVCVDPSXDS && DefOpc != PPC::XVCVDPUXDS) return false; unsigned DefReg = - TII->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); + TRI->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); if (TargetRegisterInfo::isVirtualRegister(DefReg)) { MachineInstr *LoadMI = MRI->getVRegDef(DefReg); if (LoadMI && LoadMI->getOpcode() == PPC::LXVDSX) @@ -324,10 +324,9 @@ bool PPCMIPeephole::simplifyCode(void) { }; if (DefMI && (Immed == 0 || Immed == 3)) { if (DefOpc == PPC::LXVDSX || isConversionOfLoadAndSplat()) { - DEBUG(dbgs() - << "Optimizing load-and-splat/splat " - "to load-and-splat/copy: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Optimizing load-and-splat/splat " + "to load-and-splat/copy: "); + LLVM_DEBUG(MI.dump()); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(1)); @@ -341,15 +340,14 @@ bool PPCMIPeephole::simplifyCode(void) { if (DefOpc == PPC::XXPERMDI) { unsigned FeedImmed = DefMI->getOperand(3).getImm(); unsigned FeedReg1 = - TII->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); + TRI->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); unsigned FeedReg2 = - TII->lookThruCopyLike(DefMI->getOperand(2).getReg(), MRI); + TRI->lookThruCopyLike(DefMI->getOperand(2).getReg(), MRI); if ((FeedImmed == 0 || FeedImmed == 3) && FeedReg1 == FeedReg2) { - DEBUG(dbgs() - << "Optimizing splat/swap or splat/splat " - "to splat/copy: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Optimizing splat/swap or splat/splat " + "to splat/copy: "); + LLVM_DEBUG(MI.dump()); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(1)); @@ -362,8 +360,8 @@ bool PPCMIPeephole::simplifyCode(void) { // parameter. else if ((Immed == 0 || Immed == 3) && FeedImmed == 2 && FeedReg1 == FeedReg2) { - DEBUG(dbgs() << "Optimizing swap/splat => splat: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Optimizing swap/splat => splat: "); + LLVM_DEBUG(MI.dump()); MI.getOperand(1).setReg(DefMI->getOperand(1).getReg()); MI.getOperand(2).setReg(DefMI->getOperand(2).getReg()); MI.getOperand(3).setImm(3 - Immed); @@ -373,8 +371,8 @@ bool PPCMIPeephole::simplifyCode(void) { // If this is a swap fed by a swap, we can replace it // with a copy from the first swap's input. else if (Immed == 2 && FeedImmed == 2 && FeedReg1 == FeedReg2) { - DEBUG(dbgs() << "Optimizing swap/swap => copy: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Optimizing swap/swap => copy: "); + LLVM_DEBUG(MI.dump()); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(DefMI->getOperand(1)); @@ -389,8 +387,8 @@ bool PPCMIPeephole::simplifyCode(void) { DefMI->getOperand(0).setReg(MI.getOperand(0).getReg()); ToErase = &MI; Simplified = true; - DEBUG(dbgs() << "Removing redundant splat: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Removing redundant splat: "); + LLVM_DEBUG(MI.dump()); } } } @@ -402,7 +400,7 @@ bool PPCMIPeephole::simplifyCode(void) { unsigned MyOpcode = MI.getOpcode(); unsigned OpNo = MyOpcode == PPC::XXSPLTW ? 1 : 2; unsigned TrueReg = - TII->lookThruCopyLike(MI.getOperand(OpNo).getReg(), MRI); + TRI->lookThruCopyLike(MI.getOperand(OpNo).getReg(), MRI); if (!TargetRegisterInfo::isVirtualRegister(TrueReg)) break; MachineInstr *DefMI = MRI->getVRegDef(TrueReg); @@ -429,8 +427,8 @@ bool PPCMIPeephole::simplifyCode(void) { // If the instruction[s] that feed this splat have already splat // the value, this splat is redundant. if (AlreadySplat) { - DEBUG(dbgs() << "Changing redundant splat to a copy: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Changing redundant splat to a copy: "); + LLVM_DEBUG(MI.dump()); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(MI.getOperand(OpNo)); @@ -448,14 +446,14 @@ bool PPCMIPeephole::simplifyCode(void) { if (ShiftOp1 == ShiftOp2) { unsigned NewElem = (SplatImm + ShiftImm) & 0x3; if (MRI->hasOneNonDBGUse(ShiftRes)) { - DEBUG(dbgs() << "Removing redundant shift: "); - DEBUG(DefMI->dump()); + LLVM_DEBUG(dbgs() << "Removing redundant shift: "); + LLVM_DEBUG(DefMI->dump()); ToErase = DefMI; } Simplified = true; - DEBUG(dbgs() << "Changing splat immediate from " << SplatImm << - " to " << NewElem << " in instruction: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Changing splat immediate from " << SplatImm + << " to " << NewElem << " in instruction: "); + LLVM_DEBUG(MI.dump()); MI.getOperand(1).setReg(ShiftOp1); MI.getOperand(2).setImm(NewElem); } @@ -465,7 +463,7 @@ bool PPCMIPeephole::simplifyCode(void) { case PPC::XVCVDPSP: { // If this is a DP->SP conversion fed by an FRSP, the FRSP is redundant. unsigned TrueReg = - TII->lookThruCopyLike(MI.getOperand(1).getReg(), MRI); + TRI->lookThruCopyLike(MI.getOperand(1).getReg(), MRI); if (!TargetRegisterInfo::isVirtualRegister(TrueReg)) break; MachineInstr *DefMI = MRI->getVRegDef(TrueReg); @@ -474,9 +472,9 @@ bool PPCMIPeephole::simplifyCode(void) { // values. if (DefMI && DefMI->getOpcode() == PPC::XXPERMDI) { unsigned DefsReg1 = - TII->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); + TRI->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); unsigned DefsReg2 = - TII->lookThruCopyLike(DefMI->getOperand(2).getReg(), MRI); + TRI->lookThruCopyLike(DefMI->getOperand(2).getReg(), MRI); if (!TargetRegisterInfo::isVirtualRegister(DefsReg1) || !TargetRegisterInfo::isVirtualRegister(DefsReg2)) break; @@ -499,12 +497,12 @@ bool PPCMIPeephole::simplifyCode(void) { if (Use.getOperand(i).isReg() && Use.getOperand(i).getReg() == FRSPDefines) Use.getOperand(i).setReg(ConvReg1); - DEBUG(dbgs() << "Removing redundant FRSP:\n"); - DEBUG(RoundInstr->dump()); - DEBUG(dbgs() << "As it feeds instruction:\n"); - DEBUG(MI.dump()); - DEBUG(dbgs() << "Through instruction:\n"); - DEBUG(DefMI->dump()); + LLVM_DEBUG(dbgs() << "Removing redundant FRSP:\n"); + LLVM_DEBUG(RoundInstr->dump()); + LLVM_DEBUG(dbgs() << "As it feeds instruction:\n"); + LLVM_DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Through instruction:\n"); + LLVM_DEBUG(DefMI->dump()); RoundInstr->eraseFromParent(); } }; @@ -552,11 +550,11 @@ bool PPCMIPeephole::simplifyCode(void) { }; unsigned Opc = getSextLoadOp(is64Bit(MI.getOpcode()), isXForm(SrcMI->getOpcode())); - DEBUG(dbgs() << "Zero-extending load\n"); - DEBUG(SrcMI->dump()); - DEBUG(dbgs() << "and sign-extension\n"); - DEBUG(MI.dump()); - DEBUG(dbgs() << "are merged into sign-extending load\n"); + LLVM_DEBUG(dbgs() << "Zero-extending load\n"); + LLVM_DEBUG(SrcMI->dump()); + LLVM_DEBUG(dbgs() << "and sign-extension\n"); + LLVM_DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "are merged into sign-extending load\n"); SrcMI->setDesc(TII->get(Opc)); SrcMI->getOperand(0).setReg(MI.getOperand(0).getReg()); ToErase = &MI; @@ -596,11 +594,11 @@ bool PPCMIPeephole::simplifyCode(void) { }; unsigned Opc = getSextLoadOp(is64Bit(MI.getOpcode()), isXForm(SrcMI->getOpcode())); - DEBUG(dbgs() << "Zero-extending load\n"); - DEBUG(SrcMI->dump()); - DEBUG(dbgs() << "and sign-extension\n"); - DEBUG(MI.dump()); - DEBUG(dbgs() << "are merged into sign-extending load\n"); + LLVM_DEBUG(dbgs() << "Zero-extending load\n"); + LLVM_DEBUG(SrcMI->dump()); + LLVM_DEBUG(dbgs() << "and sign-extension\n"); + LLVM_DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "are merged into sign-extending load\n"); SrcMI->setDesc(TII->get(Opc)); SrcMI->getOperand(0).setReg(MI.getOperand(0).getReg()); ToErase = &MI; @@ -610,7 +608,7 @@ bool PPCMIPeephole::simplifyCode(void) { TII->isSignExtended(*SrcMI)) { // We can eliminate EXTSW if the input is known to be already // sign-extended. - DEBUG(dbgs() << "Removing redundant sign-extension\n"); + LLVM_DEBUG(dbgs() << "Removing redundant sign-extension\n"); unsigned TmpReg = MF->getRegInfo().createVirtualRegister(&PPC::G8RCRegClass); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::IMPLICIT_DEF), @@ -661,7 +659,7 @@ bool PPCMIPeephole::simplifyCode(void) { unsigned KnownZeroCount = getKnownLeadingZeroCount(SrcMI, TII); if (MI.getOperand(3).getImm() <= KnownZeroCount) { - DEBUG(dbgs() << "Removing redundant zero-extension\n"); + LLVM_DEBUG(dbgs() << "Removing redundant zero-extension\n"); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .addReg(SrcReg); @@ -727,8 +725,8 @@ bool PPCMIPeephole::simplifyCode(void) { MachineInstr *DefPhiMI = getVRegDefOrNull(&Op1, MRI); for (unsigned i = 1; i < DefPhiMI->getNumOperands(); i += 2) { MachineInstr *LiMI = getVRegDefOrNull(&DefPhiMI->getOperand(i), MRI); - DEBUG(dbgs() << "Optimizing LI to ADDI: "); - DEBUG(LiMI->dump()); + LLVM_DEBUG(dbgs() << "Optimizing LI to ADDI: "); + LLVM_DEBUG(LiMI->dump()); // There could be repeated registers in the PHI, e.g: %1 = // PHI %6, <%bb.2>, %8, <%bb.3>, %8, <%bb.6>; So if we've @@ -746,12 +744,12 @@ bool PPCMIPeephole::simplifyCode(void) { MachineInstrBuilder(*LiMI->getParent()->getParent(), *LiMI) .addReg(DominatorReg) .addImm(LiImm); // restore the imm of LI - DEBUG(LiMI->dump()); + LLVM_DEBUG(LiMI->dump()); } // Replace ADD with COPY - DEBUG(dbgs() << "Optimizing ADD to COPY: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Optimizing ADD to COPY: "); + LLVM_DEBUG(MI.dump()); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(PPC::COPY), MI.getOperand(0).getReg()) .add(Op1); @@ -849,7 +847,7 @@ static unsigned getPredicateToIncImm(MachineInstr *BI, MachineInstr *CMPI) { return 0; } -// This takes a Phi node and returns a register value for the spefied BB. +// This takes a Phi node and returns a register value for the specified BB. static unsigned getIncomingRegForBlock(MachineInstr *Phi, MachineBasicBlock *MBB) { for (unsigned I = 2, E = Phi->getNumOperands() + 1; I != E; I += 2) { @@ -979,9 +977,9 @@ static bool eligibleForCompareElimination(MachineBasicBlock &MBB, } // This function will iterate over the input map containing a pair of TOC save -// instruction and a flag. The flag will be set to false if the TOC save is proven -// redundant. This function will erase from the basic block all the TOC saves -// marked as redundant. +// instruction and a flag. The flag will be set to false if the TOC save is +// proven redundant. This function will erase from the basic block all the TOC +// saves marked as redundant. bool PPCMIPeephole::eliminateRedundantTOCSaves( std::map<MachineInstr *, bool> &TOCSaves) { bool Simplified = false; @@ -1192,16 +1190,16 @@ bool PPCMIPeephole::eliminateRedundantCompare(void) { } } - // We cannnot merge two compares if the immediates are not same. + // We cannot merge two compares if the immediates are not same. if (NewImm2 != NewImm1) continue; } - DEBUG(dbgs() << "Optimize two pairs of compare and branch:\n"); - DEBUG(CMPI1->dump()); - DEBUG(BI1->dump()); - DEBUG(CMPI2->dump()); - DEBUG(BI2->dump()); + LLVM_DEBUG(dbgs() << "Optimize two pairs of compare and branch:\n"); + LLVM_DEBUG(CMPI1->dump()); + LLVM_DEBUG(BI1->dump()); + LLVM_DEBUG(CMPI2->dump()); + LLVM_DEBUG(BI2->dump()); // We adjust opcode, predicates and immediate as we determined above. if (NewOpCode != 0 && NewOpCode != CMPI1->getOpcode()) { @@ -1260,15 +1258,15 @@ bool PPCMIPeephole::eliminateRedundantCompare(void) { BI2->getOperand(1).setIsKill(true); BI1->getOperand(1).setIsKill(false); - DEBUG(dbgs() << "into a compare and two branches:\n"); - DEBUG(CMPI1->dump()); - DEBUG(BI1->dump()); - DEBUG(BI2->dump()); + LLVM_DEBUG(dbgs() << "into a compare and two branches:\n"); + LLVM_DEBUG(CMPI1->dump()); + LLVM_DEBUG(BI1->dump()); + LLVM_DEBUG(BI2->dump()); if (IsPartiallyRedundant) { - DEBUG(dbgs() << "The following compare is moved into " - << printMBBReference(*MBBtoMoveCmp) - << " to handle partial redundancy.\n"); - DEBUG(CMPI2->dump()); + LLVM_DEBUG(dbgs() << "The following compare is moved into " + << printMBBReference(*MBBtoMoveCmp) + << " to handle partial redundancy.\n"); + LLVM_DEBUG(CMPI2->dump()); } Simplified = true; diff --git a/lib/Target/PowerPC/PPCMachineBasicBlockUtils.h b/lib/Target/PowerPC/PPCMachineBasicBlockUtils.h deleted file mode 100644 index 628ea2ab9fe6..000000000000 --- a/lib/Target/PowerPC/PPCMachineBasicBlockUtils.h +++ /dev/null @@ -1,198 +0,0 @@ -//==-- PPCMachineBasicBlockUtils.h - Functions for common MBB operations ---==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines utility functions for commonly used operations on -// MachineBasicBlock's. -// NOTE: Include this file after defining DEBUG_TYPE so that the debug messages -// can be emitted for the pass that is using this. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_PPC_MACHINE_BASIC_BLOCK_UTILS_H -#define LLVM_LIB_TARGET_PPC_MACHINE_BASIC_BLOCK_UTILS_H - -#include "PPCInstrInfo.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" - -#ifndef DEBUG_TYPE -#define DEBUG_TYPE "ppc-generic-mbb-utilities" -#endif - -using namespace llvm; - -/// Given a basic block \p Successor that potentially contains PHIs, this -/// function will look for any incoming values in the PHIs that are supposed to -/// be coming from \p OrigMBB but whose definition is actually in \p NewMBB. -/// Any such PHIs will be updated to reflect reality. -static void updatePHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB, - MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI) { - for (auto &MI : Successor->instrs()) { - if (!MI.isPHI()) - continue; - // This is a really ugly-looking loop, but it was pillaged directly from - // MachineBasicBlock::transferSuccessorsAndUpdatePHIs(). - for (unsigned i = 2, e = MI.getNumOperands()+1; i != e; i += 2) { - MachineOperand &MO = MI.getOperand(i); - if (MO.getMBB() == OrigMBB) { - // Check if the instruction is actualy defined in NewMBB. - if (MI.getOperand(i-1).isReg()) { - MachineInstr *DefMI = MRI->getVRegDef(MI.getOperand(i-1).getReg()); - if (DefMI->getParent() == NewMBB || !OrigMBB->isSuccessor(Successor)) { - MO.setMBB(NewMBB); - break; - } - } - } - } - } -} - -/// Given a basic block \p Successor that potentially contains PHIs, this -/// function will look for PHIs that have an incoming value from \p OrigMBB -/// and will add the same incoming value from \p NewMBB. -/// NOTE: This should only be used if \p NewMBB is an immediate dominator of -/// \p OrigMBB. -static void addIncomingValuesToPHIs(MachineBasicBlock *Successor, - MachineBasicBlock *OrigMBB, - MachineBasicBlock *NewMBB, - MachineRegisterInfo *MRI) { - assert(OrigMBB->isSuccessor(NewMBB) && "NewMBB must be a sucessor of OrigMBB"); - for (auto &MI : Successor->instrs()) { - if (!MI.isPHI()) - continue; - // This is a really ugly-looking loop, but it was pillaged directly from - // MachineBasicBlock::transferSuccessorsAndUpdatePHIs(). - for (unsigned i = 2, e = MI.getNumOperands()+1; i != e; i += 2) { - MachineOperand &MO = MI.getOperand(i); - if (MO.getMBB() == OrigMBB) { - MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI); - MIB.addReg(MI.getOperand(i-1).getReg()).addMBB(NewMBB); - break; - } - } - } -} - -struct BlockSplitInfo { - MachineInstr *OrigBranch; - MachineInstr *SplitBefore; - MachineInstr *SplitCond; - bool InvertNewBranch; - bool InvertOrigBranch; - bool BranchToFallThrough; - const MachineBranchProbabilityInfo *MBPI; - MachineInstr *MIToDelete; - MachineInstr *NewCond; - bool allInstrsInSameMBB() { - if (!OrigBranch || !SplitBefore || !SplitCond) - return false; - MachineBasicBlock *MBB = OrigBranch->getParent(); - if (SplitBefore->getParent() != MBB || - SplitCond->getParent() != MBB) - return false; - if (MIToDelete && MIToDelete->getParent() != MBB) - return false; - if (NewCond && NewCond->getParent() != MBB) - return false; - return true; - } -}; - -/// Splits a MachineBasicBlock to branch before \p SplitBefore. The original -/// branch is \p OrigBranch. The target of the new branch can either be the same -/// as the target of the original branch or the fallthrough successor of the -/// original block as determined by \p BranchToFallThrough. The branch -/// conditions will be inverted according to \p InvertNewBranch and -/// \p InvertOrigBranch. If an instruction that previously fed the branch is to -/// be deleted, it is provided in \p MIToDelete and \p NewCond will be used as -/// the branch condition. The branch probabilities will be set if the -/// MachineBranchProbabilityInfo isn't null. -static bool splitMBB(BlockSplitInfo &BSI) { - assert(BSI.allInstrsInSameMBB() && - "All instructions must be in the same block."); - - MachineBasicBlock *ThisMBB = BSI.OrigBranch->getParent(); - MachineFunction *MF = ThisMBB->getParent(); - MachineRegisterInfo *MRI = &MF->getRegInfo(); - assert(MRI->isSSA() && "Can only do this while the function is in SSA form."); - if (ThisMBB->succ_size() != 2) { - DEBUG(dbgs() << "Don't know how to handle blocks that don't have exactly" - << " two succesors.\n"); - return false; - } - - const PPCInstrInfo *TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo(); - unsigned OrigBROpcode = BSI.OrigBranch->getOpcode(); - unsigned InvertedOpcode = - OrigBROpcode == PPC::BC ? PPC::BCn : - OrigBROpcode == PPC::BCn ? PPC::BC : - OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR; - unsigned NewBROpcode = BSI.InvertNewBranch ? InvertedOpcode : OrigBROpcode; - MachineBasicBlock *OrigTarget = BSI.OrigBranch->getOperand(1).getMBB(); - MachineBasicBlock *OrigFallThrough = - OrigTarget == *ThisMBB->succ_begin() ? *ThisMBB->succ_rbegin() : - *ThisMBB->succ_begin(); - MachineBasicBlock *NewBRTarget = - BSI.BranchToFallThrough ? OrigFallThrough : OrigTarget; - BranchProbability ProbToNewTarget = - !BSI.MBPI ? BranchProbability::getUnknown() : - BSI.MBPI->getEdgeProbability(ThisMBB, NewBRTarget); - - // Create a new basic block. - MachineBasicBlock::iterator InsertPoint = BSI.SplitBefore; - const BasicBlock *LLVM_BB = ThisMBB->getBasicBlock(); - MachineFunction::iterator It = ThisMBB->getIterator(); - MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MF->insert(++It, NewMBB); - - // Move everything after SplitBefore into the new block. - NewMBB->splice(NewMBB->end(), ThisMBB, InsertPoint, ThisMBB->end()); - NewMBB->transferSuccessors(ThisMBB); - - // Add the two successors to ThisMBB. The probabilities come from the - // existing blocks if available. - ThisMBB->addSuccessor(NewBRTarget, ProbToNewTarget); - ThisMBB->addSuccessor(NewMBB, ProbToNewTarget.getCompl()); - - // Add the branches to ThisMBB. - BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(), - TII->get(NewBROpcode)).addReg(BSI.SplitCond->getOperand(0).getReg()) - .addMBB(NewBRTarget); - BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(), - TII->get(PPC::B)).addMBB(NewMBB); - if (BSI.MIToDelete) - BSI.MIToDelete->eraseFromParent(); - - // Change the condition on the original branch and invert it if requested. - auto FirstTerminator = NewMBB->getFirstTerminator(); - if (BSI.NewCond) { - assert(FirstTerminator->getOperand(0).isReg() && - "Can't update condition of unconditional branch."); - FirstTerminator->getOperand(0).setReg(BSI.NewCond->getOperand(0).getReg()); - } - if (BSI.InvertOrigBranch) - FirstTerminator->setDesc(TII->get(InvertedOpcode)); - - // If any of the PHIs in the successors of NewMBB reference values that - // now come from NewMBB, they need to be updated. - for (auto *Succ : NewMBB->successors()) { - updatePHIs(Succ, ThisMBB, NewMBB, MRI); - } - addIncomingValuesToPHIs(NewBRTarget, ThisMBB, NewMBB, MRI); - - DEBUG(dbgs() << "After splitting, ThisMBB:\n"; ThisMBB->dump()); - DEBUG(dbgs() << "NewMBB:\n"; NewMBB->dump()); - DEBUG(dbgs() << "New branch-to block:\n"; NewBRTarget->dump()); - return true; -} - - -#endif diff --git a/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/lib/Target/PowerPC/PPCMachineFunctionInfo.h index a9b6073106ea..b14bbad2039a 100644 --- a/lib/Target/PowerPC/PPCMachineFunctionInfo.h +++ b/lib/Target/PowerPC/PPCMachineFunctionInfo.h @@ -45,6 +45,11 @@ class PPCFunctionInfo : public MachineFunctionInfo { /// PEI. bool MustSaveLR; + /// Do we have to disable shrink-wrapping? This has to be set if we emit any + /// instructions that clobber LR in the entry block because discovering this + /// in PEI is too late (happens after shrink-wrapping); + bool ShrinkWrapDisabled = false; + /// Does this function have any stack spills. bool HasSpills = false; @@ -147,6 +152,12 @@ public: void setMustSaveLR(bool U) { MustSaveLR = U; } bool mustSaveLR() const { return MustSaveLR; } + /// We certainly don't want to shrink wrap functions if we've emitted a + /// MovePCtoLR8 as that has to go into the entry, so the prologue definitely + /// has to go into the entry block. + void setShrinkWrapDisabled(bool U) { ShrinkWrapDisabled = U; } + bool shrinkWrapDisabled() const { return ShrinkWrapDisabled; } + void setHasSpills() { HasSpills = true; } bool hasSpills() const { return HasSpills; } @@ -185,11 +196,11 @@ public: LiveInAttrs.push_back(std::make_pair(VReg, Flags)); } - /// This function returns true if the spesified vreg is + /// This function returns true if the specified vreg is /// a live-in register and sign-extended. bool isLiveInSExt(unsigned VReg) const; - /// This function returns true if the spesified vreg is + /// This function returns true if the specified vreg is /// a live-in register and zero-extended. bool isLiveInZExt(unsigned VReg) const; diff --git a/lib/Target/PowerPC/PPCPreEmitPeephole.cpp b/lib/Target/PowerPC/PPCPreEmitPeephole.cpp index 9501f0f89b81..1892d1e3dc26 100644 --- a/lib/Target/PowerPC/PPCPreEmitPeephole.cpp +++ b/lib/Target/PowerPC/PPCPreEmitPeephole.cpp @@ -35,7 +35,7 @@ STATISTIC(NumRemovedInPreEmit, "Number of instructions deleted in pre-emit peephole"); static cl::opt<bool> -RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(false), +RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true), cl::desc("Run pre-emit peephole optimizations.")); namespace { @@ -67,8 +67,8 @@ namespace { if (TII->convertToImmediateForm(MI, &DefMIToErase)) { Changed = true; NumRRConvertedInPreEmit++; - DEBUG(dbgs() << "Converted instruction to imm form: "); - DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Converted instruction to imm form: "); + LLVM_DEBUG(MI.dump()); if (DefMIToErase) { InstrsToErase.push_back(DefMIToErase); } @@ -76,8 +76,8 @@ namespace { } } for (MachineInstr *MI : InstrsToErase) { - DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: "); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << "PPC pre-emit peephole: erasing instruction: "); + LLVM_DEBUG(MI->dump()); MI->eraseFromParent(); NumRemovedInPreEmit++; } diff --git a/lib/Target/PowerPC/PPCReduceCRLogicals.cpp b/lib/Target/PowerPC/PPCReduceCRLogicals.cpp index 5b2d7191683c..173fc18b9ebf 100644 --- a/lib/Target/PowerPC/PPCReduceCRLogicals.cpp +++ b/lib/Target/PowerPC/PPCReduceCRLogicals.cpp @@ -15,18 +15,21 @@ // //===---------------------------------------------------------------------===// -#include "PPCInstrInfo.h" #include "PPC.h" +#include "PPCInstrInfo.h" #include "PPCTargetMachine.h" -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Debug.h" -#include "llvm/ADT/Statistic.h" using namespace llvm; #define DEBUG_TYPE "ppc-reduce-cr-ops" -#include "PPCMachineBasicBlockUtils.h" STATISTIC(NumContainedSingleUseBinOps, "Number of single-use binary CR logical ops contained in a block"); @@ -50,7 +53,177 @@ namespace llvm { void initializePPCReduceCRLogicalsPass(PassRegistry&); } -namespace { +/// Given a basic block \p Successor that potentially contains PHIs, this +/// function will look for any incoming values in the PHIs that are supposed to +/// be coming from \p OrigMBB but whose definition is actually in \p NewMBB. +/// Any such PHIs will be updated to reflect reality. +static void updatePHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB, + MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI) { + for (auto &MI : Successor->instrs()) { + if (!MI.isPHI()) + continue; + // This is a really ugly-looking loop, but it was pillaged directly from + // MachineBasicBlock::transferSuccessorsAndUpdatePHIs(). + for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) { + MachineOperand &MO = MI.getOperand(i); + if (MO.getMBB() == OrigMBB) { + // Check if the instruction is actually defined in NewMBB. + if (MI.getOperand(i - 1).isReg()) { + MachineInstr *DefMI = MRI->getVRegDef(MI.getOperand(i - 1).getReg()); + if (DefMI->getParent() == NewMBB || + !OrigMBB->isSuccessor(Successor)) { + MO.setMBB(NewMBB); + break; + } + } + } + } + } +} + +/// Given a basic block \p Successor that potentially contains PHIs, this +/// function will look for PHIs that have an incoming value from \p OrigMBB +/// and will add the same incoming value from \p NewMBB. +/// NOTE: This should only be used if \p NewMBB is an immediate dominator of +/// \p OrigMBB. +static void addIncomingValuesToPHIs(MachineBasicBlock *Successor, + MachineBasicBlock *OrigMBB, + MachineBasicBlock *NewMBB, + MachineRegisterInfo *MRI) { + assert(OrigMBB->isSuccessor(NewMBB) && + "NewMBB must be a successor of OrigMBB"); + for (auto &MI : Successor->instrs()) { + if (!MI.isPHI()) + continue; + // This is a really ugly-looking loop, but it was pillaged directly from + // MachineBasicBlock::transferSuccessorsAndUpdatePHIs(). + for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) { + MachineOperand &MO = MI.getOperand(i); + if (MO.getMBB() == OrigMBB) { + MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI); + MIB.addReg(MI.getOperand(i - 1).getReg()).addMBB(NewMBB); + break; + } + } + } +} + +struct BlockSplitInfo { + MachineInstr *OrigBranch; + MachineInstr *SplitBefore; + MachineInstr *SplitCond; + bool InvertNewBranch; + bool InvertOrigBranch; + bool BranchToFallThrough; + const MachineBranchProbabilityInfo *MBPI; + MachineInstr *MIToDelete; + MachineInstr *NewCond; + bool allInstrsInSameMBB() { + if (!OrigBranch || !SplitBefore || !SplitCond) + return false; + MachineBasicBlock *MBB = OrigBranch->getParent(); + if (SplitBefore->getParent() != MBB || SplitCond->getParent() != MBB) + return false; + if (MIToDelete && MIToDelete->getParent() != MBB) + return false; + if (NewCond && NewCond->getParent() != MBB) + return false; + return true; + } +}; + +/// Splits a MachineBasicBlock to branch before \p SplitBefore. The original +/// branch is \p OrigBranch. The target of the new branch can either be the same +/// as the target of the original branch or the fallthrough successor of the +/// original block as determined by \p BranchToFallThrough. The branch +/// conditions will be inverted according to \p InvertNewBranch and +/// \p InvertOrigBranch. If an instruction that previously fed the branch is to +/// be deleted, it is provided in \p MIToDelete and \p NewCond will be used as +/// the branch condition. The branch probabilities will be set if the +/// MachineBranchProbabilityInfo isn't null. +static bool splitMBB(BlockSplitInfo &BSI) { + assert(BSI.allInstrsInSameMBB() && + "All instructions must be in the same block."); + + MachineBasicBlock *ThisMBB = BSI.OrigBranch->getParent(); + MachineFunction *MF = ThisMBB->getParent(); + MachineRegisterInfo *MRI = &MF->getRegInfo(); + assert(MRI->isSSA() && "Can only do this while the function is in SSA form."); + if (ThisMBB->succ_size() != 2) { + LLVM_DEBUG( + dbgs() << "Don't know how to handle blocks that don't have exactly" + << " two successors.\n"); + return false; + } + + const PPCInstrInfo *TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo(); + unsigned OrigBROpcode = BSI.OrigBranch->getOpcode(); + unsigned InvertedOpcode = + OrigBROpcode == PPC::BC + ? PPC::BCn + : OrigBROpcode == PPC::BCn + ? PPC::BC + : OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR; + unsigned NewBROpcode = BSI.InvertNewBranch ? InvertedOpcode : OrigBROpcode; + MachineBasicBlock *OrigTarget = BSI.OrigBranch->getOperand(1).getMBB(); + MachineBasicBlock *OrigFallThrough = OrigTarget == *ThisMBB->succ_begin() + ? *ThisMBB->succ_rbegin() + : *ThisMBB->succ_begin(); + MachineBasicBlock *NewBRTarget = + BSI.BranchToFallThrough ? OrigFallThrough : OrigTarget; + BranchProbability ProbToNewTarget = + !BSI.MBPI ? BranchProbability::getUnknown() + : BSI.MBPI->getEdgeProbability(ThisMBB, NewBRTarget); + + // Create a new basic block. + MachineBasicBlock::iterator InsertPoint = BSI.SplitBefore; + const BasicBlock *LLVM_BB = ThisMBB->getBasicBlock(); + MachineFunction::iterator It = ThisMBB->getIterator(); + MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MF->insert(++It, NewMBB); + + // Move everything after SplitBefore into the new block. + NewMBB->splice(NewMBB->end(), ThisMBB, InsertPoint, ThisMBB->end()); + NewMBB->transferSuccessors(ThisMBB); + + // Add the two successors to ThisMBB. The probabilities come from the + // existing blocks if available. + ThisMBB->addSuccessor(NewBRTarget, ProbToNewTarget); + ThisMBB->addSuccessor(NewMBB, ProbToNewTarget.getCompl()); + + // Add the branches to ThisMBB. + BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(), + TII->get(NewBROpcode)) + .addReg(BSI.SplitCond->getOperand(0).getReg()) + .addMBB(NewBRTarget); + BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(), + TII->get(PPC::B)) + .addMBB(NewMBB); + if (BSI.MIToDelete) + BSI.MIToDelete->eraseFromParent(); + + // Change the condition on the original branch and invert it if requested. + auto FirstTerminator = NewMBB->getFirstTerminator(); + if (BSI.NewCond) { + assert(FirstTerminator->getOperand(0).isReg() && + "Can't update condition of unconditional branch."); + FirstTerminator->getOperand(0).setReg(BSI.NewCond->getOperand(0).getReg()); + } + if (BSI.InvertOrigBranch) + FirstTerminator->setDesc(TII->get(InvertedOpcode)); + + // If any of the PHIs in the successors of NewMBB reference values that + // now come from NewMBB, they need to be updated. + for (auto *Succ : NewMBB->successors()) { + updatePHIs(Succ, ThisMBB, NewMBB, MRI); + } + addIncomingValuesToPHIs(NewBRTarget, ThisMBB, NewMBB, MRI); + + LLVM_DEBUG(dbgs() << "After splitting, ThisMBB:\n"; ThisMBB->dump()); + LLVM_DEBUG(dbgs() << "NewMBB:\n"; NewMBB->dump()); + LLVM_DEBUG(dbgs() << "New branch-to block:\n"; NewBRTarget->dump()); + return true; +} static bool isBinary(MachineInstr &MI) { return MI.getNumOperands() == 3; @@ -149,6 +322,8 @@ computeBranchTargetAndInversion(unsigned CROp, unsigned BROp, bool UsingDef1, llvm_unreachable("Don't know how to handle this branch."); } +namespace { + class PPCReduceCRLogicals : public MachineFunctionPass { public: @@ -317,7 +492,7 @@ PPCReduceCRLogicals::createCRLogicalOpInfo(MachineInstr &MIParam) { Ret.ContainedInBlock &= (MIParam.getParent() == Ret.TrueDefs.second->getParent()); } - DEBUG(Ret.dump()); + LLVM_DEBUG(Ret.dump()); if (Ret.IsBinary && Ret.ContainedInBlock && Ret.SingleUse) { NumContainedSingleUseBinOps++; if (Ret.FeedsBR && Ret.DefsSingleUse) @@ -326,7 +501,7 @@ PPCReduceCRLogicals::createCRLogicalOpInfo(MachineInstr &MIParam) { return Ret; } -/// Looks trhough a COPY instruction to the actual definition of the CR-bit +/// Looks through a COPY instruction to the actual definition of the CR-bit /// register and returns the instruction that defines it. /// FIXME: This currently handles what is by-far the most common case: /// an instruction that defines a CR field followed by a single copy of a bit @@ -411,14 +586,15 @@ bool PPCReduceCRLogicals::handleCROp(CRLogicalOpInfo &CRI) { /// BC %vr9<kill>, <BB#2>; CRBITRC:%vr9 bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) { if (CRI.CopyDefs.first == CRI.CopyDefs.second) { - DEBUG(dbgs() << "Unable to split as the two operands are the same\n"); + LLVM_DEBUG(dbgs() << "Unable to split as the two operands are the same\n"); NumNotSplitIdenticalOperands++; return false; } if (CRI.TrueDefs.first->isCopy() || CRI.TrueDefs.second->isCopy() || CRI.TrueDefs.first->isPHI() || CRI.TrueDefs.second->isPHI()) { - DEBUG(dbgs() << "Unable to split because one of the operands is a PHI or " - "chain of copies.\n"); + LLVM_DEBUG( + dbgs() << "Unable to split because one of the operands is a PHI or " + "chain of copies.\n"); NumNotSplitChainCopies++; return false; } @@ -429,11 +605,11 @@ bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) { CRI.MI->getOpcode() != PPC::CRNAND && CRI.MI->getOpcode() != PPC::CRORC && CRI.MI->getOpcode() != PPC::CRANDC) { - DEBUG(dbgs() << "Unable to split blocks on this opcode.\n"); + LLVM_DEBUG(dbgs() << "Unable to split blocks on this opcode.\n"); NumNotSplitWrongOpcode++; return false; } - DEBUG(dbgs() << "Splitting the following CR op:\n"; CRI.dump()); + LLVM_DEBUG(dbgs() << "Splitting the following CR op:\n"; CRI.dump()); MachineBasicBlock::iterator Def1It = CRI.TrueDefs.first; MachineBasicBlock::iterator Def2It = CRI.TrueDefs.second; @@ -447,9 +623,9 @@ bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) { } } - DEBUG(dbgs() << "We will split the following block:\n";); - DEBUG(CRI.MI->getParent()->dump()); - DEBUG(dbgs() << "Before instruction:\n"; SplitBefore->dump()); + LLVM_DEBUG(dbgs() << "We will split the following block:\n";); + LLVM_DEBUG(CRI.MI->getParent()->dump()); + LLVM_DEBUG(dbgs() << "Before instruction:\n"; SplitBefore->dump()); // Get the branch instruction. MachineInstr *Branch = @@ -482,10 +658,11 @@ bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) { TargetIsFallThrough); MachineInstr *SplitCond = UsingDef1 ? CRI.CopyDefs.second : CRI.CopyDefs.first; - DEBUG(dbgs() << "We will " << (InvertNewBranch ? "invert" : "copy")); - DEBUG(dbgs() << " the original branch and the target is the " << - (TargetIsFallThrough ? "fallthrough block\n" : "orig. target block\n")); - DEBUG(dbgs() << "Original branch instruction: "; Branch->dump()); + LLVM_DEBUG(dbgs() << "We will " << (InvertNewBranch ? "invert" : "copy")); + LLVM_DEBUG(dbgs() << " the original branch and the target is the " + << (TargetIsFallThrough ? "fallthrough block\n" + : "orig. target block\n")); + LLVM_DEBUG(dbgs() << "Original branch instruction: "; Branch->dump()); BlockSplitInfo BSI { Branch, SplitBefore, SplitCond, InvertNewBranch, InvertOrigBranch, TargetIsFallThrough, MBPI, CRI.MI, UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second }; @@ -522,7 +699,7 @@ void PPCReduceCRLogicals::collectCRLogicals() { } } -} // end annonymous namespace +} // end anonymous namespace INITIALIZE_PASS_BEGIN(PPCReduceCRLogicals, DEBUG_TYPE, "PowerPC Reduce CR logical Operation", false, false) diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 6b62a82ef7bf..6647ceace5eb 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -65,6 +65,12 @@ static cl::opt<bool> EnableGPRToVecSpills("ppc-enable-gpr-to-vsr-spills", cl::Hidden, cl::init(false), cl::desc("Enable spills from gpr to vsr rather than stack")); +static cl::opt<bool> +StackPtrConst("ppc-stack-ptr-caller-preserved", + cl::desc("Consider R1 caller preserved so stack saves of " + "caller preserved registers can be LICM candidates"), + cl::init(true), cl::Hidden); + PPCRegisterInfo::PPCRegisterInfo(const PPCTargetMachine &TM) : PPCGenRegisterInfo(TM.isPPC64() ? PPC::LR8 : PPC::LR, TM.isPPC64() ? 0 : 1, @@ -100,6 +106,12 @@ PPCRegisterInfo::PPCRegisterInfo(const PPCTargetMachine &TM) ImmToIdxMap[PPC::STXV] = PPC::STXVX; ImmToIdxMap[PPC::STXSD] = PPC::STXSDX; ImmToIdxMap[PPC::STXSSP] = PPC::STXSSPX; + + // SPE + ImmToIdxMap[PPC::EVLDD] = PPC::EVLDDX; + ImmToIdxMap[PPC::EVSTDD] = PPC::EVSTDDX; + ImmToIdxMap[PPC::SPESTW] = PPC::SPESTWX; + ImmToIdxMap[PPC::SPELWZ] = PPC::SPELWZX; } /// getPointerRegClass - Return the register class to use to hold pointers. @@ -141,9 +153,23 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { if (TM.isPPC64() && MF->getInfo<PPCFunctionInfo>()->isSplitCSR()) return CSR_SRV464_TLS_PE_SaveList; + if (Subtarget.hasSPE()) + return CSR_SVR432_SPE_SaveList; + // On PPC64, we might need to save r2 (but only if it is not reserved). bool SaveR2 = MF->getRegInfo().isAllocatable(PPC::X2); + if (MF->getFunction().getCallingConv() == CallingConv::Cold) { + return TM.isPPC64() + ? (Subtarget.hasAltivec() + ? (SaveR2 ? CSR_SVR64_ColdCC_R2_Altivec_SaveList + : CSR_SVR64_ColdCC_Altivec_SaveList) + : (SaveR2 ? CSR_SVR64_ColdCC_R2_SaveList + : CSR_SVR64_ColdCC_SaveList)) + : (Subtarget.hasAltivec() ? CSR_SVR32_ColdCC_Altivec_SaveList + : CSR_SVR32_ColdCC_SaveList); + } + return TM.isPPC64() ? (Subtarget.hasAltivec() ? (SaveR2 ? CSR_SVR464_R2_Altivec_SaveList @@ -196,6 +222,13 @@ PPCRegisterInfo::getCallPreservedMask(const MachineFunction &MF, : (Subtarget.hasAltivec() ? CSR_Darwin32_Altivec_RegMask : CSR_Darwin32_RegMask); + if (CC == CallingConv::Cold) { + return TM.isPPC64() ? (Subtarget.hasAltivec() ? CSR_SVR64_ColdCC_Altivec_RegMask + : CSR_SVR64_ColdCC_RegMask) + : (Subtarget.hasAltivec() ? CSR_SVR32_ColdCC_Altivec_RegMask + : CSR_SVR32_ColdCC_RegMask); + } + return TM.isPPC64() ? (Subtarget.hasAltivec() ? CSR_SVR464_Altivec_RegMask : CSR_SVR464_RegMask) : (Subtarget.hasAltivec() ? CSR_SVR432_Altivec_RegMask @@ -286,15 +319,26 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { bool PPCRegisterInfo::isCallerPreservedPhysReg(unsigned PhysReg, const MachineFunction &MF) const { assert(TargetRegisterInfo::isPhysicalRegister(PhysReg)); - if (TM.isELFv2ABI() && PhysReg == PPC::X2) { + const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>(); + const MachineFrameInfo &MFI = MF.getFrameInfo(); + if (!TM.isPPC64()) + return false; + + if (!Subtarget.isSVR4ABI()) + return false; + if (PhysReg == PPC::X2) // X2 is guaranteed to be preserved within a function if it is reserved. // The reason it's reserved is that it's the TOC pointer (and the function // uses the TOC). In functions where it isn't reserved (i.e. leaf functions // with no TOC access), we can't claim that it is preserved. return (getReservedRegs(MF).test(PPC::X2)); - } else { - return false; - } + if (StackPtrConst && (PhysReg == PPC::X1) && !MFI.hasVarSizedObjects() + && !MFI.hasOpaqueSPAdjustment()) + // The value of the stack pointer does not change within a function after + // the prologue and before the epilogue if there are no dynamic allocations + // and no inline asm which clobbers X1. + return true; + return false; } unsigned PPCRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, @@ -307,6 +351,8 @@ unsigned PPCRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, return 0; case PPC::G8RC_NOX0RegClassID: case PPC::GPRC_NOR0RegClassID: + case PPC::SPERCRegClassID: + case PPC::SPE4RCRegClassID: case PPC::G8RCRegClassID: case PPC::GPRCRegClassID: { unsigned FP = TFI->hasFP(MF) ? 1 : 0; diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h index 0bbb71fdf9fb..91a98ee4efc7 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/lib/Target/PowerPC/PPCRegisterInfo.h @@ -85,6 +85,8 @@ public: BitVector getReservedRegs(const MachineFunction &MF) const override; bool isCallerPreservedPhysReg(unsigned PhysReg, const MachineFunction &MF) const override; + bool enableMultipleCopyHints() const override { return true; } + /// We require the register scavenger. bool requiresRegisterScavenging(const MachineFunction &MF) const override { return true; diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td b/lib/Target/PowerPC/PPCRegisterInfo.td index f7807907bd64..0e641cf9e00a 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/lib/Target/PowerPC/PPCRegisterInfo.td @@ -38,6 +38,13 @@ class GP8<GPR SubReg, string n> : PPCReg<n> { let SubRegIndices = [sub_32]; } +// SPE - One of the 32 64-bit general-purpose registers (SPE) +class SPE<GPR SubReg, string n> : PPCReg<n> { + let HWEncoding = SubReg.HWEncoding; + let SubRegs = [SubReg]; + let SubRegIndices = [sub_32]; +} + // SPR - One of the 32-bit special-purpose registers class SPR<bits<10> num, string n> : PPCReg<n> { let HWEncoding{9-0} = num; @@ -100,6 +107,12 @@ foreach Index = 0-31 in { DwarfRegNum<[Index, -2]>; } +// SPE registers +foreach Index = 0-31 in { + def S#Index : SPE<!cast<GPR>("R"#Index), "r"#Index>, + DwarfRegNum<[!add(Index, 1200), !add(Index, 1200)]>; +} + // Floating-point registers foreach Index = 0-31 in { def F#Index : FPR<Index, "f"#Index>, @@ -208,10 +221,20 @@ def CTR8 : SPR<9, "ctr">, DwarfRegNum<[66, -2]>; // VRsave register def VRSAVE: SPR<256, "vrsave">, DwarfRegNum<[109]>; +// SPE extra registers +// SPE Accumulator for multiply-accumulate SPE operations. Never directly +// accessed, so there's no real encoding for it. +def SPEACC: DwarfRegNum<[99, 111]>; +def SPEFSCR: SPR<512, "spefscr">, DwarfRegNum<[612, 112]>; + +def XER: SPR<1, "xer">, DwarfRegNum<[76]>; + // Carry bit. In the architecture this is really bit 0 of the XER register // (which really is SPR register 1); this is the only bit interesting to a // compiler. -def CARRY: SPR<1, "ca">, DwarfRegNum<[76]>; +def CARRY: SPR<1, "xer">, DwarfRegNum<[76]> { + let Aliases = [XER]; +} // FP rounding mode: bits 30 and 31 of the FP status and control register // This is not allocated as a normal register; it appears only in @@ -272,6 +295,12 @@ def G8RC_NOX0 : RegisterClass<"PPC", [i64], 64, (add (sub G8RC, X0), ZERO8)> { }]; } +def SPERC : RegisterClass<"PPC", [f64], 64, (add (sequence "S%u", 2, 12), + (sequence "S%u", 30, 13), + S31, S0, S1)>; + +def SPE4RC : RegisterClass<"PPC", [f32], 32, (add GPRC)>; + // Allocate volatiles first, then non-volatiles in reverse order. With the SVR4 // ABI the size of the Floating-point register save area is determined by the // allocated non-volatile register with the lowest register number, as FP @@ -283,7 +312,9 @@ def F8RC : RegisterClass<"PPC", [f64], 64, (add (sequence "F%u", 0, 13), (sequence "F%u", 31, 14))>; def F4RC : RegisterClass<"PPC", [f32], 32, (add F8RC)>; -def VRRC : RegisterClass<"PPC", [v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64], 128, +def VRRC : RegisterClass<"PPC", + [v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f128], + 128, (add V2, V3, V4, V5, V0, V1, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V31, V30, V29, V28, V27, V26, V25, V24, V23, V22, V21, V20)>; @@ -351,7 +382,7 @@ def CTRRC8 : RegisterClass<"PPC", [i64], 64, (add CTR8)> { } def VRSAVERC : RegisterClass<"PPC", [i32], 32, (add VRSAVE)>; -def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY)> { +def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY, XER)> { let CopyCost = -1; } diff --git a/lib/Target/PowerPC/PPCSchedule.td b/lib/Target/PowerPC/PPCSchedule.td index d240529bc731..5ad0a517c117 100644 --- a/lib/Target/PowerPC/PPCSchedule.td +++ b/lib/Target/PowerPC/PPCSchedule.td @@ -87,6 +87,8 @@ def IIC_SprMTSRIN : InstrItinClass; def IIC_SprRFI : InstrItinClass; def IIC_SprSC : InstrItinClass; def IIC_FPGeneral : InstrItinClass; +def IIC_FPDGeneral : InstrItinClass; +def IIC_FPSGeneral : InstrItinClass; def IIC_FPAddSub : InstrItinClass; def IIC_FPCompare : InstrItinClass; def IIC_FPDivD : InstrItinClass; @@ -133,5 +135,6 @@ include "PPCScheduleP7.td" include "PPCScheduleP8.td" include "PPCScheduleP9.td" include "PPCScheduleA2.td" +include "PPCScheduleE500.td" include "PPCScheduleE500mc.td" include "PPCScheduleE5500.td" diff --git a/lib/Target/PowerPC/PPCScheduleE500.td b/lib/Target/PowerPC/PPCScheduleE500.td new file mode 100644 index 000000000000..d7c2bd15a258 --- /dev/null +++ b/lib/Target/PowerPC/PPCScheduleE500.td @@ -0,0 +1,274 @@ +//===-- PPCScheduleE500.td - e500 Scheduling Defs ------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the itinerary class data for the Freescale e500 32-bit +// Power processor. +// +// All information is derived from the "e500 Core Reference Manual", +// Freescale Document Number E500MCRM, Rev. 1, 03/2012. +// +//===----------------------------------------------------------------------===// +// Relevant functional units in the Freescale e500 core: +// +// * Decode & Dispatch +// Can dispatch up to 2 instructions per clock cycle to either the GPR Issue +// queues (GIQx) or Branch issue queue (BIQ). +def E500_DIS0 : FuncUnit; // Dispatch stage - insn 1 +def E500_DIS1 : FuncUnit; // Dispatch stage - insn 2 + +// * Execute +// 6 pipelined execution units: SU0, SU1, BU, LSU, MU. +// Some instructions can only execute in SU0 but not SU1. +def E500_SU0 : FuncUnit; // Simple unit 0 +def E500_SU1 : FuncUnit; // Simple unit 1 +def E500_BU : FuncUnit; // Branch unit +def E500_MU : FuncUnit; // MU pipeline +def E500_LSU_0 : FuncUnit; // LSU pipeline + +def E500_GPR_Bypass : Bypass; +def E500_CR_Bypass : Bypass; +def E500_DivBypass : Bypass; + +def PPCE500Itineraries : ProcessorItineraries< + [E500_DIS0, E500_DIS1, E500_SU0, E500_SU1, E500_BU, + E500_MU, E500_LSU_0], + [E500_CR_Bypass, E500_GPR_Bypass, E500_DivBypass], [ + InstrItinData<IIC_IntSimple, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1, 1], // Latency = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntGeneral, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1, 1], // Latency = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntISEL, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1, 1, 1], // Latency = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass, + E500_CR_Bypass]>, + InstrItinData<IIC_IntCompare, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [5, 1, 1], // Latency = 1 or 2 + [E500_CR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntDivW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_MU], 0>, + InstrStage<14, [E500_MU]>], + [17, 1, 1], // Latency=4..35, Repeat= 4..35 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntMulHW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_MU]>], + [7, 1, 1], // Latency = 4, Repeat rate = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntMulHWU, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_MU]>], + [7, 1, 1], // Latency = 4, Repeat rate = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntMulLI, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_MU]>], + [7, 1, 1], // Latency = 4, Repeat rate = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntRotate, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1, 1], // Latency = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntShift, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1, 1], // Latency = 1 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_IntTrapW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<2, [E500_SU0]>], + [5, 1], // Latency = 2, Repeat rate = 2 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_BrB, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_BU]>], + [4, 1], // Latency = 1 + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_BrCR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_BU]>], + [4, 1, 1], // Latency = 1 + [E500_CR_Bypass, + E500_CR_Bypass, E500_CR_Bypass]>, + InstrItinData<IIC_BrMCR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_BU]>], + [4, 1], // Latency = 1 + [E500_CR_Bypass, E500_CR_Bypass]>, + InstrItinData<IIC_BrMCRX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1, 1], // Latency = 1 + [E500_CR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStDCBA, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3, Repeat rate = 1 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStDCBF, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStDCBI, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStLoad, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStLoadUpd, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass], + 2>, // 2 micro-ops + InstrItinData<IIC_LdStLoadUpdX,[InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass], + 2>, // 2 micro-ops + InstrItinData<IIC_LdStStore, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStStoreUpd,[InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [NoBypass, E500_GPR_Bypass], + 2>, // 2 micro-ops + InstrItinData<IIC_LdStICBI, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStLHA, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStLHAU, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStLHAUX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStLMW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [7, 1], // Latency = r+3 + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStLWARX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<3, [E500_LSU_0]>], + [6, 1, 1], // Latency = 3, Repeat rate = 3 + [E500_GPR_Bypass, + E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStSTWCX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>], + [6, 1], // Latency = 3 + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_LdStSync, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0]>]>, + InstrItinData<IIC_SprMFSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_SU0]>], + [7, 1], + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprMTMSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<2, [E500_SU0, E500_SU1]>], + [5, 1], // Latency = 2, Repeat rate = 4 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprMTSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0]>], + [5, 1], + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprTLBSYNC, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_LSU_0], 0>]>, + InstrItinData<IIC_SprMFCR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<5, [E500_SU0]>], + [8, 1], + [E500_GPR_Bypass, E500_CR_Bypass]>, + InstrItinData<IIC_SprMFCRF, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<5, [E500_SU0]>], + [8, 1], + [E500_GPR_Bypass, E500_CR_Bypass]>, + InstrItinData<IIC_SprMFPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_SU0]>], + [7, 1], // Latency = 4, Repeat rate = 4 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprMFMSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_SU0]>], + [7, 1], // Latency = 4, Repeat rate = 4 + [E500_GPR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprMFSPR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1], // Latency = 1, Repeat rate = 1 + [E500_GPR_Bypass, E500_CR_Bypass]>, + InstrItinData<IIC_SprMTPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0]>], + [4, 1], // Latency = 1, Repeat rate = 1 + [E500_CR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprMFTB, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_SU0]>], + [7, 1], // Latency = 4, Repeat rate = 4 + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprMTSPR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0, E500_SU1]>], + [4, 1], // Latency = 1, Repeat rate = 1 + [E500_CR_Bypass, E500_GPR_Bypass]>, + InstrItinData<IIC_SprMTSRIN, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0]>], + [4, 1], + [NoBypass, E500_GPR_Bypass]>, + InstrItinData<IIC_FPDGeneral, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<6, [E500_MU]>], + [9, 1, 1], // Latency = 6, Repeat rate = 1 + [NoBypass]>, + InstrItinData<IIC_FPSGeneral, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_MU]>], + [7, 1, 1], // Latency = 4, Repeat rate = 1 + [NoBypass]>, + InstrItinData<IIC_FPDivD, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<32, [E500_MU]>], + [35, 1, 1], // Latency = 32, Repeat rate = 32 + [E500_DivBypass]>, + InstrItinData<IIC_FPDivS, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<29, [E500_MU]>], + [32, 1, 1], // Latency = 29, Repeat rate = 29 + [E500_DivBypass]>, + InstrItinData<IIC_VecGeneral, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<1, [E500_SU0]>], + [4, 1, 1], // Latency = 1, Repeat rate = 1 + [NoBypass]>, + InstrItinData<IIC_VecComplex, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, + InstrStage<4, [E500_MU]>], + [7, 1, 1], // Latency = 4, Repeat rate = 1 + [NoBypass]> +]>; + +// ===---------------------------------------------------------------------===// +// e500 machine model for scheduling and other instruction cost heuristics. + +def PPCE500Model : SchedMachineModel { + let IssueWidth = 2; // 2 micro-ops are dispatched per cycle. + let LoadLatency = 5; // Optimistic load latency assuming bypass. + // This is overriden by OperandCycles if the + // Itineraries are queried instead. + + let CompleteModel = 0; + + let Itineraries = PPCE500Itineraries; +} diff --git a/lib/Target/PowerPC/PPCScheduleE500mc.td b/lib/Target/PowerPC/PPCScheduleE500mc.td index 15d5991b938c..5f95f2a79f66 100644 --- a/lib/Target/PowerPC/PPCScheduleE500mc.td +++ b/lib/Target/PowerPC/PPCScheduleE500mc.td @@ -19,299 +19,299 @@ // * Decode & Dispatch // Can dispatch up to 2 instructions per clock cycle to either the GPR Issue // queues (GIQx), FP Issue Queue (FIQ), or Branch issue queue (BIQ). -def E500_DIS0 : FuncUnit; // Dispatch stage - insn 1 -def E500_DIS1 : FuncUnit; // Dispatch stage - insn 2 +def E500mc_DIS0 : FuncUnit; // Dispatch stage - insn 1 +def E500mc_DIS1 : FuncUnit; // Dispatch stage - insn 2 // * Execute // 6 pipelined execution units: SFX0, SFX1, BU, FPU, LSU, CFX. // Some instructions can only execute in SFX0 but not SFX1. // The CFX has a bypass path, allowing non-divide instructions to execute // while a divide instruction is executed. -def E500_SFX0 : FuncUnit; // Simple unit 0 -def E500_SFX1 : FuncUnit; // Simple unit 1 -def E500_BU : FuncUnit; // Branch unit -def E500_CFX_DivBypass +def E500mc_SFX0 : FuncUnit; // Simple unit 0 +def E500mc_SFX1 : FuncUnit; // Simple unit 1 +def E500mc_BU : FuncUnit; // Branch unit +def E500mc_CFX_DivBypass : FuncUnit; // CFX divide bypass path -def E500_CFX_0 : FuncUnit; // CFX pipeline -def E500_LSU_0 : FuncUnit; // LSU pipeline -def E500_FPU_0 : FuncUnit; // FPU pipeline +def E500mc_CFX_0 : FuncUnit; // CFX pipeline +def E500mc_LSU_0 : FuncUnit; // LSU pipeline +def E500mc_FPU_0 : FuncUnit; // FPU pipeline -def E500_GPR_Bypass : Bypass; -def E500_FPR_Bypass : Bypass; -def E500_CR_Bypass : Bypass; +def E500mc_GPR_Bypass : Bypass; +def E500mc_FPR_Bypass : Bypass; +def E500mc_CR_Bypass : Bypass; def PPCE500mcItineraries : ProcessorItineraries< - [E500_DIS0, E500_DIS1, E500_SFX0, E500_SFX1, E500_BU, E500_CFX_DivBypass, - E500_CFX_0, E500_LSU_0, E500_FPU_0], - [E500_CR_Bypass, E500_GPR_Bypass, E500_FPR_Bypass], [ - InstrItinData<IIC_IntSimple, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_DIS0, E500mc_DIS1, E500mc_SFX0, E500mc_SFX1, E500mc_BU, E500mc_CFX_DivBypass, + E500mc_CFX_0, E500mc_LSU_0, E500mc_FPU_0], + [E500mc_CR_Bypass, E500mc_GPR_Bypass, E500mc_FPR_Bypass], [ + InstrItinData<IIC_IntSimple, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1, 1], // Latency = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntGeneral, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntGeneral, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1, 1], // Latency = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntISEL, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntISEL, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1, 1, 1], // Latency = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass, - E500_CR_Bypass]>, - InstrItinData<IIC_IntCompare, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass, + E500mc_CR_Bypass]>, + InstrItinData<IIC_IntCompare, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [5, 1, 1], // Latency = 1 or 2 - [E500_CR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntDivW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_CFX_0], 0>, - InstrStage<14, [E500_CFX_DivBypass]>], + [E500mc_CR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntDivW, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_CFX_0], 0>, + InstrStage<14, [E500mc_CFX_DivBypass]>], [17, 1, 1], // Latency=4..35, Repeat= 4..35 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntMFFS, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<8, [E500_FPU_0]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntMFFS, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<8, [E500mc_FPU_0]>], [11], // Latency = 8 - [E500_FPR_Bypass]>, - InstrItinData<IIC_IntMTFSB0, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<8, [E500_FPU_0]>], + [E500mc_FPR_Bypass]>, + InstrItinData<IIC_IntMTFSB0, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<8, [E500mc_FPU_0]>], [11, 1, 1], // Latency = 8 [NoBypass, NoBypass, NoBypass]>, - InstrItinData<IIC_IntMulHW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_CFX_0]>], + InstrItinData<IIC_IntMulHW, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_CFX_0]>], [7, 1, 1], // Latency = 4, Repeat rate = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntMulHWU, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_CFX_0]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntMulHWU, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_CFX_0]>], [7, 1, 1], // Latency = 4, Repeat rate = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntMulLI, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_CFX_0]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntMulLI, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_CFX_0]>], [7, 1, 1], // Latency = 4, Repeat rate = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntRotate, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntRotate, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1, 1], // Latency = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntShift, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntShift, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1, 1], // Latency = 1 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_IntTrapW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<2, [E500_SFX0]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_IntTrapW, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<2, [E500mc_SFX0]>], [5, 1], // Latency = 2, Repeat rate = 2 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_BrB, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_BU]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_BrB, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_BU]>], [4, 1], // Latency = 1 - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_BrCR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_BU]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_BrCR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_BU]>], [4, 1, 1], // Latency = 1 - [E500_CR_Bypass, - E500_CR_Bypass, E500_CR_Bypass]>, - InstrItinData<IIC_BrMCR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_BU]>], + [E500mc_CR_Bypass, + E500mc_CR_Bypass, E500mc_CR_Bypass]>, + InstrItinData<IIC_BrMCR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_BU]>], [4, 1], // Latency = 1 - [E500_CR_Bypass, E500_CR_Bypass]>, - InstrItinData<IIC_BrMCRX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_CR_Bypass, E500mc_CR_Bypass]>, + InstrItinData<IIC_BrMCRX, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1, 1], // Latency = 1 - [E500_CR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStDCBA, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_CR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStDCBA, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3, Repeat rate = 1 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStDCBF, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStDCBF, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStDCBI, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStDCBI, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStLoad, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStLoad, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStLoadUpd, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStLoadUpd, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass], 2>, // 2 micro-ops - InstrItinData<IIC_LdStLoadUpdX,[InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + InstrItinData<IIC_LdStLoadUpdX,[InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass], 2>, // 2 micro-ops - InstrItinData<IIC_LdStStore, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + InstrItinData<IIC_LdStStore, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStStoreUpd,[InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStStoreUpd,[InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [NoBypass, E500_GPR_Bypass], + [NoBypass, E500mc_GPR_Bypass], 2>, // 2 micro-ops - InstrItinData<IIC_LdStICBI, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + InstrItinData<IIC_LdStICBI, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStSTFD, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStSTFD, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1, 1], // Latency = 3 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStSTFDU, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStSTFDU, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1, 1], // Latency = 3 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass], 2>, // 2 micro-ops - InstrItinData<IIC_LdStLFD, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + InstrItinData<IIC_LdStLFD, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [7, 1, 1], // Latency = 4 - [E500_FPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStLFDU, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_FPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStLFDU, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [7, 1, 1], // Latency = 4 - [E500_FPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass], + [E500mc_FPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass], 2>, // 2 micro-ops - InstrItinData<IIC_LdStLFDUX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + InstrItinData<IIC_LdStLFDUX, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [7, 1, 1], // Latency = 4 - [E500_FPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass], + [E500mc_FPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass], 2>, // 2 micro-ops - InstrItinData<IIC_LdStLHA, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + InstrItinData<IIC_LdStLHA, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStLHAU, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStLHAU, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStLHAUX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStLHAUX, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStLMW, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStLMW, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [7, 1], // Latency = r+3 - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStLWARX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<3, [E500_LSU_0]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStLWARX, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<3, [E500mc_LSU_0]>], [6, 1, 1], // Latency = 3, Repeat rate = 3 - [E500_GPR_Bypass, - E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStSTWCX, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>], + [E500mc_GPR_Bypass, + E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStSTWCX, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>], [6, 1], // Latency = 3 - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_LdStSync, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0]>]>, - InstrItinData<IIC_SprMFSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<4, [E500_SFX0]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_LdStSync, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0]>]>, + InstrItinData<IIC_SprMFSR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<4, [E500mc_SFX0]>], [7, 1], - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprMTMSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<2, [E500_SFX0, E500_SFX1]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprMTMSR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<2, [E500mc_SFX0, E500mc_SFX1]>], [5, 1], // Latency = 2, Repeat rate = 4 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprMTSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprMTSR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0]>], [5, 1], - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprTLBSYNC, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_LSU_0], 0>]>, - InstrItinData<IIC_SprMFCR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<5, [E500_SFX0]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprTLBSYNC, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_LSU_0], 0>]>, + InstrItinData<IIC_SprMFCR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<5, [E500mc_SFX0]>], [8, 1], - [E500_GPR_Bypass, E500_CR_Bypass]>, - InstrItinData<IIC_SprMFCRF, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<5, [E500_SFX0]>], + [E500mc_GPR_Bypass, E500mc_CR_Bypass]>, + InstrItinData<IIC_SprMFCRF, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<5, [E500mc_SFX0]>], [8, 1], - [E500_GPR_Bypass, E500_CR_Bypass]>, - InstrItinData<IIC_SprMFPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<4, [E500_SFX0]>], + [E500mc_GPR_Bypass, E500mc_CR_Bypass]>, + InstrItinData<IIC_SprMFPMR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<4, [E500mc_SFX0]>], [7, 1], // Latency = 4, Repeat rate = 4 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprMFMSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<4, [E500_SFX0]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprMFMSR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<4, [E500mc_SFX0]>], [7, 1], // Latency = 4, Repeat rate = 4 - [E500_GPR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprMFSPR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [E500mc_GPR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprMFSPR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1], // Latency = 1, Repeat rate = 1 - [E500_GPR_Bypass, E500_CR_Bypass]>, - InstrItinData<IIC_SprMTPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0]>], + [E500mc_GPR_Bypass, E500mc_CR_Bypass]>, + InstrItinData<IIC_SprMTPMR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0]>], [4, 1], // Latency = 1, Repeat rate = 1 - [E500_CR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprMFTB, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<4, [E500_SFX0]>], + [E500mc_CR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprMFTB, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<4, [E500mc_SFX0]>], [7, 1], // Latency = 4, Repeat rate = 4 - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprMTSPR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0, E500_SFX1]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprMTSPR, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0, E500mc_SFX1]>], [4, 1], // Latency = 1, Repeat rate = 1 - [E500_CR_Bypass, E500_GPR_Bypass]>, - InstrItinData<IIC_SprMTSRIN, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<1, [E500_SFX0]>], + [E500mc_CR_Bypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_SprMTSRIN, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<1, [E500mc_SFX0]>], [4, 1], - [NoBypass, E500_GPR_Bypass]>, - InstrItinData<IIC_FPGeneral, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<2, [E500_FPU_0]>], + [NoBypass, E500mc_GPR_Bypass]>, + InstrItinData<IIC_FPGeneral, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<2, [E500mc_FPU_0]>], [11, 1, 1], // Latency = 8, Repeat rate = 2 - [E500_FPR_Bypass, - E500_FPR_Bypass, E500_FPR_Bypass]>, - InstrItinData<IIC_FPAddSub, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<4, [E500_FPU_0]>], + [E500mc_FPR_Bypass, + E500mc_FPR_Bypass, E500mc_FPR_Bypass]>, + InstrItinData<IIC_FPAddSub, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<4, [E500mc_FPU_0]>], [13, 1, 1], // Latency = 10, Repeat rate = 4 - [E500_FPR_Bypass, - E500_FPR_Bypass, E500_FPR_Bypass]>, - InstrItinData<IIC_FPCompare, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<2, [E500_FPU_0]>], + [E500mc_FPR_Bypass, + E500mc_FPR_Bypass, E500mc_FPR_Bypass]>, + InstrItinData<IIC_FPCompare, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<2, [E500mc_FPU_0]>], [11, 1, 1], // Latency = 8, Repeat rate = 2 - [E500_CR_Bypass, - E500_FPR_Bypass, E500_FPR_Bypass]>, - InstrItinData<IIC_FPDivD, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<68, [E500_FPU_0]>], + [E500mc_CR_Bypass, + E500mc_FPR_Bypass, E500mc_FPR_Bypass]>, + InstrItinData<IIC_FPDivD, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<68, [E500mc_FPU_0]>], [71, 1, 1], // Latency = 68, Repeat rate = 68 - [E500_FPR_Bypass, - E500_FPR_Bypass, E500_FPR_Bypass]>, - InstrItinData<IIC_FPDivS, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<38, [E500_FPU_0]>], + [E500mc_FPR_Bypass, + E500mc_FPR_Bypass, E500mc_FPR_Bypass]>, + InstrItinData<IIC_FPDivS, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<38, [E500mc_FPU_0]>], [41, 1, 1], // Latency = 38, Repeat rate = 38 - [E500_FPR_Bypass, - E500_FPR_Bypass, E500_FPR_Bypass]>, - InstrItinData<IIC_FPFused, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<4, [E500_FPU_0]>], + [E500mc_FPR_Bypass, + E500mc_FPR_Bypass, E500mc_FPR_Bypass]>, + InstrItinData<IIC_FPFused, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<4, [E500mc_FPU_0]>], [13, 1, 1, 1], // Latency = 10, Repeat rate = 4 - [E500_FPR_Bypass, - E500_FPR_Bypass, E500_FPR_Bypass, - E500_FPR_Bypass]>, - InstrItinData<IIC_FPRes, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>, - InstrStage<38, [E500_FPU_0]>], + [E500mc_FPR_Bypass, + E500mc_FPR_Bypass, E500mc_FPR_Bypass, + E500mc_FPR_Bypass]>, + InstrItinData<IIC_FPRes, [InstrStage<1, [E500mc_DIS0, E500mc_DIS1], 0>, + InstrStage<38, [E500mc_FPU_0]>], [41, 1], // Latency = 38, Repeat rate = 38 - [E500_FPR_Bypass, E500_FPR_Bypass]> + [E500mc_FPR_Bypass, E500mc_FPR_Bypass]> ]>; // ===---------------------------------------------------------------------===// diff --git a/lib/Target/PowerPC/PPCScheduleP9.td b/lib/Target/PowerPC/PPCScheduleP9.td index b24f4fc603a1..e1a480117315 100644 --- a/lib/Target/PowerPC/PPCScheduleP9.td +++ b/lib/Target/PowerPC/PPCScheduleP9.td @@ -13,18 +13,31 @@ include "PPCInstrInfo.td" def P9Model : SchedMachineModel { + // The maximum number of instructions to be issued at the same time. + // While a value of 8 is technically correct since 8 instructions can be + // fetched from the instruction cache. However, only 6 instructions may be + // actually dispatched at a time. let IssueWidth = 8; + // Load latency is 4 or 5 cycles depending on the load. This latency assumes + // that we have a cache hit. For a cache miss the load latency will be more. + // There are two instructions (lxvl, lxvll) that have a latencty of 6 cycles. + // However it is not worth bumping this value up to 6 when the vast majority + // of instructions are 4 or 5 cycles. let LoadLatency = 5; + // A total of 16 cycles to recover from a branch mispredict. let MispredictPenalty = 16; // Try to make sure we have at least 10 dispatch groups in a loop. + // A dispatch group is 6 instructions. let LoopMicroOpBufferSize = 60; let CompleteModel = 1; - let UnsupportedFeatures = [HasQPX]; + // Do not support QPX (Quad Processing eXtension) or SPE (Signal Procesing + // Engine) on Power 9. + let UnsupportedFeatures = [HasQPX, HasSPE]; } @@ -36,6 +49,12 @@ let SchedModel = P9Model in { def DISPATCHER : ProcResource<12>; // Issue Ports + // An instruction can go down one of two issue queues. + // Address Generation (AGEN) mainly for loads and stores. + // Execution (EXEC) for most other instructions. + // Some instructions cannot be run on just any issue queue and may require an + // Even or an Odd queue. The EXECE represents the even queues and the EXECO + // represents the odd queues. def IP_AGEN : ProcResource<4>; def IP_EXEC : ProcResource<4>; def IP_EXECE : ProcResource<2> { @@ -48,6 +67,7 @@ let SchedModel = P9Model in { } // Pipeline Groups + // Four ALU (Fixed Point Arithmetic) units in total. Two even, two Odd. def ALU : ProcResource<4>; def ALUE : ProcResource<2> { //Even ALU pipelines @@ -57,7 +77,11 @@ let SchedModel = P9Model in { //Odd ALU pipelines let Super = ALU; } + + // Two DIV (Fixed Point Divide) units. def DIV : ProcResource<2>; + + // Four DP (Floating Point) units in total. Two even, two Odd. def DP : ProcResource<4>; def DPE : ProcResource<2> { //Even DP pipelines @@ -67,15 +91,23 @@ let SchedModel = P9Model in { //Odd DP pipelines let Super = DP; } + + // Four LS (Load or Store) units. def LS : ProcResource<4>; + + // Two PM (Permute) units. def PM : ProcResource<2>; + + // Only one DFU (Decimal Floating Point and Quad Precision) unit. def DFU : ProcResource<1>; + + // Only one Branch unit. def BR : ProcResource<1> { let BufferSize = 16; } - def CY : ProcResource<1>; - def TestGroup : ProcResGroup<[ALU, DP]>; + // Only one CY (Crypto) unit. + def CY : ProcResource<1>; // ***************** SchedWriteRes Definitions ***************** @@ -107,6 +139,11 @@ let SchedModel = P9Model in { } //Pipeline Groups + + // ALU Units + // An ALU may take either 2 or 3 cycles to complete the operation. + // However, the ALU unit is only every busy for 1 cycle at a time and may + // receive new instructions each cycle. def P9_ALU_2C : SchedWriteRes<[ALU]> { let Latency = 2; } @@ -131,26 +168,13 @@ let SchedModel = P9Model in { let Latency = 3; } - def P9_ALU_4C : SchedWriteRes<[ALU]> { - let Latency = 4; - } - - def P9_ALUE_4C : SchedWriteRes<[ALUE]> { - let Latency = 4; - } - - def P9_ALUO_4C : SchedWriteRes<[ALUO]> { - let Latency = 4; - } - - def P9_ALU_5C : SchedWriteRes<[ALU]> { + // DIV Unit + // A DIV unit may take from 5 to 40 cycles to complete. + // Some DIV operations may keep the unit busy for up to 8 cycles. + def P9_DIV_5C : SchedWriteRes<[DIV]> { let Latency = 5; } - def P9_ALU_6C : SchedWriteRes<[ALU]> { - let Latency = 6; - } - def P9_DIV_12C : SchedWriteRes<[DIV]> { let Latency = 12; } @@ -170,6 +194,9 @@ let SchedModel = P9Model in { let Latency = 40; } + // DP Unit + // A DP unit may take from 2 to 36 cycles to complete. + // Some DP operations keep the unit busy for up to 10 cycles. def P9_DP_2C : SchedWriteRes<[DP]> { let Latency = 2; } @@ -220,6 +247,16 @@ let SchedModel = P9Model in { let Latency = 27; } + def P9_DPE_27C_10 : SchedWriteRes<[DP]> { + let ResourceCycles = [10]; + let Latency = 27; + } + + def P9_DPO_27C_10 : SchedWriteRes<[DP]> { + let ResourceCycles = [10]; + let Latency = 27; + } + def P9_DP_33C_8 : SchedWriteRes<[DP]> { let ResourceCycles = [8]; let Latency = 33; @@ -240,14 +277,28 @@ let SchedModel = P9Model in { let Latency = 36; } - def P9_PM_3C : SchedWriteRes<[PM]> { - let Latency = 3; + def P9_DPE_36C_10 : SchedWriteRes<[DP]> { + let ResourceCycles = [10]; + let Latency = 36; } - def P9_PM_7C : SchedWriteRes<[PM]> { + def P9_DPO_36C_10 : SchedWriteRes<[DP]> { + let ResourceCycles = [10]; + let Latency = 36; + } + + // PM Unit + // Three cycle permute operations. + def P9_PM_3C : SchedWriteRes<[PM]> { let Latency = 3; } + // Load and Store Units + // Loads can have 4, 5 or 6 cycles of latency. + // Stores are listed as having a single cycle of latency. This is not + // completely accurate since it takes more than 1 cycle to actually store + // the value. However, since the store does not produce a result it can be + // considered complete after one cycle. def P9_LS_1C : SchedWriteRes<[LS]> { let Latency = 1; } @@ -260,25 +311,44 @@ let SchedModel = P9Model in { let Latency = 5; } + def P9_LS_6C : SchedWriteRes<[LS]> { + let Latency = 6; + } + + // DFU Unit + // Some of the most expensive ops use the DFU. + // Can take from 12 cycles to 76 cycles to obtain a result. + // The unit may be busy for up to 62 cycles. def P9_DFU_12C : SchedWriteRes<[DFU]> { let Latency = 12; } + def P9_DFU_23C : SchedWriteRes<[DFU]> { + let Latency = 23; + let ResourceCycles = [11]; + } + def P9_DFU_24C : SchedWriteRes<[DFU]> { let Latency = 24; let ResourceCycles = [12]; } + def P9_DFU_37C : SchedWriteRes<[DFU]> { + let Latency = 37; + let ResourceCycles = [25]; + } + def P9_DFU_58C : SchedWriteRes<[DFU]> { let Latency = 58; let ResourceCycles = [44]; } - def P9_DFU_76C : SchedWriteRes<[TestGroup, DFU]> { + def P9_DFU_76C : SchedWriteRes<[DFU]> { let Latency = 76; let ResourceCycles = [62]; } + // 2 or 5 cycle latencies for the branch unit. def P9_BR_2C : SchedWriteRes<[BR]> { let Latency = 2; } @@ -287,138 +357,43 @@ let SchedModel = P9Model in { let Latency = 5; } + // 6 cycle latency for the crypto unit def P9_CY_6C : SchedWriteRes<[CY]> { let Latency = 6; } // ***************** WriteSeq Definitions ***************** + // These are combinations of the resources listed above. + // The idea is that some cracked instructions cannot be done in parallel and + // so the latencies for their resources must be added. def P9_LoadAndALUOp_6C : WriteSequence<[P9_LS_4C, P9_ALU_2C]>; def P9_LoadAndALUOp_7C : WriteSequence<[P9_LS_5C, P9_ALU_2C]>; + def P9_LoadAndALU2Op_7C : WriteSequence<[P9_LS_4C, P9_ALU_3C]>; + def P9_LoadAndALU2Op_8C : WriteSequence<[P9_LS_5C, P9_ALU_3C]>; def P9_LoadAndPMOp_8C : WriteSequence<[P9_LS_5C, P9_PM_3C]>; def P9_LoadAndLoadOp_8C : WriteSequence<[P9_LS_4C, P9_LS_4C]>; + def P9_IntDivAndALUOp_18C_8 : WriteSequence<[P9_DIV_16C_8, P9_ALU_2C]>; def P9_IntDivAndALUOp_26C_8 : WriteSequence<[P9_DIV_24C_8, P9_ALU_2C]>; def P9_IntDivAndALUOp_42C_8 : WriteSequence<[P9_DIV_40C_8, P9_ALU_2C]>; + def P9_StoreAndALUOp_3C : WriteSequence<[P9_LS_1C, P9_ALU_2C]>; def P9_StoreAndALUOp_4C : WriteSequence<[P9_LS_1C, P9_ALU_3C]>; def P9_ALUOpAndALUOp_4C : WriteSequence<[P9_ALU_2C, P9_ALU_2C]>; + def P9_ALU2OpAndALU2Op_6C : WriteSequence<[P9_ALU_3C, P9_ALU_3C]>; + def P9_ALUOpAndALUOpAndALUOp_6C : + WriteSequence<[P9_ALU_2C, P9_ALU_2C, P9_ALU_2C]>; + def P9_DPOpAndALUOp_7C : WriteSequence<[P9_DP_5C, P9_ALU_2C]>; def P9_DPOpAndALUOp_9C : WriteSequence<[P9_DP_7C, P9_ALU_2C]>; + def P9_DPOpAndALU2Op_10C : WriteSequence<[P9_DP_7C, P9_ALU_3C]>; def P9_DPOpAndALUOp_24C_5 : WriteSequence<[P9_DP_22C_5, P9_ALU_2C]>; def P9_DPOpAndALUOp_35C_8 : WriteSequence<[P9_DP_33C_8, P9_ALU_2C]>; + def P9_DPOpAndALU2Op_25C_5 : WriteSequence<[P9_DP_22C_5, P9_ALU_3C]>; + def P9_DPOpAndALU2Op_29C_5 : WriteSequence<[P9_DP_26C_5, P9_ALU_3C]>; + def P9_DPOpAndALU2Op_36C_8 : WriteSequence<[P9_DP_33C_8, P9_ALU_3C]>; + def P9_DPOpAndALU2Op_39C_10 : WriteSequence<[P9_DP_36C_10, P9_ALU_3C]>; + def P9_BROpAndALUOp_7C : WriteSequence<[P9_BR_5C, P9_ALU_2C]>; - // ***************** Defining Itinerary Class Resources ***************** - - // The following itineraries are fully covered by the InstRW definitions in - // P9InstrResources.td so aren't listed here. - // IIC_FPDivD, IIC_FPDivS, IIC_FPFused, IIC_IntDivD, IIC_LdStLFDU, - // IIC_LdStLFDUX - - def : ItinRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C, DISP_1C], - [IIC_IntSimple, IIC_IntGeneral, IIC_IntRFID, - IIC_IntRotateD, IIC_IntRotateDI, IIC_IntTrapD, - IIC_SprRFI]>; - - def : ItinRW<[P9_ALU_3C, IP_EXEC_1C, DISP_1C, DISP_1C], - [IIC_IntTrapW]>; - - def : ItinRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_IntISEL, IIC_IntRotate, IIC_IntShift]>; - - def : ItinRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C, DISP_1C], [IIC_IntCompare]>; - - def : ItinRW<[P9_ALUE_2C, P9_ALUO_2C, IP_EXECE_1C, IP_EXECO_1C, - DISP_1C, DISP_1C], [IIC_VecGeneral, IIC_FPCompare]>; - - def : ItinRW<[P9_DP_5C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_IntMulHW, IIC_IntMulHWU, IIC_IntMulLI, IIC_IntMulHD]>; - - def : ItinRW<[P9_LS_5C, IP_EXEC_1C, DISP_1C, DISP_1C], - [IIC_LdStLoad, IIC_LdStLD, IIC_LdStLFD]>; - - def : ItinRW<[P9_LS_4C, P9_ALU_2C, IP_EXEC_1C, IP_EXEC_1C, - DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStLoadUpd, IIC_LdStLDU]>; - - def : ItinRW<[P9_LS_4C, P9_ALU_2C, IP_EXECE_1C, IP_EXECO_1C, - DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStLoadUpdX, IIC_LdStLDUX]>; - - def : ItinRW<[P9_LS_1C, P9_ALU_2C, IP_EXEC_1C, IP_EXEC_1C, IP_AGEN_1C, - DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStSTFDU]>; - - def : ItinRW<[P9_LoadAndALUOp_6C, - IP_AGEN_1C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStLHA, IIC_LdStLWA]>; - - def : ItinRW<[P9_LoadAndALUOp_6C, P9_ALU_2C, - IP_AGEN_1C, IP_EXEC_1C, IP_EXEC_1C, - DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStLHAU, IIC_LdStLHAUX]>; - - // IIC_LdStLMW contains two microcoded insns. This is not accurate, but - // those insns are not used that much, if at all. - def : ItinRW<[P9_LS_4C, IP_EXEC_1C, DISP_1C, DISP_1C], - [IIC_LdStLWARX, IIC_LdStLDARX, IIC_LdStLMW]>; - - def : ItinRW<[P9_LS_4C, IP_EXEC_1C, DISP_1C, DISP_1C], - [IIC_LdStCOPY, IIC_SprABORT, IIC_LdStPASTE, IIC_LdStDCBF, - IIC_LdStICBI, IIC_LdStSync, IIC_SprISYNC, IIC_SprMSGSYNC, - IIC_SprSLBIA, IIC_SprSLBSYNC, IIC_SprTLBSYNC]>; - - def : ItinRW<[P9_LS_1C, IP_EXEC_1C, IP_AGEN_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStSTFD, IIC_LdStSTD, IIC_LdStStore]>; - - def : ItinRW<[P9_LS_1C, P9_ALU_2C, IP_EXEC_1C, IP_EXEC_1C, IP_AGEN_1C, - DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStSTDU, IIC_LdStSTDUX, IIC_LdStStoreUpd, IIC_SprSLBIEG, - IIC_SprTLBIA, IIC_SprTLBIE]>; - - def : ItinRW<[P9_StoreAndALUOp_4C, IP_EXEC_1C, IP_EXEC_1C, IP_AGEN_1C, - DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_LdStSTDCX, IIC_LdStSTWCX]>; - - def : ItinRW<[P9_ALU_5C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_BrCR, IIC_IntMTFSB0]>; - - def : ItinRW<[P9_ALUOpAndALUOp_4C, P9_ALU_2C, IP_EXEC_1C, IP_EXEC_1C, - IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, DISP_1C, - DISP_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_SprMFCR, IIC_SprMFCRF, IIC_BrMCR, IIC_BrMCRX, IIC_IntMFFS]>; - - def : ItinRW<[P9_BR_2C, DISP_1C], [IIC_BrB]>; - def : ItinRW<[P9_BR_5C, DISP_1C], [IIC_SprMFSPR]>; - - // This class should be broken down to instruction level, once some missing - // info is obtained. - def : ItinRW<[P9_LoadAndALUOp_6C, IP_EXEC_1C, IP_AGEN_1C, - DISP_1C, DISP_1C, DISP_1C], [IIC_SprMTSPR]>; - - def : ItinRW<[P9_LoadAndLoadOp_8C, IP_EXEC_1C, DISP_1C, DISP_1C], - [IIC_SprSLBIE, IIC_SprSLBMFEE, IIC_SprSLBMFEV, IIC_SprSLBMTE, - IIC_SprTLBIEL]>; - - // IIC_VecFP is added here although many instructions with that itinerary - // use very different resources. It would appear that instructions were - // given that itinerary rather carelessly over time. Specific instructions - // that use different resources are listed in various InstrRW classes. - def : ItinRW<[P9_DP_7C, IP_EXEC_1C, DISP_1C, DISP_1C, DISP_1C], - [IIC_FPGeneral, IIC_FPAddSub, IIC_VecFP]>; - - def : ItinRW<[P9_ALUE_3C, P9_ALUO_3C, IP_EXECE_1C, IP_EXECO_1C, - DISP_1C, DISP_1C], [IIC_VecFPCompare]>; - - def : ItinRW<[P9_PM_3C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C], - [IIC_VecPerm]>; - - def : ItinRW<[P9_DP_36C_10, IP_EXEC_1C], [IIC_FPSqrtD]>; - def : ItinRW<[P9_DP_26C_5, P9_DP_26C_5, IP_EXEC_1C, IP_EXEC_1C], [IIC_FPSqrtS]>; - - def : ItinRW<[P9_DIV_12C, IP_EXECE_1C, DISP_1C, DISP_1C], - [IIC_SprMFMSR, IIC_SprMFPMR, IIC_SprMFSR, IIC_SprMFTB, - IIC_SprMTMSR, IIC_SprMTMSRD, IIC_SprMTPMR, IIC_SprMTSR]>; - - def : ItinRW<[], [IIC_SprSTOP]>; - + // Include the resource requirements of individual instructions. include "P9InstrResources.td" } diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index ccf0f80c336b..c0cbfd779cb9 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -65,6 +65,7 @@ void PPCSubtarget::initializeEnvironment() { HasHardFloat = false; HasAltivec = false; HasSPE = false; + HasFPU = false; HasQPX = false; HasVSX = false; HasP8Vector = false; @@ -106,6 +107,7 @@ void PPCSubtarget::initializeEnvironment() { HasFloat128 = false; IsISA3_0 = false; UseLongCalls = false; + SecurePlt = false; HasPOPCNTD = POPCNTD_Unavailable; } @@ -136,6 +138,16 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { if (isDarwin()) HasLazyResolverStubs = true; + if (HasSPE && IsPPC64) + report_fatal_error( "SPE is only supported for 32-bit targets.\n", false); + if (HasSPE && (HasAltivec || HasQPX || HasVSX || HasFPU)) + report_fatal_error( + "SPE and traditional floating point cannot both be enabled.\n", false); + + // If not SPE, set standard FPU + if (!HasSPE) + HasFPU = true; + // QPX requires a 32-byte aligned stack. Note that we need to do this if // we're compiling for a BG/Q system regardless of whether or not QPX // is enabled because external functions will assume this alignment. @@ -163,27 +175,8 @@ bool PPCSubtarget::hasLazyResolverStub(const GlobalValue *GV) const { return false; } -// Embedded cores need aggressive scheduling (and some others also benefit). -static bool needsAggressiveScheduling(unsigned Directive) { - switch (Directive) { - default: return false; - case PPC::DIR_440: - case PPC::DIR_A2: - case PPC::DIR_E500mc: - case PPC::DIR_E5500: - case PPC::DIR_PWR7: - case PPC::DIR_PWR8: - // FIXME: Same as P8 until POWER9 scheduling info is available - case PPC::DIR_PWR9: - return true; - } -} - bool PPCSubtarget::enableMachineScheduler() const { - // Enable MI scheduling for the embedded cores. - // FIXME: Enable this for all cores (some additional modeling - // may be necessary). - return needsAggressiveScheduling(DarwinDirective); + return true; } // This overrides the PostRAScheduler bit in the SchedModel for each CPU. @@ -201,19 +194,19 @@ void PPCSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { void PPCSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy, unsigned NumRegionInstrs) const { - if (needsAggressiveScheduling(DarwinDirective)) { - Policy.OnlyTopDown = false; - Policy.OnlyBottomUp = false; - } - + // The GenericScheduler that we use defaults to scheduling bottom up only. + // We want to schedule from both the top and the bottom and so we set + // OnlyBottomUp to false. + // We want to do bi-directional scheduling since it provides a more balanced + // schedule leading to better performance. + Policy.OnlyBottomUp = false; // Spilling is generally expensive on all PPC cores, so always enable // register-pressure tracking. Policy.ShouldTrackPressure = true; } bool PPCSubtarget::useAA() const { - // Use AA during code generation for the embedded cores. - return needsAggressiveScheduling(DarwinDirective); + return true; } bool PPCSubtarget::enableSubRegLiveness() const { diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index c351b5c04a05..c56f254d6bec 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -46,6 +46,7 @@ namespace PPC { DIR_750, DIR_970, DIR_A2, + DIR_E500, DIR_E500mc, DIR_E5500, DIR_PWR3, @@ -94,6 +95,7 @@ protected: bool HasHardFloat; bool IsPPC64; bool HasAltivec; + bool HasFPU; bool HasSPE; bool HasQPX; bool HasVSX; @@ -133,6 +135,7 @@ protected: bool HasFloat128; bool IsISA3_0; bool UseLongCalls; + bool SecurePlt; POPCNTDKind HasPOPCNTD; @@ -238,6 +241,7 @@ public: bool hasFPCVT() const { return HasFPCVT; } bool hasAltivec() const { return HasAltivec; } bool hasSPE() const { return HasSPE; } + bool hasFPU() const { return HasFPU; } bool hasQPX() const { return HasQPX; } bool hasVSX() const { return HasVSX; } bool hasP8Vector() const { return HasP8Vector; } @@ -255,6 +259,7 @@ public: bool hasOnlyMSYNC() const { return HasOnlyMSYNC; } bool isPPC4xx() const { return IsPPC4xx; } bool isPPC6xx() const { return IsPPC6xx; } + bool isSecurePlt() const {return SecurePlt; } bool isE500() const { return IsE500; } bool isFeatureMFTB() const { return FeatureMFTB; } bool isDeprecatedDST() const { return DeprecatedDST; } diff --git a/lib/Target/PowerPC/PPCTLSDynamicCall.cpp b/lib/Target/PowerPC/PPCTLSDynamicCall.cpp index 49f2699ab082..ac36abbe8439 100644 --- a/lib/Target/PowerPC/PPCTLSDynamicCall.cpp +++ b/lib/Target/PowerPC/PPCTLSDynamicCall.cpp @@ -77,7 +77,7 @@ protected: continue; } - DEBUG(dbgs() << "TLS Dynamic Call Fixup:\n " << MI); + LLVM_DEBUG(dbgs() << "TLS Dynamic Call Fixup:\n " << MI); unsigned OutReg = MI.getOperand(0).getReg(); unsigned InReg = MI.getOperand(1).getReg(); @@ -108,7 +108,7 @@ protected: } // We create ADJCALLSTACKUP and ADJCALLSTACKDOWN around _tls_get_addr - // as schduling fence to avoid it is scheduled before + // as scheduling fence to avoid it is scheduled before // mflr in the prologue and the address in LR is clobbered (PR25839). // We don't really need to save data to the stack - the clobbered // registers are already saved when the SDNode (e.g. PPCaddiTlsgdLAddr) diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index 20a83c973026..a8d7955ef548 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -23,8 +23,8 @@ #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/TargetLoweringObjectFile.h" #include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/CodeGen/MachineScheduler.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" @@ -32,6 +32,7 @@ #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Scalar.h" #include <cassert> @@ -303,7 +304,12 @@ namespace { class PPCPassConfig : public TargetPassConfig { public: PPCPassConfig(PPCTargetMachine &TM, PassManagerBase &PM) - : TargetPassConfig(TM, PM) {} + : 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) + substitutePass(&PostRASchedulerID, &PostMachineSchedulerID); + } PPCTargetMachine &getPPCTargetMachine() const { return getTM<PPCTargetMachine>(); @@ -343,7 +349,7 @@ void PPCPassConfig::addIRPasses() { // 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. - addPass(createSeparateConstOffsetFromGEPPass(TM, true)); + addPass(createSeparateConstOffsetFromGEPPass(true)); // Call EarlyCSE pass to find and remove subexpressions in the lowered // result. addPass(createEarlyCSEPass()); diff --git a/lib/Target/PowerPC/PPCTargetObjectFile.h b/lib/Target/PowerPC/PPCTargetObjectFile.h index 8343a90696d9..417b8ed0d612 100644 --- a/lib/Target/PowerPC/PPCTargetObjectFile.h +++ b/lib/Target/PowerPC/PPCTargetObjectFile.h @@ -10,8 +10,8 @@ #ifndef LLVM_LIB_TARGET_POWERPC_PPCTARGETOBJECTFILE_H #define LLVM_LIB_TARGET_POWERPC_PPCTARGETOBJECTFILE_H -#include "llvm/CodeGen/TargetLoweringObjectFile.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -25,7 +25,7 @@ namespace llvm { MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override; - /// \brief Describe a TLS variable address within debug info. + /// Describe a TLS variable address within debug info. const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override; }; diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp index aa4073f7ea02..226c75f704f4 100644 --- a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -27,6 +27,11 @@ static cl::opt<unsigned> CacheLineSize("ppc-loop-prefetch-cache-line", cl::Hidden, cl::init(64), cl::desc("The loop prefetch cache line size")); +static cl::opt<bool> +EnablePPCColdCC("ppc-enable-coldcc", cl::Hidden, cl::init(false), + cl::desc("Enable using coldcc calling conv for cold " + "internal functions")); + //===----------------------------------------------------------------------===// // // PPC cost model. @@ -215,6 +220,14 @@ void PPCTTIImpl::getUnrollingPreferences(Loop *L, ScalarEvolution &SE, BaseT::getUnrollingPreferences(L, SE, UP); } +// This function returns true to allow using coldcc calling convention. +// Returning true results in coldcc being used for functions which are cold at +// all call sites when the callers of the functions are not calling any other +// non coldcc functions. +bool PPCTTIImpl::useColdCCForColdCall(Function &F) { + return EnablePPCColdCC; +} + bool PPCTTIImpl::enableAggressiveInterleaving(bool LoopHasReductions) { // On the A2, always unroll aggressively. For QPX unaligned loads, we depend // on combining the loads generated for consecutive accesses, and failure to diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.h b/lib/Target/PowerPC/PPCTargetTransformInfo.h index b42dae4a0254..2ee2b3eb8084 100644 --- a/lib/Target/PowerPC/PPCTargetTransformInfo.h +++ b/lib/Target/PowerPC/PPCTargetTransformInfo.h @@ -61,7 +61,7 @@ public: /// \name Vector TTI Implementations /// @{ - + bool useColdCCForColdCall(Function &F); bool enableAggressiveInterleaving(bool LoopHasReductions); const TTI::MemCmpExpansionOptions *enableMemCmpExpansion( bool IsZeroCmp) const; diff --git a/lib/Target/PowerPC/PPCVSXFMAMutate.cpp b/lib/Target/PowerPC/PPCVSXFMAMutate.cpp index f15af790de8f..6586f503a7b8 100644 --- a/lib/Target/PowerPC/PPCVSXFMAMutate.cpp +++ b/lib/Target/PowerPC/PPCVSXFMAMutate.cpp @@ -241,7 +241,7 @@ protected: assert(OldFMAReg == AddendMI->getOperand(0).getReg() && "Addend copy not tied to old FMA output!"); - DEBUG(dbgs() << "VSX FMA Mutation:\n " << MI); + LLVM_DEBUG(dbgs() << "VSX FMA Mutation:\n " << MI); MI.getOperand(0).setReg(KilledProdReg); MI.getOperand(1).setReg(KilledProdReg); @@ -273,7 +273,7 @@ protected: MI.getOperand(2).setIsUndef(OtherProdRegUndef); } - DEBUG(dbgs() << " -> " << MI); + LLVM_DEBUG(dbgs() << " -> " << MI); // The killed product operand was killed here, so we can reuse it now // for the result of the fma. @@ -310,7 +310,7 @@ protected: NewFMAInt.addSegment(LiveInterval::Segment(AI->start, AI->end, NewFMAValNo)); } - DEBUG(dbgs() << " extended: " << NewFMAInt << '\n'); + LLVM_DEBUG(dbgs() << " extended: " << NewFMAInt << '\n'); // Extend the live interval of the addend source (it might end at the // copy to be removed, or somewhere in between there and here). This @@ -323,15 +323,15 @@ protected: LiveRange &AddendSrcRange = LIS->getRegUnit(Unit); AddendSrcRange.extendInBlock(LIS->getMBBStartIdx(&MBB), FMAIdx.getRegSlot()); - DEBUG(dbgs() << " extended: " << AddendSrcRange << '\n'); + LLVM_DEBUG(dbgs() << " extended: " << AddendSrcRange << '\n'); } FMAInt.removeValNo(FMAValNo); - DEBUG(dbgs() << " trimmed: " << FMAInt << '\n'); + LLVM_DEBUG(dbgs() << " trimmed: " << FMAInt << '\n'); // Remove the (now unused) copy. - DEBUG(dbgs() << " removing: " << *AddendMI << '\n'); + LLVM_DEBUG(dbgs() << " removing: " << *AddendMI << '\n'); LIS->RemoveMachineInstrFromMaps(*AddendMI); AddendMI->eraseFromParent(); diff --git a/lib/Target/PowerPC/PPCVSXSwapRemoval.cpp b/lib/Target/PowerPC/PPCVSXSwapRemoval.cpp index 8a5fb9fdaef1..1e8a1750ec3b 100644 --- a/lib/Target/PowerPC/PPCVSXSwapRemoval.cpp +++ b/lib/Target/PowerPC/PPCVSXSwapRemoval.cpp @@ -51,6 +51,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -248,7 +249,7 @@ bool PPCVSXSwapRemoval::gatherVectorInstructions() { for (MachineBasicBlock &MBB : *MF) { for (MachineInstr &MI : MBB) { - if (MI.isDebugValue()) + if (MI.isDebugInstr()) continue; bool RelevantInstr = false; @@ -519,14 +520,16 @@ bool PPCVSXSwapRemoval::gatherVectorInstructions() { // permute control vectors (for shift values 1, 2, 3). However, // VPERM has a more restrictive register class. case PPC::XXSLDWI: + case PPC::XSCVDPSPN: + case PPC::XSCVSPDPN: break; } } } if (RelevantFunction) { - DEBUG(dbgs() << "Swap vector when first built\n\n"); - DEBUG(dumpSwapVector()); + LLVM_DEBUG(dbgs() << "Swap vector when first built\n\n"); + LLVM_DEBUG(dumpSwapVector()); } return RelevantFunction; @@ -585,14 +588,14 @@ unsigned PPCVSXSwapRemoval::lookThruCopyLike(unsigned SrcReg, // as such so their containing webs will not be optimized. void PPCVSXSwapRemoval::formWebs() { - DEBUG(dbgs() << "\n*** Forming webs for swap removal ***\n\n"); + LLVM_DEBUG(dbgs() << "\n*** Forming webs for swap removal ***\n\n"); for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { MachineInstr *MI = SwapVector[EntryIdx].VSEMI; - DEBUG(dbgs() << "\n" << SwapVector[EntryIdx].VSEId << " "); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << "\n" << SwapVector[EntryIdx].VSEId << " "); + LLVM_DEBUG(MI->dump()); // It's sufficient to walk vector uses and join them to their unique // definitions. In addition, check full vector register operands @@ -622,10 +625,11 @@ void PPCVSXSwapRemoval::formWebs() { (void)EC->unionSets(SwapVector[DefIdx].VSEId, SwapVector[EntryIdx].VSEId); - DEBUG(dbgs() << format("Unioning %d with %d\n", SwapVector[DefIdx].VSEId, - SwapVector[EntryIdx].VSEId)); - DEBUG(dbgs() << " Def: "); - DEBUG(DefMI->dump()); + LLVM_DEBUG(dbgs() << format("Unioning %d with %d\n", + SwapVector[DefIdx].VSEId, + SwapVector[EntryIdx].VSEId)); + LLVM_DEBUG(dbgs() << " Def: "); + LLVM_DEBUG(DefMI->dump()); } } } @@ -636,7 +640,7 @@ void PPCVSXSwapRemoval::formWebs() { // as rejected. void PPCVSXSwapRemoval::recordUnoptimizableWebs() { - DEBUG(dbgs() << "\n*** Rejecting webs for swap removal ***\n\n"); + LLVM_DEBUG(dbgs() << "\n*** Rejecting webs for swap removal ***\n\n"); for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); @@ -654,12 +658,13 @@ void PPCVSXSwapRemoval::recordUnoptimizableWebs() { SwapVector[Repr].WebRejected = 1; - DEBUG(dbgs() << - format("Web %d rejected for physreg, partial reg, or not " - "swap[pable]\n", Repr)); - DEBUG(dbgs() << " in " << EntryIdx << ": "); - DEBUG(SwapVector[EntryIdx].VSEMI->dump()); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG( + dbgs() << format("Web %d rejected for physreg, partial reg, or not " + "swap[pable]\n", + Repr)); + LLVM_DEBUG(dbgs() << " in " << EntryIdx << ": "); + LLVM_DEBUG(SwapVector[EntryIdx].VSEMI->dump()); + LLVM_DEBUG(dbgs() << "\n"); } // Reject webs than contain swapping loads that feed something other @@ -680,13 +685,13 @@ void PPCVSXSwapRemoval::recordUnoptimizableWebs() { SwapVector[Repr].WebRejected = 1; - DEBUG(dbgs() << - format("Web %d rejected for load not feeding swap\n", Repr)); - DEBUG(dbgs() << " def " << EntryIdx << ": "); - DEBUG(MI->dump()); - DEBUG(dbgs() << " use " << UseIdx << ": "); - DEBUG(UseMI.dump()); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << format( + "Web %d rejected for load not feeding swap\n", Repr)); + LLVM_DEBUG(dbgs() << " def " << EntryIdx << ": "); + LLVM_DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << " use " << UseIdx << ": "); + LLVM_DEBUG(UseMI.dump()); + LLVM_DEBUG(dbgs() << "\n"); } } @@ -704,13 +709,13 @@ void PPCVSXSwapRemoval::recordUnoptimizableWebs() { SwapVector[Repr].WebRejected = 1; - DEBUG(dbgs() << - format("Web %d rejected for store not fed by swap\n", Repr)); - DEBUG(dbgs() << " def " << DefIdx << ": "); - DEBUG(DefMI->dump()); - DEBUG(dbgs() << " use " << EntryIdx << ": "); - DEBUG(MI->dump()); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << format( + "Web %d rejected for store not fed by swap\n", Repr)); + LLVM_DEBUG(dbgs() << " def " << DefIdx << ": "); + LLVM_DEBUG(DefMI->dump()); + LLVM_DEBUG(dbgs() << " use " << EntryIdx << ": "); + LLVM_DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << "\n"); } // Ensure all uses of the register defined by DefMI feed store @@ -721,21 +726,22 @@ void PPCVSXSwapRemoval::recordUnoptimizableWebs() { if (SwapVector[UseIdx].VSEMI->getOpcode() != MI->getOpcode()) { SwapVector[Repr].WebRejected = 1; - DEBUG(dbgs() << - format("Web %d rejected for swap not feeding only stores\n", - Repr)); - DEBUG(dbgs() << " def " << " : "); - DEBUG(DefMI->dump()); - DEBUG(dbgs() << " use " << UseIdx << ": "); - DEBUG(SwapVector[UseIdx].VSEMI->dump()); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG( + dbgs() << format( + "Web %d rejected for swap not feeding only stores\n", Repr)); + LLVM_DEBUG(dbgs() << " def " + << " : "); + LLVM_DEBUG(DefMI->dump()); + LLVM_DEBUG(dbgs() << " use " << UseIdx << ": "); + LLVM_DEBUG(SwapVector[UseIdx].VSEMI->dump()); + LLVM_DEBUG(dbgs() << "\n"); } } } } - DEBUG(dbgs() << "Swap vector after web analysis:\n\n"); - DEBUG(dumpSwapVector()); + LLVM_DEBUG(dbgs() << "Swap vector after web analysis:\n\n"); + LLVM_DEBUG(dumpSwapVector()); } // Walk the swap vector entries looking for swaps fed by permuting loads @@ -745,7 +751,7 @@ void PPCVSXSwapRemoval::recordUnoptimizableWebs() { // such that multiple loads feed the same swap, etc.) void PPCVSXSwapRemoval::markSwapsForRemoval() { - DEBUG(dbgs() << "\n*** Marking swaps for removal ***\n\n"); + LLVM_DEBUG(dbgs() << "\n*** Marking swaps for removal ***\n\n"); for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { @@ -760,8 +766,8 @@ void PPCVSXSwapRemoval::markSwapsForRemoval() { int UseIdx = SwapMap[&UseMI]; SwapVector[UseIdx].WillRemove = 1; - DEBUG(dbgs() << "Marking swap fed by load for removal: "); - DEBUG(UseMI.dump()); + LLVM_DEBUG(dbgs() << "Marking swap fed by load for removal: "); + LLVM_DEBUG(UseMI.dump()); } } @@ -775,8 +781,8 @@ void PPCVSXSwapRemoval::markSwapsForRemoval() { int DefIdx = SwapMap[DefMI]; SwapVector[DefIdx].WillRemove = 1; - DEBUG(dbgs() << "Marking swap feeding store for removal: "); - DEBUG(DefMI->dump()); + LLVM_DEBUG(dbgs() << "Marking swap feeding store for removal: "); + LLVM_DEBUG(DefMI->dump()); } } else if (SwapVector[EntryIdx].IsSwappable && @@ -821,8 +827,8 @@ void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { MachineInstr *MI = SwapVector[EntryIdx].VSEMI; unsigned NElts; - DEBUG(dbgs() << "Changing splat: "); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << "Changing splat: "); + LLVM_DEBUG(MI->dump()); switch (MI->getOpcode()) { default: @@ -845,8 +851,8 @@ void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { else MI->getOperand(1).setImm(EltNo); - DEBUG(dbgs() << " Into: "); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << " Into: "); + LLVM_DEBUG(MI->dump()); break; } @@ -859,8 +865,8 @@ void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { case SHValues::SH_XXPERMDI: { MachineInstr *MI = SwapVector[EntryIdx].VSEMI; - DEBUG(dbgs() << "Changing XXPERMDI: "); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << "Changing XXPERMDI: "); + LLVM_DEBUG(MI->dump()); unsigned Selector = MI->getOperand(3).getImm(); if (Selector == 0 || Selector == 3) @@ -872,8 +878,14 @@ void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { MI->getOperand(1).setReg(Reg2); MI->getOperand(2).setReg(Reg1); - DEBUG(dbgs() << " Into: "); - DEBUG(MI->dump()); + // We also need to swap kill flag associated with the register. + bool IsKill1 = MI->getOperand(1).isKill(); + bool IsKill2 = MI->getOperand(2).isKill(); + MI->getOperand(1).setIsKill(IsKill2); + MI->getOperand(2).setIsKill(IsKill1); + + LLVM_DEBUG(dbgs() << " Into: "); + LLVM_DEBUG(MI->dump()); break; } @@ -883,16 +895,16 @@ void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { case SHValues::SH_COPYWIDEN: { MachineInstr *MI = SwapVector[EntryIdx].VSEMI; - DEBUG(dbgs() << "Changing SUBREG_TO_REG: "); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << "Changing SUBREG_TO_REG: "); + LLVM_DEBUG(MI->dump()); unsigned DstReg = MI->getOperand(0).getReg(); const TargetRegisterClass *DstRC = MRI->getRegClass(DstReg); unsigned NewVReg = MRI->createVirtualRegister(DstRC); MI->getOperand(0).setReg(NewVReg); - DEBUG(dbgs() << " Into: "); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << " Into: "); + LLVM_DEBUG(MI->dump()); auto InsertPoint = ++MachineBasicBlock::iterator(MI); @@ -908,19 +920,19 @@ void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), TII->get(PPC::COPY), VSRCTmp1) .addReg(NewVReg); - DEBUG(std::prev(InsertPoint)->dump()); + LLVM_DEBUG(std::prev(InsertPoint)->dump()); insertSwap(MI, InsertPoint, VSRCTmp2, VSRCTmp1); - DEBUG(std::prev(InsertPoint)->dump()); + LLVM_DEBUG(std::prev(InsertPoint)->dump()); BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), TII->get(PPC::COPY), DstReg) .addReg(VSRCTmp2); - DEBUG(std::prev(InsertPoint)->dump()); + LLVM_DEBUG(std::prev(InsertPoint)->dump()); } else { insertSwap(MI, InsertPoint, DstReg, NewVReg); - DEBUG(std::prev(InsertPoint)->dump()); + LLVM_DEBUG(std::prev(InsertPoint)->dump()); } break; } @@ -931,7 +943,7 @@ void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { // a copy operation. bool PPCVSXSwapRemoval::removeSwaps() { - DEBUG(dbgs() << "\n*** Removing swaps ***\n\n"); + LLVM_DEBUG(dbgs() << "\n*** Removing swaps ***\n\n"); bool Changed = false; @@ -944,9 +956,9 @@ bool PPCVSXSwapRemoval::removeSwaps() { MI->getOperand(0).getReg()) .add(MI->getOperand(1)); - DEBUG(dbgs() << format("Replaced %d with copy: ", - SwapVector[EntryIdx].VSEId)); - DEBUG(MI->dump()); + LLVM_DEBUG(dbgs() << format("Replaced %d with copy: ", + SwapVector[EntryIdx].VSEId)); + LLVM_DEBUG(MI->dump()); MI->eraseFromParent(); } |
