summaryrefslogtreecommitdiff
path: root/lib/Target/Sparc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Sparc')
-rw-r--r--lib/Target/Sparc/AsmParser/SparcAsmParser.cpp55
-rw-r--r--lib/Target/Sparc/Disassembler/SparcDisassembler.cpp4
-rw-r--r--lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp23
-rw-r--r--lib/Target/Sparc/InstPrinter/SparcInstPrinter.h2
-rwxr-xr-xlib/Target/Sparc/LeonFeatures.td4
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp20
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp2
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h (renamed from lib/Target/Sparc/SparcTargetStreamer.h)5
-rw-r--r--lib/Target/Sparc/Sparc.td6
-rw-r--r--lib/Target/Sparc/SparcAsmPrinter.cpp2
-rw-r--r--lib/Target/Sparc/SparcISelLowering.cpp378
-rw-r--r--lib/Target/Sparc/SparcISelLowering.h20
-rw-r--r--lib/Target/Sparc/SparcInstr64Bit.td2
-rw-r--r--lib/Target/Sparc/SparcInstrAliases.td5
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.td79
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.cpp4
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.h2
-rw-r--r--lib/Target/Sparc/SparcSubtarget.cpp2
-rw-r--r--lib/Target/Sparc/SparcSubtarget.h4
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp23
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.h4
21 files changed, 271 insertions, 375 deletions
diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index 35f52f7d279b..691421e533ea 100644
--- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -78,6 +78,8 @@ class SparcAsmParser : public MCTargetAsmParser {
// Custom parse functions for Sparc specific operands.
OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
+ OperandMatchResultTy parseMembarTag(OperandVector &Operands);
+
OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
OperandMatchResultTy
@@ -256,6 +258,7 @@ public:
bool isMem() const override { return isMEMrr() || isMEMri(); }
bool isMEMrr() const { return Kind == k_MemoryReg; }
bool isMEMri() const { return Kind == k_MemoryImm; }
+ bool isMembarTag() const { return Kind == k_Immediate; }
bool isIntReg() const {
return (Kind == k_Register && Reg.Kind == rk_IntReg);
@@ -366,6 +369,12 @@ public:
addExpr(Inst, Expr);
}
+ void addMembarTagOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCExpr *Expr = getImm();
+ addExpr(Inst, Expr);
+ }
+
static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
auto Op = make_unique<SparcOperand>(k_Token);
Op->Tok.Data = Str.data();
@@ -742,6 +751,52 @@ SparcAsmParser::parseMEMOperand(OperandVector &Operands) {
return MatchOperand_Success;
}
+OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) {
+ SMLoc S = Parser.getTok().getLoc();
+ const MCExpr *EVal;
+ int64_t ImmVal = 0;
+
+ std::unique_ptr<SparcOperand> Mask;
+ if (parseSparcAsmOperand(Mask) == MatchOperand_Success) {
+ if (!Mask->isImm() || !Mask->getImm()->evaluateAsAbsolute(ImmVal) ||
+ ImmVal < 0 || ImmVal > 127) {
+ Error(S, "invalid membar mask number");
+ return MatchOperand_ParseFail;
+ }
+ }
+
+ while (getLexer().getKind() == AsmToken::Hash) {
+ SMLoc TagStart = getLexer().getLoc();
+ Parser.Lex(); // Eat the '#'.
+ unsigned MaskVal = StringSwitch<unsigned>(Parser.getTok().getString())
+ .Case("LoadLoad", 0x1)
+ .Case("StoreLoad", 0x2)
+ .Case("LoadStore", 0x4)
+ .Case("StoreStore", 0x8)
+ .Case("Lookaside", 0x10)
+ .Case("MemIssue", 0x20)
+ .Case("Sync", 0x40)
+ .Default(0);
+
+ Parser.Lex(); // Eat the identifier token.
+
+ if (!MaskVal) {
+ Error(TagStart, "unknown membar tag");
+ return MatchOperand_ParseFail;
+ }
+
+ ImmVal |= MaskVal;
+
+ if (getLexer().getKind() == AsmToken::Pipe)
+ Parser.Lex(); // Eat the '|'.
+ }
+
+ EVal = MCConstantExpr::create(ImmVal, getContext());
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ Operands.push_back(SparcOperand::CreateImm(EVal, S, E));
+ return MatchOperand_Success;
+}
+
OperandMatchResultTy
SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
diff --git a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
index 3e30dae1537f..0045e63a824e 100644
--- a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ b/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -11,9 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "Sparc.h"
-#include "SparcRegisterInfo.h"
-#include "SparcSubtarget.h"
+#include "MCTargetDesc/SparcMCTargetDesc.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
diff --git a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
index c1512cbdc44f..d152efae6d1f 100644
--- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
+++ b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
@@ -195,3 +195,26 @@ bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,
llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX.");
return true;
}
+
+void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ static const char *const TagNames[] = {
+ "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore",
+ "#Lookaside", "#MemIssue", "#Sync"};
+
+ unsigned Imm = MI->getOperand(opNum).getImm();
+
+ if (Imm > 127) {
+ O << Imm;
+ return;
+ }
+
+ bool First = true;
+ for (unsigned i = 0; i < sizeof(TagNames) / sizeof(char *); i++) {
+ if (Imm & (1 << i)) {
+ O << (First ? "" : " | ") << TagNames[i];
+ First = false;
+ }
+ }
+}
diff --git a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
index 6f06d1ddae32..89015eb137c2 100644
--- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
+++ b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
@@ -49,6 +49,8 @@ public:
raw_ostream &OS);
bool printGetPCX(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &OS);
+ void printMembarTag(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
+ raw_ostream &O);
};
} // end namespace llvm
diff --git a/lib/Target/Sparc/LeonFeatures.td b/lib/Target/Sparc/LeonFeatures.td
index a7dea068cb11..61e5f16e0a1e 100755
--- a/lib/Target/Sparc/LeonFeatures.td
+++ b/lib/Target/Sparc/LeonFeatures.td
@@ -58,3 +58,7 @@ def FixAllFDIVSQRT : SubtargetFeature<
"true",
"LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store"
>;
+
+def LeonCycleCounter
+ : SubtargetFeature<"leoncyclecounter", "HasLeonCycleCounter", "true",
+ "Use the Leon cycle counter register">;
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index 5f5e2ef7d45a..d7f1e3a1ab1d 100644
--- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -100,6 +100,20 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
}
}
+/// getFixupKindNumBytes - The number of bytes the fixup may change.
+static unsigned getFixupKindNumBytes(unsigned Kind) {
+ switch (Kind) {
+ default:
+ return 4;
+ case FK_Data_1:
+ return 1;
+ case FK_Data_2:
+ return 2;
+ case FK_Data_8:
+ return 8;
+ }
+}
+
namespace {
class SparcAsmBackend : public MCAsmBackend {
protected:
@@ -290,13 +304,13 @@ namespace {
Value = adjustFixupValue(Fixup.getKind(), Value);
if (!Value) return; // Doesn't change encoding.
+ unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
unsigned Offset = Fixup.getOffset();
-
// For each byte of the fragment that the fixup touches, mask in the bits
// from the fixup value. The Value has been "split up" into the
// appropriate bitfields above.
- for (unsigned i = 0; i != 4; ++i) {
- unsigned Idx = Endian == support::little ? i : 3 - i;
+ for (unsigned i = 0; i != NumBytes; ++i) {
+ unsigned Idx = Endian == support::little ? i : (NumBytes - 1) - i;
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
index f736a37a266c..4ddb72643a91 100644
--- a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
+++ b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
@@ -13,11 +13,11 @@
//===----------------------------------------------------------------------===//
#include "SparcMCExpr.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/Object/ELF.h"
using namespace llvm;
diff --git a/lib/Target/Sparc/SparcTargetStreamer.h b/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h
index 3b503503abce..8bb418e39ab4 100644
--- a/lib/Target/Sparc/SparcTargetStreamer.h
+++ b/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_TARGET_SPARC_SPARCTARGETSTREAMER_H
-#define LLVM_LIB_TARGET_SPARC_SPARCTARGETSTREAMER_H
+#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCTARGETSTREAMER_H
+#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCTARGETSTREAMER_H
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCStreamer.h"
@@ -33,7 +33,6 @@ public:
SparcTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
void emitSparcRegisterIgnore(unsigned reg) override;
void emitSparcRegisterScratch(unsigned reg) override;
-
};
// This part is for ELF object output
diff --git a/lib/Target/Sparc/Sparc.td b/lib/Target/Sparc/Sparc.td
index 2f9b57f76041..0412215be8ab 100644
--- a/lib/Target/Sparc/Sparc.td
+++ b/lib/Target/Sparc/Sparc.td
@@ -49,6 +49,9 @@ def FeatureVIS3
def FeatureLeon
: SubtargetFeature<"leon", "IsLeon", "true",
"Enable LEON extensions">;
+def FeaturePWRPSR
+ : SubtargetFeature<"leonpwrpsr", "HasPWRPSR", "true",
+ "Enable the PWRPSR instruction">;
def FeatureHardQuad
: SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
@@ -159,7 +162,8 @@ def : Processor<"leon4", LEON4Itineraries,
// LEON 4 FT (GR740)
// TO DO: Place-holder: Processor specific features will be added *very* soon here.
def : Processor<"gr740", LEON4Itineraries,
- [FeatureLeon, UMACSMACSupport, LeonCASA]>;
+ [FeatureLeon, UMACSMACSupport, LeonCASA, LeonCycleCounter,
+ FeaturePWRPSR]>;
//===----------------------------------------------------------------------===//
// Declare the target which we are implementing
diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp
index 19fb94534b25..5f0e359a3b00 100644
--- a/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -14,10 +14,10 @@
#include "InstPrinter/SparcInstPrinter.h"
#include "MCTargetDesc/SparcMCExpr.h"
+#include "MCTargetDesc/SparcTargetStreamer.h"
#include "Sparc.h"
#include "SparcInstrInfo.h"
#include "SparcTargetMachine.h"
-#include "SparcTargetStreamer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp
index b04c6b112682..ae2257618a55 100644
--- a/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/lib/Target/Sparc/SparcISelLowering.cpp
@@ -780,6 +780,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
const unsigned StackOffset = 92;
bool hasStructRetAttr = false;
+ unsigned SRetArgSize = 0;
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
i != e;
@@ -824,6 +825,11 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
MemOpChains.push_back(
DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
hasStructRetAttr = true;
+ // sret only allowed on first argument
+ assert(Outs[realArgIdx].OrigArgIndex == 0);
+ PointerType *Ty = cast<PointerType>(CLI.getArgs()[0].Ty);
+ Type *ElementTy = Ty->getElementType();
+ SRetArgSize = DAG.getDataLayout().getTypeAllocSize(ElementTy);
continue;
}
@@ -846,12 +852,10 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
if (VA.getLocVT() == MVT::f64) {
// Move from the float value from float registers into the
// integer registers.
-
- // TODO: The f64 -> v2i32 conversion is super-inefficient for
- // constants: it sticks them in the constant pool, then loads
- // to a fp register, then stores to temp memory, then loads to
- // integer registers.
- Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg);
+ if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Arg))
+ Arg = bitcastConstantFPToInt(C, dl, DAG);
+ else
+ Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg);
}
SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
@@ -932,7 +936,6 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
InFlag = Chain.getValue(1);
}
- unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0;
bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS);
// If the callee is a GlobalAddress node (quite common, every direct call is)
@@ -1032,51 +1035,6 @@ unsigned SparcTargetLowering::getRegisterByName(const char* RegName, EVT VT,
report_fatal_error("Invalid register name global variable");
}
-// This functions returns true if CalleeName is a ABI function that returns
-// a long double (fp128).
-static bool isFP128ABICall(const char *CalleeName)
-{
- static const char *const ABICalls[] =
- { "_Q_add", "_Q_sub", "_Q_mul", "_Q_div",
- "_Q_sqrt", "_Q_neg",
- "_Q_itoq", "_Q_stoq", "_Q_dtoq", "_Q_utoq",
- "_Q_lltoq", "_Q_ulltoq",
- nullptr
- };
- for (const char * const *I = ABICalls; *I != nullptr; ++I)
- if (strcmp(CalleeName, *I) == 0)
- return true;
- return false;
-}
-
-unsigned
-SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const
-{
- const Function *CalleeFn = nullptr;
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- CalleeFn = dyn_cast<Function>(G->getGlobal());
- } else if (ExternalSymbolSDNode *E =
- dyn_cast<ExternalSymbolSDNode>(Callee)) {
- const Function &F = DAG.getMachineFunction().getFunction();
- const Module *M = F.getParent();
- const char *CalleeName = E->getSymbol();
- CalleeFn = M->getFunction(CalleeName);
- if (!CalleeFn && isFP128ABICall(CalleeName))
- return 16; // Return sizeof(fp128)
- }
-
- if (!CalleeFn)
- return 0;
-
- // It would be nice to check for the sret attribute on CalleeFn here,
- // but since it is not part of the function type, any check will misfire.
-
- PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType());
- Type *ElementTy = Ty->getElementType();
- return DAG.getDataLayout().getTypeAllocSize(ElementTy);
-}
-
-
// Fixup floating point arguments in the ... part of a varargs call.
//
// The SPARC v9 ABI requires that floating point arguments are treated the same
@@ -1587,9 +1545,6 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
setOperationAction(ISD::SELECT_CC, MVT::f128, Custom);
- setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);
- setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
-
setOperationAction(ISD::ADDC, MVT::i32, Custom);
setOperationAction(ISD::ADDE, MVT::i32, Custom);
setOperationAction(ISD::SUBC, MVT::i32, Custom);
@@ -1841,6 +1796,13 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FMUL, MVT::f32, Promote);
}
+ // Custom combine bitcast between f64 and v2i32
+ if (!Subtarget->is64Bit())
+ setTargetDAGCombine(ISD::BITCAST);
+
+ if (Subtarget->hasLeonCycleCounter())
+ setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
+
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
setMinFunctionAlignment(2);
@@ -1863,8 +1825,6 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
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::EH_SJLJ_SETJMP: return "SPISD::EH_SJLJ_SETJMP";
- case SPISD::EH_SJLJ_LONGJMP: return "SPISD::EH_SJLJ_LONGJMP";
case SPISD::Hi: return "SPISD::Hi";
case SPISD::Lo: return "SPISD::Lo";
case SPISD::FTOI: return "SPISD::FTOI";
@@ -1906,8 +1866,8 @@ void SparcTargetLowering::computeKnownBitsForTargetNode
case SPISD::SELECT_ICC:
case SPISD::SELECT_XCC:
case SPISD::SELECT_FCC:
- DAG.computeKnownBits(Op.getOperand(1), Known, Depth+1);
- DAG.computeKnownBits(Op.getOperand(0), Known2, Depth+1);
+ Known = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
+ Known2 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
// Only known if known in both the LHS and RHS.
Known.One &= Known2.One;
@@ -2537,20 +2497,6 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);
}
-SDValue SparcTargetLowering::LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG,
- const SparcTargetLowering &TLI) const {
- SDLoc DL(Op);
- return DAG.getNode(SPISD::EH_SJLJ_SETJMP, DL,
- DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0), Op.getOperand(1));
-
-}
-
-SDValue SparcTargetLowering::LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG,
- const SparcTargetLowering &TLI) const {
- SDLoc DL(Op);
- return DAG.getNode(SPISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0), Op.getOperand(1));
-}
-
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,
const SparcTargetLowering &TLI) {
MachineFunction &MF = DAG.getMachineFunction();
@@ -2666,7 +2612,8 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) {
}
static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
- const SparcSubtarget *Subtarget) {
+ const SparcSubtarget *Subtarget,
+ bool AlwaysFlush = false) {
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
MFI.setFrameAddressIsTaken(true);
@@ -2676,17 +2623,11 @@ static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
unsigned stackBias = Subtarget->getStackPointerBias();
SDValue FrameAddr;
-
- if (depth == 0) {
- FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
- if (Subtarget->is64Bit())
- FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
- DAG.getIntPtrConstant(stackBias, dl));
- return FrameAddr;
- }
+ SDValue Chain;
// flush first to make sure the windowed registers' values are in stack
- SDValue Chain = getFLUSHW(Op, DAG);
+ Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode();
+
FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
@@ -2735,7 +2676,7 @@ static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
}
// Need frame address to find return address of the caller.
- SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget);
+ SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget, true);
unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
SDValue Ptr = DAG.getNode(ISD::ADD,
@@ -3085,8 +3026,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
hasHardQuad);
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this,
hasHardQuad);
- case ISD::EH_SJLJ_SETJMP: return LowerEH_SJLJ_SETJMP(Op, DAG, *this);
- case ISD::EH_SJLJ_LONGJMP: return LowerEH_SJLJ_LONGJMP(Op, DAG, *this);
case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
case ISD::VAARG: return LowerVAARG(Op, DAG);
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,
@@ -3120,6 +3059,40 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
}
}
+SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C,
+ const SDLoc &DL,
+ SelectionDAG &DAG) const {
+ APInt V = C->getValueAPF().bitcastToAPInt();
+ SDValue Lo = DAG.getConstant(V.zextOrTrunc(32), DL, MVT::i32);
+ SDValue Hi = DAG.getConstant(V.lshr(32).zextOrTrunc(32), DL, MVT::i32);
+ if (DAG.getDataLayout().isLittleEndian())
+ std::swap(Lo, Hi);
+ return DAG.getBuildVector(MVT::v2i32, DL, {Hi, Lo});
+}
+
+SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ SDLoc dl(N);
+ SDValue Src = N->getOperand(0);
+
+ if (isa<ConstantFPSDNode>(Src) && N->getSimpleValueType(0) == MVT::v2i32 &&
+ Src.getSimpleValueType() == MVT::f64)
+ return bitcastConstantFPToInt(cast<ConstantFPSDNode>(Src), dl, DCI.DAG);
+
+ return SDValue();
+}
+
+SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ switch (N->getOpcode()) {
+ default:
+ break;
+ case ISD::BITCAST:
+ return PerformBITCASTCombine(N, DCI);
+ }
+ return SDValue();
+}
+
MachineBasicBlock *
SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const {
@@ -3135,13 +3108,6 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case SP::SELECT_CC_DFP_FCC:
case SP::SELECT_CC_QFP_FCC:
return expandSelectCC(MI, BB, SP::FBCOND);
- case SP::EH_SJLJ_SETJMP32ri:
- case SP::EH_SJLJ_SETJMP32rr:
- return emitEHSjLjSetJmp(MI, BB);
- case SP::EH_SJLJ_LONGJMP32rr:
- case SP::EH_SJLJ_LONGJMP32ri:
- return emitEHSjLjLongJmp(MI, BB);
-
}
}
@@ -3201,205 +3167,6 @@ SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB,
return SinkMBB;
}
-MachineBasicBlock *
-SparcTargetLowering::emitEHSjLjLongJmp(MachineInstr &MI,
- MachineBasicBlock *MBB) const {
- DebugLoc DL = MI.getDebugLoc();
- const TargetInstrInfo *TII = Subtarget->getInstrInfo();
-
- MachineFunction *MF = MBB->getParent();
- MachineRegisterInfo &MRI = MF->getRegInfo();
- MachineInstrBuilder MIB;
-
- MVT PVT = getPointerTy(MF->getDataLayout());
- unsigned RegSize = PVT.getStoreSize();
- assert(PVT == MVT::i32 && "Invalid Pointer Size!");
-
- unsigned Buf = MI.getOperand(0).getReg();
- unsigned JmpLoc = MRI.createVirtualRegister(&SP::IntRegsRegClass);
-
- // TO DO: If we do 64-bit handling, this perhaps should be FLUSHW, not TA 3
- MIB = BuildMI(*MBB, MI, DL, TII->get(SP::TRAPri), SP::G0).addImm(3).addImm(SPCC::ICC_A);
-
- // Instruction to restore FP
- const unsigned FP = SP::I6;
- MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
- .addReg(FP)
- .addReg(Buf)
- .addImm(0);
-
- // Instruction to load jmp location
- MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
- .addReg(JmpLoc, RegState::Define)
- .addReg(Buf)
- .addImm(RegSize);
-
- // Instruction to restore SP
- const unsigned SP = SP::O6;
- MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
- .addReg(SP)
- .addReg(Buf)
- .addImm(2 * RegSize);
-
- // Instruction to restore I7
- MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
- .addReg(SP::I7)
- .addReg(Buf, RegState::Kill)
- .addImm(3 * RegSize);
-
- // Jump to JmpLoc
- BuildMI(*MBB, MI, DL, TII->get(SP::JMPLrr)).addReg(SP::G0).addReg(JmpLoc, RegState::Kill).addReg(SP::G0);
-
- MI.eraseFromParent();
- return MBB;
-}
-
-MachineBasicBlock *
-SparcTargetLowering::emitEHSjLjSetJmp(MachineInstr &MI,
- MachineBasicBlock *MBB) const {
- DebugLoc DL = MI.getDebugLoc();
- const TargetInstrInfo *TII = Subtarget->getInstrInfo();
- const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
-
- MachineFunction *MF = MBB->getParent();
- MachineRegisterInfo &MRI = MF->getRegInfo();
- MachineInstrBuilder MIB;
-
- MVT PVT = getPointerTy(MF->getDataLayout());
- unsigned RegSize = PVT.getStoreSize();
- assert(PVT == MVT::i32 && "Invalid Pointer Size!");
-
- unsigned DstReg = MI.getOperand(0).getReg();
- const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
- assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!");
- (void)TRI;
- unsigned mainDstReg = MRI.createVirtualRegister(RC);
- unsigned restoreDstReg = MRI.createVirtualRegister(RC);
-
- // For v = setjmp(buf), we generate
- //
- // thisMBB:
- // buf[0] = FP
- // buf[RegSize] = restoreMBB <-- takes address of restoreMBB
- // buf[RegSize * 2] = O6
- // buf[RegSize * 3] = I7
- // Ensure restoreMBB remains in the relocations list (done using a bn instruction)
- // b mainMBB
- //
- // mainMBB:
- // v_main = 0
- // b sinkMBB
- //
- // restoreMBB:
- // v_restore = 1
- // --fall through--
- //
- // sinkMBB:
- // v = phi(main, restore)
-
- const BasicBlock *BB = MBB->getBasicBlock();
- MachineFunction::iterator It = ++MBB->getIterator();
- MachineBasicBlock *thisMBB = MBB;
- MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(BB);
- MachineBasicBlock *restoreMBB = MF->CreateMachineBasicBlock(BB);
- MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB);
-
- MF->insert(It, mainMBB);
- MF->insert(It, restoreMBB);
- MF->insert(It, sinkMBB);
- restoreMBB->setHasAddressTaken();
-
- // Transfer the remainder of BB and its successor edges to sinkMBB.
- sinkMBB->splice(sinkMBB->begin(), MBB,
- std::next(MachineBasicBlock::iterator(MI)),
- MBB->end());
- sinkMBB->transferSuccessorsAndUpdatePHIs(MBB);
-
- unsigned LabelReg = MRI.createVirtualRegister(&SP::IntRegsRegClass);
- unsigned LabelReg2 = MRI.createVirtualRegister(&SP::IntRegsRegClass);
- unsigned BufReg = MI.getOperand(1).getReg();
-
- // Instruction to store FP
- const unsigned FP = SP::I6;
- MIB = BuildMI(thisMBB, DL, TII->get(SP::STri))
- .addReg(BufReg)
- .addImm(0)
- .addReg(FP);
-
- // Instructions to store jmp location
- MIB = BuildMI(thisMBB, DL, TII->get(SP::SETHIi))
- .addReg(LabelReg, RegState::Define)
- .addMBB(restoreMBB, SparcMCExpr::VK_Sparc_HI);
-
- MIB = BuildMI(thisMBB, DL, TII->get(SP::ORri))
- .addReg(LabelReg2, RegState::Define)
- .addReg(LabelReg, RegState::Kill)
- .addMBB(restoreMBB, SparcMCExpr::VK_Sparc_LO);
-
- MIB = BuildMI(thisMBB, DL, TII->get(SP::STri))
- .addReg(BufReg)
- .addImm(RegSize)
- .addReg(LabelReg2, RegState::Kill);
-
- // Instruction to store SP
- const unsigned SP = SP::O6;
- MIB = BuildMI(thisMBB, DL, TII->get(SP::STri))
- .addReg(BufReg)
- .addImm(2 * RegSize)
- .addReg(SP);
-
- // Instruction to store I7
- MIB = BuildMI(thisMBB, DL, TII->get(SP::STri))
- .addReg(BufReg)
- .addImm(3 * RegSize)
- .addReg(SP::I7);
-
-
- // FIX ME: This next instruction ensures that the restoreMBB block address remains
- // valid through optimization passes and serves no other purpose. The ICC_N ensures
- // that the branch is never taken. This commented-out code here was an alternative
- // attempt to achieve this which brought myriad problems.
- //MIB = BuildMI(thisMBB, DL, TII->get(SP::EH_SjLj_Setup)).addMBB(restoreMBB, SparcMCExpr::VK_Sparc_None);
- MIB = BuildMI(thisMBB, DL, TII->get(SP::BCOND))
- .addMBB(restoreMBB)
- .addImm(SPCC::ICC_N);
-
- MIB = BuildMI(thisMBB, DL, TII->get(SP::BCOND))
- .addMBB(mainMBB)
- .addImm(SPCC::ICC_A);
-
- thisMBB->addSuccessor(mainMBB);
- thisMBB->addSuccessor(restoreMBB);
-
-
- // mainMBB:
- MIB = BuildMI(mainMBB, DL, TII->get(SP::ORrr))
- .addReg(mainDstReg, RegState::Define)
- .addReg(SP::G0)
- .addReg(SP::G0);
- MIB = BuildMI(mainMBB, DL, TII->get(SP::BCOND)).addMBB(sinkMBB).addImm(SPCC::ICC_A);
-
- mainMBB->addSuccessor(sinkMBB);
-
-
- // restoreMBB:
- MIB = BuildMI(restoreMBB, DL, TII->get(SP::ORri))
- .addReg(restoreDstReg, RegState::Define)
- .addReg(SP::G0)
- .addImm(1);
- //MIB = BuildMI(restoreMBB, DL, TII->get(SP::BCOND)).addMBB(sinkMBB).addImm(SPCC::ICC_A);
- restoreMBB->addSuccessor(sinkMBB);
-
- // sinkMBB:
- MIB = BuildMI(*sinkMBB, sinkMBB->begin(), DL,
- TII->get(SP::PHI), DstReg)
- .addReg(mainDstReg).addMBB(mainMBB)
- .addReg(restoreDstReg).addMBB(restoreMBB);
-
- MI.eraseFromParent();
- return sinkMBB;
-}
-
//===----------------------------------------------------------------------===//
// Sparc Inline Assembly Support
//===----------------------------------------------------------------------===//
@@ -3494,23 +3261,23 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
else
return std::make_pair(0U, &SP::IntRegsRegClass);
case 'f':
- if (VT == MVT::f32)
+ if (VT == MVT::f32 || VT == MVT::i32)
return std::make_pair(0U, &SP::FPRegsRegClass);
- else if (VT == MVT::f64)
+ else if (VT == MVT::f64 || VT == MVT::i64)
return std::make_pair(0U, &SP::LowDFPRegsRegClass);
else if (VT == MVT::f128)
return std::make_pair(0U, &SP::LowQFPRegsRegClass);
- llvm_unreachable("Unknown ValueType for f-register-type!");
- break;
+ // This will generate an error message
+ return std::make_pair(0U, nullptr);
case 'e':
- if (VT == MVT::f32)
+ if (VT == MVT::f32 || VT == MVT::i32)
return std::make_pair(0U, &SP::FPRegsRegClass);
- else if (VT == MVT::f64)
+ else if (VT == MVT::f64 || VT == MVT::i64 )
return std::make_pair(0U, &SP::DFPRegsRegClass);
else if (VT == MVT::f128)
return std::make_pair(0U, &SP::QFPRegsRegClass);
- llvm_unreachable("Unknown ValueType for e-register-type!");
- break;
+ // This will generate an error message
+ return std::make_pair(0U, nullptr);
}
} else if (!Constraint.empty() && Constraint.size() <= 5
&& Constraint[0] == '{' && *(Constraint.end()-1) == '}') {
@@ -3587,7 +3354,16 @@ void SparcTargetLowering::ReplaceNodeResults(SDNode *N,
getLibcallName(libCall),
1));
return;
-
+ case ISD::READCYCLECOUNTER: {
+ assert(Subtarget->hasLeonCycleCounter());
+ SDValue Lo = DAG.getCopyFromReg(N->getOperand(0), dl, SP::ASR23, MVT::i32);
+ SDValue Hi = DAG.getCopyFromReg(Lo, dl, SP::G0, MVT::i32);
+ SDValue Ops[] = { Lo, Hi };
+ SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops);
+ Results.push_back(Pair);
+ Results.push_back(N->getOperand(0));
+ return;
+ }
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP:
// Custom lower only if it involves f128 or i64.
diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h
index 0cbbda787881..718851db25bf 100644
--- a/lib/Target/Sparc/SparcISelLowering.h
+++ b/lib/Target/Sparc/SparcISelLowering.h
@@ -33,9 +33,6 @@ namespace llvm {
SELECT_XCC, // Select between two values using the current XCC flags.
SELECT_FCC, // Select between two values using the current FCC flags.
- EH_SJLJ_SETJMP, // builtin setjmp operation
- EH_SJLJ_LONGJMP, // builtin longjmp operation
-
Hi, Lo, // Hi/Lo operations, typically on a global address.
FTOI, // FP to Int within a FP register.
@@ -171,12 +168,6 @@ namespace llvm {
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG,
- const SparcTargetLowering &TLI) const ;
- SDValue LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG,
- const SparcTargetLowering &TLI) const ;
-
- unsigned getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const;
SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const;
SDValue makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF,
SelectionDAG &DAG) const;
@@ -192,6 +183,13 @@ namespace llvm {
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
+ SDValue PerformBITCASTCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+
+ SDValue bitcastConstantFPToInt(ConstantFPSDNode *C, const SDLoc &DL,
+ SelectionDAG &DAG) const;
+
+ SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
+
bool ShouldShrinkFPConstant(EVT VT) const override {
// Do not shrink FP constpool if VT == MVT::f128.
// (ldd, call _Q_fdtoq) is more expensive than two ldds.
@@ -213,10 +211,6 @@ namespace llvm {
MachineBasicBlock *expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB,
unsigned BROpcode) const;
- MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI,
- MachineBasicBlock *MBB) const;
- MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr &MI,
- MachineBasicBlock *MBB) const;
};
} // end namespace llvm
diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td
index f6518c936ebc..0b94c6b614eb 100644
--- a/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/lib/Target/Sparc/SparcInstr64Bit.td
@@ -239,7 +239,7 @@ let Predicates = [Is64Bit] in {
let DecoderMethod = "DecodeLoadInt" in
defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>;
-let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in
+let mayLoad = 1, isAsmParserOnly = 1 in
def TLS_LDXrr : F3_1<3, 0b001011,
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
"ldx [$addr], $dst, $sym",
diff --git a/lib/Target/Sparc/SparcInstrAliases.td b/lib/Target/Sparc/SparcInstrAliases.td
index 352090ed92c1..35987390d7ba 100644
--- a/lib/Target/Sparc/SparcInstrAliases.td
+++ b/lib/Target/Sparc/SparcInstrAliases.td
@@ -470,10 +470,15 @@ def : InstAlias<"wr $simm13, %wim", (WRWIMri G0, i32imm:$simm13), 0>;
def : InstAlias<"wr $rs2, %tbr", (WRTBRrr G0, IntRegs:$rs2), 0>;
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>;
// flush -> flush %g0
def : InstAlias<"flush", (FLUSH), 0>;
+// unimp -> unimp 0
+def : InstAlias<"unimp", (UNIMP 0), 0>;
+
def : MnemonicAlias<"iflush", "flush">;
def : MnemonicAlias<"stub", "stb">;
diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td
index 5b7fb3c485e8..558b37aeebcb 100644
--- a/lib/Target/Sparc/SparcInstrInfo.td
+++ b/lib/Target/Sparc/SparcInstrInfo.td
@@ -56,6 +56,11 @@ def HasHardQuad : Predicate<"Subtarget->hasHardQuad()">;
// instruction
def HasLeonCASA : Predicate<"Subtarget->hasLeonCasa()">;
+// HasPWRPSR - This is true when the target processor supports partial
+// writes to the PSR register that only affects the ET field.
+def HasPWRPSR : Predicate<"Subtarget->hasPWRPSR()">,
+ AssemblerPredicate<"FeaturePWRPSR">;
+
// HasUMAC_SMAC - This is true when the target processor supports the
// UMAC and SMAC instructions
def HasUMAC_SMAC : Predicate<"Subtarget->hasUmacSmac()">;
@@ -89,10 +94,22 @@ def HI22 : SDNodeXForm<imm, [{
MVT::i32);
}]>;
+// Return the complement of a HI22 immediate value.
+def HI22_not : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant(~(unsigned)N->getZExtValue() >> 10, SDLoc(N),
+ MVT::i32);
+}]>;
+
def SETHIimm : PatLeaf<(imm), [{
return isShiftedUInt<22, 10>(N->getZExtValue());
}], HI22>;
+// The N->hasOneUse() prevents the immediate from being instantiated in both
+// normal and complement form.
+def SETHIimm_not : PatLeaf<(i32 imm), [{
+ return N->hasOneUse() && isShiftedUInt<22, 10>(~(unsigned)N->getZExtValue());
+}], HI22_not>;
+
// Addressing modes.
def ADDRrr : ComplexPattern<iPTR, 2, "SelectADDRrr", [], []>;
def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>;
@@ -121,6 +138,16 @@ def MEMri : Operand<iPTR> {
def TLSSym : Operand<iPTR>;
+def SparcMembarTagAsmOperand : AsmOperandClass {
+ let Name = "MembarTag";
+ let ParserMethod = "parseMembarTag";
+}
+
+def MembarTag : Operand<i32> {
+ let PrintMethod = "printMembarTag";
+ let ParserMatchClass = SparcMembarTagAsmOperand;
+}
+
// Branch targets have OtherVT type.
def brtarget : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
@@ -169,9 +196,6 @@ SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
def SDTSPtlsld :
SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
-def SDTSPeh_sjlj_setjmp : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisPtrTy<1>]>;
-def SDTSPeh_sjlj_longjmp: SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
-
def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;
def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;
def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
@@ -190,13 +214,6 @@ 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 SPsjlj_setjmp: SDNode<"SPISD::EH_SJLJ_SETJMP",
- SDTSPeh_sjlj_setjmp,
- [SDNPHasChain, SDNPSideEffect]>;
-def SPsjlj_longjmp: SDNode<"SPISD::EH_SJLJ_LONGJMP",
- SDTSPeh_sjlj_longjmp,
- [SDNPHasChain, SDNPSideEffect]>;
-
// These are target-independent nodes, but have target-specific formats.
def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>,
SDTCisVT<1, i32> ]>;
@@ -473,27 +490,6 @@ let usesCustomInserter = 1, Uses = [FCC0] in {
[(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>;
}
-let hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1 in {
- let Defs = [WIM] in
- def EH_SJLJ_SETJMP32ri : Pseudo<(outs IntRegs:$dst), (ins MEMri:$buf),
- "#EH_SJLJ_SETJMP32",
- [(set i32:$dst, (SPsjlj_setjmp ADDRri:$buf))]>,
- Requires<[Is32Bit]>;
- def EH_SJLJ_SETJMP32rr : Pseudo<(outs IntRegs:$dst), (ins MEMrr:$buf),
- "#EH_SJLJ_SETJMP32",
- [(set i32:$dst, (SPsjlj_setjmp ADDRrr:$buf))]>,
- Requires<[Is32Bit]>;
- let isTerminator = 1 in
- def EH_SJLJ_LONGJMP32ri : Pseudo<(outs), (ins MEMri:$buf),
- "#EH_SJLJ_LONGJMP32",
- [(SPsjlj_longjmp ADDRri:$buf)]>,
- Requires<[Is32Bit]>;
- def EH_SJLJ_LONGJMP32rr : Pseudo<(outs), (ins MEMrr:$buf),
- "#EH_SJLJ_LONGJMP32",
- [(SPsjlj_longjmp ADDRrr:$buf)]>,
- Requires<[Is32Bit]>;
-}
-
// Section B.1 - Load Integer Instructions, p. 90
let DecoderMethod = "DecodeLoadInt" in {
defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8, IntRegs, i32>;
@@ -680,6 +676,12 @@ def XNORri : F3_2<2, 0b000111,
(outs IntRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13),
"xnor $rs1, $simm13, $rd", []>;
+def : Pat<(and IntRegs:$rs1, SETHIimm_not:$rs2),
+ (ANDNrr i32:$rs1, (SETHIi SETHIimm_not:$rs2))>;
+
+def : Pat<(or IntRegs:$rs1, SETHIimm_not:$rs2),
+ (ORNrr i32:$rs1, (SETHIi SETHIimm_not:$rs2))>;
+
let Defs = [ICC] in {
defm ANDCC : F3_12np<"andcc", 0b010001>;
defm ANDNCC : F3_12np<"andncc", 0b010101>;
@@ -1316,7 +1318,7 @@ let Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in {
//===----------------------------------------------------------------------===//
// Instructions for Thread Local Storage(TLS).
//===----------------------------------------------------------------------===//
-let isCodeGenOnly = 1, isAsmParserOnly = 1 in {
+let isAsmParserOnly = 1 in {
def TLS_ADDrr : F3_1<2, 0b000000,
(outs IntRegs:$rd),
(ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym),
@@ -1511,7 +1513,7 @@ def : Pat<(ctpop i32:$src),
(POPCrr (SRLri $src, 0))>;
let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in
- def MEMBARi : F3_2<2, 0b101000, (outs), (ins simm13Op:$simm13),
+ def MEMBARi : F3_2<2, 0b101000, (outs), (ins MembarTag:$simm13),
"membar $simm13", []>;
// The CAS instruction, unlike other instructions, only comes in a
@@ -1569,6 +1571,17 @@ let Predicates = [HasUMAC_SMAC], Defs = [Y, ASR18], Uses = [Y, ASR18] in {
[], IIC_smac_umac>;
}
+// The partial write WRPSR instruction has a non-zero destination
+// register value to separate it from the standard instruction.
+let Predicates = [HasPWRPSR], Defs = [PSR], rd=1 in {
+ def PWRPSRrr : F3_1<2, 0b110001,
+ (outs), (ins IntRegs:$rs1, IntRegs:$rs2),
+ "pwr $rs1, $rs2, %psr", []>;
+ def PWRPSRri : F3_2<2, 0b110001,
+ (outs), (ins IntRegs:$rs1, simm13Op:$simm13),
+ "pwr $rs1, $simm13, %psr", []>;
+}
+
let Defs = [ICC] in {
defm TADDCC : F3_12np<"taddcc", 0b100000>;
defm TSUBCC : F3_12np<"tsubcc", 0b100001>;
diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp
index b9647eaa3d51..33caa66154ff 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.cpp
+++ b/lib/Target/Sparc/SparcRegisterInfo.cpp
@@ -95,6 +95,10 @@ BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
}
}
+ // Reserve ASR1-ASR31
+ for (unsigned n = 0; n < 31; n++)
+ Reserved.set(SP::ASR1 + n);
+
return Reserved;
}
diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h
index 2a279dad5ae2..8dd2569d10de 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.h
+++ b/lib/Target/Sparc/SparcRegisterInfo.h
@@ -35,8 +35,6 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF,
unsigned Kind) const override;
- bool enableMultipleCopyHints() const override { return true; }
-
void eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
diff --git a/lib/Target/Sparc/SparcSubtarget.cpp b/lib/Target/Sparc/SparcSubtarget.cpp
index 40c5683f8495..5301fc30a006 100644
--- a/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/lib/Target/Sparc/SparcSubtarget.cpp
@@ -44,9 +44,11 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU,
// Leon features
HasLeonCasa = false;
HasUmacSmac = false;
+ HasPWRPSR = false;
InsertNOPLoad = false;
FixAllFDIVSQRT = false;
DetectRoundChange = false;
+ HasLeonCycleCounter = false;
// Determine default and user specified characteristics
std::string CPUName = CPU;
diff --git a/lib/Target/Sparc/SparcSubtarget.h b/lib/Target/Sparc/SparcSubtarget.h
index 588a6765bcdf..24ea41a266e7 100644
--- a/lib/Target/Sparc/SparcSubtarget.h
+++ b/lib/Target/Sparc/SparcSubtarget.h
@@ -47,9 +47,11 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
// LEON features
bool HasUmacSmac;
bool HasLeonCasa;
+ bool HasPWRPSR;
bool InsertNOPLoad;
bool FixAllFDIVSQRT;
bool DetectRoundChange;
+ bool HasLeonCycleCounter;
SparcInstrInfo InstrInfo;
SparcTargetLowering TLInfo;
@@ -92,9 +94,11 @@ public:
// Leon options
bool hasUmacSmac() const { return HasUmacSmac; }
bool hasLeonCasa() const { return HasLeonCasa; }
+ bool hasPWRPSR() const { return HasPWRPSR; }
bool insertNOPLoad() const { return InsertNOPLoad; }
bool fixAllFDIVSQRT() const { return FixAllFDIVSQRT; }
bool detectRoundChange() const { return DetectRoundChange; }
+ bool hasLeonCycleCounter() const { return HasLeonCycleCounter; }
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp
index 07f9e7250bd9..5b467235f809 100644
--- a/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -70,11 +70,16 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
// pic32 PIC_ Medium GOT < 2^32 bytes
//
// All code models require that the text segment is smaller than 2GB.
-static CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM,
- Reloc::Model RM, bool Is64Bit,
- bool JIT) {
- if (CM)
+static CodeModel::Model
+getEffectiveSparcCodeModel(Optional<CodeModel::Model> CM, Reloc::Model RM,
+ bool Is64Bit, bool JIT) {
+ if (CM) {
+ if (*CM == CodeModel::Tiny)
+ report_fatal_error("Target does not support the tiny CodeModel");
+ if (*CM == CodeModel::Kernel)
+ report_fatal_error("Target does not support the kernel CodeModel");
return *CM;
+ }
if (Is64Bit) {
if (JIT)
return CodeModel::Large;
@@ -88,11 +93,11 @@ 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)
- : LLVMTargetMachine(
- T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options,
- getEffectiveRelocModel(RM),
- getEffectiveCodeModel(CM, getEffectiveRelocModel(RM), is64bit, JIT),
- OL),
+ : LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options,
+ getEffectiveRelocModel(RM),
+ getEffectiveSparcCodeModel(
+ CM, getEffectiveRelocModel(RM), is64bit, JIT),
+ OL),
TLOF(make_unique<SparcELFTargetObjectFile>()),
Subtarget(TT, CPU, FS, *this, is64bit), is64Bit(is64bit) {
initAsmInfo();
diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h
index b0d76abeba7d..d1eb1d329a4c 100644
--- a/lib/Target/Sparc/SparcTargetMachine.h
+++ b/lib/Target/Sparc/SparcTargetMachine.h
@@ -40,10 +40,6 @@ public:
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
}
-
- bool isMachineVerifierClean() const override {
- return false;
- }
};
/// Sparc 32-bit target machine