[Mips] Add support to match more patterns for DEXT and CINS

This patch adds support for recognizing more patterns to match to DEXT and
CINS instructions.
It finds cases where multiple instructions could be replaced with a single
DEXT or CINS instruction.

For example, for the following:

define i64 @dext_and32(i64 zeroext %a) {
entry:

 %and = and i64 %a, 4294967295
 ret i64 %and
}

instead of generating:

 0000000000000088 <dext_and32>:

 88:   64010001        daddiu  at,zero,1
 8c:   0001083c        dsll32  at,at,0x0
 90:   6421ffff        daddiu  at,at,-1
 94:   03e00008        jr      ra
 98:   00811024        and     v0,a0,at
 9c:   00000000        nop

the following gets generated:

 0000000000000068 <dext_and32>:

 68:   03e00008        jr      ra
 6c:   7c82f803        dext    v0,a0,0x0,0x20

Cases that are covered:

DEXT:

 1. and $src, mask where mask > 0xffff
 2. zext $src zero extend from i32 to i64

CINS:

 1. and (shl $src, pos), mask
 2. shl (and $src, mask), pos
 3. zext (shl $src, pos) zero extend from i32 to i64

Patch by Violeta Vukobrat.

Differential Revision: https://reviews.llvm.org/D30464

llvm-svn: 297832
This commit is contained in:
Petar Jovanovic 2017-03-15 13:10:08 +00:00
parent 92e8a65b1a
commit 51463c570e
10 changed files with 490 additions and 63 deletions

View File

@ -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;
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>, EXTS_FM<0x32>, ASE_CNMIPS;
def CINS32: ExtsCins<"cins32", II_INS>, EXTS_FM<0x33>, ASE_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

View File

@ -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();
SDValue FirstOperand = N->getOperand(0);
unsigned FirstOperandOpc = FirstOperand.getOpcode();
SDValue Mask = N->getOperand(1);
EVT ValTy = N->getValueType(0);
SDLoc DL(N);
// Op's first operand must be a shift right.
if (ShiftRightOpc != ISD::SRA && ShiftRightOpc != ISD::SRL)
return SDValue();
// 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
SDLoc DL(N);
return DAG.getNode(MipsISD::Ext, DL, ValTy,
ShiftRight.getOperand(0),
// 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
// 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();

View File

@ -116,6 +116,7 @@ namespace llvm {
Ext,
Ins,
CIns,
// EXTR.W instrinsic nodes.
EXTP,

View File

@ -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);

View File

@ -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:

92
test/CodeGen/Mips/cins.ll Normal file
View File

@ -0,0 +1,92 @@
; 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
}

105
test/CodeGen/Mips/dext.ll Normal file
View File

@ -0,0 +1,105 @@
; 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
}

View File

@ -8,8 +8,8 @@
; 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
@ -37,9 +37,15 @@ entry:
; 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]])
@ -63,9 +69,15 @@ entry:
; 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]])
@ -94,9 +106,15 @@ entry:
; 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]])
@ -123,9 +141,15 @@ entry:
; 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]])
@ -159,9 +183,17 @@ entry:
; 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]])
@ -191,9 +223,15 @@ entry:
; 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]])
@ -217,9 +255,15 @@ entry:
; 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]])
@ -247,7 +291,9 @@ entry:
; 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]])
@ -297,18 +343,29 @@ entry:
; 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]])
@ -365,12 +422,25 @@ entry:
; 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]])
@ -430,6 +500,10 @@ entry:
; 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]])
@ -444,6 +518,21 @@ entry:
; 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

View File

@ -1,15 +1,15 @@
; 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
@ -242,12 +242,16 @@ entry:
}
; 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:
@ -414,17 +418,19 @@ 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:

View File

@ -11,7 +11,8 @@ 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: