From: Petar Jovanovic Date: Wed, 15 Mar 2017 13:10:08 +0000 (+0000) Subject: [Mips] Add support to match more patterns for DEXT and CINS X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=71148e9b8fff260ffb8597acac4a23cf7f1cee4a;p=llvm [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 : 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 : 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297832 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index f3081d32bae..99025fe1341 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/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: let TwoOperandAliasConstraint = "$rd = $rs"; } -class ExtsCins: - 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: + 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/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index f0f2424f722..4df6979d8a7 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/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(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(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(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(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(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(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/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index abc34be6377..2dcafd51061 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -116,6 +116,7 @@ namespace llvm { Ext, Ins, + CIns, // EXTR.W instrinsic nodes. EXTP, diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index a25a9165a17..b90077d7807 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/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 : SDNodeXFormgetZExtValue()); +}]>; + // 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/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index c78c24bf47b..71bccc52482 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/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: diff --git a/test/CodeGen/Mips/cins.ll b/test/CodeGen/Mips/cins.ll new file mode 100644 index 00000000000..4fe25564d1c --- /dev/null +++ b/test/CodeGen/Mips/cins.ll @@ -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 + +} diff --git a/test/CodeGen/Mips/dext.ll b/test/CodeGen/Mips/dext.ll new file mode 100644 index 00000000000..1794f16b2cd --- /dev/null +++ b/test/CodeGen/Mips/dext.ll @@ -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 + +} diff --git a/test/CodeGen/Mips/load-store-left-right.ll b/test/CodeGen/Mips/load-store-left-right.ll index 6def55cf883..b998772d367 100644 --- a/test/CodeGen/Mips/load-store-left-right.ll +++ b/test/CodeGen/Mips/load-store-left-right.ll @@ -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 diff --git a/test/CodeGen/Mips/mips64-f128.ll b/test/CodeGen/Mips/mips64-f128.ll index 237b4c5f1ee..a6dafb1abfd 100644 --- a/test/CodeGen/Mips/mips64-f128.ll +++ b/test/CodeGen/Mips/mips64-f128.ll @@ -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: diff --git a/test/MC/Mips/sext_64_32.ll b/test/MC/Mips/sext_64_32.ll index 5679829e8ea..f6c468187d7 100644 --- a/test/MC/Mips/sext_64_32.ll +++ b/test/MC/Mips/sext_64_32.ll @@ -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: