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>;
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";
}
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>,
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)>;
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
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";
setTargetDAGCombine(ISD::OR);
setTargetDAGCombine(ISD::ADD);
setTargetDAGCombine(ISD::AssertZext);
+ setTargetDAGCombine(ISD::SHL);
if (ABI.IsO32()) {
// These libcalls are not available in 32-bit.
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));
}
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;
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();
Ext,
Ins,
+ CIns,
// EXTR.W instrinsic nodes.
EXTP,
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]>;
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);
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:
--- /dev/null
+; RUN: llc -march=mips64 -mcpu=octeon -target-abi=n64 < %s -o - | FileCheck %s
+
+define i64 @cins_zext(i32 signext %n) {
+entry:
+ %shl = shl i32 %n, 5
+ %conv = zext i32 %shl to i64
+ ret i64 %conv
+
+; CHECK-LABEL: cins_zext:
+; CHECK: cins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 5, 26
+
+}
+
+define i64 @cins_and_shl(i64 zeroext %n) {
+entry:
+ %and = shl i64 %n, 8
+ %shl = and i64 %and, 16776960
+ ret i64 %shl
+
+; CHECK-LABEL: cins_and_shl:
+; CHECK: cins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 8, 15
+
+}
+
+define i64 @cins_and_shl32(i64 zeroext %n) {
+entry:
+ %and = shl i64 %n, 38
+ %shl = and i64 %and, 18014123631575040
+ ret i64 %shl
+
+; CHECK-LABEL: cins_and_shl32:
+; CHECK: cins32 $[[R0:[0-9]+]], $[[R1:[0-9]+]], 6, 15
+
+}
+
+define zeroext i16 @cins_and_shl_16(i16 zeroext %n) {
+entry:
+ %0 = shl i16 %n, 2
+ %1 = and i16 %0, 60
+ ret i16 %1
+
+; CHECK-LABEL: cins_and_shl_16:
+; CHECK: cins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 2, 3
+
+}
+
+define zeroext i8 @cins_and_shl_8(i8 zeroext %n) {
+entry:
+ %0 = shl i8 %n, 2
+ %1 = and i8 %0, 12
+ ret i8 %1
+
+; CHECK-LABEL: cins_and_shl_8:
+; CHECK: cins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 2, 1
+
+}
+
+define i32 @cins_i32(i32 signext %a) {
+entry:
+ %and = shl i32 %a, 17
+ %shl = and i32 %and, 536739840
+ ret i32 %shl
+
+; CHECK-LABEL: cins_i32:
+; CHECK: cins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 17, 11
+
+}
+
+define i64 @cins_shl_and(i32 signext %n) {
+entry:
+ %and = and i32 %n, 65535
+ %conv = zext i32 %and to i64
+ %shl = shl nuw nsw i64 %conv, 31
+ ret i64 %shl
+
+; CHECK-LABEL: cins_shl_and:
+; CHECK: cins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 31, 15
+
+}
+
+
+define i64 @cins_shl_and32(i32 signext %n) {
+entry:
+ %and = and i32 %n, 65535
+ %conv = zext i32 %and to i64
+ %shl = shl nuw nsw i64 %conv, 47
+ ret i64 %shl
+
+; CHECK-LABEL: cins_shl_and32:
+; CHECK: cins32 $[[R0:[0-9]+]], $[[R1:[0-9]+]], 15, 15
+
+}
--- /dev/null
+; RUN: llc -march=mips64 -mcpu=mips64r2 -target-abi=n64 < %s -o - | FileCheck %s
+
+define i64 @dext_add_zext(i32 signext %n) {
+entry:
+ %add = add i32 %n, 1
+ %res = zext i32 %add to i64
+ ret i64 %res
+
+; CHECK-LABEL: dext_add_zext:
+; CHECK: dext $[[R0:[0-9]+]], $[[R0:[0-9]+]], 0, 32
+
+}
+
+define i32 @ext_and24(i32 signext %a) {
+entry:
+ %and = and i32 %a, 16777215
+ ret i32 %and
+
+; CHECK-LABEL: ext_and24:
+; CHECK: ext $[[R0:[0-9]+]], $[[R1:[0-9]+]], 0, 24
+
+}
+
+define i64 @dext_and32(i64 zeroext %a) {
+entry:
+ %and = and i64 %a, 4294967295
+ ret i64 %and
+
+; CHECK-LABEL: dext_and32:
+; CHECK: dext $[[R0:[0-9]+]], $[[R1:[0-9]+]], 0, 32
+
+}
+
+define i64 @dext_and35(i64 zeroext %a) {
+entry:
+ %and = and i64 %a, 34359738367
+ ret i64 %and
+
+; CHECK-LABEL: dext_and35:
+; CHECK: dextm $[[R0:[0-9]+]], $[[R1:[0-9]+]], 0, 35
+
+}
+
+define i64 @dext_and20(i64 zeroext %a) {
+entry:
+ %and = and i64 %a, 1048575
+ ret i64 %and
+
+; CHECK-LABEL: dext_and20:
+; CHECK: dext $[[R0:[0-9]+]], $[[R1:[0-9]+]], 0, 20
+
+}
+
+define i64 @dext_and16(i64 zeroext %a) {
+entry:
+ %and = and i64 %a, 65535
+ ret i64 %and
+
+; CHECK-LABEL: dext_and16:
+; CHECK: andi $[[R0:[0-9]+]], $[[R1:[0-9]+]], 65535
+
+}
+
+define i64 @dext_lsr_and20(i64 zeroext %a) {
+entry:
+ %shr = lshr i64 %a, 5
+ %and = and i64 %shr, 1048575
+ ret i64 %and
+
+; CHECK-LABEL: dext_lsr_and20:
+; CHECK: dext $[[R0:[0-9]+]], $[[R1:[0-9]+]], 5, 20
+
+}
+
+define i64 @dext_lsr_and8(i64 zeroext %a) {
+entry:
+ %shr = lshr i64 %a, 40
+ %and = and i64 %shr, 255
+ ret i64 %and
+
+; CHECK-LABEL: dext_lsr_and8:
+; CHECK: dextu $[[R0:[0-9]+]], $[[R1:[0-9]+]], 40, 8
+
+}
+
+define i64 @dext_zext(i32 signext %a) {
+entry:
+ %conv = zext i32 %a to i64
+ ret i64 %conv
+
+; CHECK-LABEL: dext_zext:
+; CHECK: dext $[[R0:[0-9]+]], $[[R1:[0-9]+]], 0, 32
+
+}
+
+define i64 @dext_and_lsr(i64 zeroext %n) {
+entry:
+ %and = lshr i64 %n, 8
+ %shr = and i64 %and, 4095
+ ret i64 %shr
+
+; CHECK-LABEL: dext_and_lsr:
+; CHECK: dext $[[R0:[0-9]+]], $[[R1:[0-9]+]], 8, 12
+
+}
; RUN: llc -march=mips64 -mcpu=mips4 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64,MIPS64-EB %s
; RUN: llc -march=mips64el -mcpu=mips64 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64,MIPS64-EL %s
; RUN: llc -march=mips64 -mcpu=mips64 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64,MIPS64-EB %s
-; RUN: llc -march=mips64el -mcpu=mips64r2 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64,MIPS64-EL %s
-; RUN: llc -march=mips64 -mcpu=mips64r2 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64,MIPS64-EB %s
+; RUN: llc -march=mips64el -mcpu=mips64r2 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64,MIPS64R2-EL %s
+; RUN: llc -march=mips64 -mcpu=mips64r2 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64,MIPS64R2-EB %s
; RUN: llc -march=mips64el -mcpu=mips64r6 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64R6,MIPS64R6-EL %s
; RUN: llc -march=mips64 -mcpu=mips64r6 -target-abi=n64 -relocation-model=pic < %s | FileCheck -check-prefixes=ALL,MIPS64R6,MIPS64R6-EB %s
; MIPS64-EL: lwl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
; MIPS64-EL: lwr $[[R0]], 0($[[R1]])
+; MIPS64R2-EL: lwl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
+; MIPS64R2-EL: lwr $[[R0]], 0($[[R1]])
+
; MIPS64-EB: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
; MIPS64-EB: lwr $[[R0]], 3($[[R1]])
+; MIPS64R2-EB: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
+; MIPS64R2-EB: lwr $[[R0]], 3($[[R1]])
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(si)(
; MIPS64R6: lw $2, 0($[[PTR]])
; MIPS64-EL: swl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
; MIPS64-EL: swr $[[R0]], 0($[[R1]])
+; MIPS64R2-EL: swl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
+; MIPS64R2-EL: swr $[[R0]], 0($[[R1]])
+
; MIPS64-EB: swl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
; MIPS64-EB: swr $[[R0]], 3($[[R1]])
+; MIPS64R2-EB: swl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
+; MIPS64R2-EB: swr $[[R0]], 3($[[R1]])
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(si)(
; MIPS64R6: sw $4, 0($[[PTR]])
; MIPS64-EL: ldl $[[R0:[0-9]+]], 7($[[R1:[0-9]+]])
; MIPS64-EL: ldr $[[R0]], 0($[[R1]])
+; MIPS64R2-EL: ldl $[[R0:[0-9]+]], 7($[[R1:[0-9]+]])
+; MIPS64R2-EL: ldr $[[R0]], 0($[[R1]])
+
; MIPS64-EB: ldl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
; MIPS64-EB: ldr $[[R0]], 7($[[R1]])
+; MIPS64R2-EB: ldl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
+; MIPS64R2-EB: ldr $[[R0]], 7($[[R1]])
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(sll)(
; MIPS64R6: ld $2, 0($[[PTR]])
; MIPS64-EL: lwl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
; MIPS64-EL: lwr $[[R0]], 0($[[R1]])
+; MIPS64R2-EL: lwl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
+; MIPS64R2-EL: lwr $[[R0]], 0($[[R1]])
+
; MIPS64-EB: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
; MIPS64-EB: lwr $[[R0]], 3($[[R1]])
+; MIPS64R2-EB: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
+; MIPS64R2-EB: lwr $[[R0]], 3($[[R1]])
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(si)(
; MIPS64R6: lw $2, 0($[[PTR]])
; MIPS64-EL-DAG: daddiu $[[R4:[0-9]+]], $[[R3]], -1
; MIPS64-EL-DAG: and ${{[0-9]+}}, $[[R0]], $[[R4]]
+; MIPS64R2-EL-DAG: lwl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
+; MIPS64R2-EL-DAG: lwr $[[R0]], 0($[[R1]])
+; MIPS64R2-EL-DAG: dext $[[R0]], $[[R0]], 0, 32
+
; MIPS64-EB: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
; MIPS64-EB: lwr $[[R0]], 3($[[R1]])
+; MIPS64R2-EB: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
+; MIPS64R2-EB: lwr $[[R0]], 3($[[R1]])
+; MIPS64R2-EB: dext $[[R0]], $[[R0]], 0, 32
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(sui)(
; MIPS64R6: lwu $2, 0($[[PTR]])
; MIPS64-EL: sdl $[[R0:[0-9]+]], 7($[[R1:[0-9]+]])
; MIPS64-EL: sdr $[[R0]], 0($[[R1]])
+; MIPS64R2-EL: sdl $[[R0:[0-9]+]], 7($[[R1:[0-9]+]])
+; MIPS64R2-EL: sdr $[[R0]], 0($[[R1]])
+
; MIPS64-EB: sdl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
; MIPS64-EB: sdr $[[R0]], 7($[[R1]])
+; MIPS64R2-EB: sdl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
+; MIPS64R2-EB: sdr $[[R0]], 7($[[R1]])
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(sll)(
; MIPS64R6: sd $4, 0($[[PTR]])
; MIPS64-EL: swl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
; MIPS64-EL: swr $[[R0]], 0($[[R1]])
+; MIPS64R2-EL: swl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]])
+; MIPS64R2-EL: swr $[[R0]], 0($[[R1]])
+
; MIPS64-EB: swl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
; MIPS64-EB: swr $[[R0]], 3($[[R1]])
+; MIPS64R2-EB: swl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]])
+; MIPS64R2-EB: swr $[[R0]], 3($[[R1]])
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(si)(
; MIPS64R6: sw $4, 0($[[PTR]])
; MIPS32-EB: lw $[[PTR:[0-9]+]], %got(struct_s0)(
; MIPS32R6: lw $[[PTR:[0-9]+]], %got(struct_s0)(
; MIPS64-EL: ld $[[PTR:[0-9]+]], %got_disp(struct_s0)(
+; MIPS64R2-EL: ld $[[PTR:[0-9]+]], %got_disp(struct_s0)(
; MIPS64-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s0)(
+; MIPS64R2-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s0)(
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(struct_s0)(
; MIPS32-DAG: lbu $[[R1:[0-9]+]], 0($[[PTR]])
; MIPS32R6-DAG: sw $[[R1]], 4($[[PTR]])
; MIPS64-EL: ld $[[PTR:[0-9]+]], %got_disp(struct_s1)(
+; MIPS64R2-EL: ld $[[PTR:[0-9]+]], %got_disp(struct_s1)(
; MIPS64-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s1)(
+; MIPS64R2-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s1)(
; MIPS64-EL-DAG: lwl $[[R1:[0-9]+]], 3($[[PTR]])
; MIPS64-EL-DAG: lwr $[[R1]], 0($[[PTR]])
; MIPS64-EL-DAG: swl $[[R1]], 7($[[PTR]])
; MIPS64-EL-DAG: swr $[[R1]], 4($[[PTR]])
+; MIPS64R2-EL-DAG: lwl $[[R1:[0-9]+]], 3($[[PTR]])
+; MIPS64R2-EL-DAG: lwr $[[R1]], 0($[[PTR]])
+; MIPS64R2-EL-DAG: swl $[[R1]], 7($[[PTR]])
+; MIPS64R2-EL-DAG: swr $[[R1]], 4($[[PTR]])
+
; MIPS64-EB-DAG: lwl $[[R1:[0-9]+]], 0($[[PTR]])
; MIPS64-EB-DAG: lwr $[[R1]], 3($[[PTR]])
; MIPS64-EB-DAG: swl $[[R1]], 4($[[PTR]])
; MIPS64-EB-DAG: swr $[[R1]], 7($[[PTR]])
+; MIPS64R2-EB-DAG: lwl $[[R1:[0-9]+]], 0($[[PTR]])
+; MIPS64R2-EB-DAG: lwr $[[R1]], 3($[[PTR]])
+; MIPS64R2-EB-DAG: swl $[[R1]], 4($[[PTR]])
+; MIPS64R2-EB-DAG: swr $[[R1]], 7($[[PTR]])
; MIPS64-NOLEFTRIGHT-DAG: lbu $[[R1:[0-9]+]], 0($[[PTR]])
; MIPS64-NOLEFTRIGHT-DAG: sb $[[R1]], 4($[[PTR]])
; MIPS64-EL-DAG: sdl $[[R1]], 15($[[PTR]])
; MIPS64-EL-DAG: sdr $[[R1]], 8($[[PTR]])
+; MIPS64R2-EL: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)(
+
+; MIPS64R2-EL-DAG: ldl $[[R1:[0-9]+]], 7($[[PTR]])
+; MIPS64R2-EL-DAG: ldr $[[R1]], 0($[[PTR]])
+; MIPS64R2-EL-DAG: sdl $[[R1]], 15($[[PTR]])
+; MIPS64R2-EL-DAG: sdr $[[R1]], 8($[[PTR]])
+
; MIPS64-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)(
; MIPS64-EB-DAG: ldl $[[R1:[0-9]+]], 0($[[PTR]])
; MIPS64-EB-DAG: ldr $[[R1]], 7($[[PTR]])
; MIPS64-EB-DAG: sdl $[[R1]], 8($[[PTR]])
; MIPS64-EB-DAG: sdr $[[R1]], 15($[[PTR]])
+; MIPS64R2-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)(
+; MIPS64R2-EB-DAG: ldl $[[R1:[0-9]+]], 0($[[PTR]])
+; MIPS64R2-EB-DAG: ldr $[[R1]], 7($[[PTR]])
+; MIPS64R2-EB-DAG: sdl $[[R1]], 8($[[PTR]])
+; MIPS64R2-EB-DAG: sdr $[[R1]], 15($[[PTR]])
+
; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)(
; MIPS64R6-DAG: ld $[[R1:[0-9]+]], 0($[[PTR]])
; MIPS64R6-DAG: sd $[[R1]], 8($[[PTR]])
; MIPS64-EL-DAG: lwl $[[R1:[0-9]+]], 3($[[PTR]])
; MIPS64-EL-DAG: lwr $[[R1]], 0($[[PTR]])
+; MIPS64R2-EL: ld $[[SPTR:[0-9]+]], %got_disp(arr)(
+; MIPS64R2-EL-DAG: lwl $[[R1:[0-9]+]], 3($[[PTR]])
+; MIPS64R2-EL-DAG: lwr $[[R1]], 0($[[PTR]])
+
; MIPS64-EB: ld $[[SPTR:[0-9]+]], %got_disp(arr)(
; MIPS64-EB-DAG: lbu $[[R2:[0-9]+]], 5($[[PTR]])
; MIPS64-EB-DAG: lbu $[[R3:[0-9]+]], 4($[[PTR]])
; MIPS64-EB-DAG: dsll $[[T4:[0-9]+]], $[[R4]], 8
; MIPS64-EB-DAG: or $4, $[[T3]], $[[T4]]
+; MIPS64R2-EB: ld $[[SPTR:[0-9]+]], %got_disp(arr)(
+; MIPS64R2-EB-DAG: lbu $[[R1:[0-9]+]], 5($[[PTR]])
+; MIPS64R2-EB-DAG: lbu $[[R2:[0-9]+]], 4($[[PTR]])
+; MIPS64R2-EB-DAG: dsll $[[T0:[0-9]+]], $[[R2]], 8
+; MIPS64R2-EB-DAG: or $[[T1:[0-9]+]], $[[T0]], $[[R1]]
+; MIPS64R2-EB-DAG: dsll $[[T1]], $[[T1]], 16
+; MIPS64R2-EB-DAG: lwl $[[R3:[0-9]+]], 0($[[PTR]])
+; MIPS64R2-EB-DAG: lwr $[[R3]], 3($[[PTR]])
+; MIPS64R2-EB-DAG: dext $[[R3]], $[[R3]], 0, 32
+; MIPS64R2-EB-DAG: dsll $[[R3]], $[[R3]], 32
+; MIPS64R2-EB-DAG: or $[[T2:[0-9]+]], $[[R3]], $[[T1]]
+; MIPS64R2-EB-DAG: lbu $[[R4:[0-9]+]], 6($[[PTR]])
+; MIPS64R2-EB-DAG: dsll $[[T3:[0-9]+]], $[[R4]], 8
+; MIPS64R2-EB-DAG: or $4, $[[T2]], $[[T3]]
+
; MIPS64R6: ld $[[SPTR:[0-9]+]], %got_disp(arr)(
tail call void @extern_func([7 x i8]* byval @arr) nounwind
; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips4 -mattr=+soft-float -O1 \
; RUN: -disable-mips-delay-filler -relocation-model=pic < %s | FileCheck \
-; RUN: %s -check-prefixes=ALL,C_CC_FMT,PRER6
+; RUN: %s -check-prefixes=ALL,C_CC_FMT,PRER6,NOT-R2R6
; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips64 -mattr=+soft-float -O1 \
; RUN: -disable-mips-delay-filler -relocation-model=pic < %s | FileCheck \
-; RUN: %s -check-prefixes=ALL,C_CC_FMT,PRER6
+; RUN: %s -check-prefixes=ALL,C_CC_FMT,PRER6,NOT-R2R6
; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips64r2 -mattr=+soft-float \
; RUN: -O1 -disable-mips-delay-filler -relocation-model=pic < %s | FileCheck \
-; RUN: %s -check-prefixes=ALL,C_CC_FMT,PRER6
+; RUN: %s -check-prefixes=ALL,C_CC_FMT,PRER6,R2R6
; RUN: llc -mtriple=mips64el-unknown-unknown -mcpu=mips64r6 -mattr=+soft-float \
; RUN: -O1 -disable-mips-delay-filler -relocation-model=pic < %s | FileCheck \
-; RUN: %s -check-prefixes=ALL,CMP_CC_FMT,R6
+; RUN: %s -check-prefixes=ALL,CMP_CC_FMT,R6,R2R6
@gld0 = external global fp128
@gld1 = external global fp128
}
; ALL-LABEL: libcall1_fabsl:
-; ALL-DAG: ld $[[R0:[0-9]+]], 8($[[R4:[0-9]+]])
-; ALL-DAG: daddiu $[[R1:[0-9]+]], $zero, 1
-; ALL-DAG: dsll $[[R2:[0-9]+]], $[[R1]], 63
-; ALL-DAG: daddiu $[[R3:[0-9]+]], $[[R2]], -1
-; ALL-DAG: and $4, $[[R0]], $[[R3]]
-; ALL-DAG: ld $2, 0($[[R4]])
+; NOT-R2R6-DAG: ld $[[R0:[0-9]+]], 8($[[R4:[0-9]+]])
+; NOT-R2R6-DAG: daddiu $[[R1:[0-9]+]], $zero, 1
+; NOT-R2R6-DAG: dsll $[[R2:[0-9]+]], $[[R1]], 63
+; NOT-R2R6-DAG: daddiu $[[R3:[0-9]+]], $[[R2]], -1
+; NOT-R2R6-DAG: and $4, $[[R0]], $[[R3]]
+; NOT-R2R6-DAG: ld $2, 0($[[R4]])
+
+; R2R6-DAG: ld $[[R0:[0-9]+]], 0($[[R3:[0-9]+]])
+; R2R6-DAG: ld $[[R1:[0-9]+]], 8($[[R3]])
+; R2R6-DAG: dextm $[[R2:[0-9]+]], $[[R1]], 0, 63
define fp128 @libcall1_fabsl() {
entry:
declare fp128 @llvm.powi.f128(fp128, i32) #3
; ALL-LABEL: libcall2_copysignl:
-; ALL-DAG: daddiu $[[R2:[0-9]+]], $zero, 1
-; ALL-DAG: dsll $[[R3:[0-9]+]], $[[R2]], 63
-; ALL-DAG: ld $[[R0:[0-9]+]], %got_disp(gld1)
-; ALL-DAG: ld $[[R1:[0-9]+]], 8($[[R0]])
-; ALL-DAG: and $[[R4:[0-9]+]], $[[R1]], $[[R3]]
-; ALL-DAG: ld $[[R5:[0-9]+]], %got_disp(gld0)
-; ALL-DAG: ld $[[R6:[0-9]+]], 8($[[R5]])
-; ALL-DAG: daddiu $[[R7:[0-9]+]], $[[R3]], -1
-; ALL-DAG: and $[[R8:[0-9]+]], $[[R6]], $[[R7]]
-; ALL-DAG: or $4, $[[R8]], $[[R4]]
-; ALL-DAG: ld $2, 0($[[R5]])
+; ALL-DAG: daddiu $[[R2:[0-9]+]], $zero, 1
+; ALL-DAG: dsll $[[R3:[0-9]+]], $[[R2]], 63
+; ALL-DAG: ld $[[R0:[0-9]+]], %got_disp(gld1)
+; ALL-DAG: ld $[[R1:[0-9]+]], 8($[[R0]])
+; ALL-DAG: and $[[R4:[0-9]+]], $[[R1]], $[[R3]]
+; ALL-DAG: ld $[[R5:[0-9]+]], %got_disp(gld0)
+; ALL-DAG: ld $[[R6:[0-9]+]], 8($[[R5]])
+; NOT-R2R6-DAG: daddiu $[[R7:[0-9]+]], $[[R3]], -1
+; NOT-R2R6-DAG: and $[[R8:[0-9]+]], $[[R6]], $[[R7]]
+; NOT-R2R6-DAG: or $4, $[[R8]], $[[R4]]
+; R2R6-DAG: dextm $[[R7:[0-9]+]], $[[R6]], 0, 63
+; R2R6-DAG: or $4, $[[R7]], $[[R4]]
+; ALL-DAG: ld $2, 0($[[R5]])
define fp128 @libcall2_copysignl() {
entry:
ret i64 %conv
}
-; CHECK: dsll32 ${{[a-z0-9]+}}, ${{[a-z0-9]+}}, 0
+; CHECK-LABEL: foo_2:
+; CHECK: dext ${{[a-z0-9]+}}, ${{[a-z0-9]+}}, 0, 32
define i64 @foo_2(i32 %ival_2) nounwind readnone {
entry: