Index: clang/test/CodeGen/mips16-mult.c =================================================================== --- /dev/null +++ clang/test/CodeGen/mips16-mult.c @@ -0,0 +1,10 @@ +// REQUIRES: mips-registered-target +// RUN: %clang --target=mipsel-unknown-linux -mips16 -c -o %t %s + +// Check for BugZilla bug 49146 "Crash with MIPS16 Multiply". +// The bug does not manifest when using the "-S" or "-emit-llvm" options. + +unsigned do_mult(unsigned n, unsigned m) +{ + return n * m; +} Index: llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -191,6 +191,13 @@ default: break; + case ISD::MUL: { + MultOpc = Mips::MultRxRy16; + auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, true, false); + ReplaceNode(Node, LoHi.first); + return true; + } + /// Mul with two results case ISD::SMUL_LOHI: case ISD::UMUL_LOHI: { Index: llvm/lib/Target/Mips/Mips16InstrInfo.td =================================================================== --- llvm/lib/Target/Mips/Mips16InstrInfo.td +++ llvm/lib/Target/Mips/Mips16InstrInfo.td @@ -298,25 +298,6 @@ FI8_MOV32R16<(outs GPR32:$r32), (ins CPU16Regs:$rz), !strconcat(asmstr, "\t$r32, $rz"), [], itin>; -// -// This are pseudo formats for multiply -// This first one can be changed to non-pseudo now. -// -// MULT -// -class FMULT16_ins : - MipsPseudo16<(outs), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry"), []>; - -// -// MULT-LO -// -class FMULT16_LO_ins : - MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry\n\tmflo\t$rz"), []> { - let isCodeGenOnly=1; -} - // // RR-type instruction format // @@ -347,6 +328,10 @@ FRR16 ; +class FRR16_mult_ins f, string asmstr, InstrItinClass itin> : + FRR16 ; + class FUnaryRR16_ins f, string asmstr, InstrItinClass itin> : FRR16 ; @@ -731,6 +716,7 @@ def DivuRxRy16: FRR16_div_ins<0b11011, "divu", IIM16Alu> { let Defs = [HI0, LO0]; } + // // Format: JAL target MIPS16e // Purpose: Jump and Link @@ -892,29 +878,12 @@ let isMoveReg = 0; } -// -// Pseudo Instruction for mult -// -def MultRxRy16: FMULT16_ins<"mult", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; - let Defs = [HI0, LO0]; -} - -def MultuRxRy16: FMULT16_ins<"multu", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; - let Defs = [HI0, LO0]; -} - // // Format: MULT rx, ry MIPS16e // Purpose: Multiply Word // To multiply 32-bit signed integers. // -def MultRxRyRz16: FMULT16_LO_ins<"mult", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; +def MultRxRy16: FRR16_mult_ins<0b11000, "mult", IIM16Alu> { let Defs = [HI0, LO0]; } @@ -923,12 +892,11 @@ // Purpose: Multiply Unsigned Word // To multiply 32-bit unsigned integers. // -def MultuRxRyRz16: FMULT16_LO_ins<"multu", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; +def MultuRxRy16: FRR16_mult_ins<0b11001, "multu", IIM16Alu> { let Defs = [HI0, LO0]; } + // // Format: NEG rx, ry MIPS16e // Purpose: Negate @@ -1313,7 +1281,6 @@ def: ArithLogic16_pat; def: ArithLogic16_pat; -def: ArithLogic16_pat; def: ArithLogic16_pat; def: ArithLogic16_pat; def: ArithLogic16_pat; @@ -1557,6 +1524,20 @@ <(MipsDivRemU16 CPU16Regs:$rx, CPU16Regs:$ry), (DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>; +// +// MipsMult +// +def: Mips16Pat + <(MipsMult16 CPU16Regs:$rx, CPU16Regs:$ry), + (MultRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>; + +// +// MipsMultu +// +def: Mips16Pat + <(MipsMultu16 CPU16Regs:$rx, CPU16Regs:$ry), + (MultuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>; + // signed a,b // x = (a>=b)?x:y // Index: llvm/lib/Target/Mips/MipsISelLowering.h =================================================================== --- llvm/lib/Target/Mips/MipsISelLowering.h +++ llvm/lib/Target/Mips/MipsISelLowering.h @@ -131,6 +131,8 @@ // Mult nodes. Mult, Multu, + Mult16, + Multu16, // MAdd/Sub nodes MAdd, Index: llvm/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm/lib/Target/Mips/MipsISelLowering.cpp +++ llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -205,6 +205,8 @@ case MipsISD::MTLOHI: return "MipsISD::MTLOHI"; case MipsISD::Mult: return "MipsISD::Mult"; case MipsISD::Multu: return "MipsISD::Multu"; + case MipsISD::Mult16: return "MipsISD::Mult16"; + case MipsISD::Multu16: return "MipsISD::Multu16"; case MipsISD::MAdd: return "MipsISD::MAdd"; case MipsISD::MAddu: return "MipsISD::MAddu"; case MipsISD::MSub: return "MipsISD::MSub"; Index: llvm/lib/Target/Mips/MipsInstrInfo.td =================================================================== --- llvm/lib/Target/Mips/MipsInstrInfo.td +++ llvm/lib/Target/Mips/MipsInstrInfo.td @@ -30,7 +30,7 @@ def SDT_MipsMAddMSub : SDTypeProfile<1, 3, [SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; -def SDT_MipsDivRem16 : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>; +def SDT_MipsMultDiv16 : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>; def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; @@ -100,8 +100,10 @@ def MipsMTLOHI : SDNode<"MipsISD::MTLOHI", SDT_MTLOHI>; // Mult nodes. -def MipsMult : SDNode<"MipsISD::Mult", SDT_MipsMultDiv>; -def MipsMultu : SDNode<"MipsISD::Multu", SDT_MipsMultDiv>; +def MipsMult : SDNode<"MipsISD::Mult", SDT_MipsMultDiv>; +def MipsMultu : SDNode<"MipsISD::Multu", SDT_MipsMultDiv>; +def MipsMult16 : SDNode<"MipsISD::Mult16", SDT_MipsMultDiv16>; +def MipsMultu16 : SDNode<"MipsISD::Multu16", SDT_MipsMultDiv16>; // MAdd*/MSub* nodes def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub>; @@ -112,9 +114,9 @@ // DivRem(u) nodes def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsMultDiv>; def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsMultDiv>; -def MipsDivRem16 : SDNode<"MipsISD::DivRem16", SDT_MipsDivRem16, +def MipsDivRem16 : SDNode<"MipsISD::DivRem16", SDT_MipsMultDiv16, [SDNPOutGlue]>; -def MipsDivRemU16 : SDNode<"MipsISD::DivRemU16", SDT_MipsDivRem16, +def MipsDivRemU16 : SDNode<"MipsISD::DivRemU16", SDT_MipsMultDiv16, [SDNPOutGlue]>; // Target constant nodes that are not part of any isel patterns and remain Index: llvm/lib/Target/Mips/MipsScheduleGeneric.td =================================================================== --- llvm/lib/Target/Mips/MipsScheduleGeneric.td +++ llvm/lib/Target/Mips/MipsScheduleGeneric.td @@ -203,8 +203,7 @@ // MIPS16e // ======= -def : InstRW<[GenericWriteHILO], (instrs MultRxRy16, MultuRxRy16, - MultRxRyRz16, MultuRxRyRz16)>; +def : InstRW<[GenericWriteHILO], (instrs MultRxRy16, MultuRxRy16)>; def : InstRW<[GenericWriteDIV], (instrs DivRxRy16)>;