MipsISelLowering.h [plain text]
#ifndef MipsISELLOWERING_H
#define MipsISELLOWERING_H
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
#include "MipsSubtarget.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/IR/Function.h"
#include "llvm/Target/TargetLowering.h"
#include <deque>
#include <string>
namespace llvm {
namespace MipsISD {
enum NodeType {
FIRST_NUMBER = ISD::BUILTIN_OP_END,
JmpLink,
TailCall,
Hi,
Lo,
GPRel,
ThreadPointer,
FPBrcond,
FPCmp,
CMovFP_T,
CMovFP_F,
TruncIntFP,
Ret,
EH_RETURN,
MFHI,
MFLO,
MTLOHI,
Mult,
Multu,
MAdd,
MAddu,
MSub,
MSubu,
DivRem,
DivRemU,
DivRem16,
DivRemU16,
BuildPairF64,
ExtractElementF64,
Wrapper,
DynAlloc,
Sync,
Ext,
Ins,
EXTP,
EXTPDP,
EXTR_S_H,
EXTR_W,
EXTR_R_W,
EXTR_RS_W,
SHILO,
MTHLIP,
MULSAQ_S_W_PH,
MAQ_S_W_PHL,
MAQ_S_W_PHR,
MAQ_SA_W_PHL,
MAQ_SA_W_PHR,
DPAU_H_QBL,
DPAU_H_QBR,
DPSU_H_QBL,
DPSU_H_QBR,
DPAQ_S_W_PH,
DPSQ_S_W_PH,
DPAQ_SA_L_W,
DPSQ_SA_L_W,
DPA_W_PH,
DPS_W_PH,
DPAQX_S_W_PH,
DPAQX_SA_W_PH,
DPAX_W_PH,
DPSX_W_PH,
DPSQX_S_W_PH,
DPSQX_SA_W_PH,
MULSA_W_PH,
MULT,
MULTU,
MADD_DSP,
MADDU_DSP,
MSUB_DSP,
MSUBU_DSP,
SHLL_DSP,
SHRA_DSP,
SHRL_DSP,
SETCC_DSP,
SELECT_CC_DSP,
VALL_ZERO,
VANY_ZERO,
VALL_NONZERO,
VANY_NONZERO,
VCEQ,
VCLE_S,
VCLE_U,
VCLT_S,
VCLT_U,
VSMAX,
VSMIN,
VUMAX,
VUMIN,
VSHF, SHF, ILVEV, ILVOD, ILVL, ILVR, PCKEV, PCKOD,
VNOR,
VEXTRACT_SEXT_ELT,
VEXTRACT_ZEXT_ELT,
LWL = ISD::FIRST_TARGET_MEMORY_OPCODE,
LWR,
SWL,
SWR,
LDL,
LDR,
SDL,
SDR
};
}
class MipsFunctionInfo;
class MipsTargetLowering : public TargetLowering {
bool isMicroMips;
public:
explicit MipsTargetLowering(MipsTargetMachine &TM);
static const MipsTargetLowering *create(MipsTargetMachine &TM);
virtual MVT getScalarShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
virtual void LowerOperationWrapper(SDNode *N,
SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG) const;
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
SelectionDAG &DAG) const;
virtual const char *getTargetNodeName(unsigned Opcode) const;
EVT getSetCCResultType(LLVMContext &Context, EVT VT) const;
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
virtual MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
struct LTStr {
bool operator()(const char *S1, const char *S2) const {
return strcmp(S1, S2) < 0;
}
};
protected:
SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
template<class NodeTy>
SDValue getAddrLocal(NodeTy *N, EVT Ty, SelectionDAG &DAG,
bool HasMips64) const {
SDLoc DL(N);
unsigned GOTFlag = HasMips64 ? 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 = HasMips64 ? 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);
}
template<class NodeTy>
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);
}
template<class NodeTy>
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);
}
template<class NodeTy>
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));
}
virtual void
getOpndList(SmallVectorImpl<SDValue> &Ops,
std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const;
struct ByValArgInfo {
unsigned FirstIdx; unsigned NumRegs; unsigned Address;
ByValArgInfo() : FirstIdx(0), NumRegs(0), Address(0) {}
};
class MipsCC {
public:
enum SpecialCallingConvType {
Mips16RetHelperConv, NoSpecialCallingConv
};
MipsCC(CallingConv::ID CallConv, bool IsO32, bool IsFP64, CCState &Info,
SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv);
void analyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
bool IsVarArg, bool IsSoftFloat,
const SDNode *CallNode,
std::vector<ArgListEntry> &FuncArgs);
void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
bool IsSoftFloat,
Function::const_arg_iterator FuncArg);
void analyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
bool IsSoftFloat, const SDNode *CallNode,
const Type *RetTy) const;
void analyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
bool IsSoftFloat, const Type *RetTy) const;
const CCState &getCCInfo() const { return CCInfo; }
bool hasByValArg() const { return !ByValArgs.empty(); }
unsigned regSize() const { return IsO32 ? 4 : 8; }
unsigned numIntArgRegs() const;
unsigned reservedArgArea() const;
const uint16_t *intArgRegs() const;
typedef SmallVectorImpl<ByValArgInfo>::const_iterator byval_iterator;
byval_iterator byval_begin() const { return ByValArgs.begin(); }
byval_iterator byval_end() const { return ByValArgs.end(); }
private:
void handleByValArg(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags);
bool useRegsForByval() const { return CallConv != CallingConv::Fast; }
llvm::CCAssignFn *fixedArgFn() const;
llvm::CCAssignFn *varArgFn() const;
const uint16_t *shadowRegs() const;
void allocateRegs(ByValArgInfo &ByVal, unsigned ByValSize,
unsigned Align);
MVT getRegVT(MVT VT, const Type *OrigTy, const SDNode *CallNode,
bool IsSoftFloat) const;
template<typename Ty>
void analyzeReturn(const SmallVectorImpl<Ty> &RetVals, bool IsSoftFloat,
const SDNode *CallNode, const Type *RetTy) const;
CCState &CCInfo;
CallingConv::ID CallConv;
bool IsO32, IsFP64;
SpecialCallingConvType SpecialCallingConv;
SmallVector<ByValArgInfo, 2> ByValArgs;
};
protected:
SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const;
const MipsSubtarget *Subtarget;
bool HasMips64, IsN64, IsO32;
private:
SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG,
unsigned Flag) const;
SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG,
unsigned Flag) const;
SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG,
unsigned Flag) const;
SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG,
unsigned Flag) const;
SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG,
unsigned Flag) const;
MipsCC::SpecialCallingConvType getSpecialCallingConv(SDValue Callee) const;
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SDLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals,
const SDNode *CallNode, const Type *RetTy) const;
SDValue lowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerEH_RETURN(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 lowerADD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
virtual bool
isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
unsigned NextStackOffset,
const MipsFunctionInfo& FI) const = 0;
void copyByValRegs(SDValue Chain, SDLoc DL,
std::vector<SDValue> &OutChains, SelectionDAG &DAG,
const ISD::ArgFlagsTy &Flags,
SmallVectorImpl<SDValue> &InVals,
const Argument *FuncArg,
const MipsCC &CC, const ByValArgInfo &ByVal) const;
void passByValArg(SDValue Chain, SDLoc DL,
std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr,
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
const MipsCC &CC, const ByValArgInfo &ByVal,
const ISD::ArgFlagsTy &Flags, bool isLittle) const;
void writeVarArgRegs(std::vector<SDValue> &OutChains, const MipsCC &CC,
SDValue Chain, SDLoc DL, SelectionDAG &DAG) const;
virtual SDValue
LowerFormalArguments(SDValue Chain,
CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SDLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain,
SDValue Arg, SDLoc DL, bool IsTailCall,
SelectionDAG &DAG) const;
virtual SDValue
LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const;
virtual bool
CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
LLVMContext &Context) const;
virtual SDValue
LowerReturn(SDValue Chain,
CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,
SDLoc dl, SelectionDAG &DAG) const;
ConstraintType getConstraintType(const std::string &Constraint) const;
ConstraintWeight getSingleConstraintMatchWeight(
AsmOperandInfo &info, const char *constraint) const;
std::pair<unsigned, const TargetRegisterClass *>
parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const;
std::pair<unsigned, const TargetRegisterClass*>
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT VT) const;
virtual void LowerAsmOperandForConstraint(SDValue Op,
std::string &Constraint,
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const;
virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const;
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
virtual EVT getOptimalMemOpType(uint64_t Size, unsigned DstAlign,
unsigned SrcAlign,
bool IsMemset, bool ZeroMemset,
bool MemcpyStrSrc,
MachineFunction &MF) const;
virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
virtual unsigned getJumpTableEncoding() const;
MachineBasicBlock *emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode, bool Nand = false) const;
MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr *MI,
MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode,
bool Nand = false) const;
MachineBasicBlock *emitAtomicCmpSwap(MachineInstr *MI,
MachineBasicBlock *BB, unsigned Size) const;
MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr *MI,
MachineBasicBlock *BB, unsigned Size) const;
};
const MipsTargetLowering *createMips16TargetLowering(MipsTargetMachine &TM);
const MipsTargetLowering *createMipsSETargetLowering(MipsTargetMachine &TM);
}
#endif // MipsISELLOWERING_H