1//===-- RISCVInstrInfoM.td - RISC-V 'M' instructions -------*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file describes the RISC-V instructions from the standard 'M', Integer 10// Multiplication and Division instruction set extension. 11// 12//===----------------------------------------------------------------------===// 13 14//===----------------------------------------------------------------------===// 15// RISC-V specific DAG Nodes. 16//===----------------------------------------------------------------------===// 17 18def riscv_divw : SDNode<"RISCVISD::DIVW", SDTIntBinOp>; 19def riscv_divuw : SDNode<"RISCVISD::DIVUW", SDTIntBinOp>; 20def riscv_remuw : SDNode<"RISCVISD::REMUW", SDTIntBinOp>; 21 22//===----------------------------------------------------------------------===// 23// Instructions 24//===----------------------------------------------------------------------===// 25 26let Predicates = [HasStdExtM] in { 27def MUL : ALU_rr<0b0000001, 0b000, "mul">, 28 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 29def MULH : ALU_rr<0b0000001, 0b001, "mulh">, 30 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 31def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">, 32 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 33def MULHU : ALU_rr<0b0000001, 0b011, "mulhu">, 34 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 35def DIV : ALU_rr<0b0000001, 0b100, "div">, 36 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 37def DIVU : ALU_rr<0b0000001, 0b101, "divu">, 38 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 39def REM : ALU_rr<0b0000001, 0b110, "rem">, 40 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 41def REMU : ALU_rr<0b0000001, 0b111, "remu">, 42 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 43} // Predicates = [HasStdExtM] 44 45let Predicates = [HasStdExtM, IsRV64] in { 46def MULW : ALUW_rr<0b0000001, 0b000, "mulw">, 47 Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>; 48def DIVW : ALUW_rr<0b0000001, 0b100, "divw">, 49 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 50def DIVUW : ALUW_rr<0b0000001, 0b101, "divuw">, 51 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 52def REMW : ALUW_rr<0b0000001, 0b110, "remw">, 53 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 54def REMUW : ALUW_rr<0b0000001, 0b111, "remuw">, 55 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 56} // Predicates = [HasStdExtM, IsRV64] 57 58//===----------------------------------------------------------------------===// 59// Pseudo-instructions and codegen patterns 60//===----------------------------------------------------------------------===// 61 62let Predicates = [HasStdExtM] in { 63def : PatGprGpr<mul, MUL>; 64def : PatGprGpr<mulhs, MULH>; 65def : PatGprGpr<mulhu, MULHU>; 66// No ISDOpcode for mulhsu 67def : PatGprGpr<sdiv, DIV>; 68def : PatGprGpr<udiv, DIVU>; 69def : PatGprGpr<srem, REM>; 70def : PatGprGpr<urem, REMU>; 71} // Predicates = [HasStdExtM] 72 73let Predicates = [HasStdExtM, IsRV64] in { 74def : Pat<(sext_inreg (mul GPR:$rs1, GPR:$rs2), i32), 75 (MULW GPR:$rs1, GPR:$rs2)>; 76 77def : PatGprGpr<riscv_divw, DIVW>; 78def : PatGprGpr<riscv_divuw, DIVUW>; 79def : PatGprGpr<riscv_remuw, REMUW>; 80 81// Handle the specific cases where using DIVU/REMU would be correct and result 82// in fewer instructions than emitting DIVUW/REMUW then zero-extending the 83// result. 84def : Pat<(and (riscv_divuw (assertzexti32 GPR:$rs1), 85 (assertzexti32 GPR:$rs2)), 0xffffffff), 86 (DIVU GPR:$rs1, GPR:$rs2)>; 87def : Pat<(and (riscv_remuw (assertzexti32 GPR:$rs1), 88 (assertzexti32 GPR:$rs2)), 0xffffffff), 89 (REMU GPR:$rs1, GPR:$rs2)>; 90 91// Although the sexti32 operands may not have originated from an i32 srem, 92// this pattern is safe as it is impossible for two sign extended inputs to 93// produce a result where res[63:32]=0 and res[31]=1. 94def : Pat<(srem (sexti32 GPR:$rs1), (sexti32 GPR:$rs2)), 95 (REMW GPR:$rs1, GPR:$rs2)>; 96def : Pat<(sext_inreg (srem (sexti32 GPR:$rs1), 97 (sexti32 GPR:$rs2)), i32), 98 (REMW GPR:$rs1, GPR:$rs2)>; 99} // Predicates = [HasStdExtM, IsRV64] 100