aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp')
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp190
1 files changed, 148 insertions, 42 deletions
diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 9c511bd77822..93c5f496ce97 100644
--- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -112,8 +112,11 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::FIRST_NUMBER: break;
case MipsISD::JmpLink: return "MipsISD::JmpLink";
case MipsISD::TailCall: return "MipsISD::TailCall";
+ case MipsISD::Highest: return "MipsISD::Highest";
+ case MipsISD::Higher: return "MipsISD::Higher";
case MipsISD::Hi: return "MipsISD::Hi";
case MipsISD::Lo: return "MipsISD::Lo";
+ case MipsISD::GotHi: return "MipsISD::GotHi";
case MipsISD::GPRel: return "MipsISD::GPRel";
case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer";
case MipsISD::Ret: return "MipsISD::Ret";
@@ -144,6 +147,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::Sync: return "MipsISD::Sync";
case MipsISD::Ext: return "MipsISD::Ext";
case MipsISD::Ins: return "MipsISD::Ins";
+ case MipsISD::CIns: return "MipsISD::CIns";
case MipsISD::LWL: return "MipsISD::LWL";
case MipsISD::LWR: return "MipsISD::LWR";
case MipsISD::SWL: return "MipsISD::SWL";
@@ -425,6 +429,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setTargetDAGCombine(ISD::OR);
setTargetDAGCombine(ISD::ADD);
setTargetDAGCombine(ISD::AssertZext);
+ setTargetDAGCombine(ISD::SHL);
if (ABI.IsO32()) {
// These libcalls are not available in 32-bit.
@@ -699,41 +704,81 @@ static SDValue performCMovFPCombine(SDNode *N, SelectionDAG &DAG,
static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget &Subtarget) {
- // Pattern match EXT.
- // $dst = and ((sra or srl) $src , pos), (2**size - 1)
- // => ext $dst, $src, size, pos
if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert())
return SDValue();
- SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1);
- unsigned ShiftRightOpc = ShiftRight.getOpcode();
-
- // Op's first operand must be a shift right.
- if (ShiftRightOpc != ISD::SRA && ShiftRightOpc != ISD::SRL)
- return SDValue();
+ SDValue FirstOperand = N->getOperand(0);
+ unsigned FirstOperandOpc = FirstOperand.getOpcode();
+ SDValue Mask = N->getOperand(1);
+ EVT ValTy = N->getValueType(0);
+ SDLoc DL(N);
- // The second operand of the shift must be an immediate.
+ uint64_t Pos = 0, SMPos, SMSize;
ConstantSDNode *CN;
- if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1))))
- return SDValue();
-
- uint64_t Pos = CN->getZExtValue();
- uint64_t SMPos, SMSize;
+ SDValue NewOperand;
+ unsigned Opc;
// Op's second operand must be a shifted mask.
if (!(CN = dyn_cast<ConstantSDNode>(Mask)) ||
!isShiftedMask(CN->getZExtValue(), SMPos, SMSize))
return SDValue();
- // Return if the shifted mask does not start at bit 0 or the sum of its size
- // and Pos exceeds the word's size.
- EVT ValTy = N->getValueType(0);
- if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits())
- return SDValue();
+ if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) {
+ // Pattern match EXT.
+ // $dst = and ((sra or srl) $src , pos), (2**size - 1)
+ // => ext $dst, $src, pos, size
+
+ // The second operand of the shift must be an immediate.
+ if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))))
+ return SDValue();
+
+ Pos = CN->getZExtValue();
+
+ // Return if the shifted mask does not start at bit 0 or the sum of its size
+ // and Pos exceeds the word's size.
+ if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits())
+ return SDValue();
+
+ Opc = MipsISD::Ext;
+ NewOperand = FirstOperand.getOperand(0);
+ } else if (FirstOperandOpc == ISD::SHL && Subtarget.hasCnMips()) {
+ // Pattern match CINS.
+ // $dst = and (shl $src , pos), mask
+ // => cins $dst, $src, pos, size
+ // mask is a shifted mask with consecutive 1's, pos = shift amount,
+ // size = population count.
+
+ // The second operand of the shift must be an immediate.
+ if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))))
+ return SDValue();
+
+ Pos = CN->getZExtValue();
+
+ if (SMPos != Pos || Pos >= ValTy.getSizeInBits() || SMSize >= 32 ||
+ Pos + SMSize > ValTy.getSizeInBits())
+ return SDValue();
+
+ NewOperand = FirstOperand.getOperand(0);
+ // SMSize is 'location' (position) in this case, not size.
+ SMSize--;
+ Opc = MipsISD::CIns;
+ } else {
+ // Pattern match EXT.
+ // $dst = and $src, (2**size - 1) , if size > 16
+ // => ext $dst, $src, pos, size , pos = 0
- SDLoc DL(N);
- return DAG.getNode(MipsISD::Ext, DL, ValTy,
- ShiftRight.getOperand(0),
+ // If the mask is <= 0xffff, andi can be used instead.
+ if (CN->getZExtValue() <= 0xffff)
+ return SDValue();
+
+ // Return if the mask doesn't start at position 0.
+ if (SMPos)
+ return SDValue();
+
+ Opc = MipsISD::Ext;
+ NewOperand = FirstOperand;
+ }
+ return DAG.getNode(Opc, DL, ValTy, NewOperand,
DAG.getConstant(Pos, DL, MVT::i32),
DAG.getConstant(SMSize, DL, MVT::i32));
}
@@ -852,6 +897,58 @@ static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+
+static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget &Subtarget) {
+ // Pattern match CINS.
+ // $dst = shl (and $src , imm), pos
+ // => cins $dst, $src, pos, size
+
+ if (DCI.isBeforeLegalizeOps() || !Subtarget.hasCnMips())
+ return SDValue();
+
+ SDValue FirstOperand = N->getOperand(0);
+ unsigned FirstOperandOpc = FirstOperand.getOpcode();
+ SDValue SecondOperand = N->getOperand(1);
+ EVT ValTy = N->getValueType(0);
+ SDLoc DL(N);
+
+ uint64_t Pos = 0, SMPos, SMSize;
+ ConstantSDNode *CN;
+ SDValue NewOperand;
+
+ // The second operand of the shift must be an immediate.
+ if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)))
+ return SDValue();
+
+ Pos = CN->getZExtValue();
+
+ if (Pos >= ValTy.getSizeInBits())
+ return SDValue();
+
+ if (FirstOperandOpc != ISD::AND)
+ return SDValue();
+
+ // AND's second operand must be a shifted mask.
+ if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||
+ !isShiftedMask(CN->getZExtValue(), SMPos, SMSize))
+ return SDValue();
+
+ // Return if the shifted mask does not start at bit 0 or the sum of its size
+ // and Pos exceeds the word's size.
+ if (SMPos != 0 || SMSize > 32 || Pos + SMSize > ValTy.getSizeInBits())
+ return SDValue();
+
+ NewOperand = FirstOperand.getOperand(0);
+ // SMSize is 'location' (position) in this case, not size.
+ SMSize--;
+
+ return DAG.getNode(MipsISD::CIns, DL, ValTy, NewOperand,
+ DAG.getConstant(Pos, DL, MVT::i32),
+ DAG.getConstant(SMSize, DL, MVT::i32));
+}
+
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
const {
SelectionDAG &DAG = DCI.DAG;
@@ -875,6 +972,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return performADDCombine(N, DAG, DCI, Subtarget);
case ISD::AssertZext:
return performAssertZextCombine(N, DAG, DCI, Subtarget);
+ case ISD::SHL:
+ return performSHLCombine(N, DAG, DCI, Subtarget);
}
return SDValue();
@@ -1733,7 +1832,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
const GlobalValue *GV = N->getGlobal();
- if (!isPositionIndependent() && !ABI.IsN64()) {
+ if (!isPositionIndependent()) {
const MipsTargetObjectFile *TLOF =
static_cast<const MipsTargetObjectFile *>(
getTargetMachine().getObjFileLowering());
@@ -1742,8 +1841,10 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
// %gp_rel relocation
return getAddrGPRel(N, SDLoc(N), Ty, DAG);
- // %hi/%lo relocation
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ // %hi/%lo relocation
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ // %highest/%higher/%hi/%lo relocation
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
}
// Every other architecture would use shouldAssumeDSOLocal in here, but
@@ -1777,8 +1878,9 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op,
BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
EVT Ty = Op.getValueType();
- if (!isPositionIndependent() && !ABI.IsN64())
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ if (!isPositionIndependent())
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
}
@@ -1820,8 +1922,9 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
Args.push_back(Entry);
TargetLowering::CallLoweringInfo CLI(DAG);
- CLI.setDebugLoc(DL).setChain(DAG.getEntryNode())
- .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args));
+ CLI.setDebugLoc(DL)
+ .setChain(DAG.getEntryNode())
+ .setLibCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args));
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
SDValue Ret = CallResult.first;
@@ -1870,8 +1973,9 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const
JumpTableSDNode *N = cast<JumpTableSDNode>(Op);
EVT Ty = Op.getValueType();
- if (!isPositionIndependent() && !ABI.IsN64())
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ if (!isPositionIndependent())
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
}
@@ -1882,7 +1986,7 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
EVT Ty = Op.getValueType();
- if (!isPositionIndependent() && !ABI.IsN64()) {
+ if (!isPositionIndependent()) {
const MipsTargetObjectFile *TLOF =
static_cast<const MipsTargetObjectFile *>(
getTargetMachine().getObjFileLowering());
@@ -1892,10 +1996,11 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const
// %gp_rel relocation
return getAddrGPRel(N, SDLoc(N), Ty, DAG);
- return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
+ return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+ : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
}
- return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
+ return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
}
SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const {
@@ -2796,14 +2901,13 @@ 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 = (ABI.IsN64() || IsPIC); // true if calls are translated to
- // jalr $25
+
SDValue CalleeLo;
EVT Ty = Callee.getValueType();
bool GlobalOrExternal = false, IsCallReloc = false;
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- if (IsPICCall) {
+ if (IsPIC) {
const GlobalValue *Val = G->getGlobal();
InternalLinkage = Val->hasInternalLinkage();
@@ -2828,7 +2932,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
const char *Sym = S->getSymbol();
- if (!ABI.IsN64() && !IsPIC) // !N64 && static
+ if (!IsPIC) // static
Callee = DAG.getTargetExternalSymbol(
Sym, getPointerTy(DAG.getDataLayout()), MipsII::MO_NO_FLAG);
else if (LargeGOT) {
@@ -2836,7 +2940,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
MipsII::MO_CALL_LO16, Chain,
FuncInfo->callPtrInfo(Sym));
IsCallReloc = true;
- } else { // N64 || PIC
+ } else { // PIC
Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain,
FuncInfo->callPtrInfo(Sym));
IsCallReloc = true;
@@ -2848,7 +2952,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVector<SDValue, 8> Ops(1, Chain);
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
- getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage,
+ getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, InternalLinkage,
IsCallReloc, CLI, Callee, Chain);
if (IsTailCall) {
@@ -3683,7 +3787,9 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
}
unsigned MipsTargetLowering::getJumpTableEncoding() const {
- if (ABI.IsN64())
+
+ // FIXME: For space reasons this should be: EK_GPRel32BlockAddress.
+ if (ABI.IsN64() && isPositionIndependent())
return MachineJumpTableInfo::EK_GPRel64BlockAddress;
return TargetLowering::getJumpTableEncoding();