Changeset View
Changeset View
Standalone View
Standalone View
lib/Target/Mips/MipsISelLowering.cpp
Show First 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { | ||||
default: return NULL; | default: return NULL; | ||||
} | } | ||||
} | } | ||||
MipsTargetLowering:: | MipsTargetLowering:: | ||||
MipsTargetLowering(MipsTargetMachine &TM) | MipsTargetLowering(MipsTargetMachine &TM) | ||||
: TargetLowering(TM, new MipsTargetObjectFile()), | : TargetLowering(TM, new MipsTargetObjectFile()), | ||||
Subtarget(&TM.getSubtarget<MipsSubtarget>()), | Subtarget(&TM.getSubtarget<MipsSubtarget>()), | ||||
HasMips64(Subtarget->hasMips64()), IsN64(Subtarget->isABI_N64()), | IsGP64bit(Subtarget->isGP64bit()), IsN64(Subtarget->isABI_N64()), | ||||
dsanders: I generally agree with the use of IsGP64bit but we may need to hang on to HasMips64 as well. | |||||
IsO32(Subtarget->isABI_O32()) { | IsO32(Subtarget->isABI_O32()) { | ||||
// Mips does not have i1 type, so use i32 for | // Mips does not have i1 type, so use i32 for | ||||
// setcc operations results (slt, sgt, ...). | // setcc operations results (slt, sgt, ...). | ||||
setBooleanContents(ZeroOrOneBooleanContent); | setBooleanContents(ZeroOrOneBooleanContent); | ||||
setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); | setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); | ||||
// Load extented operations for i1 types must be promoted | // Load extented operations for i1 types must be promoted | ||||
setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); | setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); | ||||
Show All 30 Lines | MipsTargetLowering(MipsTargetMachine &TM) | ||||
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); | setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); | ||||
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | ||||
if (!TM.Options.NoNaNsFPMath) { | if (!TM.Options.NoNaNsFPMath) { | ||||
setOperationAction(ISD::FABS, MVT::f32, Custom); | setOperationAction(ISD::FABS, MVT::f32, Custom); | ||||
setOperationAction(ISD::FABS, MVT::f64, Custom); | setOperationAction(ISD::FABS, MVT::f64, Custom); | ||||
} | } | ||||
if (HasMips64) { | if (IsGP64bit) { | ||||
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); | setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); | ||||
setOperationAction(ISD::BlockAddress, MVT::i64, Custom); | setOperationAction(ISD::BlockAddress, MVT::i64, Custom); | ||||
setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); | setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); | ||||
setOperationAction(ISD::JumpTable, MVT::i64, Custom); | setOperationAction(ISD::JumpTable, MVT::i64, Custom); | ||||
setOperationAction(ISD::ConstantPool, MVT::i64, Custom); | setOperationAction(ISD::ConstantPool, MVT::i64, Custom); | ||||
setOperationAction(ISD::SELECT, MVT::i64, Custom); | setOperationAction(ISD::SELECT, MVT::i64, Custom); | ||||
setOperationAction(ISD::LOAD, MVT::i64, Custom); | setOperationAction(ISD::LOAD, MVT::i64, Custom); | ||||
setOperationAction(ISD::STORE, MVT::i64, Custom); | setOperationAction(ISD::STORE, MVT::i64, Custom); | ||||
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); | setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); | ||||
} | } | ||||
if (!HasMips64) { | if (!IsGP64bit) { | ||||
setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); | setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); | ||||
setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); | setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); | ||||
setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); | setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); | ||||
} | } | ||||
setOperationAction(ISD::ADD, MVT::i32, Custom); | setOperationAction(ISD::ADD, MVT::i32, Custom); | ||||
if (HasMips64) | if (IsGP64bit) | ||||
setOperationAction(ISD::ADD, MVT::i64, Custom); | setOperationAction(ISD::ADD, MVT::i64, Custom); | ||||
setOperationAction(ISD::SDIV, MVT::i32, Expand); | setOperationAction(ISD::SDIV, MVT::i32, Expand); | ||||
setOperationAction(ISD::SREM, MVT::i32, Expand); | setOperationAction(ISD::SREM, MVT::i32, Expand); | ||||
setOperationAction(ISD::UDIV, MVT::i32, Expand); | setOperationAction(ISD::UDIV, MVT::i32, Expand); | ||||
setOperationAction(ISD::UREM, MVT::i32, Expand); | setOperationAction(ISD::UREM, MVT::i32, Expand); | ||||
setOperationAction(ISD::SDIV, MVT::i64, Expand); | setOperationAction(ISD::SDIV, MVT::i64, Expand); | ||||
setOperationAction(ISD::SREM, MVT::i64, Expand); | setOperationAction(ISD::SREM, MVT::i64, Expand); | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | if (!Subtarget->hasBitCount()) { | ||||
setOperationAction(ISD::CTLZ, MVT::i64, Expand); | setOperationAction(ISD::CTLZ, MVT::i64, Expand); | ||||
} | } | ||||
if (!Subtarget->hasSwap()) { | if (!Subtarget->hasSwap()) { | ||||
setOperationAction(ISD::BSWAP, MVT::i32, Expand); | setOperationAction(ISD::BSWAP, MVT::i32, Expand); | ||||
setOperationAction(ISD::BSWAP, MVT::i64, Expand); | setOperationAction(ISD::BSWAP, MVT::i64, Expand); | ||||
} | } | ||||
if (HasMips64) { | if (IsGP64bit) { | ||||
setLoadExtAction(ISD::SEXTLOAD, MVT::i32, Custom); | setLoadExtAction(ISD::SEXTLOAD, MVT::i32, Custom); | ||||
setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Custom); | setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Custom); | ||||
setLoadExtAction(ISD::EXTLOAD, MVT::i32, Custom); | setLoadExtAction(ISD::EXTLOAD, MVT::i32, Custom); | ||||
setTruncStoreAction(MVT::i64, MVT::i32, Custom); | setTruncStoreAction(MVT::i64, MVT::i32, Custom); | ||||
} | } | ||||
setOperationAction(ISD::TRAP, MVT::Other, Legal); | setOperationAction(ISD::TRAP, MVT::Other, Legal); | ||||
setTargetDAGCombine(ISD::SDIVREM); | setTargetDAGCombine(ISD::SDIVREM); | ||||
setTargetDAGCombine(ISD::UDIVREM); | setTargetDAGCombine(ISD::UDIVREM); | ||||
setTargetDAGCombine(ISD::SELECT); | setTargetDAGCombine(ISD::SELECT); | ||||
setTargetDAGCombine(ISD::AND); | setTargetDAGCombine(ISD::AND); | ||||
setTargetDAGCombine(ISD::OR); | setTargetDAGCombine(ISD::OR); | ||||
setTargetDAGCombine(ISD::ADD); | setTargetDAGCombine(ISD::ADD); | ||||
setMinFunctionAlignment(HasMips64 ? 3 : 2); | setMinFunctionAlignment(IsGP64bit ? 3 : 2); | ||||
dsandersAuthorUnsubmitted Not Done ReplyInline ActionsThis is a pre-existing issue, but this looks wrong. I'm told that in GCC, functions are 4-byte aligned for in O32, N32, and N64 ABI's. I'll look into this. dsanders: This is a pre-existing issue, but this looks wrong. I'm told that in GCC, functions are 4-byte… | |||||
setStackPointerRegisterToSaveRestore(IsN64 ? Mips::SP_64 : Mips::SP); | setStackPointerRegisterToSaveRestore(IsN64 ? Mips::SP_64 : Mips::SP); | ||||
setExceptionPointerRegister(IsN64 ? Mips::A0_64 : Mips::A0); | setExceptionPointerRegister(IsN64 ? Mips::A0_64 : Mips::A0); | ||||
setExceptionSelectorRegister(IsN64 ? Mips::A1_64 : Mips::A1); | setExceptionSelectorRegister(IsN64 ? Mips::A1_64 : Mips::A1); | ||||
MaxStoresPerMemcpy = 16; | MaxStoresPerMemcpy = 16; | ||||
▲ Show 20 Lines • Show All 1,112 Lines • ▼ Show 20 Lines | if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { | ||||
return DAG.getNode(ISD::ADD, DL, MVT::i32, GPReg, GPRelNode); | return DAG.getNode(ISD::ADD, DL, MVT::i32, GPReg, GPRelNode); | ||||
} | } | ||||
// %hi/%lo relocation | // %hi/%lo relocation | ||||
return getAddrNonPIC(N, Ty, DAG); | return getAddrNonPIC(N, Ty, DAG); | ||||
} | } | ||||
if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV))) | if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV))) | ||||
return getAddrLocal(N, Ty, DAG, HasMips64); | return getAddrLocal(N, Ty, DAG, IsGP64bit); | ||||
dsandersAuthorUnsubmitted Not Done ReplyInline ActionsI need to find out if this is the right predicate. I'm not sure if the use of MO_GOT_OFST is related to 64-bit targets in general, >=MIPS64 specifically, or ABI's. What ever the outcome of that investigation, the parameter in the declaration and body will need to be renamed to match the new meaning. dsanders: I need to find out if this is the right predicate. I'm not sure if the use of MO_GOT_OFST is… | |||||
if (LargeGOT) | if (LargeGOT) | ||||
return getAddrGlobalLargeGOT(N, Ty, DAG, MipsII::MO_GOT_HI16, | return getAddrGlobalLargeGOT(N, Ty, DAG, MipsII::MO_GOT_HI16, | ||||
MipsII::MO_GOT_LO16, DAG.getEntryNode(), | MipsII::MO_GOT_LO16, DAG.getEntryNode(), | ||||
MachinePointerInfo::getGOT()); | MachinePointerInfo::getGOT()); | ||||
return getAddrGlobal(N, Ty, DAG, | return getAddrGlobal(N, Ty, DAG, | ||||
HasMips64 ? MipsII::MO_GOT_DISP : MipsII::MO_GOT16, | IsGP64bit ? MipsII::MO_GOT_DISP : MipsII::MO_GOT16, | ||||
DAG.getEntryNode(), MachinePointerInfo::getGOT()); | DAG.getEntryNode(), MachinePointerInfo::getGOT()); | ||||
} | } | ||||
SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, | SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, | ||||
SelectionDAG &DAG) const { | SelectionDAG &DAG) const { | ||||
BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); | BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); | ||||
EVT Ty = Op.getValueType(); | EVT Ty = Op.getValueType(); | ||||
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) | if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) | ||||
return getAddrNonPIC(N, Ty, DAG); | return getAddrNonPIC(N, Ty, DAG); | ||||
return getAddrLocal(N, Ty, DAG, HasMips64); | return getAddrLocal(N, Ty, DAG, IsGP64bit); | ||||
} | } | ||||
SDValue MipsTargetLowering:: | SDValue MipsTargetLowering:: | ||||
lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const | lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const | ||||
{ | { | ||||
// If the relocation model is PIC, use the General Dynamic TLS Model or | // If the relocation model is PIC, use the General Dynamic TLS Model or | ||||
// Local Dynamic TLS model, otherwise use the Initial Exec or | // Local Dynamic TLS model, otherwise use the Initial Exec or | ||||
// Local Exec TLS Model. | // Local Exec TLS Model. | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
lowerJumpTable(SDValue Op, SelectionDAG &DAG) const | lowerJumpTable(SDValue Op, SelectionDAG &DAG) const | ||||
{ | { | ||||
JumpTableSDNode *N = cast<JumpTableSDNode>(Op); | JumpTableSDNode *N = cast<JumpTableSDNode>(Op); | ||||
EVT Ty = Op.getValueType(); | EVT Ty = Op.getValueType(); | ||||
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) | if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) | ||||
return getAddrNonPIC(N, Ty, DAG); | return getAddrNonPIC(N, Ty, DAG); | ||||
return getAddrLocal(N, Ty, DAG, HasMips64); | return getAddrLocal(N, Ty, DAG, IsGP64bit); | ||||
} | } | ||||
SDValue MipsTargetLowering:: | SDValue MipsTargetLowering:: | ||||
lowerConstantPool(SDValue Op, SelectionDAG &DAG) const | lowerConstantPool(SDValue Op, SelectionDAG &DAG) const | ||||
{ | { | ||||
// gp_rel relocation | // gp_rel relocation | ||||
// FIXME: we should reference the constant pool using small data sections, | // FIXME: we should reference the constant pool using small data sections, | ||||
// but the asm printer currently doesn't support this feature without | // but the asm printer currently doesn't support this feature without | ||||
// hacking it. This feature should come soon so we can uncomment the | // hacking it. This feature should come soon so we can uncomment the | ||||
// stuff below. | // stuff below. | ||||
//if (IsInSmallSection(C->getType())) { | //if (IsInSmallSection(C->getType())) { | ||||
// SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, MVT::i32, CP); | // SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, MVT::i32, CP); | ||||
// SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); | // SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); | ||||
// ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); | // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); | ||||
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); | ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); | ||||
EVT Ty = Op.getValueType(); | EVT Ty = Op.getValueType(); | ||||
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) | if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) | ||||
return getAddrNonPIC(N, Ty, DAG); | return getAddrNonPIC(N, Ty, DAG); | ||||
return getAddrLocal(N, Ty, DAG, HasMips64); | return getAddrLocal(N, Ty, DAG, IsGP64bit); | ||||
} | } | ||||
SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { | SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { | ||||
MachineFunction &MF = DAG.getMachineFunction(); | MachineFunction &MF = DAG.getMachineFunction(); | ||||
MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); | MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); | ||||
SDLoc DL(Op); | SDLoc DL(Op); | ||||
SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), | SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), | ||||
▲ Show 20 Lines • Show All 840 Lines • ▼ Show 20 Lines | MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, | ||||
EVT Ty = Callee.getValueType(); | EVT Ty = Callee.getValueType(); | ||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { | ||||
if (IsPICCall) { | if (IsPICCall) { | ||||
const GlobalValue *Val = G->getGlobal(); | const GlobalValue *Val = G->getGlobal(); | ||||
InternalLinkage = Val->hasInternalLinkage(); | InternalLinkage = Val->hasInternalLinkage(); | ||||
if (InternalLinkage) | if (InternalLinkage) | ||||
Callee = getAddrLocal(G, Ty, DAG, HasMips64); | Callee = getAddrLocal(G, Ty, DAG, IsGP64bit); | ||||
else if (LargeGOT) | else if (LargeGOT) | ||||
Callee = getAddrGlobalLargeGOT(G, Ty, DAG, MipsII::MO_CALL_HI16, | Callee = getAddrGlobalLargeGOT(G, Ty, DAG, MipsII::MO_CALL_HI16, | ||||
MipsII::MO_CALL_LO16, Chain, | MipsII::MO_CALL_LO16, Chain, | ||||
FuncInfo->callPtrInfo(Val)); | FuncInfo->callPtrInfo(Val)); | ||||
else | else | ||||
Callee = getAddrGlobal(G, Ty, DAG, MipsII::MO_GOT_CALL, Chain, | Callee = getAddrGlobal(G, Ty, DAG, MipsII::MO_GOT_CALL, Chain, | ||||
FuncInfo->callPtrInfo(Val)); | FuncInfo->callPtrInfo(Val)); | ||||
} else | } else | ||||
▲ Show 20 Lines • Show All 503 Lines • ▼ Show 20 Lines | if (Constraint.size() == 1) { | ||||
case 'd': // Address register. Same as 'r' unless generating MIPS16 code. | case 'd': // Address register. Same as 'r' unless generating MIPS16 code. | ||||
case 'y': // Same as 'r'. Exists for compatibility. | case 'y': // Same as 'r'. Exists for compatibility. | ||||
case 'r': | case 'r': | ||||
if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { | if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { | ||||
if (Subtarget->inMips16Mode()) | if (Subtarget->inMips16Mode()) | ||||
return std::make_pair(0U, &Mips::CPU16RegsRegClass); | return std::make_pair(0U, &Mips::CPU16RegsRegClass); | ||||
return std::make_pair(0U, &Mips::GPR32RegClass); | return std::make_pair(0U, &Mips::GPR32RegClass); | ||||
} | } | ||||
if (VT == MVT::i64 && !HasMips64) | if (VT == MVT::i64 && !IsGP64bit) | ||||
return std::make_pair(0U, &Mips::GPR32RegClass); | return std::make_pair(0U, &Mips::GPR32RegClass); | ||||
if (VT == MVT::i64 && HasMips64) | if (VT == MVT::i64 && IsGP64bit) | ||||
return std::make_pair(0U, &Mips::GPR64RegClass); | return std::make_pair(0U, &Mips::GPR64RegClass); | ||||
// This will generate an error message | // This will generate an error message | ||||
return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0)); | return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0)); | ||||
case 'f': // FPU or MSA register | case 'f': // FPU or MSA register | ||||
if (VT == MVT::v16i8) | if (VT == MVT::v16i8) | ||||
return std::make_pair(0U, &Mips::MSA128BRegClass); | return std::make_pair(0U, &Mips::MSA128BRegClass); | ||||
else if (VT == MVT::v8i16 || VT == MVT::v8f16) | else if (VT == MVT::v8i16 || VT == MVT::v8f16) | ||||
return std::make_pair(0U, &Mips::MSA128HRegClass); | return std::make_pair(0U, &Mips::MSA128HRegClass); | ||||
▲ Show 20 Lines • Show All 628 Lines • Show Last 20 Lines |
I generally agree with the use of IsGP64bit but we may need to hang on to HasMips64 as well.