X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsISelLowering.cpp;h=66c495bc3e92fdc4743e2b5a73bb492bfc3f7449;hp=e3f4b11e0c1cae022b74010441a4d1aa83890af6;hb=de9bf0f80e8262b0eae2e826a35dde0a346391e4;hpb=b4b823941cb12bc50a07c9e6f0c648a72cfa9683 diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index e3f4b11e0c1..66c495bc3e9 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -14,6 +14,7 @@ #include "MipsISelLowering.h" #include "InstPrinter/MipsInstPrinter.h" #include "MCTargetDesc/MipsBaseInfo.h" +#include "MipsCCState.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" @@ -26,6 +27,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/CallingConv.h" @@ -52,180 +54,11 @@ NoZeroDivCheck("mno-check-zero-division", cl::Hidden, cl::desc("MIPS: Don't trap on integer division by zero."), cl::init(false)); -cl::opt -EnableMipsFastISel("mips-fast-isel", cl::Hidden, - cl::desc("Allow mips-fast-isel to be used"), - cl::init(false)); - -static const MCPhysReg O32IntRegs[4] = { - Mips::A0, Mips::A1, Mips::A2, Mips::A3 -}; - -static const MCPhysReg Mips64IntRegs[8] = { - Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, - Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64 -}; - static const MCPhysReg Mips64DPRegs[8] = { Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64, Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64 }; -static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode); - -namespace { -class MipsCCState : public CCState { -public: - enum SpecialCallingConvType { Mips16RetHelperConv, NoSpecialCallingConv }; - - /// Determine the SpecialCallingConvType for the given callee - static SpecialCallingConvType - getSpecialCallingConvForCallee(const SDNode *Callee, - const MipsSubtarget &Subtarget) { - SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv; - if (Subtarget.inMips16HardFloat()) { - if (const GlobalAddressSDNode *G = - dyn_cast(Callee)) { - llvm::StringRef Sym = G->getGlobal()->getName(); - Function *F = G->getGlobal()->getParent()->getFunction(Sym); - if (F && F->hasFnAttribute("__Mips16RetHelper")) { - SpecialCallingConv = Mips16RetHelperConv; - } - } - } - return SpecialCallingConv; - } - -private: - /// Identify lowered values that originated from f128 arguments and record - /// this for use by RetCC_MipsN. - void - PreAnalyzeCallResultForF128(const SmallVectorImpl &Ins, - const TargetLowering::CallLoweringInfo &CLI) { - for (unsigned i = 0; i < Ins.size(); ++i) - OriginalArgWasF128.push_back( - originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode())); - } - - /// Identify lowered values that originated from f128 arguments and record - /// this for use by RetCC_MipsN. - void PreAnalyzeReturnForF128(const SmallVectorImpl &Outs) { - const MachineFunction &MF = getMachineFunction(); - for (unsigned i = 0; i < Outs.size(); ++i) - OriginalArgWasF128.push_back( - originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); - } - - /// Identify lowered values that originated from f128 arguments and record - /// this. - void PreAnalyzeCallOperands( - const SmallVectorImpl &Outs, - std::vector &FuncArgs, - const SDNode *CallNode) { - for (unsigned i = 0; i < Outs.size(); ++i) { - OriginalArgWasF128.push_back( - originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode)); - CallOperandIsFixed.push_back(Outs[i].IsFixed); - } - } - - /// Identify lowered values that originated from f128 arguments and record - /// this. - void - PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl &Ins) { - const MachineFunction &MF = getMachineFunction(); - for (unsigned i = 0; i < Ins.size(); ++i) { - Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin(); - - // SRet arguments cannot originate from f128 or {f128} returns so we just - // push false. We have to handle this specially since SRet arguments - // aren't mapped to an original argument. - if (Ins[i].Flags.isSRet()) { - OriginalArgWasF128.push_back(false); - continue; - } - - assert(Ins[i].OrigArgIndex < MF.getFunction()->arg_size()); - std::advance(FuncArg, Ins[i].OrigArgIndex); - OriginalArgWasF128.push_back( - originalTypeIsF128(FuncArg->getType(), nullptr)); - } - } - - /// Records whether the value has been lowered from an f128. - SmallVector OriginalArgWasF128; - - /// Records whether the value was a fixed argument. - /// See ISD::OutputArg::IsFixed, - SmallVector CallOperandIsFixed; - - // Used to handle MIPS16-specific calling convention tweaks. - // FIXME: This should probably be a fully fledged calling convention. - SpecialCallingConvType SpecialCallingConv; - -public: - - MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - SmallVectorImpl &locs, LLVMContext &C, - SpecialCallingConvType SpecialCC = NoSpecialCallingConv) - : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {} - - void - AnalyzeCallOperands(const SmallVectorImpl &Outs, - CCAssignFn Fn, - std::vector &FuncArgs, - const SDNode *CallNode) { - PreAnalyzeCallOperands(Outs, FuncArgs, CallNode); - CCState::AnalyzeCallOperands(Outs, Fn); - OriginalArgWasF128.clear(); - CallOperandIsFixed.clear(); - } - - // The AnalyzeCallOperands in the base class is not usable since we must - // provide a means of accessing ArgListEntry::IsFixed. Delete them from this - // class. This doesn't stop them being used via the base class though. - void AnalyzeCallOperands(const SmallVectorImpl &Outs, - CCAssignFn Fn) = delete; - void AnalyzeCallOperands(const SmallVectorImpl &Outs, - SmallVectorImpl &Flags, - CCAssignFn Fn) = delete; - - void AnalyzeFormalArguments(const SmallVectorImpl &Ins, - CCAssignFn Fn) { - PreAnalyzeFormalArgumentsForF128(Ins); - CCState::AnalyzeFormalArguments(Ins, Fn); - OriginalArgWasF128.clear(); - } - - void AnalyzeCallResult(const SmallVectorImpl &Ins, - CCAssignFn Fn, - const TargetLowering::CallLoweringInfo &CLI) { - PreAnalyzeCallResultForF128(Ins, CLI); - CCState::AnalyzeCallResult(Ins, Fn); - OriginalArgWasF128.clear(); - } - - void AnalyzeReturn(const SmallVectorImpl &Outs, - CCAssignFn Fn) { - PreAnalyzeReturnForF128(Outs); - CCState::AnalyzeReturn(Outs, Fn); - OriginalArgWasF128.clear(); - } - - bool CheckReturn(const SmallVectorImpl &ArgsFlags, - CCAssignFn Fn) { - PreAnalyzeReturnForF128(ArgsFlags); - bool Return = CCState::CheckReturn(ArgsFlags, Fn); - OriginalArgWasF128.clear(); - return Return; - } - - bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } - bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; } - SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; } -}; -} - // If I is a shifted mask, set the size (Size) and the first bit of the // mask (Pos), and return true. // For example, if I is 0x003ff800, (Pos, Size) = (11, 11). @@ -233,7 +66,7 @@ static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { if (!isShiftedMask_64(I)) return false; - Size = CountPopulation_64(I); + Size = countPopulation(I); Pos = countTrailingZeros(I); return true; } @@ -275,7 +108,8 @@ SDValue MipsTargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty, } const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { - switch (Opcode) { + switch ((MipsISD::NodeType)Opcode) { + case MipsISD::FIRST_NUMBER: break; case MipsISD::JmpLink: return "MipsISD::JmpLink"; case MipsISD::TailCall: return "MipsISD::TailCall"; case MipsISD::Hi: return "MipsISD::Hi"; @@ -283,6 +117,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::GPRel: return "MipsISD::GPRel"; case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; case MipsISD::Ret: return "MipsISD::Ret"; + case MipsISD::ERet: return "MipsISD::ERet"; case MipsISD::EH_RETURN: return "MipsISD::EH_RETURN"; case MipsISD::FPBrcond: return "MipsISD::FPBrcond"; case MipsISD::FPCmp: return "MipsISD::FPCmp"; @@ -305,6 +140,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64"; case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; case MipsISD::Wrapper: return "MipsISD::Wrapper"; + case MipsISD::DynAlloc: return "MipsISD::DynAlloc"; case MipsISD::Sync: return "MipsISD::Sync"; case MipsISD::Ext: return "MipsISD::Ext"; case MipsISD::Ins: return "MipsISD::Ins"; @@ -324,6 +160,28 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::EXTR_RS_W: return "MipsISD::EXTR_RS_W"; case MipsISD::SHILO: return "MipsISD::SHILO"; case MipsISD::MTHLIP: return "MipsISD::MTHLIP"; + case MipsISD::MULSAQ_S_W_PH: return "MipsISD::MULSAQ_S_W_PH"; + case MipsISD::MAQ_S_W_PHL: return "MipsISD::MAQ_S_W_PHL"; + case MipsISD::MAQ_S_W_PHR: return "MipsISD::MAQ_S_W_PHR"; + case MipsISD::MAQ_SA_W_PHL: return "MipsISD::MAQ_SA_W_PHL"; + case MipsISD::MAQ_SA_W_PHR: return "MipsISD::MAQ_SA_W_PHR"; + case MipsISD::DPAU_H_QBL: return "MipsISD::DPAU_H_QBL"; + case MipsISD::DPAU_H_QBR: return "MipsISD::DPAU_H_QBR"; + case MipsISD::DPSU_H_QBL: return "MipsISD::DPSU_H_QBL"; + case MipsISD::DPSU_H_QBR: return "MipsISD::DPSU_H_QBR"; + case MipsISD::DPAQ_S_W_PH: return "MipsISD::DPAQ_S_W_PH"; + case MipsISD::DPSQ_S_W_PH: return "MipsISD::DPSQ_S_W_PH"; + case MipsISD::DPAQ_SA_L_W: return "MipsISD::DPAQ_SA_L_W"; + case MipsISD::DPSQ_SA_L_W: return "MipsISD::DPSQ_SA_L_W"; + case MipsISD::DPA_W_PH: return "MipsISD::DPA_W_PH"; + case MipsISD::DPS_W_PH: return "MipsISD::DPS_W_PH"; + case MipsISD::DPAQX_S_W_PH: return "MipsISD::DPAQX_S_W_PH"; + case MipsISD::DPAQX_SA_W_PH: return "MipsISD::DPAQX_SA_W_PH"; + case MipsISD::DPAX_W_PH: return "MipsISD::DPAX_W_PH"; + case MipsISD::DPSX_W_PH: return "MipsISD::DPSX_W_PH"; + case MipsISD::DPSQX_S_W_PH: return "MipsISD::DPSQX_S_W_PH"; + case MipsISD::DPSQX_SA_W_PH: return "MipsISD::DPSQX_SA_W_PH"; + case MipsISD::MULSA_W_PH: return "MipsISD::MULSA_W_PH"; case MipsISD::MULT: return "MipsISD::MULT"; case MipsISD::MULTU: return "MipsISD::MULTU"; case MipsISD::MADD_DSP: return "MipsISD::MADD_DSP"; @@ -360,13 +218,13 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::PCKEV: return "MipsISD::PCKEV"; case MipsISD::PCKOD: return "MipsISD::PCKOD"; case MipsISD::INSVE: return "MipsISD::INSVE"; - default: return nullptr; } + return nullptr; } MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) - : TargetLowering(TM, new MipsTargetObjectFile()), Subtarget(STI) { + : TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) { // Mips does not have i1 type, so use i32 for // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); @@ -378,12 +236,29 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, ZeroOrNegativeOneBooleanContent); // Load extented operations for i1 types must be promoted - setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + for (MVT VT : MVT::integer_valuetypes()) { + setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); + } + + // MIPS doesn't have extending float->double load/store. Set LoadExtAction + // for f32, f16 + for (MVT VT : MVT::fp_valuetypes()) { + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand); + } + + // Set LoadExtAction for f16 vectors to Expand + for (MVT VT : MVT::fp_vector_valuetypes()) { + MVT F16VT = MVT::getVectorVT(MVT::f16, VT.getVectorNumElements()); + if (F16VT.isValid()) + setLoadExtAction(ISD::EXTLOAD, VT, F16VT, Expand); + } + + setTruncStoreAction(MVT::f32, MVT::f16, Expand); + setTruncStoreAction(MVT::f64, MVT::f16, Expand); - // MIPS doesn't have extending float->double load/store - setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); setTruncStoreAction(MVT::f64, MVT::f32, Expand); // Used by legalize types to correctly generate the setcc result. @@ -421,6 +296,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::LOAD, MVT::i64, Custom); setOperationAction(ISD::STORE, MVT::i64, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); + setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); } if (!Subtarget.isGP64bit()) { @@ -496,6 +374,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::FREM, MVT::f32, Expand); setOperationAction(ISD::FREM, MVT::f64, Expand); + // Lower f16 conversion operations into library calls + setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand); + setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand); + setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand); + setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand); + setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); @@ -507,10 +391,10 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); - setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); + if (!Subtarget.isGP64bit()) { + setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); + } setInsertFencesForAtomic(true); @@ -531,9 +415,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::BSWAP, MVT::i64, Expand); if (Subtarget.isGP64bit()) { - setLoadExtAction(ISD::SEXTLOAD, MVT::i32, Custom); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Custom); - setLoadExtAction(ISD::EXTLOAD, MVT::i32, Custom); + setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom); + setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); setTruncStoreAction(MVT::i64, MVT::i32, Custom); } @@ -550,14 +434,9 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, // The arguments on the stack are defined in terms of 4-byte slots on O32 // and 8-byte slots on N32/N64. - setMinStackArgumentAlignment( - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4); - - setStackPointerRegisterToSaveRestore(Subtarget.isABI_N64() ? Mips::SP_64 - : Mips::SP); + setMinStackArgumentAlignment((ABI.IsN32() || ABI.IsN64()) ? 8 : 4); - setExceptionPointerRegister(Subtarget.isABI_N64() ? Mips::A0_64 : Mips::A0); - setExceptionSelectorRegister(Subtarget.isABI_N64() ? Mips::A1_64 : Mips::A1); + setStackPointerRegisterToSaveRestore(ABI.IsN64() ? Mips::SP_64 : Mips::SP); MaxStoresPerMemcpy = 16; @@ -576,12 +455,13 @@ const MipsTargetLowering *MipsTargetLowering::create(const MipsTargetMachine &TM FastISel * MipsTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) const { - if (!EnableMipsFastISel) + if (!funcInfo.MF->getTarget().Options.EnableFastISel) return TargetLowering::createFastISel(funcInfo, libInfo); return Mips::createFastISel(funcInfo, libInfo); } -EVT MipsTargetLowering::getSetCCResultType(LLVMContext &, EVT VT) const { +EVT MipsTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, + EVT VT) const { if (!VT.isVector()) return MVT::i32; return VT.changeVectorElementTypeToInteger(); @@ -683,7 +563,7 @@ static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { ISD::CondCode CC = cast(Op.getOperand(2))->get(); return DAG.getNode(MipsISD::FPCmp, DL, MVT::Glue, LHS, RHS, - DAG.getConstant(condCodeToFCC(CC), MVT::i32)); + DAG.getConstant(condCodeToFCC(CC), DL, MVT::i32)); } // Creates and returns a CMovFPT/F node. @@ -776,6 +656,33 @@ static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } +static SDValue performCMovFPCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget &Subtarget) { + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + + SDValue ValueIfTrue = N->getOperand(0), ValueIfFalse = N->getOperand(2); + + ConstantSDNode *FalseC = dyn_cast(ValueIfFalse); + if (!FalseC || FalseC->getZExtValue()) + return SDValue(); + + // Since RHS (False) is 0, we swap the order of the True/False operands + // (obviously also inverting the condition) so that we can + // take advantage of conditional moves using the $0 register. + // Example: + // return (a != 0) ? x : 0; + // load $reg, x + // movz $reg, $0, a + unsigned Opc = (N->getOpcode() == MipsISD::CMovFP_T) ? MipsISD::CMovFP_F : + MipsISD::CMovFP_T; + + SDValue FCC = N->getOperand(1), Glue = N->getOperand(3); + return DAG.getNode(Opc, SDLoc(N), ValueIfFalse.getValueType(), + ValueIfFalse, FCC, ValueIfTrue, Glue); +} + static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget) { @@ -811,9 +718,11 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits()) return SDValue(); - return DAG.getNode(MipsISD::Ext, SDLoc(N), ValTy, - ShiftRight.getOperand(0), DAG.getConstant(Pos, MVT::i32), - DAG.getConstant(SMSize, MVT::i32)); + SDLoc DL(N); + return DAG.getNode(MipsISD::Ext, DL, ValTy, + ShiftRight.getOperand(0), + DAG.getConstant(Pos, DL, MVT::i32), + DAG.getConstant(SMSize, DL, MVT::i32)); } static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, @@ -865,9 +774,11 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits())) return SDValue(); - return DAG.getNode(MipsISD::Ins, SDLoc(N), ValTy, Shl.getOperand(0), - DAG.getConstant(SMPos0, MVT::i32), - DAG.getConstant(SMSize0, MVT::i32), And0.getOperand(0)); + SDLoc DL(N); + return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0), + DAG.getConstant(SMPos0, DL, MVT::i32), + DAG.getConstant(SMSize0, DL, MVT::i32), + And0.getOperand(0)); } static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, @@ -909,6 +820,9 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return performDivRemCombine(N, DAG, DCI, Subtarget); case ISD::SELECT: return performSELECTCombine(N, DAG, DCI, Subtarget); + case MipsISD::CMovFP_F: + case MipsISD::CMovFP_T: + return performCMovFPCombine(N, DAG, DCI, Subtarget); case ISD::AND: return performANDCombine(N, DAG, DCI, Subtarget); case ISD::OR: @@ -1096,18 +1010,35 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case Mips::DIVU: case Mips::MOD: case Mips::MODU: - return insertDivByZeroTrap( - MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), false); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false); case Mips::PseudoDSDIV: case Mips::PseudoDUDIV: case Mips::DDIV: case Mips::DDIVU: case Mips::DMOD: case Mips::DMODU: - return insertDivByZeroTrap( - MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), true); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true); case Mips::SEL_D: return emitSEL_D(MI, BB); + + case Mips::PseudoSELECT_I: + case Mips::PseudoSELECT_I64: + case Mips::PseudoSELECT_S: + case Mips::PseudoSELECT_D32: + case Mips::PseudoSELECT_D64: + return emitPseudoSELECT(MI, BB, false, Mips::BNE); + case Mips::PseudoSELECTFP_F_I: + case Mips::PseudoSELECTFP_F_I64: + case Mips::PseudoSELECTFP_F_S: + case Mips::PseudoSELECTFP_F_D32: + case Mips::PseudoSELECTFP_F_D64: + return emitPseudoSELECT(MI, BB, true, Mips::BC1F); + case Mips::PseudoSELECTFP_T_I: + case Mips::PseudoSELECTFP_T_I64: + case Mips::PseudoSELECTFP_T_S: + case Mips::PseudoSELECTFP_T_D32: + case Mips::PseudoSELECTFP_T_D64: + return emitPseudoSELECT(MI, BB, true, Mips::BC1T); } } @@ -1122,8 +1053,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, AND, NOR, ZERO, BEQ; @@ -1160,8 +1090,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = BB; - ++It; + MachineFunction::iterator It = ++BB->getIterator(); MF->insert(It, loopMBB); MF->insert(It, exitMBB); @@ -1206,8 +1135,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, unsigned SrcReg) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); if (Subtarget.hasMips32r2() && Size == 1) { @@ -1243,8 +1171,7 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1274,8 +1201,7 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = BB; - ++It; + MachineFunction::iterator It = ++BB->getIterator(); MF->insert(It, loopMBB); MF->insert(It, sinkMBB); MF->insert(It, exitMBB); @@ -1341,7 +1267,8 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( // beq success,$0,loopMBB BB = loopMBB; - BuildMI(BB, DL, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); + unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; + BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); if (Nand) { // and andres, oldval, incr2 // nor binopres, $0, andres @@ -1364,7 +1291,8 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( .addReg(OldVal).addReg(Mask2); BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal0).addReg(NewVal); - BuildMI(BB, DL, TII->get(Mips::SC), Success) + unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; + BuildMI(BB, DL, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::BEQ)) .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); @@ -1394,20 +1322,24 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, ZERO, BNE, BEQ; - if (Size == 4) { - LL = isMicroMips ? Mips::LL_MM : Mips::LL; - SC = isMicroMips ? Mips::SC_MM : Mips::SC; + if (Size == 4) { + if (isMicroMips) { + LL = Mips::LL_MM; + SC = Mips::SC_MM; + } else { + LL = Subtarget.hasMips32r6() ? Mips::LL_R6 : Mips::LL; + SC = Subtarget.hasMips32r6() ? Mips::SC_R6 : Mips::SC; + } ZERO = Mips::ZERO; BNE = Mips::BNE; BEQ = Mips::BEQ; } else { - LL = Mips::LLD; - SC = Mips::SCD; + LL = Subtarget.hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; + SC = Subtarget.hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; ZERO = Mips::ZERO_64; BNE = Mips::BNE64; BEQ = Mips::BEQ64; @@ -1425,8 +1357,7 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = BB; - ++It; + MachineFunction::iterator It = ++BB->getIterator(); MF->insert(It, loop1MBB); MF->insert(It, loop2MBB); MF->insert(It, exitMBB); @@ -1477,8 +1408,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1510,8 +1440,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = BB; - ++It; + MachineFunction::iterator It = ++BB->getIterator(); MF->insert(It, loop1MBB); MF->insert(It, loop2MBB); MF->insert(It, sinkMBB); @@ -1575,7 +1504,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, // and maskedoldval0,oldval,mask // bne maskedoldval0,shiftedcmpval,sinkMBB BB = loop1MBB; - BuildMI(BB, DL, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); + unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; + BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0) .addReg(OldVal).addReg(Mask); BuildMI(BB, DL, TII->get(Mips::BNE)) @@ -1591,7 +1521,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, .addReg(OldVal).addReg(Mask2); BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal1).addReg(ShiftedNewVal); - BuildMI(BB, DL, TII->get(Mips::SC), Success) + unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; + BuildMI(BB, DL, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::BEQ)) .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); @@ -1613,10 +1544,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const { MachineFunction *MF = BB->getParent(); - const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); MachineBasicBlock::iterator II(MI); @@ -1646,22 +1575,23 @@ SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { SDValue Table = Op.getOperand(1); SDValue Index = Op.getOperand(2); SDLoc DL(Op); - EVT PTy = getPointerTy(); + auto &TD = DAG.getDataLayout(); + EVT PTy = getPointerTy(TD); unsigned EntrySize = - DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(*getDataLayout()); + DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD); Index = DAG.getNode(ISD::MUL, DL, PTy, Index, - DAG.getConstant(EntrySize, PTy)); + DAG.getConstant(EntrySize, DL, PTy)); SDValue Addr = DAG.getNode(ISD::ADD, DL, PTy, Index, Table); EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); - Addr = DAG.getExtLoad(ISD::SEXTLOAD, DL, PTy, Chain, Addr, - MachinePointerInfo::getJumpTable(), MemVT, false, false, - false, 0); + Addr = + DAG.getExtLoad(ISD::SEXTLOAD, DL, PTy, Chain, Addr, + MachinePointerInfo::getJumpTable(DAG.getMachineFunction()), + MemVT, false, false, false, 0); Chain = Addr.getValue(1); - if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || - Subtarget.isABI_N64()) { + if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || ABI.IsN64()) { // For PIC, the sequence is: // BRIND(load(Jumptable + index) + RelocBase) // RelocBase can be JumpTable, GOT or some sort of global base. @@ -1690,7 +1620,7 @@ SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const { Mips::CondCode CC = (Mips::CondCode)cast(CCNode)->getZExtValue(); unsigned Opc = invertFPCondCodeUser(CC) ? Mips::BRANCH_F : Mips::BRANCH_T; - SDValue BrCode = DAG.getConstant(Opc, MVT::i32); + SDValue BrCode = DAG.getConstant(Opc, DL, MVT::i32); SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32); return DAG.getNode(MipsISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode, FCC0, Dest, CondRes); @@ -1715,10 +1645,10 @@ lowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); EVT Ty = Op.getOperand(0).getValueType(); - SDValue Cond = DAG.getNode(ISD::SETCC, DL, - getSetCCResultType(*DAG.getContext(), Ty), - Op.getOperand(0), Op.getOperand(1), - Op.getOperand(4)); + SDValue Cond = + DAG.getNode(ISD::SETCC, DL, getSetCCResultType(DAG.getDataLayout(), + *DAG.getContext(), Ty), + Op.getOperand(0), Op.getOperand(1), Op.getOperand(4)); return DAG.getNode(ISD::SELECT, DL, Op.getValueType(), Cond, Op.getOperand(2), Op.getOperand(3)); @@ -1731,10 +1661,11 @@ SDValue MipsTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const { assert(Cond.getOpcode() == MipsISD::FPCmp && "Floating point operand expected."); - SDValue True = DAG.getConstant(1, MVT::i32); - SDValue False = DAG.getConstant(0, MVT::i32); + SDLoc DL(Op); + SDValue True = DAG.getConstant(1, DL, MVT::i32); + SDValue False = DAG.getConstant(0, DL, MVT::i32); - return createCMovFP(DAG, Cond, True, False, SDLoc(Op)); + return createCMovFP(DAG, Cond, True, False, DL); } SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, @@ -1743,33 +1674,31 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, GlobalAddressSDNode *N = cast(Op); const GlobalValue *GV = N->getGlobal(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) { - const MipsTargetObjectFile &TLOF = - (const MipsTargetObjectFile&)getObjFileLowering(); - - if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + const MipsTargetObjectFile *TLOF = + static_cast( + getTargetMachine().getObjFileLowering()); + if (TLOF->IsGlobalInSmallSection(GV, getTargetMachine())) // %gp_rel relocation - return getAddrGPRel(N, Ty, DAG); + return getAddrGPRel(N, SDLoc(N), Ty, DAG); // %hi/%lo relocation - return getAddrNonPIC(N, Ty, DAG); + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); } if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa(GV))) - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); if (LargeGOT) - return getAddrGlobalLargeGOT(N, Ty, DAG, MipsII::MO_GOT_HI16, - MipsII::MO_GOT_LO16, DAG.getEntryNode(), - MachinePointerInfo::getGOT()); + return getAddrGlobalLargeGOT( + N, SDLoc(N), Ty, DAG, MipsII::MO_GOT_HI16, MipsII::MO_GOT_LO16, + DAG.getEntryNode(), + MachinePointerInfo::getGOT(DAG.getMachineFunction())); - return getAddrGlobal(N, Ty, DAG, - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) - ? MipsII::MO_GOT_DISP - : MipsII::MO_GOT16, - DAG.getEntryNode(), MachinePointerInfo::getGOT()); + return getAddrGlobal( + N, SDLoc(N), Ty, DAG, + (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT16, + DAG.getEntryNode(), MachinePointerInfo::getGOT(DAG.getMachineFunction())); } SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, @@ -1777,12 +1706,10 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, BlockAddressSDNode *N = cast(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) - return getAddrNonPIC(N, Ty, DAG); + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering:: @@ -1793,9 +1720,12 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const // Local Exec TLS Model. GlobalAddressSDNode *GA = cast(Op); + if (DAG.getTarget().Options.EmulatedTLS) + return LowerToTLSEmulatedModel(GA, DAG); + SDLoc DL(GA); const GlobalValue *GV = GA->getGlobal(); - EVT PtrVT = getPointerTy(); + EVT PtrVT = getPointerTy(DAG.getDataLayout()); TLSModel::Model model = getTargetMachine().getTLSModel(GV); @@ -1870,12 +1800,10 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const JumpTableSDNode *N = cast(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) - return getAddrNonPIC(N, Ty, DAG); + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering:: @@ -1884,20 +1812,20 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const ConstantPoolSDNode *N = cast(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) { - const MipsTargetObjectFile &TLOF = - (const MipsTargetObjectFile&)getObjFileLowering(); + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + const MipsTargetObjectFile *TLOF = + static_cast( + getTargetMachine().getObjFileLowering()); - if (TLOF.IsConstantInSmallSection(N->getConstVal(), getTargetMachine())) + if (TLOF->IsConstantInSmallSection(DAG.getDataLayout(), N->getConstVal(), + getTargetMachine())) // %gp_rel relocation - return getAddrGPRel(N, Ty, DAG); + return getAddrGPRel(N, SDLoc(N), Ty, DAG); - return getAddrNonPIC(N, Ty, DAG); + return getAddrNonPIC(N, SDLoc(N), Ty, DAG); } - return getAddrLocal(N, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { @@ -1906,7 +1834,7 @@ SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), - getPointerTy()); + getPointerTy(MF.getDataLayout())); // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. @@ -1923,12 +1851,11 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { unsigned Align = Node->getConstantOperandVal(3); const Value *SV = cast(Node->getOperand(2))->getValue(); SDLoc DL(Node); - unsigned ArgSlotSizeInBytes = - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4; + unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4; - SDValue VAListLoad = DAG.getLoad(getPointerTy(), DL, Chain, VAListPtr, - MachinePointerInfo(SV), false, false, false, - 0); + SDValue VAListLoad = + DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, VAListPtr, + MachinePointerInfo(SV), false, false, false, 0); SDValue VAList = VAListLoad; // Re-align the pointer if necessary. @@ -1942,19 +1869,21 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { assert(((Align & (Align-1)) == 0) && "Expected Align to be a power of 2"); VAList = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, - DAG.getConstant(Align - 1, - VAList.getValueType())); + DAG.getConstant(Align - 1, DL, VAList.getValueType())); VAList = DAG.getNode(ISD::AND, DL, VAList.getValueType(), VAList, - DAG.getConstant(-(int64_t)Align, + DAG.getConstant(-(int64_t)Align, DL, VAList.getValueType())); } // Increment the pointer, VAList, to the next vaarg. - unsigned ArgSizeInBytes = getDataLayout()->getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); + auto &TD = DAG.getDataLayout(); + unsigned ArgSizeInBytes = + TD.getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); SDValue Tmp3 = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, - DAG.getConstant(RoundUpToAlignment(ArgSizeInBytes, ArgSlotSizeInBytes), - VAList.getValueType())); + DAG.getConstant(RoundUpToAlignment(ArgSizeInBytes, + ArgSlotSizeInBytes), + DL, VAList.getValueType())); // Store the incremented VAList to the legalized pointer Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr, MachinePointerInfo(SV), false, false, 0); @@ -1967,7 +1896,7 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { if (!Subtarget.isLittle() && ArgSizeInBytes < ArgSlotSizeInBytes) { unsigned Adjustment = ArgSlotSizeInBytes - ArgSizeInBytes; VAList = DAG.getNode(ISD::ADD, DL, VAListPtr.getValueType(), VAList, - DAG.getIntPtrConstant(Adjustment)); + DAG.getIntPtrConstant(Adjustment, DL)); } // Load the actual argument out of the pointer VAList return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo(), false, false, @@ -1978,9 +1907,9 @@ static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, bool HasExtractInsert) { EVT TyX = Op.getOperand(0).getValueType(); EVT TyY = Op.getOperand(1).getValueType(); - SDValue Const1 = DAG.getConstant(1, MVT::i32); - SDValue Const31 = DAG.getConstant(31, MVT::i32); SDLoc DL(Op); + SDValue Const1 = DAG.getConstant(1, DL, MVT::i32); + SDValue Const31 = DAG.getConstant(31, DL, MVT::i32); SDValue Res; // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it @@ -2016,7 +1945,8 @@ static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Res); SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Op.getOperand(0), DAG.getConstant(0, MVT::i32)); + Op.getOperand(0), + DAG.getConstant(0, DL, MVT::i32)); return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res); } @@ -2025,8 +1955,8 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, unsigned WidthX = Op.getOperand(0).getValueSizeInBits(); unsigned WidthY = Op.getOperand(1).getValueSizeInBits(); EVT TyX = MVT::getIntegerVT(WidthX), TyY = MVT::getIntegerVT(WidthY); - SDValue Const1 = DAG.getConstant(1, MVT::i32); SDLoc DL(Op); + SDValue Const1 = DAG.getConstant(1, DL, MVT::i32); // Bitcast to integer nodes. SDValue X = DAG.getNode(ISD::BITCAST, DL, TyX, Op.getOperand(0)); @@ -2036,7 +1966,7 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, // ext E, Y, width(Y) - 1, 1 ; extract bit width(Y)-1 of Y // ins X, E, width(X) - 1, 1 ; insert extracted bit at bit width(X)-1 of X SDValue E = DAG.getNode(MipsISD::Ext, DL, TyY, Y, - DAG.getConstant(WidthY - 1, MVT::i32), Const1); + DAG.getConstant(WidthY - 1, DL, MVT::i32), Const1); if (WidthX > WidthY) E = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, E); @@ -2044,7 +1974,8 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, E = DAG.getNode(ISD::TRUNCATE, DL, TyX, E); SDValue I = DAG.getNode(MipsISD::Ins, DL, TyX, E, - DAG.getConstant(WidthX - 1, MVT::i32), Const1, X); + DAG.getConstant(WidthX - 1, DL, MVT::i32), Const1, + X); return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), I); } @@ -2056,7 +1987,7 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, SDValue SllX = DAG.getNode(ISD::SHL, DL, TyX, X, Const1); SDValue SrlX = DAG.getNode(ISD::SRL, DL, TyX, SllX, Const1); SDValue SrlY = DAG.getNode(ISD::SRL, DL, TyY, Y, - DAG.getConstant(WidthY - 1, MVT::i32)); + DAG.getConstant(WidthY - 1, DL, MVT::i32)); if (WidthX > WidthY) SrlY = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, SrlY); @@ -2064,7 +1995,7 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, SrlY = DAG.getNode(ISD::TRUNCATE, DL, TyX, SrlY); SDValue SllY = DAG.getNode(ISD::SHL, DL, TyX, SrlY, - DAG.getConstant(WidthX - 1, MVT::i32)); + DAG.getConstant(WidthX - 1, DL, MVT::i32)); SDValue Or = DAG.getNode(ISD::OR, DL, TyX, SrlX, SllY); return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Or); } @@ -2087,9 +2018,8 @@ lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); SDLoc DL(Op); - SDValue FrameAddr = - DAG.getCopyFromReg(DAG.getEntryNode(), DL, - Subtarget.isABI_N64() ? Mips::FP_64 : Mips::FP, VT); + SDValue FrameAddr = DAG.getCopyFromReg( + DAG.getEntryNode(), DL, ABI.IsN64() ? Mips::FP_64 : Mips::FP, VT); return FrameAddr; } @@ -2105,7 +2035,7 @@ SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MVT VT = Op.getSimpleValueType(); - unsigned RA = Subtarget.isABI_N64() ? Mips::RA_64 : Mips::RA; + unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA; MFI->setReturnAddressIsTaken(true); // Return RA, which contains the return address. Mark it an implicit live-in. @@ -2127,17 +2057,17 @@ SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) SDValue Offset = Op.getOperand(1); SDValue Handler = Op.getOperand(2); SDLoc DL(Op); - EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; + EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; // Store stack offset in V1, store jump target in V0. Glue CopyToReg and // EH_RETURN nodes, so that instructions are emitted back-to-back. - unsigned OffsetReg = Subtarget.isABI_N64() ? Mips::V1_64 : Mips::V1; - unsigned AddrReg = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; + unsigned OffsetReg = ABI.IsN64() ? Mips::V1_64 : Mips::V1; + unsigned AddrReg = ABI.IsN64() ? Mips::V0_64 : Mips::V0; Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue()); Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1)); return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain, DAG.getRegister(OffsetReg, Ty), - DAG.getRegister(AddrReg, getPointerTy()), + DAG.getRegister(AddrReg, getPointerTy(MF.getDataLayout())), Chain.getValue(1)); } @@ -2148,35 +2078,35 @@ SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op, unsigned SType = 0; SDLoc DL(Op); return DAG.getNode(MipsISD::Sync, DL, MVT::Other, Op.getOperand(0), - DAG.getConstant(SType, MVT::i32)); + DAG.getConstant(SType, DL, MVT::i32)); } SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); + MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32; + SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); SDValue Shamt = Op.getOperand(2); - - // if shamt < 32: + // if shamt < (VT.bits): // lo = (shl lo, shamt) // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) // else: // lo = 0 // hi = (shl lo, shamt[4:0]) SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, - DAG.getConstant(-1, MVT::i32)); - SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, - DAG.getConstant(1, MVT::i32)); - SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, ShiftRight1Lo, - Not); - SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, Shamt); - SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); - SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, MVT::i32, Lo, Shamt); + DAG.getConstant(-1, DL, MVT::i32)); + SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, + DAG.getConstant(1, DL, VT)); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); + SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, - DAG.getConstant(0x20, MVT::i32)); - Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, - DAG.getConstant(0, MVT::i32), ShiftLeftLo); - Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftLeftLo, Or); + DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); + Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, + DAG.getConstant(0, DL, VT), ShiftLeftLo); + Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftLeftLo, Or); SDValue Ops[2] = {Lo, Hi}; return DAG.getMergeValues(Ops, DL); @@ -2187,8 +2117,9 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, SDLoc DL(Op); SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); SDValue Shamt = Op.getOperand(2); + MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32; - // if shamt < 32: + // if shamt < (VT.bits): // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) // if isSRA: // hi = (sra hi, shamt) @@ -2202,22 +2133,21 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, // lo = (srl hi, shamt[4:0]) // hi = 0 SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, - DAG.getConstant(-1, MVT::i32)); - SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, - DAG.getConstant(1, MVT::i32)); - SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, ShiftLeft1Hi, Not); - SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, Shamt); - SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); - SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, MVT::i32, - Hi, Shamt); + DAG.getConstant(-1, DL, MVT::i32)); + SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, + DAG.getConstant(1, DL, VT)); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); + SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, + DL, VT, Hi, Shamt); SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, - DAG.getConstant(0x20, MVT::i32)); - SDValue Shift31 = DAG.getNode(ISD::SRA, DL, MVT::i32, Hi, - DAG.getConstant(31, MVT::i32)); - Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftRightHi, Or); - Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, - IsSRA ? Shift31 : DAG.getConstant(0, MVT::i32), - ShiftRightHi); + DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); + SDValue Ext = DAG.getNode(ISD::SRA, DL, VT, Hi, + DAG.getConstant(VT.getSizeInBits() - 1, DL, VT)); + Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or); + Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, + IsSRA ? Ext : DAG.getConstant(0, DL, VT), ShiftRightHi); SDValue Ops[2] = {Lo, Hi}; return DAG.getMergeValues(Ops, DL); @@ -2233,7 +2163,7 @@ static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD, if (Offset) Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, - DAG.getConstant(Offset, BasePtrVT)); + DAG.getConstant(Offset, DL, BasePtrVT)); SDValue Ops[] = { Chain, Ptr, Src }; return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, @@ -2298,7 +2228,7 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { // (set tmp2, (shl tmp1, 32)) // (set dst, (srl tmp2, 32)) SDLoc DL(LD); - SDValue Const32 = DAG.getConstant(32, MVT::i32); + SDValue Const32 = DAG.getConstant(32, DL, MVT::i32); SDValue SLL = DAG.getNode(ISD::SHL, DL, MVT::i64, LWR, Const32); SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i64, SLL, Const32); SDValue Ops[] = { SRL, LWR.getValue(1) }; @@ -2314,7 +2244,7 @@ static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD, if (Offset) Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, - DAG.getConstant(Offset, BasePtrVT)); + DAG.getConstant(Offset, DL, BasePtrVT)); SDValue Ops[] = { Chain, Value, Ptr }; return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, @@ -2396,8 +2326,9 @@ SDValue MipsTargetLowering::lowerADD(SDValue Op, SelectionDAG &DAG) const { EVT ValTy = Op->getValueType(0); int FI = MFI->CreateFixedObject(Op.getValueSizeInBits() / 8, 0, false); SDValue InArgsAddr = DAG.getFrameIndex(FI, ValTy); - return DAG.getNode(ISD::ADD, SDLoc(Op), ValTy, InArgsAddr, - DAG.getConstant(0, ValTy)); + SDLoc DL(Op); + return DAG.getNode(ISD::ADD, DL, ValTy, InArgsAddr, + DAG.getConstant(0, DL, ValTy)); } SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, @@ -2429,9 +2360,9 @@ SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State, const MCPhysReg *F64Regs) { - - static const unsigned IntRegsSize = 4, FloatRegsSize = 2; + CCState &State, ArrayRef F64Regs) { + const MipsSubtarget &Subtarget = static_cast( + State.getMachineFunction().getSubtarget()); static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 }; static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 }; @@ -2440,6 +2371,19 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, if (ArgFlags.isByVal()) return true; + // Promote i8 and i16 + if (ArgFlags.isInReg() && !Subtarget.isLittle()) { + if (LocVT == MVT::i8 || LocVT == MVT::i16 || LocVT == MVT::i32) { + LocVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExtUpper; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExtUpper; + else + LocInfo = CCValAssign::AExtUpper; + } + } + // Promote i8 and i16 if (LocVT == MVT::i8 || LocVT == MVT::i16) { LocVT = MVT::i32; @@ -2456,39 +2400,39 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following // is true: function is vararg, argument is 3rd or higher, there is previous // argument which is not f32 or f64. - bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 - || State.getFirstUnallocated(F32Regs, FloatRegsSize) != ValNo; + bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 || + State.getFirstUnallocated(F32Regs) != ValNo; unsigned OrigAlign = ArgFlags.getOrigAlign(); bool isI64 = (ValVT == MVT::i32 && OrigAlign == 8); if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); // If this is the first part of an i64 arg, // the allocated register must be either A0 or A2. if (isI64 && (Reg == Mips::A1 || Reg == Mips::A3)) - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); LocVT = MVT::i32; } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { // Allocate int register and shadow next int register. If first // available register is Mips::A1 or Mips::A3, shadow it too. - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); if (Reg == Mips::A1 || Reg == Mips::A3) - Reg = State.AllocateReg(IntRegs, IntRegsSize); - State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); + State.AllocateReg(IntRegs); LocVT = MVT::i32; } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { // we are guaranteed to find an available float register if (ValVT == MVT::f32) { - Reg = State.AllocateReg(F32Regs, FloatRegsSize); + Reg = State.AllocateReg(F32Regs); // Shadow int register - State.AllocateReg(IntRegs, IntRegsSize); + State.AllocateReg(IntRegs); } else { - Reg = State.AllocateReg(F64Regs, FloatRegsSize); + Reg = State.AllocateReg(F64Regs); // Shadow int registers - unsigned Reg2 = State.AllocateReg(IntRegs, IntRegsSize); + unsigned Reg2 = State.AllocateReg(IntRegs); if (Reg2 == Mips::A1 || Reg2 == Mips::A3) - State.AllocateReg(IntRegs, IntRegsSize); - State.AllocateReg(IntRegs, IntRegsSize); + State.AllocateReg(IntRegs); + State.AllocateReg(IntRegs); } } else llvm_unreachable("Cannot handle this ValVT."); @@ -2519,6 +2463,10 @@ static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); } +static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + CCState &State) LLVM_ATTRIBUTE_UNUSED; + #include "MipsGenCallingConv.inc" //===----------------------------------------------------------------------===// @@ -2536,15 +2484,16 @@ MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, SDValue Arg, SDLoc DL, bool IsTailCall, SelectionDAG &DAG) const { if (!IsTailCall) { - SDValue PtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, - DAG.getIntPtrConstant(Offset)); + SDValue PtrOff = + DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr, + DAG.getIntPtrConstant(Offset, DL)); return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo(), false, false, 0); } MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); int FI = MFI->CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false); - SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(), /*isVolatile=*/ true, false, 0); } @@ -2566,8 +2515,8 @@ getOpndList(SmallVectorImpl &Ops, // used for the function (that is, Mips linker doesn't generate lazy binding // stub for a function whose address is taken in the program). if (IsPICCall && !InternalLinkage && IsCallReloc) { - unsigned GPReg = Subtarget.isABI_N64() ? Mips::GP_64 : Mips::GP; - EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; + unsigned GPReg = ABI.IsN64() ? Mips::GP_64 : Mips::GP; + EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty))); } @@ -2590,9 +2539,9 @@ getOpndList(SmallVectorImpl &Ops, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. - const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); - const uint32_t *Mask = TRI->getCallPreservedMask(CLI.CallConv); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + const uint32_t *Mask = + TRI->getCallPreservedMask(CLI.DAG.getMachineFunction(), CLI.CallConv); assert(Mask && "Missing call preserved mask for calling convention"); if (Subtarget.inMips16HardFloat()) { if (GlobalAddressSDNode *G = dyn_cast(CLI.Callee)) { @@ -2627,7 +2576,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); MipsFunctionInfo *FuncInfo = MF.getInfo(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; @@ -2636,7 +2585,10 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MipsCCState CCInfo( CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(), MipsCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget)); - MipsCC MipsCCInfo(CallConv, Subtarget, CCInfo); + + // Allocate the reserved argument area. It seems strange to do this from the + // caller side but removing it breaks the frame size calculation. + CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), Callee.getNode()); @@ -2660,14 +2612,14 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // byval arguments to the stack. unsigned StackAlignment = TFL->getStackAlignment(); NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment); - SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); + SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); if (!IsTailCall) Chain = DAG.getCALLSEQ_START(Chain, NextStackOffsetVal, DL); - SDValue StackPtr = DAG.getCopyFromReg( - Chain, DL, Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP, - getPointerTy()); + SDValue StackPtr = + DAG.getCopyFromReg(Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP, + getPointerTy(DAG.getDataLayout())); // With EABI is it possible to have 16 args on registers. std::deque< std::pair > RegsToPass; @@ -2681,6 +2633,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, CCValAssign &VA = ArgLocs[i]; MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); ISD::ArgFlagsTy Flags = Outs[i].Flags; + bool UseUpperBits = false; // ByVal Arg. if (Flags.isByVal()) { @@ -2694,15 +2647,16 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, assert(!IsTailCall && "Do not tail-call optimize if there is a byval argument."); passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, - MipsCCInfo, FirstByValReg, LastByValReg, Flags, - Subtarget.isLittle(), VA); + FirstByValReg, LastByValReg, Flags, Subtarget.isLittle(), + VA); CCInfo.nextInRegsParam(); continue; } // Promote the value if needed. switch (VA.getLocInfo()) { - default: llvm_unreachable("Unknown loc info!"); + default: + llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: if (VA.isRegLoc()) { if ((ValVT == MVT::f32 && LocVT == MVT::i32) || @@ -2711,9 +2665,9 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); else if (ValVT == MVT::f64 && LocVT == MVT::i32) { SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Arg, DAG.getConstant(0, MVT::i32)); + Arg, DAG.getConstant(0, DL, MVT::i32)); SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Arg, DAG.getConstant(1, MVT::i32)); + Arg, DAG.getConstant(1, DL, MVT::i32)); if (!Subtarget.isLittle()) std::swap(Lo, Hi); unsigned LocRegLo = VA.getLocReg(); @@ -2727,17 +2681,34 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, case CCValAssign::BCvt: Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); break; + case CCValAssign::SExtUpper: + UseUpperBits = true; + // Fallthrough case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); break; + case CCValAssign::ZExtUpper: + UseUpperBits = true; + // Fallthrough case CCValAssign::ZExt: Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, LocVT, Arg); break; + case CCValAssign::AExtUpper: + UseUpperBits = true; + // Fallthrough case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, DL, LocVT, Arg); break; } + if (UseUpperBits) { + unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); + unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); + Arg = DAG.getNode( + ISD::SHL, DL, VA.getLocVT(), Arg, + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); + } + // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { @@ -2762,9 +2733,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. - bool IsPICCall = - (Subtarget.isABI_N64() || IsPIC); // true if calls are translated to - // jalr $25 + bool IsPICCall = (ABI.IsN64() || IsPIC); // true if calls are translated to + // jalr $25 bool GlobalOrExternal = false, InternalLinkage = false, IsCallReloc = false; SDValue CalleeLo; EVT Ty = Callee.getValueType(); @@ -2775,36 +2745,36 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, InternalLinkage = Val->hasInternalLinkage(); if (InternalLinkage) - Callee = getAddrLocal(G, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + Callee = getAddrLocal(G, DL, Ty, DAG, ABI.IsN32() || ABI.IsN64()); else if (LargeGOT) { - Callee = getAddrGlobalLargeGOT(G, Ty, DAG, MipsII::MO_CALL_HI16, + Callee = getAddrGlobalLargeGOT(G, DL, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Val)); IsCallReloc = true; } else { - Callee = getAddrGlobal(G, Ty, DAG, MipsII::MO_GOT_CALL, Chain, + Callee = getAddrGlobal(G, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Val)); IsCallReloc = true; } } else - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0, + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, + getPointerTy(DAG.getDataLayout()), 0, MipsII::MO_NO_FLAG); GlobalOrExternal = true; } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { const char *Sym = S->getSymbol(); - if (!Subtarget.isABI_N64() && !IsPIC) // !N64 && static - Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy(), - MipsII::MO_NO_FLAG); + if (!ABI.IsN64() && !IsPIC) // !N64 && static + Callee = DAG.getTargetExternalSymbol( + Sym, getPointerTy(DAG.getDataLayout()), MipsII::MO_NO_FLAG); else if (LargeGOT) { - Callee = getAddrGlobalLargeGOT(S, Ty, DAG, MipsII::MO_CALL_HI16, + Callee = getAddrGlobalLargeGOT(S, DL, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; } else { // N64 || PIC - Callee = getAddrGlobal(S, Ty, DAG, MipsII::MO_GOT_CALL, Chain, + Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; } @@ -2826,7 +2796,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, - DAG.getIntPtrConstant(0, true), InFlag, DL); + DAG.getIntPtrConstant(0, DL, true), InFlag, DL); InFlag = Chain.getValue(1); // Handle result values, copying them out of physregs into vregs that we @@ -2865,7 +2835,7 @@ SDValue MipsTargetLowering::LowerCallResult( VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; Val = DAG.getNode( Shift, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); } switch (VA.getLocInfo()) { @@ -2900,6 +2870,60 @@ SDValue MipsTargetLowering::LowerCallResult( return Chain; } +static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, + EVT ArgVT, SDLoc DL, SelectionDAG &DAG) { + MVT LocVT = VA.getLocVT(); + EVT ValVT = VA.getValVT(); + + // Shift into the upper bits if necessary. + switch (VA.getLocInfo()) { + default: + break; + case CCValAssign::AExtUpper: + case CCValAssign::SExtUpper: + case CCValAssign::ZExtUpper: { + unsigned ValSizeInBits = ArgVT.getSizeInBits(); + unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); + unsigned Opcode = + VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; + Val = DAG.getNode( + Opcode, DL, VA.getLocVT(), Val, + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); + break; + } + } + + // If this is an value smaller than the argument slot size (32-bit for O32, + // 64-bit for N32/N64), it has been promoted in some way to the argument slot + // size. Extract the value and insert any appropriate assertions regarding + // sign/zero extension. + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: + break; + case CCValAssign::AExtUpper: + case CCValAssign::AExt: + Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); + break; + case CCValAssign::SExtUpper: + case CCValAssign::SExt: + Val = DAG.getNode(ISD::AssertSext, DL, LocVT, Val, DAG.getValueType(ValVT)); + Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); + break; + case CCValAssign::ZExtUpper: + case CCValAssign::ZExt: + Val = DAG.getNode(ISD::AssertZext, DL, LocVT, Val, DAG.getValueType(ValVT)); + Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); + break; + case CCValAssign::BCvt: + Val = DAG.getNode(ISD::BITCAST, DL, ValVT, Val); + break; + } + + return Val; +} + //===----------------------------------------------------------------------===// // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -2926,9 +2950,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, SmallVector ArgLocs; MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); - MipsCC MipsCCInfo(CallConv, Subtarget, CCInfo); - Function::const_arg_iterator FuncArg = - DAG.getMachineFunction().getFunction()->arg_begin(); + CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); + const Function *Func = DAG.getMachineFunction().getFunction(); + Function::const_arg_iterator FuncArg = Func->arg_begin(); + + if (Func->hasFnAttribute("interrupt") && !Func->arg_empty()) + report_fatal_error( + "Functions with the interrupt attribute cannot have arguments!"); CCInfo.AnalyzeFormalArguments(Ins, CC_Mips_FixedArg); MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(), @@ -2939,13 +2967,16 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; - std::advance(FuncArg, Ins[i].OrigArgIndex - CurArgIdx); - CurArgIdx = Ins[i].OrigArgIndex; + if (Ins[i].isOrigArg()) { + std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx); + CurArgIdx = Ins[i].getOrigArgIndex(); + } EVT ValVT = VA.getValVT(); ISD::ArgFlagsTy Flags = Ins[i].Flags; bool IsRegLoc = VA.isRegLoc(); if (Flags.isByVal()) { + assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit"); unsigned FirstByValReg, LastByValReg; unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); @@ -2954,7 +2985,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, "ByVal args of size 0 should have been ignored by front-end."); assert(ByValIdx < CCInfo.getInRegsParamsCount()); copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, - MipsCCInfo, FirstByValReg, LastByValReg, VA); + FirstByValReg, LastByValReg, VA, CCInfo); CCInfo.nextInRegsParam(); continue; } @@ -2970,28 +3001,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); - // If this is an 8 or 16-bit value, it has been passed promoted - // to 32 bits. Insert an assert[sz]ext to capture this, then - // truncate to the right size. - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: - break; - case CCValAssign::SExt: - ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, - DAG.getValueType(ValVT)); - ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); - break; - case CCValAssign::ZExt: - ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, - DAG.getValueType(ValVT)); - ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); - break; - case CCValAssign::BCvt: - ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); - break; - } + ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); // Handle floating point arguments passed in integer registers and // long double arguments passed in floating point registers. @@ -2999,7 +3009,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, (RegVT == MVT::i64 && ValVT == MVT::f64) || (RegVT == MVT::f64 && ValVT == MVT::i64)) ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); - else if (Subtarget.isABI_O32() && RegVT == MVT::i32 && + else if (ABI.IsO32() && RegVT == MVT::i32 && ValVT == MVT::f64) { unsigned Reg2 = addLiveIn(DAG.getMachineFunction(), getNextIntArgReg(ArgReg), RC); @@ -3012,21 +3022,35 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, InVals.push_back(ArgValue); } else { // VA.isRegLoc() + MVT LocVT = VA.getLocVT(); + + if (ABI.IsO32()) { + // We ought to be able to use LocVT directly but O32 sets it to i32 + // when allocating floating point values to integer registers. + // This shouldn't influence how we load the value into registers unless + // we are targeting softfloat. + if (VA.getValVT().isFloatingPoint() && !Subtarget.useSoftFloat()) + LocVT = VA.getValVT(); + } // sanity check assert(VA.isMemLoc()); // The stack pointer offset is relative to the caller stack frame. - int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, + int FI = MFI->CreateFixedObject(LocVT.getSizeInBits() / 8, VA.getLocMemOffset(), true); // Create load nodes to retrieve arguments from the stack - SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - SDValue Load = DAG.getLoad(ValVT, DL, Chain, FIN, - MachinePointerInfo::getFixedStack(FI), - false, false, false, 0); - InVals.push_back(Load); - OutChains.push_back(Load.getValue(1)); + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); + SDValue ArgValue = DAG.getLoad( + LocVT, DL, Chain, FIN, + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), + false, false, false, 0); + OutChains.push_back(ArgValue.getValue(1)); + + ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); + + InVals.push_back(ArgValue); } } @@ -3038,7 +3062,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, unsigned Reg = MipsFI->getSRetReturnReg(); if (!Reg) { Reg = MF.getRegInfo().createVirtualRegister( - getRegClassFor(Subtarget.isABI_N64() ? MVT::i64 : MVT::i32)); + getRegClassFor(ABI.IsN64() ? MVT::i64 : MVT::i32)); MipsFI->setSRetReturnReg(Reg); } SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); @@ -3048,7 +3072,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, } if (IsVarArg) - writeVarArgRegs(OutChains, MipsCCInfo, Chain, DL, DAG, CCInfo); + writeVarArgRegs(OutChains, Chain, DL, DAG, CCInfo); // All stores are grouped in one node to allow the matching between // the size of Ins and InVals. This only happens when on varg functions @@ -3074,9 +3098,30 @@ MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, return CCInfo.CheckReturn(Outs, RetCC_Mips); } +bool +MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { + if (Subtarget.hasMips3() && Subtarget.useSoftFloat()) { + if (Type == MVT::i32) + return true; + } + return IsSigned; +} + SDValue -MipsTargetLowering::LowerReturn(SDValue Chain, - CallingConv::ID CallConv, bool IsVarArg, +MipsTargetLowering::LowerInterruptReturn(SmallVectorImpl &RetOps, + SDLoc DL, SelectionDAG &DAG) const { + + MachineFunction &MF = DAG.getMachineFunction(); + MipsFunctionInfo *MipsFI = MF.getInfo(); + + MipsFI->setISR(); + + return DAG.getNode(MipsISD::ERet, DL, MVT::Other, RetOps); +} + +SDValue +MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, SDLoc DL, SelectionDAG &DAG) const { @@ -3134,7 +3179,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); Val = DAG.getNode( ISD::SHL, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); } Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); @@ -3154,12 +3199,13 @@ MipsTargetLowering::LowerReturn(SDValue Chain, if (!Reg) llvm_unreachable("sret virtual register not created in the entry block"); - SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy()); - unsigned V0 = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; + SDValue Val = + DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout())); + unsigned V0 = ABI.IsN64() ? Mips::V0_64 : Mips::V0; Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Flag); Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(V0, getPointerTy())); + RetOps.push_back(DAG.getRegister(V0, getPointerTy(DAG.getDataLayout()))); } RetOps[0] = Chain; // Update chain. @@ -3168,7 +3214,11 @@ MipsTargetLowering::LowerReturn(SDValue Chain, if (Flag.getNode()) RetOps.push_back(Flag); - // Return on Mips is always a "jr $ra" + // ISRs must use "eret". + if (DAG.getMachineFunction().getFunction()->hasFnAttribute("interrupt")) + return LowerInterruptReturn(RetOps, DL, DAG); + + // Standard return on Mips is a "jr $ra" return DAG.getNode(MipsISD::Ret, DL, MVT::Other, RetOps); } @@ -3178,9 +3228,8 @@ MipsTargetLowering::LowerReturn(SDValue Chain, /// getConstraintType - Given a constraint letter, return the type of /// constraint it is for this target. -MipsTargetLowering::ConstraintType MipsTargetLowering:: -getConstraintType(const std::string &Constraint) const -{ +MipsTargetLowering::ConstraintType +MipsTargetLowering::getConstraintType(StringRef Constraint) const { // Mips specific constraints // GCC config/mips/constraints.md // @@ -3206,6 +3255,10 @@ getConstraintType(const std::string &Constraint) const return C_Memory; } } + + if (Constraint == "ZC") + return C_Memory; + return TargetLowering::getConstraintType(Constraint); } @@ -3266,9 +3319,8 @@ MipsTargetLowering::getSingleConstraintMatchWeight( /// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag /// that is returned indicates whether parsing was successful. The second flag /// is true if the numeric part exists. -static std::pair -parsePhysicalReg(StringRef C, std::string &Prefix, - unsigned long long &Reg) { +static std::pair parsePhysicalReg(StringRef C, StringRef &Prefix, + unsigned long long &Reg) { if (C.front() != '{' || C.back() != '}') return std::make_pair(false, false); @@ -3276,7 +3328,7 @@ parsePhysicalReg(StringRef C, std::string &Prefix, StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1; I = std::find_if(B, E, std::ptr_fun(isdigit)); - Prefix.assign(B, I - B); + Prefix = StringRef(B, I - B); // The second flag is set to false if no numeric characters were found. if (I == E) @@ -3290,9 +3342,9 @@ parsePhysicalReg(StringRef C, std::string &Prefix, std::pair MipsTargetLowering:: parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); + Subtarget.getRegisterInfo(); const TargetRegisterClass *RC; - std::string Prefix; + StringRef Prefix; unsigned long long Reg; std::pair R = parsePhysicalReg(C, Prefix, Reg); @@ -3308,7 +3360,7 @@ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { RC = TRI->getRegClass(Prefix == "hi" ? Mips::HI32RegClassID : Mips::LO32RegClassID); return std::make_pair(*(RC->begin()), RC); - } else if (Prefix.compare(0, 4, "$msa") == 0) { + } else if (Prefix.startswith("$msa")) { // Parse $msa(ir|csr|access|save|modify|request|map|unmap) // No numeric characters follow the name. @@ -3364,9 +3416,10 @@ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { /// Given a register class constraint, like 'r', if this corresponds directly /// to an LLVM register class, return a register of 0 and the register class /// pointer. -std::pair MipsTargetLowering:: -getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const -{ +std::pair +MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + StringRef Constraint, + MVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { case 'd': // Address register. Same as 'r' unless generating MIPS16 code. @@ -3422,7 +3475,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const if (R.second) return R; - return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); + return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); } /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops @@ -3431,6 +3484,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, std::vector&Ops, SelectionDAG &DAG) const { + SDLoc DL(Op); SDValue Result; // Only support length 1 constraints for now. @@ -3445,7 +3499,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if (isInt<16>(Val)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3455,7 +3509,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getZExtValue(); if (Val == 0) { - Result = DAG.getTargetConstant(0, Type); + Result = DAG.getTargetConstant(0, DL, Type); break; } } @@ -3465,7 +3519,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); uint64_t Val = (uint64_t)C->getZExtValue(); if (isUInt<16>(Val)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3475,7 +3529,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((isInt<32>(Val)) && ((Val & 0xffff) == 0)){ - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3485,7 +3539,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((Val >= -65535) && (Val <= -1)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3495,7 +3549,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((isInt<15>(Val))) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3505,7 +3559,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((Val <= 65535) && (Val >= 1)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3520,8 +3574,9 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); } -bool MipsTargetLowering::isLegalAddressingMode(const AddrMode &AM, - Type *Ty) const { +bool MipsTargetLowering::isLegalAddressingMode(const DataLayout &DL, + const AddrMode &AM, Type *Ty, + unsigned AS) const { // No global is ever allowed as a base. if (AM.BaseGV) return false; @@ -3566,94 +3621,21 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { } unsigned MipsTargetLowering::getJumpTableEncoding() const { - if (Subtarget.isABI_N64()) + if (ABI.IsN64()) return MachineJumpTableInfo::EK_GPRel64BlockAddress; return TargetLowering::getJumpTableEncoding(); } -/// This function returns true if CallSym is a long double emulation routine. -static bool isF128SoftLibCall(const char *CallSym) { - const char *const LibCalls[] = - {"__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", "__extendsftf2", - "__fixtfdi", "__fixtfsi", "__fixtfti", "__fixunstfdi", "__fixunstfsi", - "__fixunstfti", "__floatditf", "__floatsitf", "__floattitf", - "__floatunditf", "__floatunsitf", "__floatuntitf", "__getf2", "__gttf2", - "__letf2", "__lttf2", "__multf3", "__netf2", "__powitf2", "__subtf3", - "__trunctfdf2", "__trunctfsf2", "__unordtf2", - "ceill", "copysignl", "cosl", "exp2l", "expl", "floorl", "fmal", "fmodl", - "log10l", "log2l", "logl", "nearbyintl", "powl", "rintl", "sinl", "sqrtl", - "truncl"}; - - const char *const *End = LibCalls + array_lengthof(LibCalls); - - // Check that LibCalls is sorted alphabetically. - MipsTargetLowering::LTStr Comp; - -#ifndef NDEBUG - for (const char *const *I = LibCalls; I < End - 1; ++I) - assert(Comp(*I, *(I + 1))); -#endif - - return std::binary_search(LibCalls, End, CallSym, Comp); -} - -/// This function returns true if Ty is fp128, {f128} or i128 which was -/// originally a fp128. -static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode) { - if (Ty->isFP128Ty()) - return true; - - if (Ty->isStructTy() && Ty->getStructNumElements() == 1 && - Ty->getStructElementType(0)->isFP128Ty()) - return true; - - const ExternalSymbolSDNode *ES = - dyn_cast_or_null(CallNode); - - // If the Ty is i128 and the function being called is a long double emulation - // routine, then the original type is f128. - return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol())); -} - -MipsTargetLowering::MipsCC::MipsCC(CallingConv::ID CC, - const MipsSubtarget &Subtarget_, - CCState &Info) - : CallConv(CC), Subtarget(Subtarget_) { - // Pre-allocate reserved argument area. - Info.AllocateStack(reservedArgArea(), 1); -} - -unsigned MipsTargetLowering::MipsCC::reservedArgArea() const { - return (Subtarget.isABI_O32() && (CallConv != CallingConv::Fast)) ? 16 : 0; -} - -const ArrayRef MipsTargetLowering::MipsCC::intArgRegs() const { - if (Subtarget.isABI_O32()) - return makeArrayRef(O32IntRegs); - return makeArrayRef(Mips64IntRegs); -} - -MVT MipsTargetLowering::MipsCC::getRegVT(MVT VT, const Type *OrigTy, - const SDNode *CallNode, - bool IsSoftFloat) const { - if (IsSoftFloat || Subtarget.isABI_O32()) - return VT; - - // Check if the original type was fp128. - if (originalTypeIsF128(OrigTy, CallNode)) { - assert(VT == MVT::i64); - return MVT::f64; - } - - return VT; +bool MipsTargetLowering::useSoftFloat() const { + return Subtarget.useSoftFloat(); } void MipsTargetLowering::copyByValRegs( SDValue Chain, SDLoc DL, std::vector &OutChains, SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl &InVals, - const Argument *FuncArg, const MipsCC &CC, unsigned FirstReg, - unsigned LastReg, const CCValAssign &VA) const { + const Argument *FuncArg, unsigned FirstReg, unsigned LastReg, + const CCValAssign &VA, MipsCCState &State) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); @@ -3661,16 +3643,17 @@ void MipsTargetLowering::copyByValRegs( unsigned RegAreaSize = NumRegs * GPRSizeInBytes; unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); int FrameObjOffset; + ArrayRef ByValArgRegs = ABI.GetByValArgRegs(); if (RegAreaSize) FrameObjOffset = - (int)CC.reservedArgArea() - - (int)((CC.intArgRegs().size() - FirstReg) * GPRSizeInBytes); + (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - + (int)((ByValArgRegs.size() - FirstReg) * GPRSizeInBytes); else FrameObjOffset = VA.getLocMemOffset(); // Create frame object. - EVT PtrTy = getPointerTy(); + EVT PtrTy = getPointerTy(DAG.getDataLayout()); int FI = MFI->CreateFixedObject(FrameObjSize, FrameObjOffset, true); SDValue FIN = DAG.getFrameIndex(FI, PtrTy); InVals.push_back(FIN); @@ -3683,11 +3666,11 @@ void MipsTargetLowering::copyByValRegs( const TargetRegisterClass *RC = getRegClassFor(RegTy); for (unsigned I = 0; I < NumRegs; ++I) { - unsigned ArgReg = CC.intArgRegs()[FirstReg + I]; + unsigned ArgReg = ByValArgRegs[FirstReg + I]; unsigned VReg = addLiveIn(MF, ArgReg, RC); unsigned Offset = I * GPRSizeInBytes; SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, - DAG.getConstant(Offset, PtrTy)); + DAG.getConstant(Offset, DL, PtrTy)); SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy), StorePtr, MachinePointerInfo(FuncArg, Offset), false, false, 0); @@ -3700,25 +3683,26 @@ void MipsTargetLowering::passByValArg( SDValue Chain, SDLoc DL, std::deque> &RegsToPass, SmallVectorImpl &MemOpChains, SDValue StackPtr, - MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, const MipsCC &CC, - unsigned FirstReg, unsigned LastReg, const ISD::ArgFlagsTy &Flags, - bool isLittle, const CCValAssign &VA) const { + MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, + unsigned LastReg, const ISD::ArgFlagsTy &Flags, bool isLittle, + const CCValAssign &VA) const { unsigned ByValSizeInBytes = Flags.getByValSize(); unsigned OffsetInBytes = 0; // From beginning of struct unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); unsigned Alignment = std::min(Flags.getByValAlign(), RegSizeInBytes); - EVT PtrTy = getPointerTy(), RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); + EVT PtrTy = getPointerTy(DAG.getDataLayout()), + RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); unsigned NumRegs = LastReg - FirstReg; if (NumRegs) { - const ArrayRef ArgRegs = CC.intArgRegs(); + ArrayRef ArgRegs = ABI.GetByValArgRegs(); bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); unsigned I = 0; // Copy words to registers. for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, PtrTy)); + DAG.getConstant(OffsetInBytes, DL, PtrTy)); SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, MachinePointerInfo(), false, false, false, Alignment); @@ -3744,7 +3728,8 @@ void MipsTargetLowering::passByValArg( // Load subword. SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, PtrTy)); + DAG.getConstant(OffsetInBytes, DL, + PtrTy)); SDValue LoadVal = DAG.getExtLoad( ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, false, @@ -3760,7 +3745,7 @@ void MipsTargetLowering::passByValArg( Shamt = (RegSizeInBytes - (TotalBytesLoaded + LoadSizeInBytes)) * 8; SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal, - DAG.getConstant(Shamt, MVT::i32)); + DAG.getConstant(Shamt, DL, MVT::i32)); if (Val.getNode()) Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift); @@ -3781,21 +3766,23 @@ void MipsTargetLowering::passByValArg( // Copy remainder of byval arg to it with memcpy. unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes; SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, PtrTy)); + DAG.getConstant(OffsetInBytes, DL, PtrTy)); SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr, - DAG.getIntPtrConstant(VA.getLocMemOffset())); - Chain = DAG.getMemcpy(Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, PtrTy), + DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); + Chain = DAG.getMemcpy(Chain, DL, Dst, Src, + DAG.getConstant(MemCpySize, DL, PtrTy), Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false, + /*isTailCall=*/false, MachinePointerInfo(), MachinePointerInfo()); MemOpChains.push_back(Chain); } void MipsTargetLowering::writeVarArgRegs(std::vector &OutChains, - const MipsCC &CC, SDValue Chain, - SDLoc DL, SelectionDAG &DAG, + SDValue Chain, SDLoc DL, + SelectionDAG &DAG, CCState &State) const { - const ArrayRef ArgRegs = CC.intArgRegs(); - unsigned Idx = State.getFirstUnallocated(ArgRegs.data(), ArgRegs.size()); + ArrayRef ArgRegs = ABI.GetVarArgRegs(); + unsigned Idx = State.getFirstUnallocated(ArgRegs); unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); const TargetRegisterClass *RC = getRegClassFor(RegTy); @@ -3809,9 +3796,11 @@ void MipsTargetLowering::writeVarArgRegs(std::vector &OutChains, if (ArgRegs.size() == Idx) VaArgOffset = RoundUpToAlignment(State.getNextStackOffset(), RegSizeInBytes); - else - VaArgOffset = (int)CC.reservedArgArea() - - (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); + else { + VaArgOffset = + (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - + (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); + } // Record the frame index of the first variable argument // which is a value necessary to VASTART. @@ -3827,7 +3816,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector &OutChains, unsigned Reg = addLiveIn(MF, ArgRegs[I], RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy); FI = MFI->CreateFixedObject(RegSizeInBytes, VaArgOffset, true); - SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); + SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff, MachinePointerInfo(), false, false, 0); cast(Store.getNode())->getMemOperand()->setValue( @@ -3838,8 +3827,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector &OutChains, void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, unsigned Align) const { - MachineFunction &MF = State->getMachineFunction(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); assert(Size && "Byval argument's size shouldn't be 0."); @@ -3850,10 +3838,10 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, if (State->getCallingConv() != CallingConv::Fast) { unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - const ArrayRef IntArgRegs = Subtarget.getABI().GetByValArgRegs(); + ArrayRef IntArgRegs = ABI.GetByValArgRegs(); // FIXME: The O32 case actually describes no shadow registers. const MCPhysReg *ShadowRegs = - Subtarget.isABI_O32() ? IntArgRegs.data() : Mips64DPRegs; + ABI.IsO32() ? IntArgRegs.data() : Mips64DPRegs; // We used to check the size as well but we can't do that anymore since // CCState::HandleByVal() rounds up the size after calling this function. @@ -3861,7 +3849,7 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, "Byval argument's alignment should be a multiple of" "RegSizeInBytes."); - FirstReg = State->getFirstUnallocated(IntArgRegs.data(), IntArgRegs.size()); + FirstReg = State->getFirstUnallocated(IntArgRegs); // If Align > RegSizeInBytes, the first arg register must be even. // FIXME: This condition happens to do the right thing but it's not the @@ -3881,3 +3869,101 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); } + +MachineBasicBlock * +MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB, + bool isFPCmp, unsigned Opc) const { + assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) && + "Subtarget already supports SELECT nodes with the use of" + "conditional-move instructions."); + + const TargetInstrInfo *TII = + Subtarget.getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + + // To "insert" a SELECT instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = ++BB->getIterator(); + + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), BB, + std::next(MachineBasicBlock::iterator(MI)), BB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(BB); + + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + if (isFPCmp) { + // bc1[tf] cc, sinkMBB + BuildMI(BB, DL, TII->get(Opc)) + .addReg(MI->getOperand(1).getReg()) + .addMBB(sinkMBB); + } else { + // bne rs, $0, sinkMBB + BuildMI(BB, DL, TII->get(Opc)) + .addReg(MI->getOperand(1).getReg()) + .addReg(Mips::ZERO) + .addMBB(sinkMBB); + } + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] + // ... + BB = sinkMBB; + + BuildMI(*BB, BB->begin(), DL, + TII->get(Mips::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB) + .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB); + + MI->eraseFromParent(); // The pseudo instruction is gone now. + + return BB; +} + +// FIXME? Maybe this could be a TableGen attribute on some registers and +// this table could be generated automatically from RegInfo. +unsigned MipsTargetLowering::getRegisterByName(const char* RegName, EVT VT, + SelectionDAG &DAG) const { + // Named registers is expected to be fairly rare. For now, just support $28 + // since the linux kernel uses it. + if (Subtarget.isGP64bit()) { + unsigned Reg = StringSwitch(RegName) + .Case("$28", Mips::GP_64) + .Default(0); + if (Reg) + return Reg; + } else { + unsigned Reg = StringSwitch(RegName) + .Case("$28", Mips::GP) + .Default(0); + if (Reg) + return Reg; + } + report_fatal_error("Invalid register name global variable"); +}