summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/Mips/Mips64InstrInfo.td63
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.cpp142
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.h1
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td5
-rw-r--r--llvm/lib/Target/Mips/MipsSEISelLowering.cpp3
5 files changed, 174 insertions, 40 deletions
diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td
index f3081d32bae..99025fe1341 100644
--- a/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -326,6 +326,14 @@ let AdditionalPredicates = [NotInMicroMips] in {
EXT_FM<5>, ISA_MIPS64R2;
}
+let isCodeGenOnly = 1, AdditionalPredicates = [NotInMicroMips] in {
+ def DEXT64_32 : InstSE<(outs GPR64Opnd:$rt),
+ (ins GPR32Opnd:$rs, uimm5_report_uimm6:$pos,
+ uimm5_plus1:$size),
+ "dext $rt, $rs, $pos, $size", [], II_EXT, FrmR, "dext">,
+ EXT_FM<3>, ISA_MIPS64R2;
+}
+
let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt),
"dsll\t$rd, $rt, 32", [], II_DSLL>;
@@ -356,11 +364,11 @@ class Count1s<string opstr, RegisterOperand RO>:
let TwoOperandAliasConstraint = "$rd = $rs";
}
-class ExtsCins<string opstr, InstrItinClass itin,
- SDPatternOperator Op = null_frag>:
- InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, uimm5:$pos, uimm5:$lenm1),
- !strconcat(opstr, " $rt, $rs, $pos, $lenm1"),
- [(set GPR64Opnd:$rt, (Op GPR64Opnd:$rs, imm:$pos, imm:$lenm1))],
+class ExtsCins<string opstr, InstrItinClass itin, RegisterOperand RO,
+ PatFrag PosImm, SDPatternOperator Op = null_frag>:
+ InstSE<(outs RO:$rt), (ins RO:$rs, uimm5:$pos, uimm5:$lenm1),
+ !strconcat(opstr, "\t$rt, $rs, $pos, $lenm1"),
+ [(set RO:$rt, (Op RO:$rs, PosImm:$pos, imm:$lenm1))],
itin, FrmR, opstr> {
let TwoOperandAliasConstraint = "$rt = $rs";
}
@@ -424,13 +432,28 @@ def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>,
let Defs = [HI0, LO0, P0, P1, P2];
}
-// Extract a signed bit field /+32
-def EXTS : ExtsCins<"exts", II_EXT>, EXTS_FM<0x3a>, ASE_CNMIPS;
-def EXTS32: ExtsCins<"exts32", II_EXT>, EXTS_FM<0x3b>, ASE_CNMIPS;
-
-// Clear and insert a bit field /+32
-def CINS : ExtsCins<"cins", II_INS>, EXTS_FM<0x32>, ASE_CNMIPS;
-def CINS32: ExtsCins<"cins32", II_INS>, EXTS_FM<0x33>, ASE_CNMIPS;
+let AdditionalPredicates = [NotInMicroMips] in {
+ // Extract a signed bit field /+32
+ def EXTS : ExtsCins<"exts", II_EXT, GPR64Opnd, immZExt5>, EXTS_FM<0x3a>,
+ ASE_MIPS64_CNMIPS;
+ def EXTS32: ExtsCins<"exts32", II_EXT, GPR64Opnd, immZExt5Plus32>,
+ EXTS_FM<0x3b>, ASE_MIPS64_CNMIPS;
+
+ // Clear and insert a bit field /+32
+ def CINS : ExtsCins<"cins", II_INS, GPR64Opnd, immZExt5, MipsCIns>,
+ EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
+ def CINS32: ExtsCins<"cins32", II_INS, GPR64Opnd, immZExt5Plus32, MipsCIns>,
+ EXTS_FM<0x33>, ASE_MIPS64_CNMIPS;
+ let isCodeGenOnly = 1 in {
+ def CINS_i32 : ExtsCins<"cins", II_INS, GPR32Opnd, immZExt5, MipsCIns>,
+ EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
+ def CINS64_32 :InstSE<(outs GPR64Opnd:$rt),
+ (ins GPR32Opnd:$rs, uimm5:$pos, uimm5:$lenm1),
+ "cins\t$rt, $rs, $pos, $lenm1", [], II_INS, FrmR,
+ "cins">,
+ EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
+ }
+}
// Move to multiplier/product register
def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>,
@@ -646,6 +669,14 @@ def : MipsPat<(i64 (anyext GPR32:$src)),
def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>;
def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(i64 (zext GPR32:$src)), (DEXT64_32 GPR32:$src, 0, 32)>,
+ ISA_MIPS64R2;
+ def : MipsPat<(i64 (zext (i32 (shl GPR32:$rt, immZExt5:$imm)))),
+ (CINS64_32 GPR32:$rt, imm:$imm, (immZExt5To31 imm:$imm))>,
+ ASE_MIPS64_CNMIPS;
+}
+
// Sign extend in register
def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)),
(SLL64_64 GPR64:$src)>;
@@ -796,21 +827,21 @@ def : MipsInstAlias<"bbit1 $rs, $p, $offset",
def : MipsInstAlias<"exts $rt, $rs, $pos, $lenm1",
(EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rs,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
def : MipsInstAlias<"exts $rt, $pos, $lenm1",
(EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rt,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
// cins with $pos 32-63 in converted to cins32 with $pos 0-31
def : MipsInstAlias<"cins $rt, $rs, $pos, $lenm1",
(CINS32 GPR64Opnd:$rt, GPR64Opnd:$rs,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
def : MipsInstAlias<"cins $rt, $pos, $lenm1",
(CINS32 GPR64Opnd:$rt, GPR64Opnd:$rt,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_CNMIPS;
+ ASE_MIPS64_CNMIPS;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index f0f2424f722..4df6979d8a7 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -147,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";
@@ -428,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.
@@ -702,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));
}
@@ -855,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;
@@ -878,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();
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index abc34be6377..2dcafd51061 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -116,6 +116,7 @@ namespace llvm {
Ext,
Ins,
+ CIns,
// EXTR.W instrinsic nodes.
EXTP,
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index a25a9165a17..b90077d7807 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -138,6 +138,7 @@ def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain,SDNPSideEffect]>;
def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>;
def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>;
+def MipsCIns : SDNode<"MipsISD::CIns", SDT_Ext>;
def MipsLWL : SDNode<"MipsISD::LWL", SDTMipsLoadLR,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
@@ -1172,6 +1173,10 @@ def immZExt5Plus33 : PatLeaf<(imm), [{
return isUInt<5>(N->getZExtValue() - 33);
}]>;
+def immZExt5To31 : SDNodeXForm<imm, [{
+ return getImm(N, 31 - N->getZExtValue());
+}]>;
+
// True if (N + 1) fits in 16-bit field.
def immSExt16Plus1 : PatLeaf<(imm), [{
return isInt<17>(N->getSExtValue()) && isInt<16>(N->getSExtValue() + 1);
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
index c78c24bf47b..71bccc52482 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -1123,7 +1123,8 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
case ISD::MUL:
return performMULCombine(N, DAG, DCI, this);
case ISD::SHL:
- return performSHLCombine(N, DAG, DCI, Subtarget);
+ Val = performSHLCombine(N, DAG, DCI, Subtarget);
+ break;
case ISD::SRA:
return performSRACombine(N, DAG, DCI, Subtarget);
case ISD::SRL:
OpenPOWER on IntegriCloud