Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -329,6 +329,14 @@ 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>; @@ -359,11 +367,11 @@ 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"; } @@ -427,13 +435,28 @@ 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>, @@ -649,6 +672,14 @@ 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)>; @@ -799,21 +830,21 @@ 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 Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -116,6 +116,7 @@ Ext, Ins, + CIns, // EXTR.W instrinsic nodes. EXTP, Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -147,6 +147,7 @@ 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 @@ 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 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 @@ 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 @@ 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(); Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -138,6 +138,7 @@ 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 @@ 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); Index: lib/Target/Mips/MipsSEISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEISelLowering.cpp +++ lib/Target/Mips/MipsSEISelLowering.cpp @@ -1123,7 +1123,8 @@ 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: Index: test/CodeGen/Mips/cins.ll =================================================================== --- /dev/null +++ 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 + +} Index: test/CodeGen/Mips/dext.ll =================================================================== --- /dev/null +++ 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 + +} Index: test/CodeGen/Mips/load-store-left-right.ll =================================================================== --- test/CodeGen/Mips/load-store-left-right.ll +++ 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; MIPS64-EL-DAG: daddiu $[[R4:[0-9]+]], $[[R3]], -1 ; MIPS64-EL-DAG: and ${{[0-9]+}}, $[[R0]], $[[R4]] +; MIPS64R2-EL: lwl $[[R0:[0-9]+]], 3($[[R1:[0-9]+]]) +; MIPS64R2-EL: lwr $[[R0]], 0($[[R1]]) +; MIPS64R2-EL: dext $[[R0]], $[[R0]], 0, 32 + ; MIPS64-EB: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]]) ; MIPS64-EB: lwr $[[R0]], 3($[[R1]]) +; MIPS64R2-EB-DAG: lwl $[[R0:[0-9]+]], 0($[[R1:[0-9]+]]) +; MIPS64R2-EB-DAG: lwr $[[R0]], 3($[[R1]]) +; MIPS64R2-EB-DAG: dext $[[R0]], $[[R0]], 0, 32 + ; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(sui)( ; MIPS64R6: lwu $2, 0($[[PTR]]) @@ -191,9 +223,15 @@ ; 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 @@ ; 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 @@ ; 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)( ; FIXME: We should be able to do better than this on MIPS32r6/MIPS64r6 since @@ -284,7 +330,9 @@ ; MIPS32R6-DAG: sh $[[R1]], 6($[[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-DAG: lbu $[[R1:[0-9]+]], 0($[[PTR]]) ; MIPS64-DAG: sb $[[R1]], 4($[[PTR]]) ; MIPS64-DAG: lbu $[[R1:[0-9]+]], 1($[[PTR]]) @@ -345,6 +393,16 @@ ; MIPS64-EL-DAG: swl $[[R1]], 15($[[PTR]]) ; MIPS64-EL-DAG: swr $[[R1]], 12($[[PTR]]) +; MIPS64R2-EL: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)( +; MIPS64R2-EL-DAG: lwl $[[R1:[0-9]+]], 3($[[PTR]]) +; MIPS64R2-EL-DAG: lwr $[[R1]], 0($[[PTR]]) +; MIPS64R2-EL-DAG: swl $[[R1]], 11($[[PTR]]) +; MIPS64R2-EL-DAG: swr $[[R1]], 8($[[PTR]]) +; MIPS64R2-EL-DAG: lwl $[[R1:[0-9]+]], 7($[[PTR]]) +; MIPS64R2-EL-DAG: lwr $[[R1]], 4($[[PTR]]) +; MIPS64R2-EL-DAG: swl $[[R1]], 15($[[PTR]]) +; MIPS64R2-EL-DAG: swr $[[R1]], 12($[[PTR]]) + ; MIPS64-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)( ; MIPS64-EB-DAG: lwl $[[R1:[0-9]+]], 0($[[PTR]]) ; MIPS64-EB-DAG: lwr $[[R1]], 3($[[PTR]]) @@ -355,6 +413,16 @@ ; MIPS64-EB-DAG: swl $[[R1]], 12($[[PTR]]) ; MIPS64-EB-DAG: swr $[[R1]], 15($[[PTR]]) +; MIPS64R2-EB: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)( +; MIPS64R2-EB-DAG: lwl $[[R1:[0-9]+]], 0($[[PTR]]) +; MIPS64R2-EB-DAG: lwr $[[R1]], 3($[[PTR]]) +; MIPS64R2-EB-DAG: swl $[[R1]], 8($[[PTR]]) +; MIPS64R2-EB-DAG: swr $[[R1]], 11($[[PTR]]) +; MIPS64R2-EB-DAG: lwl $[[R1:[0-9]+]], 4($[[PTR]]) +; MIPS64R2-EB-DAG: lwr $[[R1]], 7($[[PTR]]) +; MIPS64R2-EB-DAG: swl $[[R1]], 12($[[PTR]]) +; MIPS64R2-EB-DAG: swr $[[R1]], 15($[[PTR]]) + ; MIPS64R6: ld $[[PTR:[0-9]+]], %got_disp(struct_s2)( ; MIPS64R6-DAG: lw $[[R1:[0-9]+]], 0($[[PTR]]) ; MIPS64R6-DAG: sw $[[R1]], 8($[[PTR]]) @@ -416,6 +484,10 @@ ; 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: lwl $[[R1:[0-9]+]], 0($[[PTR]]) ; MIPS64-EB-DAG: lwr $[[R1]], 3($[[PTR]]) @@ -430,6 +502,21 @@ ; 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: lbu $[[R1:[0-9]+]], 5($[[PTR]]) +; MIPS64R2-EB: lbu $[[R2:[0-9]+]], 4($[[PTR]]) +; MIPS64R2-EB: dsll $[[T0:[0-9]+]], $[[R2]], 8 +; MIPS64R2-EB: or $[[T1:[0-9]+]], $[[T0]], $[[R1]] +; MIPS64R2-EB: dsll $[[T1]], $[[T1]], 16 +; MIPS64R2-EB: lwl $[[R3:[0-9]+]], 0($[[PTR]]) +; MIPS64R2-EB: lwr $[[R3]], 3($[[PTR]]) +; MIPS64R2-EB: dext $[[R3]], $[[R3]], 0, 32 +; MIPS64R2-EB: dsll $[[R3]], $[[R3]], 32 +; MIPS64R2-EB: or $[[T2:[0-9]+]], $[[R3]], $[[T1]] +; MIPS64R2-EB: lbu $[[R4:[0-9]+]], 6($[[PTR]]) +; MIPS64R2-EB: dsll $[[T3:[0-9]+]], $[[R4]], 8 +; MIPS64R2-EB: or $4, $[[T2]], $[[T3]] + ; MIPS64R6: ld $[[SPTR:[0-9]+]], %got_disp(arr)( tail call void @extern_func([7 x i8]* byval @arr) nounwind Index: test/CodeGen/Mips/mips64-f128.ll =================================================================== --- test/CodeGen/Mips/mips64-f128.ll +++ 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 @@ } ; 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 @@ 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: Index: test/MC/Mips/sext_64_32.ll =================================================================== --- test/MC/Mips/sext_64_32.ll +++ test/MC/Mips/sext_64_32.ll @@ -11,7 +11,8 @@ 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: