diff options
Diffstat (limited to 'llvm/lib/Target/Sparc')
28 files changed, 874 insertions, 838 deletions
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 77e9b1d96612..4f94392d4dae 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -70,8 +70,9 @@ class SparcAsmParser : public MCTargetAsmParser { OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) override; - bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; - OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -106,7 +107,7 @@ class SparcAsmParser : public MCTargetAsmParser { const MCExpr *subExpr); // returns true if Tok is matched to a register and returns register in RegNo. - bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, + bool matchRegisterName(const AsmToken &Tok, MCRegister &RegNo, unsigned &RegKind); bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc); @@ -693,14 +694,14 @@ bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, llvm_unreachable("Implement any new match types added!"); } -bool SparcAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, +bool SparcAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) return Error(StartLoc, "invalid register name"); return false; } -OperandMatchResultTy SparcAsmParser::tryParseRegister(unsigned &RegNo, +OperandMatchResultTy SparcAsmParser::tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { const AsmToken &Tok = Parser.getTok(); @@ -1050,7 +1051,8 @@ SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { return MatchOperand_NoMatch; Parser.Lex(); // eat % - unsigned RegNo, RegKind; + MCRegister RegNo; + unsigned RegKind; if (!matchRegisterName(Parser.getTok(), RegNo, RegKind)) return MatchOperand_NoMatch; @@ -1106,9 +1108,9 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op, switch (getLexer().getKind()) { default: break; - case AsmToken::Percent: + case AsmToken::Percent: { Parser.Lex(); // Eat the '%'. - unsigned RegNo; + MCRegister RegNo; unsigned RegKind; if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) { StringRef name = Parser.getTok().getString(); @@ -1156,6 +1158,7 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op, Op = SparcOperand::CreateImm(EVal, S, E); } break; + } case AsmToken::Plus: case AsmToken::Minus: @@ -1203,7 +1206,7 @@ SparcAsmParser::parseBranchModifiers(OperandVector &Operands) { return MatchOperand_Success; } -bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegNo, +bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, MCRegister &RegNo, unsigned &RegKind) { int64_t intVal = 0; RegNo = 0; diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index 1825b95dd6ac..496c08f76a16 100644 --- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -155,11 +155,15 @@ static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, unsigned RegNo, static DecodeStatus DecodeI64RegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const MCDisassembler *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = IntRegDecoderTable[RegNo]; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; + return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); +} + +// This is used for the type "ptr_rc", which is either IntRegs or I64Regs +// depending on SparcRegisterInfo::getPointerRegClass. +static DecodeStatus DecodePointerLikeRegClass0(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const MCDisassembler *Decoder) { + return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); } static DecodeStatus DecodeFPRegsRegisterClass(MCInst &Inst, unsigned RegNo, @@ -195,9 +199,9 @@ static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst, unsigned RegNo, return MCDisassembler::Success; } -static DecodeStatus DecodeCPRegsRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, - const MCDisassembler *Decoder) { +static DecodeStatus +DecodeCoprocRegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, + const MCDisassembler *Decoder) { if (RegNo > 31) return MCDisassembler::Fail; unsigned Reg = CPRegDecoderTable[RegNo]; @@ -226,7 +230,7 @@ static DecodeStatus DecodeASRRegsRegisterClass(MCInst &Inst, unsigned RegNo, static DecodeStatus DecodePRRegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const MCDisassembler *Decoder) { - if (RegNo >= array_lengthof(PRRegDecoderTable)) + if (RegNo >= std::size(PRRegDecoderTable)) return MCDisassembler::Fail; Inst.addOperand(MCOperand::createReg(PRRegDecoderTable[RegNo])); return MCDisassembler::Success; @@ -248,9 +252,9 @@ static DecodeStatus DecodeIntPairRegisterClass(MCInst &Inst, unsigned RegNo, return S; } -static DecodeStatus DecodeCPPairRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, - const MCDisassembler *Decoder) { +static DecodeStatus +DecodeCoprocPairRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, + const MCDisassembler *Decoder) { if (RegNo > 31) return MCDisassembler::Fail; @@ -259,53 +263,10 @@ static DecodeStatus DecodeCPPairRegisterClass(MCInst &Inst, unsigned RegNo, return MCDisassembler::Success; } -static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeLoadIntPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeLoadCP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeLoadCPPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeStoreIntPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeStoreCP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeStoreCPPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder); static DecodeStatus DecodeCall(MCInst &Inst, unsigned insn, uint64_t Address, const MCDisassembler *Decoder); static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, uint64_t Address, const MCDisassembler *Decoder); -static DecodeStatus DecodeJMPL(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeReturn(MCInst &MI, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeSWAP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); -static DecodeStatus DecodeTRAP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); #include "SparcGenDisassemblerTables.inc" @@ -363,147 +324,6 @@ DecodeStatus SparcDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, return MCDisassembler::Fail; } -typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder); - -static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder, bool isLoad, - DecodeFunc DecodeRD) { - unsigned rd = fieldFromInstruction(insn, 25, 5); - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - bool isImm = fieldFromInstruction(insn, 13, 1); - bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field) - unsigned asi = fieldFromInstruction(insn, 5, 8); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - DecodeStatus status; - if (isLoad) { - status = DecodeRD(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - // Decode rs1. - status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode imm|rs2. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - if (hasAsi) - MI.addOperand(MCOperand::createImm(asi)); - - if (!isLoad) { - status = DecodeRD(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - return MCDisassembler::Success; -} - -static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeIntRegsRegisterClass); -} - -static DecodeStatus DecodeLoadIntPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeIntPairRegisterClass); -} - -static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeFPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeDFPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeQFPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadCP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeCPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadCPPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeCPPairRegisterClass); -} - -static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeIntRegsRegisterClass); -} - -static DecodeStatus DecodeStoreIntPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeIntPairRegisterClass); -} - -static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeFPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeDFPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeQFPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreCP(MCInst &Inst, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeCPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreCPPair(MCInst &Inst, unsigned insn, - uint64_t Address, - const MCDisassembler *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeCPPairRegisterClass); -} - static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, uint64_t Address, uint64_t Offset, uint64_t Width, MCInst &MI, @@ -528,138 +348,3 @@ static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, uint64_t Address, MI.addOperand(MCOperand::createImm(tgt)); return MCDisassembler::Success; } - -static DecodeStatus DecodeJMPL(MCInst &MI, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - - unsigned rd = fieldFromInstruction(insn, 25, 5); - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RD. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1. - status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1 | SIMM13. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - return MCDisassembler::Success; -} - -static DecodeStatus DecodeReturn(MCInst &MI, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RS1. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS2 | SIMM13. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSWAP(MCInst &MI, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - - unsigned rd = fieldFromInstruction(insn, 25, 5); - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field) - unsigned asi = fieldFromInstruction(insn, 5, 8); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RD. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1. - status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1 | SIMM13. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - if (hasAsi) - MI.addOperand(MCOperand::createImm(asi)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeTRAP(MCInst &MI, unsigned insn, uint64_t Address, - const MCDisassembler *Decoder) { - - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - unsigned cc =fieldFromInstruction(insn, 25, 4); - unsigned rs2 = 0; - unsigned imm7 = 0; - if (isImm) - imm7 = fieldFromInstruction(insn, 0, 7); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RS1. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1 | IMM7. - if (isImm) - MI.addOperand(MCOperand::createImm(imm7)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - // Decode CC - MI.addOperand(MCOperand::createImm(cc)); - - return MCDisassembler::Success; -} diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index 7b2d8afd3605..aa89488bbb62 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -141,7 +141,7 @@ namespace { return Sparc::NumTargetFixupKinds; } - Optional<MCFixupKind> getFixupKind(StringRef Name) const override { + std::optional<MCFixupKind> getFixupKind(StringRef Name) const override { unsigned Type; Type = llvm::StringSwitch<unsigned>(Name) #define ELF_RELOC(X, Y) .Case(#X, Y) @@ -154,7 +154,7 @@ namespace { .Case("BFD_RELOC_64", ELF::R_SPARC_64) .Default(-1u); if (Type == -1u) - return None; + return std::nullopt; return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type); } @@ -279,7 +279,7 @@ namespace { case Sparc::fixup_sparc_wplt30: if (Target.getSymA()->getSymbol().isTemporary()) return false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case Sparc::fixup_sparc_tls_gd_hi22: case Sparc::fixup_sparc_tls_gd_lo10: case Sparc::fixup_sparc_tls_gd_add: diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp index 8e4621946008..fb22ddd91ba0 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp @@ -38,9 +38,8 @@ bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const { return (STI.getFeatureBits()[Sparc::FeatureV9]) != 0; } -void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const -{ - OS << '%' << StringRef(getRegisterName(RegNo)).lower(); +void SparcInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const { + OS << '%' << StringRef(getRegisterName(Reg)).lower(); } void SparcInstPrinter::printInst(const MCInst *MI, uint64_t Address, @@ -189,12 +188,20 @@ void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, case SP::FMOVD_FCC: case SP::V9FMOVD_FCC: case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC: // Make sure CC is a fp conditional flag. - CC = (CC < 16) ? (CC + 16) : CC; + CC = (CC < SPCC::FCC_BEGIN) ? (CC + SPCC::FCC_BEGIN) : CC; break; case SP::CBCOND: case SP::CBCONDA: // Make sure CC is a cp conditional flag. - CC = (CC < 32) ? (CC + 32) : CC; + CC = (CC < SPCC::CPCC_BEGIN) ? (CC + SPCC::CPCC_BEGIN) : CC; + break; + case SP::MOVRri: + case SP::MOVRrr: + case SP::FMOVRS: + case SP::FMOVRD: + case SP::FMOVRQ: + // Make sure CC is a register conditional flag. + CC = (CC < SPCC::REG_BEGIN) ? (CC + SPCC::REG_BEGIN) : CC; break; } O << SPARCCondCodeToString((SPCC::CondCodes)CC); @@ -222,7 +229,7 @@ void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum, } bool First = true; - for (unsigned i = 0; i < sizeof(TagNames) / sizeof(char *); i++) { + for (unsigned i = 0; i < std::size(TagNames); i++) { if (Imm & (1 << i)) { O << (First ? "" : " | ") << TagNames[i]; First = false; diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h index 91b78bd03fc3..a9f4a652e0c0 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h @@ -23,7 +23,7 @@ public: const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {} - void printRegName(raw_ostream &OS, unsigned RegNo) const override; + void printRegName(raw_ostream &OS, MCRegister Reg) const override; void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override; bool printSparcAliasInstr(const MCInst *MI, const MCSubtargetInfo &STI, @@ -39,7 +39,7 @@ public: void printCustomAliasOperand(const MCInst *MI, uint64_t Address, unsigned OpIdx, unsigned PrintMethodIdx, const MCSubtargetInfo &STI, raw_ostream &O); - static const char *getRegisterName(unsigned RegNo); + static const char *getRegisterName(MCRegister Reg); void printOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, raw_ostream &OS); diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp index c5cc2ea34bb7..c4545ff56f74 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp @@ -40,7 +40,6 @@ SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Triple &TheTriple) { ExceptionsType = ExceptionHandling::DwarfCFI; - SunStyleELFSectionSwitchSyntax = true; UsesELFSectionDirectiveForBSS = true; } diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp index cc73ea7e6120..522a8877a1c6 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -227,7 +227,7 @@ void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { auto ELFSymbol = cast<MCSymbolELF>(Symbol); if (!ELFSymbol->isBindingSet()) ELFSymbol->setBinding(ELF::STB_GLOBAL); - LLVM_FALLTHROUGH; + [[fallthrough]]; } case VK_Sparc_TLS_GD_HI22: case VK_Sparc_TLS_GD_LO10: diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp index b11c786e7856..d6688c31334c 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -84,6 +84,10 @@ static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S, return new SparcTargetAsmStreamer(S, OS); } +static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) { + return new SparcTargetStreamer(S); +} + static MCInstPrinter *createSparcMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, @@ -122,6 +126,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTargetMC() { // Register the asm streamer. TargetRegistry::RegisterAsmTargetStreamer(*T, createTargetAsmStreamer); + // Register the null streamer. + TargetRegistry::RegisterNullTargetStreamer(*T, createNullTargetStreamer); + // Register the MCInstPrinter TargetRegistry::RegisterMCInstPrinter(*T, createSparcMCInstPrinter); } diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp index a322d49adb87..d2dcf200aef0 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp @@ -12,6 +12,7 @@ #include "SparcTargetStreamer.h" #include "SparcInstPrinter.h" +#include "llvm/MC/MCRegister.h" #include "llvm/Support/FormattedStream.h" using namespace llvm; diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h index 27976d166067..ef28afa06bff 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h @@ -22,9 +22,9 @@ class SparcTargetStreamer : public MCTargetStreamer { public: SparcTargetStreamer(MCStreamer &S); /// Emit ".register <reg>, #ignore". - virtual void emitSparcRegisterIgnore(unsigned reg) = 0; + virtual void emitSparcRegisterIgnore(unsigned reg){}; /// Emit ".register <reg>, #scratch". - virtual void emitSparcRegisterScratch(unsigned reg) = 0; + virtual void emitSparcRegisterScratch(unsigned reg){}; }; // This part is for ascii assembly output diff --git a/llvm/lib/Target/Sparc/Sparc.h b/llvm/lib/Target/Sparc/Sparc.h index aabc4f149829..fca7657871e8 100644 --- a/llvm/lib/Target/Sparc/Sparc.h +++ b/llvm/lib/Target/Sparc/Sparc.h @@ -19,76 +19,87 @@ #include "llvm/Target/TargetMachine.h" namespace llvm { - class FunctionPass; - class SparcTargetMachine; - class AsmPrinter; - class MCInst; - class MachineInstr; +class AsmPrinter; +class FunctionPass; +class MCInst; +class MachineInstr; +class PassRegistry; +class SparcTargetMachine; - FunctionPass *createSparcISelDag(SparcTargetMachine &TM); - FunctionPass *createSparcDelaySlotFillerPass(); +FunctionPass *createSparcISelDag(SparcTargetMachine &TM); +FunctionPass *createSparcDelaySlotFillerPass(); - void LowerSparcMachineInstrToMCInst(const MachineInstr *MI, - MCInst &OutMI, - AsmPrinter &AP); -} // end namespace llvm; +void LowerSparcMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, + AsmPrinter &AP); +void initializeSparcDAGToDAGISelPass(PassRegistry &); +} // namespace llvm namespace llvm { // Enums corresponding to Sparc condition codes, both icc's and fcc's. These // values must be kept in sync with the ones in the .td file. namespace SPCC { - enum CondCodes { - ICC_A = 8 , // Always - ICC_N = 0 , // Never - ICC_NE = 9 , // Not Equal - ICC_E = 1 , // Equal - ICC_G = 10 , // Greater - ICC_LE = 2 , // Less or Equal - ICC_GE = 11 , // Greater or Equal - ICC_L = 3 , // Less - ICC_GU = 12 , // Greater Unsigned - ICC_LEU = 4 , // Less or Equal Unsigned - ICC_CC = 13 , // Carry Clear/Great or Equal Unsigned - ICC_CS = 5 , // Carry Set/Less Unsigned - ICC_POS = 14 , // Positive - ICC_NEG = 6 , // Negative - ICC_VC = 15 , // Overflow Clear - ICC_VS = 7 , // Overflow Set + enum CondCodes { + ICC_A = 8, // Always + ICC_N = 0, // Never + ICC_NE = 9, // Not Equal + ICC_E = 1, // Equal + ICC_G = 10, // Greater + ICC_LE = 2, // Less or Equal + ICC_GE = 11, // Greater or Equal + ICC_L = 3, // Less + ICC_GU = 12, // Greater Unsigned + ICC_LEU = 4, // Less or Equal Unsigned + ICC_CC = 13, // Carry Clear/Great or Equal Unsigned + ICC_CS = 5, // Carry Set/Less Unsigned + ICC_POS = 14, // Positive + ICC_NEG = 6, // Negative + ICC_VC = 15, // Overflow Clear + ICC_VS = 7, // Overflow Set - FCC_A = 8+16, // Always - FCC_N = 0+16, // Never - FCC_U = 7+16, // Unordered - FCC_G = 6+16, // Greater - FCC_UG = 5+16, // Unordered or Greater - FCC_L = 4+16, // Less - FCC_UL = 3+16, // Unordered or Less - FCC_LG = 2+16, // Less or Greater - FCC_NE = 1+16, // Not Equal - FCC_E = 9+16, // Equal - FCC_UE = 10+16, // Unordered or Equal - FCC_GE = 11+16, // Greater or Equal - FCC_UGE = 12+16, // Unordered or Greater or Equal - FCC_LE = 13+16, // Less or Equal - FCC_ULE = 14+16, // Unordered or Less or Equal - FCC_O = 15+16, // Ordered + FCC_BEGIN = 16, + FCC_A = 8 + FCC_BEGIN, // Always + FCC_N = 0 + FCC_BEGIN, // Never + FCC_U = 7 + FCC_BEGIN, // Unordered + FCC_G = 6 + FCC_BEGIN, // Greater + FCC_UG = 5 + FCC_BEGIN, // Unordered or Greater + FCC_L = 4 + FCC_BEGIN, // Less + FCC_UL = 3 + FCC_BEGIN, // Unordered or Less + FCC_LG = 2 + FCC_BEGIN, // Less or Greater + FCC_NE = 1 + FCC_BEGIN, // Not Equal + FCC_E = 9 + FCC_BEGIN, // Equal + FCC_UE = 10 + FCC_BEGIN, // Unordered or Equal + FCC_GE = 11 + FCC_BEGIN, // Greater or Equal + FCC_UGE = 12 + FCC_BEGIN, // Unordered or Greater or Equal + FCC_LE = 13 + FCC_BEGIN, // Less or Equal + FCC_ULE = 14 + FCC_BEGIN, // Unordered or Less or Equal + FCC_O = 15 + FCC_BEGIN, // Ordered - CPCC_A = 8+32, // Always - CPCC_N = 0+32, // Never - CPCC_3 = 7+32, - CPCC_2 = 6+32, - CPCC_23 = 5+32, - CPCC_1 = 4+32, - CPCC_13 = 3+32, - CPCC_12 = 2+32, - CPCC_123 = 1+32, - CPCC_0 = 9+32, - CPCC_03 = 10+32, - CPCC_02 = 11+32, - CPCC_023 = 12+32, - CPCC_01 = 13+32, - CPCC_013 = 14+32, - CPCC_012 = 15+32 - }; + CPCC_BEGIN = 32, + CPCC_A = 8 + CPCC_BEGIN, // Always + CPCC_N = 0 + CPCC_BEGIN, // Never + CPCC_3 = 7 + CPCC_BEGIN, + CPCC_2 = 6 + CPCC_BEGIN, + CPCC_23 = 5 + CPCC_BEGIN, + CPCC_1 = 4 + CPCC_BEGIN, + CPCC_13 = 3 + CPCC_BEGIN, + CPCC_12 = 2 + CPCC_BEGIN, + CPCC_123 = 1 + CPCC_BEGIN, + CPCC_0 = 9 + CPCC_BEGIN, + CPCC_03 = 10 + CPCC_BEGIN, + CPCC_02 = 11 + CPCC_BEGIN, + CPCC_023 = 12 + CPCC_BEGIN, + CPCC_01 = 13 + CPCC_BEGIN, + CPCC_013 = 14 + CPCC_BEGIN, + CPCC_012 = 15 + CPCC_BEGIN, + + REG_BEGIN = 48, + REG_Z = 1 + REG_BEGIN, // Is zero + REG_LEZ = 2 + REG_BEGIN, // Less or equal to zero + REG_LZ = 3 + REG_BEGIN, // Less than zero + REG_NZ = 5 + REG_BEGIN, // Is not zero + REG_GZ = 6 + REG_BEGIN, // Greater than zero + REG_GEZ = 7 + REG_BEGIN // Greater than or equal to zero + }; } inline static const char *SPARCCondCodeToString(SPCC::CondCodes CC) { @@ -141,6 +152,20 @@ namespace llvm { case SPCC::CPCC_01: return "01"; case SPCC::CPCC_013: return "013"; case SPCC::CPCC_012: return "012"; + case SPCC::REG_BEGIN: + llvm_unreachable("Use of reserved cond code"); + case SPCC::REG_Z: + return "z"; + case SPCC::REG_LEZ: + return "lez"; + case SPCC::REG_LZ: + return "lz"; + case SPCC::REG_NZ: + return "nz"; + case SPCC::REG_GZ: + return "gz"; + case SPCC::REG_GEZ: + return "gez"; } llvm_unreachable("Invalid cond code"); } diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp index c8961d507c72..034e8759c2f0 100644 --- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -55,8 +55,8 @@ namespace { void emitFunctionBodyStart() override; void emitInstruction(const MachineInstr *MI) override; - static const char *getRegisterName(unsigned RegNo) { - return SparcInstPrinter::getRegisterName(RegNo); + static const char *getRegisterName(MCRegister Reg) { + return SparcInstPrinter::getRegisterName(Reg); } bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index e6d23f741ea5..8afd0a7fc09a 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -125,10 +125,14 @@ def CC_Sparc64 : CallingConv<[ def RetCC_Sparc64 : CallingConv<[ // A single f32 return value always goes in %f0. The ABI doesn't specify what // happens to multiple f32 return values outside a struct. - CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>, + CCIfType<[f32], CCCustom<"RetCC_Sparc64_Half">>, - // Otherwise, return values are passed exactly like arguments. - CCDelegateTo<CC_Sparc64> + // Otherwise, return values are passed exactly like arguments, except that + // returns that are too big to fit into the registers is passed as an sret + // instead. + CCIfInReg<CCIfType<[i32, f32], CCCustom<"RetCC_Sparc64_Half">>>, + CCIfType<[i32], CCPromoteToType<i64>>, + CCCustom<"RetCC_Sparc64_Full"> ]>; // Callee-saved registers are handled by the register window mechanism. diff --git a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp index c5d0f1de7dfd..8339f5c42908 100644 --- a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -19,6 +19,9 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "sparc-isel" +#define PASS_NAME "SPARC DAG->DAG Pattern Instruction Selection" + //===----------------------------------------------------------------------===// // Instruction Selector Implementation //===----------------------------------------------------------------------===// @@ -33,7 +36,11 @@ class SparcDAGToDAGISel : public SelectionDAGISel { /// make the right decision when generating code for different targets. const SparcSubtarget *Subtarget = nullptr; public: - explicit SparcDAGToDAGISel(SparcTargetMachine &tm) : SelectionDAGISel(tm) {} + static char ID; + + SparcDAGToDAGISel() = delete; + + explicit SparcDAGToDAGISel(SparcTargetMachine &tm) : SelectionDAGISel(ID, tm) {} bool runOnMachineFunction(MachineFunction &MF) override { Subtarget = &MF.getSubtarget<SparcSubtarget>(); @@ -52,10 +59,6 @@ public: unsigned ConstraintID, std::vector<SDValue> &OutOps) override; - StringRef getPassName() const override { - return "SPARC DAG->DAG Pattern Instruction Selection"; - } - // Include the pieces autogenerated from the target description. #include "SparcGenDAGISel.inc" @@ -65,6 +68,10 @@ private: }; } // end anonymous namespace +char SparcDAGToDAGISel::ID = 0; + +INITIALIZE_PASS(SparcDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false) + SDNode* SparcDAGToDAGISel::getGlobalBaseReg() { Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); return CurDAG->getRegister(GlobalBaseReg, diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 2cb74e7709c7..913f133465b9 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -25,6 +25,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" @@ -101,9 +102,9 @@ static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, } // Allocate a full-sized argument for the 64-bit ABI. -static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) { +static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT, + MVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { assert((LocVT == MVT::f32 || LocVT == MVT::f128 || LocVT.getSizeInBits() == 64) && "Can't handle non-64 bits locations"); @@ -133,6 +134,11 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, return true; } + // Bail out if this is a return CC and we run out of registers to place + // values into. + if (IsReturn) + return false; + // This argument goes on the stack in an 8-byte slot. // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to // the right-aligned float. The first 4 bytes of the stack slot are undefined. @@ -146,9 +152,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, // Allocate a half-sized argument for the 64-bit ABI. // // This is used when passing { float, int } structs by value in registers. -static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) { +static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT, + MVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations"); unsigned Offset = State.AllocateStack(4, Align(4)); @@ -174,10 +180,43 @@ static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, return true; } + // Bail out if this is a return CC and we run out of registers to place + // values into. + if (IsReturn) + return false; + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); return true; } +static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + return Analyze_CC_Sparc64_Full(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, + State); +} + +static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + return Analyze_CC_Sparc64_Half(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags, + State); +} + +static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + return Analyze_CC_Sparc64_Full(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, + State); +} + +static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + return Analyze_CC_Sparc64_Half(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags, + State); +} + #include "SparcGenCallingConv.inc" // The calling conventions in SparcCallingConv.td are described in terms of the @@ -191,6 +230,15 @@ static unsigned toCallerWindow(unsigned Reg) { return Reg; } +bool SparcTargetLowering::CanLowerReturn( + CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { + SmallVector<CCValAssign, 16> RVLocs; + CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context); + return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64 + : RetCC_Sparc32); +} + SDValue SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, @@ -723,7 +771,10 @@ bool SparcTargetLowering::IsEligibleForTailCallOptimization( return false; // Do not tail call opt if the stack is used to pass parameters. - if (CCInfo.getNextStackOffset() != 0) + // 64-bit targets have a slightly higher limit since the ABI requires + // to allocate some space even when all the parameters fit inside registers. + unsigned StackOffsetLimit = Subtarget->is64Bit() ? 48 : 0; + if (CCInfo.getNextStackOffset() > StackOffsetLimit) return false; // Do not tail call opt if either the callee or caller returns @@ -1018,8 +1069,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops); InFlag = Chain.getValue(1); - Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, dl, true), - DAG.getIntPtrConstant(0, dl, true), InFlag, dl); + Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InFlag, dl); InFlag = Chain.getValue(1); // Assign locations to each value returned by this call. @@ -1031,6 +1081,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, // Copy all of the result registers out of their specified physreg. for (unsigned i = 0; i != RVLocs.size(); ++i) { + assert(RVLocs[i].isRegLoc() && "Can only return in registers!"); if (RVLocs[i].getLocVT() == MVT::v2i32) { SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32); SDValue Lo = DAG.getCopyFromReg( @@ -1091,7 +1142,7 @@ Register SparcTargetLowering::getRegisterByName(const char* RegName, LLT VT, static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs, ArrayRef<ISD::OutputArg> Outs) { for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - const CCValAssign &VA = ArgLocs[i]; + CCValAssign &VA = ArgLocs[i]; MVT ValTy = VA.getLocVT(); // FIXME: What about f32 arguments? C promotes them to f64 when calling // varargs functions. @@ -1102,8 +1153,6 @@ static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs, continue; // This floating point argument should be reassigned. - CCValAssign NewVA; - // Determine the offset into the argument array. Register firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0; unsigned argSize = (ValTy == MVT::f64) ? 8 : 16; @@ -1115,21 +1164,20 @@ static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs, unsigned IReg = SP::I0 + Offset/8; if (ValTy == MVT::f64) // Full register, just bitconvert into i64. - NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), - IReg, MVT::i64, CCValAssign::BCvt); + VA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), IReg, MVT::i64, + CCValAssign::BCvt); else { assert(ValTy == MVT::f128 && "Unexpected type!"); // Full register, just bitconvert into i128 -- We will lower this into // two i64s in LowerCall_64. - NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), - IReg, MVT::i128, CCValAssign::BCvt); + VA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), IReg, + MVT::i128, CCValAssign::BCvt); } } else { // This needs to go to memory, we're out of integer registers. - NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), - Offset, VA.getLocVT(), VA.getLocInfo()); + VA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), Offset, + VA.getLocVT(), VA.getLocInfo()); } - ArgLocs[i] = NewVA; } } @@ -1142,20 +1190,21 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, SDValue Chain = CLI.Chain; auto PtrVT = getPointerTy(DAG.getDataLayout()); - // Sparc target does not yet support tail call optimization. - CLI.IsTailCall = false; - // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64); + CLI.IsTailCall = CLI.IsTailCall && IsEligibleForTailCallOptimization( + CCInfo, CLI, DAG.getMachineFunction()); + // Get the size of the outgoing arguments stack space requirement. // The stack offset computed by CC_Sparc64 includes all arguments. // Called functions expect 6 argument words to exist in the stack frame, used // or not. - unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()); + unsigned StackReserved = 6 * 8u; + unsigned ArgsSize = std::max(StackReserved, CCInfo.getNextStackOffset()); // Keep stack frames 16-byte aligned. ArgsSize = alignTo(ArgsSize, 16); @@ -1164,10 +1213,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, if (CLI.IsVarArg) fixupVariableFloatArgs(ArgLocs, CLI.Outs); + assert(!CLI.IsTailCall || ArgsSize == StackReserved); + // Adjust the stack pointer to make room for the arguments. // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls // with more than 6 arguments. - Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL); + if (!CLI.IsTailCall) + Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL); // Collect the set of registers to pass to the function and their values. // This will be emitted as a sequence of CopyToReg nodes glued to the call @@ -1227,10 +1279,16 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, MachinePointerInfo()); SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, MachinePointerInfo()); - RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), - Hi64)); - RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1), - Lo64)); + + Register HiReg = VA.getLocReg(); + Register LoReg = VA.getLocReg() + 1; + if (!CLI.IsTailCall) { + HiReg = toCallerWindow(HiReg); + LoReg = toCallerWindow(LoReg); + } + + RegsToPass.push_back(std::make_pair(HiReg, Hi64)); + RegsToPass.push_back(std::make_pair(LoReg, Lo64)); continue; } @@ -1251,7 +1309,11 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, ++i; } } - RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), Arg)); + + Register Reg = VA.getLocReg(); + if (!CLI.IsTailCall) + Reg = toCallerWindow(Reg); + RegsToPass.push_back(std::make_pair(Reg, Arg)); continue; } @@ -1319,13 +1381,16 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, Ops.push_back(InGlue); // Now the call itself. + if (CLI.IsTailCall) { + DAG.getMachineFunction().getFrameInfo().setHasTailCall(); + return DAG.getNode(SPISD::TAIL_CALL, DL, MVT::Other, Ops); + } SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); Chain = DAG.getNode(SPISD::CALL, DL, NodeTys, Ops); InGlue = Chain.getValue(1); // Revert the stack pointer immediately after the call. - Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, DL, true), - DAG.getIntPtrConstant(0, DL, true), InGlue, DL); + Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, DL); InGlue = Chain.getValue(1); // Now extract the return values. This is more or less the same as @@ -1346,6 +1411,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, // Copy all of the result registers out of their specified physreg. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); unsigned Reg = toCallerWindow(VA.getLocReg()); // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can @@ -1405,6 +1471,27 @@ TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWIn return AtomicExpansionKind::CmpXChg; } +/// intCondCCodeToRcond - Convert a DAG integer condition code to a SPARC +/// rcond condition. +static SPCC::CondCodes intCondCCodeToRcond(ISD::CondCode CC) { + switch (CC) { + default: + llvm_unreachable("Unknown/unsigned integer condition code!"); + case ISD::SETEQ: + return SPCC::REG_Z; + case ISD::SETNE: + return SPCC::REG_NZ; + case ISD::SETLT: + return SPCC::REG_LZ; + case ISD::SETGT: + return SPCC::REG_GZ; + case ISD::SETLE: + return SPCC::REG_LEZ; + case ISD::SETGE: + return SPCC::REG_GEZ; + } +} + /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC /// condition. static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { @@ -1880,12 +1967,21 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { case SPISD::FIRST_NUMBER: break; case SPISD::CMPICC: return "SPISD::CMPICC"; case SPISD::CMPFCC: return "SPISD::CMPFCC"; + case SPISD::CMPFCC_V9: + return "SPISD::CMPFCC_V9"; case SPISD::BRICC: return "SPISD::BRICC"; - case SPISD::BRXCC: return "SPISD::BRXCC"; + case SPISD::BPICC: + return "SPISD::BPICC"; + case SPISD::BPXCC: + return "SPISD::BPXCC"; case SPISD::BRFCC: return "SPISD::BRFCC"; + case SPISD::BRFCC_V9: + return "SPISD::BRFCC_V9"; case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC"; case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; + case SPISD::SELECT_REG: + return "SPISD::SELECT_REG"; case SPISD::Hi: return "SPISD::Hi"; case SPISD::Lo: return "SPISD::Lo"; case SPISD::FTOI: return "SPISD::FTOI"; @@ -1942,15 +2038,14 @@ void SparcTargetLowering::computeKnownBitsForTargetNode // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, ISD::CondCode CC, unsigned &SPCC) { - if (isNullConstant(RHS) && - CC == ISD::SETNE && + if (isNullConstant(RHS) && CC == ISD::SETNE && (((LHS.getOpcode() == SPISD::SELECT_ICC || LHS.getOpcode() == SPISD::SELECT_XCC) && LHS.getOperand(3).getOpcode() == SPISD::CMPICC) || (LHS.getOpcode() == SPISD::SELECT_FCC && - LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && - isOneConstant(LHS.getOperand(0)) && - isNullConstant(LHS.getOperand(1))) { + (LHS.getOperand(3).getOpcode() == SPISD::CMPFCC || + LHS.getOperand(3).getOpcode() == SPISD::CMPFCC_V9))) && + isOneConstant(LHS.getOperand(0)) && isNullConstant(LHS.getOperand(1))) { SDValue CMPCC = LHS.getOperand(3); SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue(); LHS = CMPCC.getOperand(0); @@ -2125,8 +2220,7 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, InFlag}; Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops); InFlag = Chain.getValue(1); - Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(1, DL, true), - DAG.getIntPtrConstant(0, DL, true), InFlag, DL); + Chain = DAG.getCALLSEQ_END(Chain, 1, 0, InFlag, DL); InFlag = Chain.getValue(1); SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag); @@ -2487,8 +2581,8 @@ static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG, } static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { + const SparcTargetLowering &TLI, bool hasHardQuad, + bool isV9) { SDValue Chain = Op.getOperand(0); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); SDValue LHS = Op.getOperand(2); @@ -2500,23 +2594,29 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG, // If this is a br_cc of a "setcc", and if the setcc got lowered into // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. LookThroughSetCC(LHS, RHS, CC, SPCC); + assert(LHS.getValueType() == RHS.getValueType()); // Get the condition flag. SDValue CompareFlag; if (LHS.getValueType().isInteger()) { CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); - // 32-bit compares use the icc flags, 64-bit uses the xcc flags. - Opc = LHS.getValueType() == MVT::i32 ? SPISD::BRICC : SPISD::BRXCC; + if (isV9) + // 32-bit compares use the icc flags, 64-bit uses the xcc flags. + Opc = LHS.getValueType() == MVT::i32 ? SPISD::BPICC : SPISD::BPXCC; + else + // Non-v9 targets don't have xcc. + Opc = SPISD::BRICC; } else { if (!hasHardQuad && LHS.getValueType() == MVT::f128) { if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); - Opc = SPISD::BRICC; + Opc = isV9 ? SPISD::BPICC : SPISD::BRICC; } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); + unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC; + CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS); if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); - Opc = SPISD::BRFCC; + Opc = isV9 ? SPISD::BRFCC_V9 : SPISD::BRFCC; } } return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest, @@ -2524,8 +2624,8 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG, } static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { + const SparcTargetLowering &TLI, bool hasHardQuad, + bool isV9, bool is64Bit) { SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); @@ -2537,9 +2637,26 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, // If this is a select_cc of a "setcc", and if the setcc got lowered into // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. LookThroughSetCC(LHS, RHS, CC, SPCC); + assert(LHS.getValueType() == RHS.getValueType()); SDValue CompareFlag; if (LHS.getValueType().isInteger()) { + // On V9 processors running in 64-bit mode, if CC compares two `i64`s + // and the RHS is zero we might be able to use a specialized select. + // All SELECT_CC between any two scalar integer types are eligible for + // lowering to specialized instructions. Additionally, f32 and f64 types + // are also eligible, but for f128 we can only use the specialized + // instruction when we have hardquad. + EVT ValType = TrueVal.getValueType(); + bool IsEligibleType = ValType.isScalarInteger() || ValType == MVT::f32 || + ValType == MVT::f64 || + (ValType == MVT::f128 && hasHardQuad); + if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 && + isNullConstant(RHS) && !ISD::isUnsignedIntSetCC(CC) && IsEligibleType) + return DAG.getNode( + SPISD::SELECT_REG, dl, TrueVal.getValueType(), TrueVal, FalseVal, + DAG.getConstant(intCondCCodeToRcond(CC), dl, MVT::i32), LHS); + CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); Opc = LHS.getValueType() == MVT::i32 ? SPISD::SELECT_ICC : SPISD::SELECT_XCC; @@ -2550,7 +2667,8 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); Opc = SPISD::SELECT_ICC; } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); + unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC; + CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS); Opc = SPISD::SELECT_FCC; if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); } @@ -2600,7 +2718,7 @@ static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { // We can't count on greater alignment than the word size. return DAG.getLoad( VT, DL, InChain, VAList, MachinePointerInfo(), - std::min(PtrVT.getFixedSizeInBits(), VT.getFixedSizeInBits()) / 8); + Align(std::min(PtrVT.getFixedSizeInBits(), VT.getFixedSizeInBits()) / 8)); } static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, @@ -3075,6 +3193,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { bool hasHardQuad = Subtarget->hasHardQuad(); bool isV9 = Subtarget->isV9(); + bool is64Bit = Subtarget->is64Bit(); switch (Op.getOpcode()) { default: llvm_unreachable("Should not custom lower this!"); @@ -3095,10 +3214,10 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { hasHardQuad); case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, *this, hasHardQuad); - case ISD::BR_CC: return LowerBR_CC(Op, DAG, *this, - hasHardQuad); - case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this, - hasHardQuad); + case ISD::BR_CC: + return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9); + case ISD::SELECT_CC: + return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit); case ISD::VASTART: return LowerVASTART(Op, DAG, *this); case ISD::VAARG: return LowerVAARG(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG, @@ -3175,6 +3294,8 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, case SP::SELECT_CC_FP_ICC: case SP::SELECT_CC_DFP_ICC: case SP::SELECT_CC_QFP_ICC: + if (Subtarget->isV9()) + return expandSelectCC(MI, BB, SP::BPICC); return expandSelectCC(MI, BB, SP::BCOND); case SP::SELECT_CC_Int_XCC: case SP::SELECT_CC_FP_XCC: @@ -3185,6 +3306,8 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, case SP::SELECT_CC_FP_FCC: case SP::SELECT_CC_DFP_FCC: case SP::SELECT_CC_QFP_FCC: + if (Subtarget->isV9()) + return expandSelectCC(MI, BB, SP::FBCOND_V9); return expandSelectCC(MI, BB, SP::FBCOND); } } diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index 2768bb20566a..563a832ee61e 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -21,37 +21,43 @@ namespace llvm { class SparcSubtarget; namespace SPISD { - enum NodeType : unsigned { - FIRST_NUMBER = ISD::BUILTIN_OP_END, - CMPICC, // Compare two GPR operands, set icc+xcc. - CMPFCC, // Compare two FP operands, set fcc. - BRICC, // Branch to dest on icc condition - BRXCC, // Branch to dest on xcc condition (64-bit only). - BRFCC, // Branch to dest on fcc condition - SELECT_ICC, // Select between two values using the current ICC flags. - SELECT_XCC, // Select between two values using the current XCC flags. - SELECT_FCC, // Select between two values using the current FCC flags. - - Hi, Lo, // Hi/Lo operations, typically on a global address. - - FTOI, // FP to Int within a FP register. - ITOF, // Int to FP within a FP register. - FTOX, // FP to Int64 within a FP register. - XTOF, // Int64 to FP within a FP register. - - CALL, // A call instruction. - RET_FLAG, // Return with a flag operand. - GLOBAL_BASE_REG, // Global base reg for PIC. - FLUSHW, // FLUSH register windows to stack. - - TAIL_CALL, // Tail call - - TLS_ADD, // For Thread Local Storage (TLS). - TLS_LD, - TLS_CALL, - - LOAD_GDOP, // Load operation w/ gdop relocation. - }; + enum NodeType : unsigned { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + CMPICC, // Compare two GPR operands, set icc+xcc. + CMPFCC, // Compare two FP operands, set fcc. + CMPFCC_V9, // Compare two FP operands, set fcc (v9 variant). + BRICC, // Branch to dest on icc condition + BPICC, // Branch to dest on icc condition, with prediction (64-bit only). + BPXCC, // Branch to dest on xcc condition, with prediction (64-bit only). + BRFCC, // Branch to dest on fcc condition + BRFCC_V9, // Branch to dest on fcc condition (v9 variant). + SELECT_ICC, // Select between two values using the current ICC flags. + SELECT_XCC, // Select between two values using the current XCC flags. + SELECT_FCC, // Select between two values using the current FCC flags. + SELECT_REG, // Select between two values using the comparison of a register + // with zero. + + Hi, + Lo, // Hi/Lo operations, typically on a global address. + + FTOI, // FP to Int within a FP register. + ITOF, // Int to FP within a FP register. + FTOX, // FP to Int64 within a FP register. + XTOF, // Int64 to FP within a FP register. + + CALL, // A call instruction. + RET_FLAG, // Return with a flag operand. + GLOBAL_BASE_REG, // Global base reg for PIC. + FLUSHW, // FLUSH register windows to stack. + + TAIL_CALL, // Tail call + + TLS_ADD, // For Thread Local Storage (TLS). + TLS_LD, + TLS_CALL, + + LOAD_GDOP, // Load operation w/ gdop relocation. + }; } class SparcTargetLowering : public TargetLowering { @@ -144,6 +150,11 @@ namespace llvm { SDValue LowerCall_64(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const; + bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, + bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + LLVMContext &Context) const override; + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td index a471d65201c3..77f203fd0d68 100644 --- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -60,6 +60,10 @@ defm SRAX : F3_S<"srax", 0b100111, 1, sra, i64, shift_imm6, I64Regs>; // Single-instruction patterns. +// Zero immediate. +def : Pat<(i64 0), (COPY (i64 G0))>, + Requires<[Is64Bit]>; + // The ALU instructions want their simm13 operands as i32 immediates. def as_i32imm : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32); @@ -147,17 +151,17 @@ defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>; defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>; def ANDXNrr : F3_1<2, 0b000101, - (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), - "andn $b, $c, $dst", - [(set i64:$dst, (and i64:$b, (not i64:$c)))]>; + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2), + "andn $rs1, $rs2, $rd", + [(set i64:$rd, (and i64:$rs1, (not i64:$rs2)))]>; def ORXNrr : F3_1<2, 0b000110, - (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), - "orn $b, $c, $dst", - [(set i64:$dst, (or i64:$b, (not i64:$c)))]>; + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2), + "orn $rs1, $rs2, $rd", + [(set i64:$rd, (or i64:$rs1, (not i64:$rs2)))]>; def XNORXrr : F3_1<2, 0b000111, - (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), - "xnor $b, $c, $dst", - [(set i64:$dst, (not (xor i64:$b, i64:$c)))]>; + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2), + "xnor $rs1, $rs2, $rd", + [(set i64:$rd, (not (xor i64:$rs1, i64:$rs2)))]>; defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>; defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>; @@ -170,9 +174,9 @@ def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd), // "LEA" form of add def LEAX_ADDri : F3_2<2, 0b000000, - (outs I64Regs:$dst), (ins MEMri:$addr), - "add ${addr:arith}, $dst", - [(set iPTR:$dst, ADDRri:$addr)]>; + (outs I64Regs:$rd), (ins (MEMri $rs1, $simm13):$addr), + "add ${addr:arith}, $rd", + [(set iPTR:$rd, ADDRri:$addr)]>; } def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>; @@ -235,21 +239,20 @@ def UDIVXri : F3_2<2, 0b001101, let Predicates = [Is64Bit] in { // 64-bit loads. -let DecoderMethod = "DecodeLoadInt" in - defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>; +defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>; let mayLoad = 1, isAsmParserOnly = 1 in { def TLS_LDXrr : F3_1<3, 0b001011, - (outs IntRegs:$dst), - (ins MEMrr:$addr, TailRelocSymTLSLoad:$sym), - "ldx [$addr], $dst, $sym", - [(set i64:$dst, + (outs IntRegs:$rd), + (ins (MEMrr $rs1, $rs2):$addr, TailRelocSymTLSLoad:$sym), + "ldx [$addr], $rd, $sym", + [(set i64:$rd, (tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>; def GDOP_LDXrr : F3_1<3, 0b001011, - (outs I64Regs:$dst), - (ins MEMrr:$addr, TailRelocSymGOTLoad:$sym), - "ldx [$addr], $dst, $sym", - [(set i64:$dst, + (outs I64Regs:$rd), + (ins (MEMrr $rs1, $rs2):$addr, TailRelocSymGOTLoad:$sym), + "ldx [$addr], $rd, $sym", + [(set i64:$rd, (load_gdop ADDRrr:$addr, tglobaladdr:$sym))]>; } @@ -279,12 +282,10 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>; def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; // Sign-extending load of i32 into i64 is a new SPARC v9 instruction. -let DecoderMethod = "DecodeLoadInt" in - defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>; +defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>; // 64-bit stores. -let DecoderMethod = "DecodeStoreInt" in - defm STX : Store<"stx", 0b001110, store, I64Regs, i64>; +defm STX : Store<"stx", 0b001110, store, I64Regs, i64>; // Truncating stores from i64 are identical to the i32 stores. def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>; @@ -310,13 +311,13 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADDRri:$dst, (i64 G0))>; // The icc flags correspond to the 32-bit result, and the xcc are for the // full 64-bit result. // -// We reuse CMPICC SDNodes for compares, but use new BRXCC branch nodes for +// We reuse CMPICC SDNodes for compares, but use new BPXCC branch nodes for // 64-bit compares. See LowerBR_CC. let Predicates = [Is64Bit] in { let Uses = [ICC], cc = 0b10 in - defm BPX : IPredBranch<"%xcc", [(SPbrxcc bb:$imm19, imm:$cond)]>; + defm BPX : IPredBranch<"%xcc", [(SPbpxcc bb:$imm19, imm:$cond)]>; // Conditional moves on %xcc. let Uses = [ICC], Constraints = "$f = $rd" in { @@ -388,47 +389,33 @@ defm : bpr_alias<"brgz", BPGZnapt, BPGZapt >; defm : bpr_alias<"brgez", BPGEZnapt, BPGEZapt>; // Move integer register on register condition (MOVr). -multiclass MOVR< bits<3> rcond, string OpcStr> { - def rr : F4_4r<0b101111, 0b00000, rcond, (outs I64Regs:$rd), - (ins I64Regs:$rs1, IntRegs:$rs2), - !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>; - - def ri : F4_4i<0b101111, rcond, (outs I64Regs:$rd), - (ins I64Regs:$rs1, i64imm:$simm10), - !strconcat(OpcStr, " $rs1, $simm10, $rd"), []>; +let Predicates = [Is64Bit], Constraints = "$f = $rd" in { + def MOVRrr : F4_4r<0b101111, 0b00000, (outs IntRegs:$rd), + (ins I64Regs:$rs1, IntRegs:$rs2, IntRegs:$f, RegCCOp:$rcond), + "movr$rcond $rs1, $rs2, $rd", + [(set i32:$rd, (SPselectreg i32:$rs2, i32:$f, imm:$rcond, i64:$rs1))]>; + + def MOVRri : F4_4i<0b101111, (outs IntRegs:$rd), + (ins I64Regs:$rs1, i32imm:$simm10, IntRegs:$f, RegCCOp:$rcond), + "movr$rcond $rs1, $simm10, $rd", + [(set i32:$rd, (SPselectreg simm10:$simm10, i32:$f, imm:$rcond, i64:$rs1))]>; } -defm MOVRRZ : MOVR<0b001, "movrz">; -defm MOVRLEZ : MOVR<0b010, "movrlez">; -defm MOVRLZ : MOVR<0b011, "movrlz">; -defm MOVRNZ : MOVR<0b101, "movrnz">; -defm MOVRGZ : MOVR<0b110, "movrgz">; -defm MOVRGEZ : MOVR<0b111, "movrgez">; - // Move FP register on integer register condition (FMOVr). -multiclass FMOVR<bits<3> rcond, string OpcStr> { - - def S : F4_4r<0b110101, 0b00101, rcond, - (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), - !strconcat(!strconcat("fmovrs", OpcStr)," $rs1, $rs2, $rd"), - []>; - def D : F4_4r<0b110101, 0b00110, rcond, - (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), - !strconcat(!strconcat("fmovrd", OpcStr)," $rs1, $rs2, $rd"), - []>; - def Q : F4_4r<0b110101, 0b00111, rcond, - (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), - !strconcat(!strconcat("fmovrq", OpcStr)," $rs1, $rs2, $rd"), - []>, Requires<[HasHardQuad]>; -} - -let Predicates = [HasV9] in { - defm FMOVRZ : FMOVR<0b001, "z">; - defm FMOVRLEZ : FMOVR<0b010, "lez">; - defm FMOVRLZ : FMOVR<0b011, "lz">; - defm FMOVRNZ : FMOVR<0b101, "nz">; - defm FMOVRGZ : FMOVR<0b110, "gz">; - defm FMOVRGEZ : FMOVR<0b111, "gez">; +let Predicates = [Is64Bit], Constraints = "$f = $rd" in { + def FMOVRS : F4_4r<0b110101, 0b00101, + (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2, FPRegs:$f, RegCCOp:$rcond), + "fmovrs$rcond $rs1, $rs2, $rd", + [(set f32:$rd, (SPselectreg f32:$rs2, f32:$f, imm:$rcond, i64:$rs1))]>; + def FMOVRD : F4_4r<0b110101, 0b00110, + (outs DFPRegs:$rd), (ins I64Regs:$rs1, DFPRegs:$rs2, DFPRegs:$f, RegCCOp:$rcond), + "fmovrd$rcond $rs1, $rs2, $rd", + [(set f64:$rd, (SPselectreg f64:$rs2, f64:$f, imm:$rcond, i64:$rs1))]>; + let Predicates = [HasHardQuad] in + def FMOVRQ : F4_4r<0b110101, 0b00111, + (outs QFPRegs:$rd), (ins I64Regs:$rs1, QFPRegs:$rs2, QFPRegs:$f, RegCCOp:$rcond), + "fmovrq$rcond $rs1, $rs2, $rd", + [(set f128:$rd, (SPselectreg f128:$rs2, f128:$f, imm:$rcond, i64:$rs1))]>; } //===----------------------------------------------------------------------===// @@ -482,6 +469,11 @@ def : Pat<(SPselectfcc i64:$t, i64:$f, imm:$cond), def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, imm:$cond), (MOVFCCri (as_i32imm $t), $f, imm:$cond)>; +def : Pat<(SPselectreg i64:$t, i64:$f, imm:$rcond, i64:$rs1), + (MOVRrr $rs1, $t, $f, imm:$rcond)>; +def : Pat<(SPselectreg (i64 simm10:$t), i64:$f, imm:$rcond, i64:$rs1), + (MOVRri $rs1, (as_i32imm $t), $f, imm:$rcond)>; + } // Predicates = [Is64Bit] diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td index 1b3ec199fc16..f10021321406 100644 --- a/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td @@ -59,6 +59,34 @@ multiclass fpcond_mov_alias<string cond, int condVal, (fmovd DFPRegs:$rd, FCCRegs:$cc, DFPRegs:$rs2, condVal)>; } +// movr<cond> rs1, rs2, rd +multiclass regcond_mov_alias<string rcond, int condVal, + Instruction movrrr, Instruction movrri, + Instruction fmovrs, Instruction fmovrd, + Instruction fmovrq> { + + // movr<cond> $rs1, $rs2, $rd + def : InstAlias<!strconcat(!strconcat("movr", rcond), " $rs1, $rs2, $rd"), + (movrrr IntRegs:$rd, I64Regs:$rs1, IntRegs:$rs2, condVal)>; + + // movr<cond> $rs1, $simm10, $rd + def : InstAlias<!strconcat(!strconcat("movr", rcond), " $rs1, $simm10, $rd"), + (movrri IntRegs:$rd, I64Regs:$rs1, i32imm:$simm10, condVal)>; + + // fmovrs<cond> $rs1, $rs2, $rd + def : InstAlias<!strconcat(!strconcat("fmovrs", rcond), " $rs1, $rs2, $rd"), + (fmovrs FPRegs:$rd, I64Regs:$rs1, FPRegs:$rs2, condVal)>; + + // fmovrd<cond> $rs1, $rs2, $rd + def : InstAlias<!strconcat(!strconcat("fmovrd", rcond), " $rs1, $rs2, $rd"), + (fmovrd DFPRegs:$rd, I64Regs:$rs1, DFPRegs:$rs2, condVal)>; + + // fmovrq<cond> $rs1, $rs2, $rd + let Predicates = [HasHardQuad] in + def : InstAlias<!strconcat(!strconcat("fmovrq", rcond), " $rs1, $rs2, $rd"), + (fmovrq QFPRegs:$rd, I64Regs:$rs1, QFPRegs:$rs2, condVal)>; +} + // Instruction aliases for integer conditional branches and moves. multiclass int_cond_alias<string cond, int condVal> { @@ -265,6 +293,14 @@ multiclass cp_cond_alias<string cond, int condVal> { (CBCONDA brtarget:$imm, condVal), 0>; } +// Instruction aliases for register conditional branches and moves. +multiclass reg_cond_alias<string rcond, int condVal> { + defm : regcond_mov_alias<rcond, condVal, + MOVRrr, MOVRri, + FMOVRS, FMOVRD, FMOVRQ>, + Requires<[Is64Bit]>; +} + defm : int_cond_alias<"a", 0b1000>; defm : int_cond_alias<"n", 0b0000>; defm : int_cond_alias<"ne", 0b1001>; @@ -331,6 +367,13 @@ defm : cp_cond_alias<"013", 0b1110>; defm : cp_cond_alias<"012", 0b1111>; let EmitPriority = 0 in defm : cp_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual +defm : reg_cond_alias<"z", 0b001>; +defm : reg_cond_alias<"lez", 0b010>; +defm : reg_cond_alias<"lz", 0b011>; +defm : reg_cond_alias<"nz", 0b101>; +defm : reg_cond_alias<"gz", 0b110>; +defm : reg_cond_alias<"gez", 0b111>; + // Section A.3 Synthetic Instructions // Most are marked as Emit=0, so that they are not used for disassembly. This is @@ -473,6 +516,14 @@ def : InstAlias<"wr $simm13, %tbr", (WRTBRri G0, i32imm:$simm13), 0>; def : InstAlias<"pwr $rs2, %psr", (PWRPSRrr G0, IntRegs:$rs2), 0>; def : InstAlias<"pwr $simm13, %psr", (PWRPSRri G0, i32imm:$simm13), 0>; +// wrpr %reg, %rd -> wrpr %reg, %g0, %rd +// wrpr imm, %rd -> wrpr %g0, imm, %rd +// Nonstandard GNU extensions. +let Predicates = [HasV9] in { + def : InstAlias<"wrpr $rs1, $rd", (WRPRrr PRRegs:$rd, IntRegs:$rs1, G0), 0>; + def : InstAlias<"wrpr $simm13, $rd", (WRPRri PRRegs:$rd, G0, i32imm:$simm13), 0>; +} + // flush -> flush %g0 def : InstAlias<"flush", (FLUSH), 0>; diff --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td index 259ce967f2df..522dcd96a112 100644 --- a/llvm/lib/Target/Sparc/SparcInstrFormats.td +++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td @@ -296,12 +296,13 @@ class F4_3<bits<6> op3, bits<6> opf_low, dag outs, dag ins, let Inst{4-0} = rs2; } -class F4_4r<bits<6> op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins, +class F4_4r<bits<6> op3, bits<5> opf_low, dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin = NoItinerary> : F4<op3, outs, ins, asmstr, pattern, itin> { - bits <5> rs1; - bits <5> rs2; + bits<5> rs1; + bits<5> rs2; + bits<3> rcond; let Inst{18-14} = rs1; let Inst{13} = 0; // IsImm let Inst{12-10} = rcond; @@ -310,12 +311,13 @@ class F4_4r<bits<6> op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins, } -class F4_4i<bits<6> op3, bits<3> rcond, dag outs, dag ins, +class F4_4i<bits<6> op3, dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin = NoItinerary> : F4<op3, outs, ins, asmstr, pattern, itin> { - bits<5> rs1; + bits<5> rs1; bits<10> simm10; + bits<3> rcond; let Inst{18-14} = rs1; let Inst{13} = 1; // IsImm let Inst{12-10} = rcond; diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp index a8a0b2cc9e67..63f662c41f93 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp @@ -117,33 +117,63 @@ static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC) case SPCC::CPCC_A: return SPCC::CPCC_N; case SPCC::CPCC_N: return SPCC::CPCC_A; - case SPCC::CPCC_3: LLVM_FALLTHROUGH; - case SPCC::CPCC_2: LLVM_FALLTHROUGH; - case SPCC::CPCC_23: LLVM_FALLTHROUGH; - case SPCC::CPCC_1: LLVM_FALLTHROUGH; - case SPCC::CPCC_13: LLVM_FALLTHROUGH; - case SPCC::CPCC_12: LLVM_FALLTHROUGH; - case SPCC::CPCC_123: LLVM_FALLTHROUGH; - case SPCC::CPCC_0: LLVM_FALLTHROUGH; - case SPCC::CPCC_03: LLVM_FALLTHROUGH; - case SPCC::CPCC_02: LLVM_FALLTHROUGH; - case SPCC::CPCC_023: LLVM_FALLTHROUGH; - case SPCC::CPCC_01: LLVM_FALLTHROUGH; - case SPCC::CPCC_013: LLVM_FALLTHROUGH; + case SPCC::CPCC_3: [[fallthrough]]; + case SPCC::CPCC_2: [[fallthrough]]; + case SPCC::CPCC_23: [[fallthrough]]; + case SPCC::CPCC_1: [[fallthrough]]; + case SPCC::CPCC_13: [[fallthrough]]; + case SPCC::CPCC_12: [[fallthrough]]; + case SPCC::CPCC_123: [[fallthrough]]; + case SPCC::CPCC_0: [[fallthrough]]; + case SPCC::CPCC_03: [[fallthrough]]; + case SPCC::CPCC_02: [[fallthrough]]; + case SPCC::CPCC_023: [[fallthrough]]; + case SPCC::CPCC_01: [[fallthrough]]; + case SPCC::CPCC_013: [[fallthrough]]; case SPCC::CPCC_012: // "Opposite" code is not meaningful, as we don't know // what the CoProc condition means here. The cond-code will // only be used in inline assembler, so this code should // not be reached in a normal compilation pass. llvm_unreachable("Meaningless inversion of co-processor cond code"); + + case SPCC::REG_BEGIN: + llvm_unreachable("Use of reserved cond code"); + case SPCC::REG_Z: + return SPCC::REG_NZ; + case SPCC::REG_LEZ: + return SPCC::REG_GZ; + case SPCC::REG_LZ: + return SPCC::REG_GEZ; + case SPCC::REG_NZ: + return SPCC::REG_Z; + case SPCC::REG_GZ: + return SPCC::REG_LEZ; + case SPCC::REG_GEZ: + return SPCC::REG_LZ; } llvm_unreachable("Invalid cond code"); } -static bool isUncondBranchOpcode(int Opc) { return Opc == SP::BA; } +static bool isUncondBranchOpcode(int Opc) { + return Opc == SP::BA || Opc == SP::BPA; +} + +static bool isI32CondBranchOpcode(int Opc) { + return Opc == SP::BCOND || Opc == SP::BPICC || Opc == SP::BPICCA || + Opc == SP::BPICCNT || Opc == SP::BPICCANT; +} + +static bool isI64CondBranchOpcode(int Opc) { + return Opc == SP::BPXCC || Opc == SP::BPXCCA || Opc == SP::BPXCCNT || + Opc == SP::BPXCCANT; +} + +static bool isFCondBranchOpcode(int Opc) { return Opc == SP::FBCOND; } static bool isCondBranchOpcode(int Opc) { - return Opc == SP::FBCOND || Opc == SP::BCOND; + return isI32CondBranchOpcode(Opc) || isI64CondBranchOpcode(Opc) || + isFCondBranchOpcode(Opc); } static bool isIndirectBranchOpcode(int Opc) { @@ -152,7 +182,14 @@ static bool isIndirectBranchOpcode(int Opc) { static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl<MachineOperand> &Cond) { - Cond.push_back(MachineOperand::CreateImm(LastInst->getOperand(1).getImm())); + unsigned Opc = LastInst->getOpcode(); + int64_t CC = LastInst->getOperand(1).getImm(); + + // Push the branch opcode into Cond too so later in insertBranch + // it can use the information to emit the correct SPARC branch opcode. + Cond.push_back(MachineOperand::CreateImm(Opc)); + Cond.push_back(MachineOperand::CreateImm(CC)); + Target = LastInst->getOperand(0).getMBB(); } @@ -246,27 +283,29 @@ unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB, const DebugLoc &DL, int *BytesAdded) const { assert(TBB && "insertBranch must not be told to insert a fallthrough"); - assert((Cond.size() == 1 || Cond.size() == 0) && - "Sparc branch conditions should have one component!"); + assert((Cond.size() <= 2) && + "Sparc branch conditions should have at most two components!"); assert(!BytesAdded && "code size not handled"); if (Cond.empty()) { assert(!FBB && "Unconditional branch with multiple successors!"); - BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB); + BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(TBB); return 1; } // Conditional branch - unsigned CC = Cond[0].getImm(); + unsigned Opc = Cond[0].getImm(); + unsigned CC = Cond[1].getImm(); - if (IsIntegerCC(CC)) - BuildMI(&MBB, DL, get(SP::BCOND)).addMBB(TBB).addImm(CC); - else + if (IsIntegerCC(CC)) { + BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC); + } else { BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC); + } if (!FBB) return 1; - BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB); + BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(FBB); return 2; } @@ -282,9 +321,8 @@ unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB, if (I->isDebugInstr()) continue; - if (I->getOpcode() != SP::BA - && I->getOpcode() != SP::BCOND - && I->getOpcode() != SP::FBCOND) + if (!isCondBranchOpcode(I->getOpcode()) && + !isUncondBranchOpcode(I->getOpcode())) break; // Not a branch I->eraseFromParent(); @@ -296,9 +334,9 @@ unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB, bool SparcInstrInfo::reverseBranchCondition( SmallVectorImpl<MachineOperand> &Cond) const { - assert(Cond.size() == 1); - SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[0].getImm()); - Cond[0].setImm(GetOppositeBranchCondition(CC)); + assert(Cond.size() <= 2); + SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[1].getImm()); + Cond[1].setImm(GetOppositeBranchCondition(CC)); return false; } @@ -391,11 +429,12 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MovMI->addRegisterKilled(SrcReg, TRI); } -void SparcInstrInfo:: -storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - Register SrcReg, bool isKill, int FI, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { +void SparcInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + Register SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI, + Register VReg) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); @@ -430,11 +469,12 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, llvm_unreachable("Can't store this register to stack slot"); } -void SparcInstrInfo:: -loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - Register DestReg, int FI, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { +void SparcInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + Register DestReg, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI, + Register VReg) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.h b/llvm/lib/Target/Sparc/SparcInstrInfo.h index b25de8e5a690..39cf791c2173 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.h +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.h @@ -85,16 +85,17 @@ public: bool KillSrc) const override; void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - Register SrcReg, bool isKill, int FrameIndex, + MachineBasicBlock::iterator MBBI, Register SrcReg, + bool isKill, int FrameIndex, const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const override; + const TargetRegisterInfo *TRI, + Register VReg) const override; void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - Register DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const override; + MachineBasicBlock::iterator MBBI, Register DestReg, + int FrameIndex, const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI, + Register VReg) const override; Register getGlobalBaseReg(MachineFunction *MF) const; diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index 481bd7d2f7fa..2c45a7218d04 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -78,6 +78,8 @@ def UseDeprecatedInsts : Predicate<"Subtarget->useDeprecatedV8Instructions()">; // Instruction Pattern Stuff //===----------------------------------------------------------------------===// +def simm10 : PatLeaf<(imm), [{ return isInt<10>(N->getSExtValue()); }]>; + def simm11 : PatLeaf<(imm), [{ return isInt<11>(N->getSExtValue()); }]>; def simm13 : PatLeaf<(imm), [{ return isInt<13>(N->getSExtValue()); }]>; @@ -211,8 +213,10 @@ def simm13Op : Operand<i32> { } // Operand for printing out a condition code. -let PrintMethod = "printCCOperand" in +let PrintMethod = "printCCOperand" in { def CCOp : Operand<i32>; + def RegCCOp : Operand<i32>; +} def SDTSPcmpicc : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>; @@ -222,6 +226,8 @@ def SDTSPbrcc : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>; def SDTSPselectcc : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>]>; +def SDTSPselectreg : +SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>, SDTCisVT<4, i64>]>; def SDTSPFTOI : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>; def SDTSPITOF : @@ -241,9 +247,12 @@ SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>; def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>; def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>; +def SPcmpfccv9 : SDNode<"SPISD::CMPFCC_V9", SDTSPcmpfcc, [SDNPOutGlue]>; def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; -def SPbrxcc : SDNode<"SPISD::BRXCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; +def SPbpicc : SDNode<"SPISD::BPICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; +def SPbpxcc : SDNode<"SPISD::BPXCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; def SPbrfcc : SDNode<"SPISD::BRFCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; +def SPbrfccv9 : SDNode<"SPISD::BRFCC_V9", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; def SPhi : SDNode<"SPISD::Hi", SDTIntUnaryOp>; def SPlo : SDNode<"SPISD::Lo", SDTIntUnaryOp>; @@ -256,6 +265,7 @@ def SPxtof : SDNode<"SPISD::XTOF", SDTSPXTOF>; def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInGlue]>; def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>; def SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInGlue]>; +def SPselectreg : SDNode<"SPISD::SELECT_REG", SDTSPselectreg, [SDNPInGlue]>; // These are target-independent nodes, but have target-specific formats. def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>, @@ -350,6 +360,14 @@ def CPCC_01 : CPCC_VAL<45>; // 0 or 1 def CPCC_013 : CPCC_VAL<46>; // 0 or 1 or 3 def CPCC_012 : CPCC_VAL<47>; // 0 or 1 or 2 +class RegCC_VAL<int N> : PatLeaf<(i32 N)>; +def RegCC_Z : RegCC_VAL<49>; // Zero +def RegCC_LEZ : RegCC_VAL<50>; // Lees or equal than zero +def RegCC_LZ : RegCC_VAL<51>; // Less than zero +def RegCC_NZ : RegCC_VAL<53>; // Not zero +def RegCC_GZ : RegCC_VAL<54>; // Greater than zero +def RegCC_GEZ : RegCC_VAL<55>; // Greater or equal to zero + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -387,22 +405,22 @@ multiclass F3_12np<string OpcStr, bits<6> Op3Val, InstrItinClass itin = IIC_iu_i multiclass Load<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode, RegisterClass RC, ValueType Ty, InstrItinClass itin = IIC_iu_instr> { def rr : F3_1<3, Op3Val, - (outs RC:$dst), (ins MEMrr:$addr), - !strconcat(OpcStr, " [$addr], $dst"), - [(set Ty:$dst, (OpNode ADDRrr:$addr))], + (outs RC:$rd), (ins (MEMrr $rs1, $rs2):$addr), + !strconcat(OpcStr, " [$addr], $rd"), + [(set Ty:$rd, (OpNode ADDRrr:$addr))], itin>; def ri : F3_2<3, Op3Val, - (outs RC:$dst), (ins MEMri:$addr), - !strconcat(OpcStr, " [$addr], $dst"), - [(set Ty:$dst, (OpNode ADDRri:$addr))], + (outs RC:$rd), (ins (MEMri $rs1, $simm13):$addr), + !strconcat(OpcStr, " [$addr], $rd"), + [(set Ty:$rd, (OpNode ADDRri:$addr))], itin>; } // TODO: Instructions of the LoadASI class are currently asm only; hooking up // CodeGen's address spaces to use these is a future task. class LoadASI<string OpcStr, bits<6> Op3Val, RegisterClass RC> : - F3_1_asi<3, Op3Val, (outs RC:$dst), (ins MEMrr:$addr, i8imm:$asi), - !strconcat(OpcStr, "a [$addr] $asi, $dst"), + F3_1_asi<3, Op3Val, (outs RC:$rd), (ins (MEMrr $rs1, $rs2):$addr, i8imm:$asi), + !strconcat(OpcStr, "a [$addr] $asi, $rd"), []>; // LoadA multiclass - As above, but also define alternate address space variant @@ -416,24 +434,24 @@ multiclass LoadA<string OpcStr, bits<6> Op3Val, bits<6> LoadAOp3Val, // The LDSTUB instruction is supported for asm only. // It is unlikely that general-purpose code could make use of it. // CAS is preferred for sparc v9. -def LDSTUBrr : F3_1<3, 0b001101, (outs IntRegs:$dst), (ins MEMrr:$addr), - "ldstub [$addr], $dst", []>; -def LDSTUBri : F3_2<3, 0b001101, (outs IntRegs:$dst), (ins MEMri:$addr), - "ldstub [$addr], $dst", []>; -def LDSTUBArr : F3_1_asi<3, 0b011101, (outs IntRegs:$dst), - (ins MEMrr:$addr, i8imm:$asi), - "ldstuba [$addr] $asi, $dst", []>; +def LDSTUBrr : F3_1<3, 0b001101, (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr), + "ldstub [$addr], $rd", []>; +def LDSTUBri : F3_2<3, 0b001101, (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr), + "ldstub [$addr], $rd", []>; +def LDSTUBArr : F3_1_asi<3, 0b011101, (outs IntRegs:$rd), + (ins (MEMrr $rs1, $rs2):$addr, i8imm:$asi), + "ldstuba [$addr] $asi, $rd", []>; // Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode, RegisterClass RC, ValueType Ty, InstrItinClass itin = IIC_st> { def rr : F3_1<3, Op3Val, - (outs), (ins MEMrr:$addr, RC:$rd), + (outs), (ins (MEMrr $rs1, $rs2):$addr, RC:$rd), !strconcat(OpcStr, " $rd, [$addr]"), [(OpNode Ty:$rd, ADDRrr:$addr)], itin>; def ri : F3_2<3, Op3Val, - (outs), (ins MEMri:$addr, RC:$rd), + (outs), (ins (MEMri $rs1, $simm13):$addr, RC:$rd), !strconcat(OpcStr, " $rd, [$addr]"), [(OpNode Ty:$rd, ADDRri:$addr)], itin>; @@ -443,7 +461,7 @@ multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode, // CodeGen's address spaces to use these is a future task. class StoreASI<string OpcStr, bits<6> Op3Val, RegisterClass RC, InstrItinClass itin = IIC_st> : - F3_1_asi<3, Op3Val, (outs), (ins MEMrr:$addr, RC:$rd, i8imm:$asi), + F3_1_asi<3, Op3Val, (outs), (ins (MEMrr $rs1, $rs2):$addr, RC:$rd, i8imm:$asi), !strconcat(OpcStr, "a $rd, [$addr] $asi"), [], itin>; @@ -558,154 +576,129 @@ let usesCustomInserter = 1, Uses = [FCC0] in { } // Section B.1 - Load Integer Instructions, p. 90 -let DecoderMethod = "DecodeLoadInt" in { - defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8, IntRegs, i32>; - defm LDSH : LoadA<"ldsh", 0b001010, 0b011010, sextloadi16, IntRegs, i32>; - defm LDUB : LoadA<"ldub", 0b000001, 0b010001, zextloadi8, IntRegs, i32>; - defm LDUH : LoadA<"lduh", 0b000010, 0b010010, zextloadi16, IntRegs, i32>; - defm LD : LoadA<"ld", 0b000000, 0b010000, load, IntRegs, i32>; -} - -let DecoderMethod = "DecodeLoadIntPair" in - defm LDD : LoadA<"ldd", 0b000011, 0b010011, load, IntPair, v2i32, IIC_ldd>; +defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8, IntRegs, i32>; +defm LDSH : LoadA<"ldsh", 0b001010, 0b011010, sextloadi16, IntRegs, i32>; +defm LDUB : LoadA<"ldub", 0b000001, 0b010001, zextloadi8, IntRegs, i32>; +defm LDUH : LoadA<"lduh", 0b000010, 0b010010, zextloadi16, IntRegs, i32>; +defm LD : LoadA<"ld", 0b000000, 0b010000, load, IntRegs, i32>; +defm LDD : LoadA<"ldd", 0b000011, 0b010011, load, IntPair, v2i32, IIC_ldd>; // Section B.2 - Load Floating-point Instructions, p. 92 -let DecoderMethod = "DecodeLoadFP" in { - defm LDF : Load<"ld", 0b100000, load, FPRegs, f32, IIC_iu_or_fpu_instr>; - def LDFArr : LoadASI<"ld", 0b110000, FPRegs>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeLoadDFP" in { - defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64, IIC_ldd>; - def LDDFArr : LoadASI<"ldd", 0b110011, DFPRegs>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeLoadQFP" in - defm LDQF : LoadA<"ldq", 0b100010, 0b110010, load, QFPRegs, f128>, - Requires<[HasV9, HasHardQuad]>; - -let DecoderMethod = "DecodeLoadCP" in - defm LDC : Load<"ld", 0b110000, load, CoprocRegs, i32>; -let DecoderMethod = "DecodeLoadCPPair" in - defm LDDC : Load<"ldd", 0b110011, load, CoprocPair, v2i32, IIC_ldd>; - -let DecoderMethod = "DecodeLoadCP", Defs = [CPSR] in { +defm LDF : Load<"ld", 0b100000, load, FPRegs, f32, IIC_iu_or_fpu_instr>; +def LDFArr : LoadASI<"ld", 0b110000, FPRegs>, + Requires<[HasV9]>; + +defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64, IIC_ldd>; +def LDDFArr : LoadASI<"ldd", 0b110011, DFPRegs>, + Requires<[HasV9]>; +defm LDQF : LoadA<"ldq", 0b100010, 0b110010, load, QFPRegs, f128>, + Requires<[HasV9, HasHardQuad]>; + +defm LDC : Load<"ld", 0b110000, load, CoprocRegs, i32>; +defm LDDC : Load<"ldd", 0b110011, load, CoprocPair, v2i32, IIC_ldd>; + +let Defs = [CPSR] in { let rd = 0 in { - def LDCSRrr : F3_1<3, 0b110001, (outs), (ins MEMrr:$addr), + def LDCSRrr : F3_1<3, 0b110001, (outs), (ins (MEMrr $rs1, $rs2):$addr), "ld [$addr], %csr", []>; - def LDCSRri : F3_2<3, 0b110001, (outs), (ins MEMri:$addr), + def LDCSRri : F3_2<3, 0b110001, (outs), (ins (MEMri $rs1, $simm13):$addr), "ld [$addr], %csr", []>; } } -let DecoderMethod = "DecodeLoadFP" in - let Defs = [FSR] in { - let rd = 0 in { - def LDFSRrr : F3_1<3, 0b100001, (outs), (ins MEMrr:$addr), - "ld [$addr], %fsr", [], IIC_iu_or_fpu_instr>; - def LDFSRri : F3_2<3, 0b100001, (outs), (ins MEMri:$addr), - "ld [$addr], %fsr", [], IIC_iu_or_fpu_instr>; - } - let rd = 1 in { - def LDXFSRrr : F3_1<3, 0b100001, (outs), (ins MEMrr:$addr), - "ldx [$addr], %fsr", []>, Requires<[HasV9]>; - def LDXFSRri : F3_2<3, 0b100001, (outs), (ins MEMri:$addr), - "ldx [$addr], %fsr", []>, Requires<[HasV9]>; - } +let Defs = [FSR] in { + let rd = 0 in { + def LDFSRrr : F3_1<3, 0b100001, (outs), (ins (MEMrr $rs1, $rs2):$addr), + "ld [$addr], %fsr", [], IIC_iu_or_fpu_instr>; + def LDFSRri : F3_2<3, 0b100001, (outs), (ins (MEMri $rs1, $simm13):$addr), + "ld [$addr], %fsr", [], IIC_iu_or_fpu_instr>; + } + let rd = 1 in { + def LDXFSRrr : F3_1<3, 0b100001, (outs), (ins (MEMrr $rs1, $rs2):$addr), + "ldx [$addr], %fsr", []>, Requires<[HasV9]>; + def LDXFSRri : F3_2<3, 0b100001, (outs), (ins (MEMri $rs1, $simm13):$addr), + "ldx [$addr], %fsr", []>, Requires<[HasV9]>; } +} let mayLoad = 1, isAsmParserOnly = 1 in { def GDOP_LDrr : F3_1<3, 0b000000, - (outs IntRegs:$dst), - (ins MEMrr:$addr, TailRelocSymGOTLoad:$sym), - "ld [$addr], $dst, $sym", - [(set i32:$dst, + (outs IntRegs:$rd), + (ins (MEMrr $rs1, $rs2):$addr, TailRelocSymGOTLoad:$sym), + "ld [$addr], $rd, $sym", + [(set i32:$rd, (load_gdop ADDRrr:$addr, tglobaladdr:$sym))]>; } // Section B.4 - Store Integer Instructions, p. 95 -let DecoderMethod = "DecodeStoreInt" in { - defm STB : StoreA<"stb", 0b000101, 0b010101, truncstorei8, IntRegs, i32>; - defm STH : StoreA<"sth", 0b000110, 0b010110, truncstorei16, IntRegs, i32>; - defm ST : StoreA<"st", 0b000100, 0b010100, store, IntRegs, i32>; -} - -let DecoderMethod = "DecodeStoreIntPair" in - defm STD : StoreA<"std", 0b000111, 0b010111, store, IntPair, v2i32>; +defm STB : StoreA<"stb", 0b000101, 0b010101, truncstorei8, IntRegs, i32>; +defm STH : StoreA<"sth", 0b000110, 0b010110, truncstorei16, IntRegs, i32>; +defm ST : StoreA<"st", 0b000100, 0b010100, store, IntRegs, i32>; +defm STD : StoreA<"std", 0b000111, 0b010111, store, IntPair, v2i32>; // Section B.5 - Store Floating-point Instructions, p. 97 -let DecoderMethod = "DecodeStoreFP" in { - defm STF : Store<"st", 0b100100, store, FPRegs, f32>; - def STFArr : StoreASI<"st", 0b110100, FPRegs>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeStoreDFP" in { - defm STDF : Store<"std", 0b100111, store, DFPRegs, f64, IIC_std>; - def STDFArr : StoreASI<"std", 0b110111, DFPRegs>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeStoreQFP" in - defm STQF : StoreA<"stq", 0b100110, 0b110110, store, QFPRegs, f128>, - Requires<[HasV9, HasHardQuad]>; +defm STF : Store<"st", 0b100100, store, FPRegs, f32>; +def STFArr : StoreASI<"st", 0b110100, FPRegs>, + Requires<[HasV9]>; +defm STDF : Store<"std", 0b100111, store, DFPRegs, f64, IIC_std>; +def STDFArr : StoreASI<"std", 0b110111, DFPRegs>, + Requires<[HasV9]>; +defm STQF : StoreA<"stq", 0b100110, 0b110110, store, QFPRegs, f128>, + Requires<[HasV9, HasHardQuad]>; + +defm STC : Store<"st", 0b110100, store, CoprocRegs, i32>; +defm STDC : Store<"std", 0b110111, store, CoprocPair, v2i32, IIC_std>; -let DecoderMethod = "DecodeStoreCP" in - defm STC : Store<"st", 0b110100, store, CoprocRegs, i32>; - -let DecoderMethod = "DecodeStoreCPPair" in - defm STDC : Store<"std", 0b110111, store, CoprocPair, v2i32, IIC_std>; - -let DecoderMethod = "DecodeStoreCP", rd = 0 in { +let rd = 0 in { let Defs = [CPSR] in { - def STCSRrr : F3_1<3, 0b110101, (outs MEMrr:$addr), (ins), + def STCSRrr : F3_1<3, 0b110101, (outs (MEMrr $rs1, $rs2):$addr), (ins), "st %csr, [$addr]", [], IIC_st>; - def STCSRri : F3_2<3, 0b110101, (outs MEMri:$addr), (ins), + def STCSRri : F3_2<3, 0b110101, (outs (MEMri $rs1, $simm13):$addr), (ins), "st %csr, [$addr]", [], IIC_st>; } let Defs = [CPQ] in { - def STDCQrr : F3_1<3, 0b110110, (outs MEMrr:$addr), (ins), + def STDCQrr : F3_1<3, 0b110110, (outs (MEMrr $rs1, $rs2):$addr), (ins), "std %cq, [$addr]", [], IIC_std>; - def STDCQri : F3_2<3, 0b110110, (outs MEMri:$addr), (ins), + def STDCQri : F3_2<3, 0b110110, (outs (MEMri $rs1, $simm13):$addr), (ins), "std %cq, [$addr]", [], IIC_std>; } } -let DecoderMethod = "DecodeStoreFP" in { - let rd = 0 in { - let Defs = [FSR] in { - def STFSRrr : F3_1<3, 0b100101, (outs MEMrr:$addr), (ins), - "st %fsr, [$addr]", [], IIC_st>; - def STFSRri : F3_2<3, 0b100101, (outs MEMri:$addr), (ins), - "st %fsr, [$addr]", [], IIC_st>; - } - let Defs = [FQ] in { - def STDFQrr : F3_1<3, 0b100110, (outs MEMrr:$addr), (ins), - "std %fq, [$addr]", [], IIC_std>; - def STDFQri : F3_2<3, 0b100110, (outs MEMri:$addr), (ins), - "std %fq, [$addr]", [], IIC_std>; - } +let rd = 0 in { + let Defs = [FSR] in { + def STFSRrr : F3_1<3, 0b100101, (outs (MEMrr $rs1, $rs2):$addr), (ins), + "st %fsr, [$addr]", [], IIC_st>; + def STFSRri : F3_2<3, 0b100101, (outs (MEMri $rs1, $simm13):$addr), (ins), + "st %fsr, [$addr]", [], IIC_st>; } - let rd = 1, Defs = [FSR] in { - def STXFSRrr : F3_1<3, 0b100101, (outs MEMrr:$addr), (ins), - "stx %fsr, [$addr]", []>, Requires<[HasV9]>; - def STXFSRri : F3_2<3, 0b100101, (outs MEMri:$addr), (ins), - "stx %fsr, [$addr]", []>, Requires<[HasV9]>; + let Defs = [FQ] in { + def STDFQrr : F3_1<3, 0b100110, (outs (MEMrr $rs1, $rs2):$addr), (ins), + "std %fq, [$addr]", [], IIC_std>; + def STDFQri : F3_2<3, 0b100110, (outs (MEMri $rs1, $simm13):$addr), (ins), + "std %fq, [$addr]", [], IIC_std>; } } +let rd = 1, Defs = [FSR] in { + def STXFSRrr : F3_1<3, 0b100101, (outs (MEMrr $rs1, $rs2):$addr), (ins), + "stx %fsr, [$addr]", []>, Requires<[HasV9]>; + def STXFSRri : F3_2<3, 0b100101, (outs (MEMri $rs1, $simm13):$addr), (ins), + "stx %fsr, [$addr]", []>, Requires<[HasV9]>; +} // Section B.8 - SWAP Register with Memory Instruction // (Atomic swap) -let Constraints = "$val = $dst", DecoderMethod = "DecodeSWAP" in { +let Constraints = "$val = $rd" in { def SWAPrr : F3_1<3, 0b001111, - (outs IntRegs:$dst), (ins MEMrr:$addr, IntRegs:$val), - "swap [$addr], $dst", - [(set i32:$dst, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>; + (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr, IntRegs:$val), + "swap [$addr], $rd", + [(set i32:$rd, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>; def SWAPri : F3_2<3, 0b001111, - (outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val), - "swap [$addr], $dst", - [(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>; + (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr, IntRegs:$val), + "swap [$addr], $rd", + [(set i32:$rd, (atomic_swap_32 ADDRri:$addr, i32:$val))]>; def SWAPArr : F3_1_asi<3, 0b011111, - (outs IntRegs:$dst), (ins MEMrr:$addr, i8imm:$asi, IntRegs:$val), - "swapa [$addr] $asi, $dst", + (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr, i8imm:$asi, IntRegs:$val), + "swapa [$addr] $asi, $rd", [/*FIXME: pattern?*/]>; } @@ -778,9 +771,9 @@ defm ADD : F3_12<"add", 0b000000, add, IntRegs, i32, simm13Op>; // "LEA" forms of add (patterns to make tblgen happy) let Predicates = [Is32Bit], isCodeGenOnly = 1 in def LEA_ADDri : F3_2<2, 0b000000, - (outs IntRegs:$dst), (ins MEMri:$addr), - "add ${addr:arith}, $dst", - [(set iPTR:$dst, ADDRri:$addr)]>; + (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr), + "add ${addr:arith}, $rd", + [(set iPTR:$rd, ADDRri:$addr)]>; let Defs = [ICC] in defm ADDCC : F3_12<"addcc", 0b010000, addc, IntRegs, i32, simm13Op>; @@ -845,19 +838,27 @@ defm SAVE : F3_12np<"save" , 0b111100>; defm RESTORE : F3_12np<"restore", 0b111101>; // Section B.21 - Branch on Integer Condition Codes Instructions, p. 119 +// Section A.7 - Branch on Integer Condition Codes with Prediction (SPARC v9) +let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { // unconditional branch class. class BranchAlways<dag ins, string asmstr, list<dag> pattern> - : F2_2<0b010, 0, (outs), ins, asmstr, pattern> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let isBarrier = 1; + : F2_2<0b010, 0, (outs), ins, asmstr, pattern>; + +// Same as BranchAlways but uses the new v9 encoding +class BranchPredictAlways<dag ins, string asmstr, list<dag> pattern> + : F2_3<0b001, 0, 1, (outs), ins, asmstr, pattern>; } -let cond = 8 in - def BA : BranchAlways<(ins brtarget:$imm22), "ba $imm22", [(br bb:$imm22)]>; +let cond = 8 in { + // If we're compiling for v9, prefer BPA rather than BA + // TODO: Disallow BA emission when FeatureV8Deprecated isn't enabled + let Predicates = [HasV9], cc = 0b00 in + def BPA : BranchPredictAlways<(ins bprtarget:$imm19), + "ba %icc, $imm19", [(br bb:$imm19)]>; + def BA : BranchAlways<(ins brtarget:$imm22), "ba $imm22", [(br bb:$imm22)]>; +} let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in { @@ -896,13 +897,13 @@ multiclass IPredBranch<string regstr, list<dag> CCPattern> { let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1, isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in { def BINDrr : F3_1<2, 0b111000, - (outs), (ins MEMrr:$ptr), - "jmp $ptr", - [(brind ADDRrr:$ptr)]>; + (outs), (ins (MEMrr $rs1, $rs2):$addr), + "jmp $addr", + [(brind ADDRrr:$addr)]>; def BINDri : F3_2<2, 0b111000, - (outs), (ins MEMri:$ptr), - "jmp $ptr", - [(brind ADDRri:$ptr)]>; + (outs), (ins (MEMri $rs1, $simm13):$addr), + "jmp $addr", + [(brind ADDRri:$addr)]>; } let Uses = [ICC] in { @@ -913,7 +914,7 @@ let Uses = [ICC] in { "b$cond,a $imm22", []>; let Predicates = [HasV9], cc = 0b00 in - defm BPI : IPredBranch<"%icc", []>; + defm BPI : IPredBranch<"%icc", [(SPbpicc bb:$imm19, imm:$cond)]>; } // Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121 @@ -953,6 +954,19 @@ let Uses = [FCC0] in { "fb$cond,a $imm22", []>; } +// Variants of FBCOND that uses V9 opcode +let Predicates = [HasV9], Uses = [FCC0], cc = 0, + isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in { + def FBCOND_V9 : F2_3<0b101, 0, 1, (outs), + (ins bprtarget:$imm19, CCOp:$cond), + "fb$cond %fcc0, $imm19", + [(SPbrfccv9 bb:$imm19, imm:$cond)], IIC_fpu_normal_instr>; + def FBCONDA_V9 : F2_3<0b101, 1, 1, (outs), + (ins bprtarget:$imm19, CCOp:$cond), + "fb$cond,a %fcc0, $imm19", + [(SPbrfccv9 bb:$imm19, imm:$cond)], IIC_fpu_normal_instr>; +} + let Predicates = [HasV9] in defm BPF : FPredBranch; @@ -991,14 +1005,14 @@ let Uses = [O6], // indirect calls: special cases of JMPL. let isCodeGenOnly = 1, rd = 15 in { def CALLrr : F3_1<2, 0b111000, - (outs), (ins MEMrr:$ptr, variable_ops), - "call $ptr", - [(call ADDRrr:$ptr)], + (outs), (ins (MEMrr $rs1, $rs2):$addr, variable_ops), + "call $addr", + [(call ADDRrr:$addr)], IIC_jmp_or_call>; def CALLri : F3_2<2, 0b111000, - (outs), (ins MEMri:$ptr, variable_ops), - "call $ptr", - [(call ADDRri:$ptr)], + (outs), (ins (MEMri $rs1, $simm13):$addr, variable_ops), + "call $addr", + [(call ADDRri:$addr)], IIC_jmp_or_call>; } } @@ -1006,16 +1020,15 @@ let Uses = [O6], // Section B.25 - Jump and Link Instruction // JMPL Instruction. -let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, - DecoderMethod = "DecodeJMPL" in { +let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { def JMPLrr: F3_1<2, 0b111000, - (outs IntRegs:$dst), (ins MEMrr:$addr), - "jmpl $addr, $dst", + (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr), + "jmpl $addr, $rd", [], IIC_jmp_or_call>; def JMPLri: F3_2<2, 0b111000, - (outs IntRegs:$dst), (ins MEMri:$addr), - "jmpl $addr, $dst", + (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr), + "jmpl $addr, $rd", [], IIC_jmp_or_call>; } @@ -1026,29 +1039,29 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, isCodeGenOnly = 1 in { let rd = 0, rs1 = 15 in def RETL: F3_2<2, 0b111000, - (outs), (ins i32imm:$val), - "jmp %o7+$val", - [(retflag simm13:$val)], + (outs), (ins i32imm:$simm13), + "jmp %o7+$simm13", + [(retflag simm13:$simm13)], IIC_jmp_or_call>; let rd = 0, rs1 = 31 in def RET: F3_2<2, 0b111000, - (outs), (ins i32imm:$val), - "jmp %i7+$val", + (outs), (ins i32imm:$simm13), + "jmp %i7+$simm13", [], IIC_jmp_or_call>; } // Section B.26 - Return from Trap Instruction let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, - isBarrier = 1, rd = 0, DecoderMethod = "DecodeReturn" in { + isBarrier = 1, rd = 0 in { def RETTrr : F3_1<2, 0b111001, - (outs), (ins MEMrr:$addr), + (outs), (ins (MEMrr $rs1, $rs2):$addr), "rett $addr", [], IIC_jmp_or_call>; def RETTri : F3_2<2, 0b111001, - (outs), (ins MEMri:$addr), + (outs), (ins (MEMri $rs1, $simm13):$addr), "rett $addr", [], IIC_jmp_or_call>; @@ -1057,7 +1070,7 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, // Section B.27 - Trap on Integer Condition Codes Instruction // conditional branch class: -let DecoderNamespace = "SparcV8", DecoderMethod = "DecodeTRAP", hasSideEffects = 1, Uses = [ICC], cc = 0b00 in +let DecoderNamespace = "SparcV8", hasSideEffects = 1, Uses = [ICC], cc = 0b00 in { def TRAPrr : TRAPSPrr<0b111010, (outs), (ins IntRegs:$rs1, IntRegs:$rs2, CCOp:$cond), @@ -1080,7 +1093,7 @@ multiclass TRAP<string regStr> { []>; } -let DecoderNamespace = "SparcV9", DecoderMethod = "DecodeTRAP", Predicates = [HasV9], hasSideEffects = 1, Uses = [ICC], cc = 0b00 in +let DecoderNamespace = "SparcV9", Predicates = [HasV9], hasSideEffects = 1, Uses = [ICC], cc = 0b00 in defm TICC : TRAP<"%icc">; @@ -1172,9 +1185,9 @@ let rd = 0 in // Section B.32 - Flush Instruction Memory let rd = 0 in { - def FLUSHrr : F3_1<2, 0b111011, (outs), (ins MEMrr:$addr), + def FLUSHrr : F3_1<2, 0b111011, (outs), (ins (MEMrr $rs1, $rs2):$addr), "flush $addr", []>; - def FLUSHri : F3_2<2, 0b111011, (outs), (ins MEMri:$addr), + def FLUSHri : F3_2<2, 0b111011, (outs), (ins (MEMri $rs1, $simm13):$addr), "flush $addr", []>; // The no-arg FLUSH is only here for the benefit of the InstAlias @@ -1399,6 +1412,31 @@ let Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in { Requires<[HasHardQuad]>; } +// A.13 Floating-Point Compare (SPARC v9) +// Note that these always write to %fcc0 instead of having its destination +// allocated automatically. +// This avoids complications with the scheduler sometimes wanting to spill +// the contents of an FCC, since SPARC v9 doesn't have facilities to spill +// an individual FCC. + +let Predicates = [HasV9], Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in { + def FCMPS_V9 : F3_3c<2, 0b110101, 0b001010001, + (outs), (ins FPRegs:$rs1, FPRegs:$rs2), + "fcmps %fcc0, $rs1, $rs2", + [(SPcmpfccv9 f32:$rs1, f32:$rs2)], + IIC_fpu_fast_instr>; + def FCMPD_V9 : F3_3c<2, 0b110101, 0b001010010, + (outs), (ins DFPRegs:$rs1, DFPRegs:$rs2), + "fcmpd %fcc0, $rs1, $rs2", + [(SPcmpfccv9 f64:$rs1, f64:$rs2)], + IIC_fpu_fast_instr>; + def FCMPQ_V9 : F3_3c<2, 0b110101, 0b001010011, + (outs), (ins QFPRegs:$rs1, QFPRegs:$rs2), + "fcmpq %fcc0, $rs1, $rs2", + [(SPcmpfccv9 f128:$rs1, f128:$rs2)]>, + Requires<[HasHardQuad]>; +} + //===----------------------------------------------------------------------===// // Instructions for Thread Local Storage(TLS). //===----------------------------------------------------------------------===// @@ -1412,10 +1450,10 @@ def TLS_ADDrr : F3_1<2, 0b000000, let mayLoad = 1 in { def TLS_LDrr : F3_1<3, 0b000000, - (outs IntRegs:$dst), - (ins MEMrr:$addr, TailRelocSymTLSLoad:$sym), - "ld [$addr], $dst, $sym", - [(set i32:$dst, + (outs IntRegs:$rd), + (ins (MEMrr $rs1, $rs2):$addr, TailRelocSymTLSLoad:$sym), + "ld [$addr], $rd, $sym", + [(set i32:$rd, (tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>; } @@ -1452,9 +1490,9 @@ def : Pat<(tailcall (iPTR texternalsym:$dst)), let isCodeGenOnly = 1, isReturn = 1, hasDelaySlot = 1, isTerminator = 1, isBarrier = 1, rd = 0 in { def TAIL_CALLri : F3_2<2, 0b111000, - (outs), (ins MEMri:$ptr, variable_ops), - "jmp $ptr", - [(tailcall ADDRri:$ptr)]>; + (outs), (ins (MEMri $rs1, $simm13):$addr, variable_ops), + "jmp $addr", + [(tailcall ADDRri:$addr)]>; } //===----------------------------------------------------------------------===// @@ -1712,10 +1750,10 @@ let hasSideEffects = 1 in { // Section A.42 - Prefetch Data let Predicates = [HasV9] in { def PREFETCHr : F3_1<3, 0b101101, - (outs), (ins MEMrr:$addr, shift_imm5:$rd), + (outs), (ins (MEMrr $rs1, $rs2):$addr, shift_imm5:$rd), "prefetch [$addr], $rd", []>; def PREFETCHi : F3_2<3, 0b101101, - (outs), (ins MEMri:$addr, shift_imm5:$rd), + (outs), (ins (MEMri $rs1, $simm13):$addr, shift_imm5:$rd), "prefetch [$addr], $rd", []>; } @@ -1744,8 +1782,7 @@ let Predicates = [HasV9] in { //===----------------------------------------------------------------------===// // Zero immediate. -def : Pat<(i32 0), - (ORrr (i32 G0), (i32 G0))>; +def : Pat<(i32 0), (COPY (i32 G0))>; // Small immediates. def : Pat<(i32 simm13:$val), (ORri (i32 G0), imm:$val)>; @@ -1826,6 +1863,16 @@ def : Pat<(atomic_store_16 ADDRri:$dst, i32:$val), (STHri ADDRri:$dst, $val)>; def : Pat<(atomic_store_32 ADDRrr:$dst, i32:$val), (STrr ADDRrr:$dst, $val)>; def : Pat<(atomic_store_32 ADDRri:$dst, i32:$val), (STri ADDRri:$dst, $val)>; +// A register pair with zero upper half. +// The upper part is done with ORrr instead of `COPY G0` +// or a normal register copy, since `COPY G0`s in that place +// will be converted into `COPY G0_G1` later on, which is not +// what we want in this case. +def : Pat<(build_vector (i32 0), (i32 IntRegs:$a2)), + (INSERT_SUBREG (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), + (ORrr (i32 G0), (i32 G0)), sub_even), + (i32 IntRegs:$a2), sub_odd)>; + // extract_vector def : Pat<(extractelt (v2i32 IntPair:$Rn), 0), (i32 (EXTRACT_SUBREG IntPair:$Rn, sub_even))>; diff --git a/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h b/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h index e1a1568d28a2..f73cd6d1b131 100644 --- a/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h +++ b/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h @@ -34,9 +34,9 @@ namespace llvm { SparcMachineFunctionInfo() : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0), IsLeafProc(false) {} - explicit SparcMachineFunctionInfo(MachineFunction &MF) - : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0), - IsLeafProc(false) {} + SparcMachineFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) + : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0), + IsLeafProc(false) {} MachineFunctionInfo * clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp index 21dced23210c..f97bf57627d1 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -160,7 +160,7 @@ static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II, } -void +bool SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { @@ -209,7 +209,8 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, } replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg); - + // replaceFI never removes II + return false; } Register SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const { diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.h b/llvm/lib/Target/Sparc/SparcRegisterInfo.h index 118ef9d80fae..5b3c1a7ad07d 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.h +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.h @@ -34,7 +34,7 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo { const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, unsigned Kind) const override; - void eliminateFrameIndex(MachineBasicBlock::iterator II, + bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS = nullptr) const override; diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.td b/llvm/lib/Target/Sparc/SparcRegisterInfo.td index 9453efb6fbb4..947bbaed8c70 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.td +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.td @@ -126,7 +126,9 @@ def OTHERWIN : SparcCtrlReg<13, "OTHERWIN">; def WSTATE : SparcCtrlReg<14, "WSTATE">; // Integer registers -def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>; +def G0 : Ri< 0, "G0">, DwarfRegNum<[0]> { + let isConstant = true; +} def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>; def G2 : Ri< 2, "G2">, DwarfRegNum<[2]>; def G3 : Ri< 3, "G3">, DwarfRegNum<[3]>; @@ -378,3 +380,4 @@ let isAllocatable = 0 in { def PRRegs : RegisterClass<"SP", [i64], 64, (add TPC, TNPC, TSTATE, TT, TICK, TBA, PSTATE, TL, PIL, CWP, CANSAVE, CANRESTORE, CLEANWIN, OTHERWIN, WSTATE)>; + diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp index 8bd51a703d47..58faaafc29d6 100644 --- a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp @@ -12,12 +12,14 @@ #include "SparcTargetMachine.h" #include "LeonPasses.h" #include "Sparc.h" +#include "SparcMachineFunctionInfo.h" #include "SparcTargetObjectFile.h" #include "TargetInfo/SparcTargetInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/MC/TargetRegistry.h" +#include <optional> using namespace llvm; extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() { @@ -25,6 +27,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() { RegisterTargetMachine<SparcV8TargetMachine> X(getTheSparcTarget()); RegisterTargetMachine<SparcV9TargetMachine> Y(getTheSparcV9Target()); RegisterTargetMachine<SparcelTargetMachine> Z(getTheSparcelTarget()); + + PassRegistry &PR = *PassRegistry::getPassRegistry(); + initializeSparcDAGToDAGISelPass(PR); } static std::string computeDataLayout(const Triple &T, bool is64Bit) { @@ -54,7 +59,7 @@ static std::string computeDataLayout(const Triple &T, bool is64Bit) { return Ret; } -static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { +static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) { return RM.value_or(Reloc::Static); } @@ -69,7 +74,7 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { // // All code models require that the text segment is smaller than 2GB. static CodeModel::Model -getEffectiveSparcCodeModel(Optional<CodeModel::Model> CM, Reloc::Model RM, +getEffectiveSparcCodeModel(std::optional<CodeModel::Model> CM, Reloc::Model RM, bool Is64Bit, bool JIT) { if (CM) { if (*CM == CodeModel::Tiny) @@ -87,10 +92,13 @@ getEffectiveSparcCodeModel(Optional<CodeModel::Model> CM, Reloc::Model RM, } /// Create an ILP32 architecture model -SparcTargetMachine::SparcTargetMachine( - const Target &T, const Triple &TT, StringRef CPU, StringRef FS, - const TargetOptions &Options, Optional<Reloc::Model> RM, - Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT, bool is64bit) +SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT, + StringRef CPU, StringRef FS, + const TargetOptions &Options, + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, + CodeGenOpt::Level OL, bool JIT, + bool is64bit) : LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options, getEffectiveRelocModel(RM), getEffectiveSparcCodeModel( @@ -134,6 +142,13 @@ SparcTargetMachine::getSubtargetImpl(const Function &F) const { return I.get(); } +MachineFunctionInfo *SparcTargetMachine::createMachineFunctionInfo( + BumpPtrAllocator &Allocator, const Function &F, + const TargetSubtargetInfo *STI) const { + return SparcMachineFunctionInfo::create<SparcMachineFunctionInfo>(Allocator, + F, STI); +} + namespace { /// Sparc Code Generator Pass Configuration Options. class SparcPassConfig : public TargetPassConfig { @@ -187,8 +202,8 @@ void SparcV8TargetMachine::anchor() { } SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, - Optional<CodeModel::Model> CM, + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} @@ -197,8 +212,8 @@ void SparcV9TargetMachine::anchor() { } SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, - Optional<CodeModel::Model> CM, + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} @@ -207,7 +222,7 @@ void SparcelTargetMachine::anchor() {} SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, - Optional<CodeModel::Model> CM, + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.h b/llvm/lib/Target/Sparc/SparcTargetMachine.h index 4083f61433b1..6e3c8e7df43f 100644 --- a/llvm/lib/Target/Sparc/SparcTargetMachine.h +++ b/llvm/lib/Target/Sparc/SparcTargetMachine.h @@ -16,6 +16,7 @@ #include "SparcInstrInfo.h" #include "SparcSubtarget.h" #include "llvm/Target/TargetMachine.h" +#include <optional> namespace llvm { @@ -24,11 +25,13 @@ class SparcTargetMachine : public LLVMTargetMachine { SparcSubtarget Subtarget; bool is64Bit; mutable StringMap<std::unique_ptr<SparcSubtarget>> SubtargetMap; + public: SparcTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT, bool is64bit); + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, + bool JIT, bool is64bit); ~SparcTargetMachine() override; const SparcSubtarget *getSubtargetImpl() const { return &Subtarget; } @@ -39,28 +42,36 @@ public: TargetLoweringObjectFile *getObjFileLowering() const override { return TLOF.get(); } + + MachineFunctionInfo * + createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, + const TargetSubtargetInfo *STI) const override; }; /// Sparc 32-bit target machine /// class SparcV8TargetMachine : public SparcTargetMachine { virtual void anchor(); + public: SparcV8TargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT); + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, + bool JIT); }; /// Sparc 64-bit target machine /// class SparcV9TargetMachine : public SparcTargetMachine { virtual void anchor(); + public: SparcV9TargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT); + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, + bool JIT); }; class SparcelTargetMachine : public SparcTargetMachine { @@ -69,8 +80,9 @@ class SparcelTargetMachine : public SparcTargetMachine { public: SparcelTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT); + std::optional<Reloc::Model> RM, + std::optional<CodeModel::Model> CM, CodeGenOpt::Level OL, + bool JIT); }; } // end namespace llvm |