aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Sparc
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Sparc')
-rw-r--r--llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp21
-rw-r--r--llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp347
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp6
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp19
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h4
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp1
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp2
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp7
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp1
-rw-r--r--llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h4
-rw-r--r--llvm/lib/Target/Sparc/Sparc.h147
-rw-r--r--llvm/lib/Target/Sparc/SparcAsmPrinter.cpp4
-rw-r--r--llvm/lib/Target/Sparc/SparcCallingConv.td10
-rw-r--r--llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp17
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp231
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.h73
-rw-r--r--llvm/lib/Target/Sparc/SparcInstr64Bit.td124
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrAliases.td51
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrFormats.td12
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.cpp120
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.h15
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.td411
-rw-r--r--llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h6
-rw-r--r--llvm/lib/Target/Sparc/SparcRegisterInfo.cpp5
-rw-r--r--llvm/lib/Target/Sparc/SparcRegisterInfo.h2
-rw-r--r--llvm/lib/Target/Sparc/SparcRegisterInfo.td5
-rw-r--r--llvm/lib/Target/Sparc/SparcTargetMachine.cpp39
-rw-r--r--llvm/lib/Target/Sparc/SparcTargetMachine.h28
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