diff options
Diffstat (limited to 'lib/Target/Sparc')
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 |