X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=lib%2FTarget%2FMips%2FMipsISelLowering.h;h=e2ca629c7496ac974abde8fe4263af62f1ca5013;hb=5fa6dffd30c24f82a615cf7d2e17252974c4b4eb;hp=9e15b9a8767c41cf407ceb1cf7475035cd9d4748;hpb=4e0980af2e9eda80cbd82895167e650d83ffe087;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 9e15b9a8767..e2ca629c749 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -15,6 +15,7 @@ #ifndef MipsISELLOWERING_H #define MipsISELLOWERING_H +#include "MCTargetDesc/MipsBaseInfo.h" #include "Mips.h" #include "MipsSubtarget.h" #include "llvm/CodeGen/CallingConvLower.h" @@ -33,6 +34,9 @@ namespace llvm { // Jump and link (call) JmpLink, + // MicroMIPS Jump and link (call) + JmpLinkMM, + // Tail call TailCall, @@ -60,8 +64,8 @@ namespace llvm { CMovFP_T, CMovFP_F, - // Floating Point Rounding - FPRound, + // FP-to-int truncation node. + TruncIntFP, // Return Ret, @@ -69,10 +73,11 @@ namespace llvm { EH_RETURN, // Node used to extract integer from accumulator. - ExtractLOHI, + MFHI, + MFLO, // Node used to insert integers to accumulator. - InsertLOHI, + MTLOHI, // Mult nodes. Mult, @@ -143,6 +148,52 @@ namespace llvm { MSUB_DSP, MSUBU_DSP, + // DSP shift nodes. + SHLL_DSP, + SHRA_DSP, + SHRL_DSP, + + // DSP setcc and select_cc nodes. + SETCC_DSP, + SELECT_CC_DSP, + + // Vector comparisons. + // These take a vector and return a boolean. + VALL_ZERO, + VANY_ZERO, + VALL_NONZERO, + VANY_NONZERO, + + // These take a vector and return a vector bitmask. + VCEQ, + VCLE_S, + VCLE_U, + VCLT_S, + VCLT_U, + + // Element-wise vector max/min. + VSMAX, + VSMIN, + VUMAX, + VUMIN, + + // Vector Shuffle with mask as an operand + VSHF, // Generic shuffle + SHF, // 4-element set shuffle. + ILVEV, // Interleave even elements + ILVOD, // Interleave odd elements + ILVL, // Interleave left elements + ILVR, // Interleave right elements + PCKEV, // Pack even elements + PCKOD, // Pack odd elements + + // Combined (XOR (OR $a, $b), -1) + VNOR, + + // Extended vector element extraction + VEXTRACT_SEXT_ELT, + VEXTRACT_ZEXT_ELT, + // Load/Store Left/Right nodes. LWL = ISD::FIRST_TARGET_MEMORY_OPCODE, LWR, @@ -161,6 +212,7 @@ namespace llvm { class MipsFunctionInfo; class MipsTargetLowering : public TargetLowering { + bool isMicroMips; public: explicit MipsTargetLowering(MipsTargetMachine &TM); @@ -186,7 +238,7 @@ namespace llvm { virtual const char *getTargetNodeName(unsigned Opcode) const; /// getSetCCResultType - get the ISD::SETCC result ValueType - EVT getSetCCResultType(EVT VT) const; + EVT getSetCCResultType(LLVMContext &Context, EVT VT) const; virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; @@ -202,12 +254,72 @@ namespace llvm { protected: SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; - SDValue getAddrLocal(SDValue Op, SelectionDAG &DAG, bool HasMips64) const; - - SDValue getAddrGlobal(SDValue Op, SelectionDAG &DAG, unsigned Flag) const; - - SDValue getAddrGlobalLargeGOT(SDValue Op, SelectionDAG &DAG, - unsigned HiFlag, unsigned LoFlag) const; + // This method creates the following nodes, which are necessary for + // computing a local symbol's address: + // + // (add (load (wrapper $gp, %got(sym)), %lo(sym)) + template + SDValue getAddrLocal(NodeTy *N, EVT Ty, SelectionDAG &DAG, + bool IsN32OrN64) const { + SDLoc DL(N); + unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; + SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), + getTargetNode(N, Ty, DAG, GOTFlag)); + SDValue Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), GOT, + MachinePointerInfo::getGOT(), false, false, + false, 0); + unsigned LoFlag = IsN32OrN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; + SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty, + getTargetNode(N, Ty, DAG, LoFlag)); + return DAG.getNode(ISD::ADD, DL, Ty, Load, Lo); + } + + // This method creates the following nodes, which are necessary for + // computing a global symbol's address: + // + // (load (wrapper $gp, %got(sym))) + template + SDValue getAddrGlobal(NodeTy *N, EVT Ty, SelectionDAG &DAG, + unsigned Flag, SDValue Chain, + const MachinePointerInfo &PtrInfo) const { + SDLoc DL(N); + SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), + getTargetNode(N, Ty, DAG, Flag)); + return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo, false, false, false, 0); + } + + // This method creates the following nodes, which are necessary for + // computing a global symbol's address in large-GOT mode: + // + // (load (wrapper (add %hi(sym), $gp), %lo(sym))) + template + SDValue getAddrGlobalLargeGOT(NodeTy *N, EVT Ty, SelectionDAG &DAG, + unsigned HiFlag, unsigned LoFlag, + SDValue Chain, + const MachinePointerInfo &PtrInfo) const { + SDLoc DL(N); + SDValue Hi = DAG.getNode(MipsISD::Hi, DL, Ty, + getTargetNode(N, Ty, DAG, HiFlag)); + Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty)); + SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, + getTargetNode(N, Ty, DAG, LoFlag)); + return DAG.getLoad(Ty, DL, Chain, Wrapper, PtrInfo, false, false, false, + 0); + } + + // This method creates the following nodes, which are necessary for + // computing a symbol's address in non-PIC mode: + // + // (add %hi(sym), %lo(sym)) + template + SDValue getAddrNonPIC(NodeTy *N, EVT Ty, SelectionDAG &DAG) const { + SDLoc DL(N); + SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); + SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); + return DAG.getNode(ISD::ADD, DL, Ty, + DAG.getNode(MipsISD::Hi, DL, Ty, Hi), + DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); + } /// This function fills Ops, which is the list of operands that will later /// be used when a function call node is created. It also generates @@ -231,7 +343,13 @@ namespace llvm { /// arguments and inquire about calling convention information. class MipsCC { public: - MipsCC(CallingConv::ID CallConv, bool IsO32, CCState &Info); + enum SpecialCallingConvType { + Mips16RetHelperConv, NoSpecialCallingConv + }; + + MipsCC(CallingConv::ID CallConv, bool IsO32, bool IsFP64, CCState &Info, + SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv); + void analyzeCallOperands(const SmallVectorImpl &Outs, bool IsVarArg, bool IsSoftFloat, @@ -266,7 +384,7 @@ namespace llvm { /// Return pointer to array of integer argument registers. const uint16_t *intArgRegs() const; - typedef SmallVector::const_iterator byval_iterator; + typedef SmallVectorImpl::const_iterator byval_iterator; byval_iterator byval_begin() const { return ByValArgs.begin(); } byval_iterator byval_end() const { return ByValArgs.end(); } @@ -303,21 +421,49 @@ namespace llvm { CCState &CCInfo; CallingConv::ID CallConv; - bool IsO32; + bool IsO32, IsFP64; + SpecialCallingConvType SpecialCallingConv; SmallVector ByValArgs; }; + protected: + SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; // Subtarget Info const MipsSubtarget *Subtarget; - bool HasMips64, IsN64, IsO32; + bool hasMips64() const { return Subtarget->hasMips64(); } + bool isO32() const { return Subtarget->isABI_O32(); } + bool isN32() const { return Subtarget->isABI_N32(); } + bool isN64() const { return Subtarget->isABI_N64(); } private: + // Create a TargetGlobalAddress node. + SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG, + unsigned Flag) const; + + // Create a TargetExternalSymbol node. + SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG, + unsigned Flag) const; + + // Create a TargetBlockAddress node. + SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG, + unsigned Flag) const; + + // Create a TargetJumpTable node. + SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, + unsigned Flag) const; + + // Create a TargetConstantPool node. + SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG, + unsigned Flag) const; + + MipsCC::SpecialCallingConvType getSpecialCallingConv(SDValue Callee) const; // Lower Operand helpers SDValue LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl &InVals, const SDNode *CallNode, const Type *RetTy) const; @@ -338,14 +484,12 @@ namespace llvm { SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG, bool IsSRA) const; - SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerADD(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; /// isEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. @@ -357,7 +501,7 @@ namespace llvm { /// copyByValArg - Copy argument registers which were used to pass a byval /// argument to the stack. Create a stack frame object for the byval /// argument. - void copyByValRegs(SDValue Chain, DebugLoc DL, + void copyByValRegs(SDValue Chain, SDLoc DL, std::vector &OutChains, SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl &InVals, @@ -365,9 +509,9 @@ namespace llvm { const MipsCC &CC, const ByValArgInfo &ByVal) const; /// passByValArg - Pass a byval argument in registers or on stack. - void passByValArg(SDValue Chain, DebugLoc DL, + void passByValArg(SDValue Chain, SDLoc DL, std::deque< std::pair > &RegsToPass, - SmallVector &MemOpChains, SDValue StackPtr, + SmallVectorImpl &MemOpChains, SDValue StackPtr, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, const MipsCC &CC, const ByValArgInfo &ByVal, const ISD::ArgFlagsTy &Flags, bool isLittle) const; @@ -376,17 +520,17 @@ namespace llvm { /// to the stack. Also create a stack frame object for the first variable /// argument. void writeVarArgRegs(std::vector &OutChains, const MipsCC &CC, - SDValue Chain, DebugLoc DL, SelectionDAG &DAG) const; + SDValue Chain, SDLoc DL, SelectionDAG &DAG) const; virtual SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Ins, - DebugLoc dl, SelectionDAG &DAG, + SDLoc dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const; SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, - SDValue Arg, DebugLoc DL, bool IsTailCall, + SDValue Arg, SDLoc DL, bool IsTailCall, SelectionDAG &DAG) const; virtual SDValue @@ -404,7 +548,7 @@ namespace llvm { CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, - DebugLoc dl, SelectionDAG &DAG) const; + SDLoc dl, SelectionDAG &DAG) const; // Inline asm support ConstraintType getConstraintType(const std::string &Constraint) const; @@ -414,9 +558,14 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; + /// This function parses registers that appear in inline-asm constraints. + /// It returns pair (0, 0) on failure. + std::pair + parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; + MVT VT) const; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. If hasMemory is