Index: lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips32r6InstrInfo.td +++ lib/Target/Mips/Mips32r6InstrInfo.td @@ -36,7 +36,6 @@ // Removed: luxc1 // Removed: lwxc1 // Removed: madd.[ds], nmadd.[ds], nmsub.[ds], sub.[ds] -// Removed: madd, maddu, msub, msubu // Removed: movf, movt // Removed: movf.fmt, movt.fmt, movn.fmt, movz.fmt // Removed: movn, movz Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1242,10 +1242,14 @@ def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>; // MADD*/MSUB* -def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, ISA_MIPS32; -def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, ISA_MIPS32; -def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, ISA_MIPS32; -def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, ISA_MIPS32; +def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, + ISA_MIPS32_NOT_32R6_64R6; +def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, + ISA_MIPS32_NOT_32R6_64R6; +def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, + ISA_MIPS32_NOT_32R6_64R6; +def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, + ISA_MIPS32_NOT_32R6_64R6; let AdditionalPredicates = [NotDSP] in { def PseudoMULT : MultDivPseudo, @@ -1255,10 +1259,14 @@ def PseudoMFHI : PseudoMFLOHI, ISA_MIPS1_NOT_32R6_64R6; def PseudoMFLO : PseudoMFLOHI, ISA_MIPS1_NOT_32R6_64R6; def PseudoMTLOHI : PseudoMTLOHI, ISA_MIPS1_NOT_32R6_64R6; -def PseudoMADD : MAddSubPseudo; -def PseudoMADDU : MAddSubPseudo; -def PseudoMSUB : MAddSubPseudo; -def PseudoMSUBU : MAddSubPseudo; +def PseudoMADD : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; +def PseudoMADDU : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; +def PseudoMSUB : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; +def PseudoMSUBU : MAddSubPseudo, + ISA_MIPS32_NOT_32R6_64R6; } def PseudoSDIV : MultDivPseudohasMips32r6()) { // MIPS32r6 replaces the accumulator-based multiplies with a three register // instruction + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); setOperationAction(ISD::MUL, MVT::i32, Legal); setOperationAction(ISD::MULHS, MVT::i32, Legal); setOperationAction(ISD::MULHU, MVT::i32, Legal); @@ -483,8 +485,8 @@ if (DCI.isBeforeLegalize()) return SDValue(); - if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 && - selectMADD(N, &DAG)) + if (Subtarget->hasMips32() && !Subtarget->hasMips32r6() && + N->getValueType(0) == MVT::i32 && selectMADD(N, &DAG)) return SDValue(N, 0); return SDValue(); Index: test/CodeGen/Mips/dsp-r1.ll =================================================================== --- test/CodeGen/Mips/dsp-r1.ll +++ test/CodeGen/Mips/dsp-r1.ll @@ -1,4 +1,4 @@ -; RUN: llc -march=mipsel -mattr=+dsp < %s | FileCheck %s +; RUN: llc -march=mipsel -mcpu=mips32 -mattr=+dsp < %s | FileCheck %s define i32 @test__builtin_mips_extr_w1(i32 %i0, i32, i64 %a0) nounwind { entry: Index: test/CodeGen/Mips/madd-msub.ll =================================================================== --- test/CodeGen/Mips/madd-msub.ll +++ test/CodeGen/Mips/madd-msub.ll @@ -1,9 +1,49 @@ -; RUN: llc -march=mips < %s | FileCheck %s -check-prefix=32 -; RUN: llc -march=mips -mattr=dsp < %s | FileCheck %s -check-prefix=DSP +; RUN: llc -march=mips -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32 +; RUN: llc -march=mips -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32 +; RUN: llc -march=mips -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R6 +; RUN: llc -march=mips -mcpu=mips32 -mattr=dsp < %s | FileCheck %s -check-prefix=DSP +; RUN: llc -march=mips -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64 +; RUN: llc -march=mips -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64 +; RUN: llc -march=mips -mcpu=mips64r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64R6 + +; FIXME: The MIPS16 test should check its output ; RUN: llc -march=mips -mcpu=mips16 < %s -; 32: madd ${{[0-9]+}} -; DSP: madd $ac +; ALL-LABEL: madd1: + +; 32-DAG: sra $[[T0:[0-9]+]], $6, 31 +; 32-DAG: mtlo $6 +; 32-DAG: [[m:m]]add ${{[45]}}, ${{[45]}} +; 32-DAG: [[m]]fhi $2 +; 32-DAG: [[m]]flo $3 + +; DSP-DAG: sra $[[T0:[0-9]+]], $6, 31 +; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 +; DSP-DAG: madd $[[AC]], ${{[45]}}, ${{[45]}} +; DSP-DAG: mfhi $2, $[[AC]] +; DSP-DAG: mflo $3, $[[AC]] + +; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6 +; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6 +; 32R6-DAG: sra $[[T3:[0-9]+]], $6, 31 +; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $[[T3]] +; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: addu $2, $[[T5]], $[[T4]] + +; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] +; 64-DAG: [[m]]flo $[[T2:[0-9]+]] +; 64-DAG: sll $[[T3:[0-9]+]], $6, 0 +; 64-DAG: daddu $2, $[[T2]], $[[T3]] + +; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] +; 64R6-DAG: sll $[[T3:[0-9]+]], $6, 0 +; 64R6-DAG: daddu $2, $[[T2]], $[[T3]] + define i64 @madd1(i32 %a, i32 %b, i32 %c) nounwind readnone { entry: %conv = sext i32 %a to i64 @@ -14,8 +54,47 @@ ret i64 %add } -; 32: maddu ${{[0-9]+}} -; DSP: maddu $ac +; ALL-LABEL: madd2: + +; FIXME: We don't really need this instruction +; 32-DAG: addiu $[[T0:[0-9]+]], $zero, 0 +; 32-DAG: mtlo $6 +; 32-DAG: [[m:m]]addu ${{[45]}}, ${{[45]}} +; 32-DAG: [[m]]fhi $2 +; 32-DAG: [[m]]flo $3 + +; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0 +; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 +; DSP-DAG: maddu $[[AC]], ${{[45]}}, ${{[45]}} +; DSP-DAG: mfhi $2, $[[AC]] +; DSP-DAG: mflo $3, $[[AC]] + +; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6 +; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6 +; FIXME: There's a redundant move here. We should remove it +; 32R6-DAG: muhu $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: addu $2, $[[T3]], $[[T2]] + +; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32 +; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 +; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32 +; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 +; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]] +; 64-DAG: [[m]]flo $[[T4:[0-9]+]] +; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32 +; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 +; 64-DAG: daddu $2, $[[T4]], $[[T6]] + +; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32 +; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 +; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32 +; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 +; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]] +; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32 +; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 +; 64R6-DAG: daddu $2, $[[T4]], $[[T6]] + define i64 @madd2(i32 %a, i32 %b, i32 %c) nounwind readnone { entry: %conv = zext i32 %a to i64 @@ -26,8 +105,38 @@ ret i64 %add } -; 32: madd ${{[0-9]+}} -; DSP: madd $ac +; ALL-LABEL: madd3: + +; 32-DAG: mthi $6 +; 32-DAG: mtlo $7 +; 32-DAG: [[m:m]]add ${{[45]}}, ${{[45]}} +; 32-DAG: [[m]]fhi $2 +; 32-DAG: [[m]]flo $3 + +; DSP-DAG: mthi $[[AC:ac[0-3]+]], $6 +; DSP-DAG: mtlo $[[AC]], $7 +; DSP-DAG: madd $[[AC]], ${{[45]}}, ${{[45]}} +; DSP-DAG: mfhi $2, $[[AC]] +; DSP-DAG: mflo $3, $[[AC]] + +; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $7 +; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $7 +; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $6 +; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: addu $2, $[[T5]], $[[T4]] + +; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] +; 64-DAG: [[m]]flo $[[T2:[0-9]+]] +; 64-DAG: daddu $2, $[[T2]], $6 + +; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] +; 64R6-DAG: daddu $2, $[[T2]], $6 + define i64 @madd3(i32 %a, i32 %b, i64 %c) nounwind readnone { entry: %conv = sext i32 %a to i64 @@ -37,8 +146,41 @@ ret i64 %add } -; 32: msub ${{[0-9]+}} -; DSP: msub $ac +; ALL-LABEL: msub1: + +; 32-DAG: sra $[[T0:[0-9]+]], $6, 31 +; 32-DAG: mtlo $6 +; 32-DAG: [[m:m]]sub ${{[45]}}, ${{[45]}} +; 32-DAG: [[m]]fhi $2 +; 32-DAG: [[m]]flo $3 + +; DSP-DAG: sra $[[T0:[0-9]+]], $6, 31 +; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 +; DSP-DAG: msub $[[AC]], ${{[45]}}, ${{[45]}} +; DSP-DAG: mfhi $2, $[[AC]] +; DSP-DAG: mflo $3, $[[AC]] + +; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: sltu $[[T3:[0-9]+]], $6, $[[T1]] +; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T3]], $[[T0]] +; 32R6-DAG: sra $[[T5:[0-9]+]], $6, 31 +; 32R6-DAG: subu $2, $[[T5]], $[[T4]] +; 32R6-DAG: subu $3, $6, $[[T1]] + +; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] +; 64-DAG: [[m]]flo $[[T2:[0-9]+]] +; 64-DAG: sll $[[T3:[0-9]+]], $6, 0 +; 64-DAG: dsubu $2, $[[T3]], $[[T2]] + +; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] +; 64R6-DAG: sll $[[T3:[0-9]+]], $6, 0 +; 64R6-DAG: dsubu $2, $[[T3]], $[[T2]] + define i64 @msub1(i32 %a, i32 %b, i32 %c) nounwind readnone { entry: %conv = sext i32 %c to i64 @@ -49,8 +191,48 @@ ret i64 %sub } -; 32: msubu ${{[0-9]+}} -; DSP: msubu $ac +; ALL-LABEL: msub2: + +; FIXME: We don't really need this instruction +; 32-DAG: addiu $[[T0:[0-9]+]], $zero, 0 +; 32-DAG: mtlo $6 +; 32-DAG: [[m:m]]subu ${{[45]}}, ${{[45]}} +; 32-DAG: [[m]]fhi $2 +; 32-DAG: [[m]]flo $3 + +; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0 +; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 +; DSP-DAG: msubu $[[AC]], ${{[45]}}, ${{[45]}} +; DSP-DAG: mfhi $2, $[[AC]] +; DSP-DAG: mflo $3, $[[AC]] + +; 32R6-DAG: muhu $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} + +; 32R6-DAG: sltu $[[T2:[0-9]+]], $6, $[[T1]] +; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]] +; 32R6-DAG: negu $2, $[[T3]] +; 32R6-DAG: subu $3, $6, $[[T1]] + +; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32 +; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 +; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32 +; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 +; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]] +; 64-DAG: [[m]]flo $[[T4:[0-9]+]] +; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32 +; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 +; 64-DAG: dsubu $2, $[[T6]], $[[T4]] + +; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32 +; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 +; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32 +; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 +; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]] +; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32 +; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 +; 64R6-DAG: dsubu $2, $[[T6]], $[[T4]] + define i64 @msub2(i32 %a, i32 %b, i32 %c) nounwind readnone { entry: %conv = zext i32 %c to i64 @@ -61,8 +243,39 @@ ret i64 %sub } -; 32: msub ${{[0-9]+}} -; DSP: msub $ac +; ALL-LABEL: msub3: + +; FIXME: We don't really need this instruction +; 32-DAG: mthi $6 +; 32-DAG: mtlo $7 +; 32-DAG: [[m:m]]sub ${{[45]}}, ${{[45]}} +; 32-DAG: [[m]]fhi $2 +; 32-DAG: [[m]]flo $3 + +; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0 +; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6 +; DSP-DAG: msub $[[AC]], ${{[45]}}, ${{[45]}} +; DSP-DAG: mfhi $2, $[[AC]] +; DSP-DAG: mflo $3, $[[AC]] + +; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: sltu $[[T2:[0-9]+]], $7, $[[T1]] +; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]] +; 32R6-DAG: subu $2, $6, $[[T3]] +; 32R6-DAG: subu $3, $7, $[[T1]] + +; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]] +; 64-DAG: [[m]]flo $[[T2:[0-9]+]] +; 64-DAG: dsubu $2, $6, $[[T2]] + +; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0 +; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0 +; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]] +; 64R6-DAG: dsubu $2, $6, $[[T2]] + define i64 @msub3(i32 %a, i32 %b, i64 %c) nounwind readnone { entry: %conv = sext i32 %a to i64 Index: test/MC/Mips/mips32r6/invalid-mips32.s =================================================================== --- /dev/null +++ test/MC/Mips/mips32r6/invalid-mips32.s @@ -0,0 +1,13 @@ +# Instructions that are invalid +# +# RUN: not llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r6 \ +# RUN: 2>%t1 +# RUN: FileCheck %s < %t1 + + .set noat + madd $s6,$13 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + madd $zero,$9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + maddu $s3,$gp # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + maddu $24,$s2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + msub $s7,$k1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + msubu $15,$a1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled Index: test/MC/Mips/mips64r6/invalid-mips64.s =================================================================== --- /dev/null +++ test/MC/Mips/mips64r6/invalid-mips64.s @@ -0,0 +1,13 @@ +# Instructions that are invalid +# +# RUN: not llvm-mc %s -triple=mips64-unknown-linux -show-encoding -mcpu=mips64r6 \ +# RUN: 2>%t1 +# RUN: FileCheck %s < %t1 + + .set noat + madd $s6,$13 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + madd $zero,$9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + maddu $s3,$gp # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + maddu $24,$s2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + msub $s7,$k1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + msubu $15,$a1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled