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">;
28def MULH    : ALU_rr<0b0000001, 0b001, "mulh">;
29def MULHSU  : ALU_rr<0b0000001, 0b010, "mulhsu">;
30def MULHU   : ALU_rr<0b0000001, 0b011, "mulhu">;
31def DIV     : ALU_rr<0b0000001, 0b100, "div">;
32def DIVU    : ALU_rr<0b0000001, 0b101, "divu">;
33def REM     : ALU_rr<0b0000001, 0b110, "rem">;
34def REMU    : ALU_rr<0b0000001, 0b111, "remu">;
35} // Predicates = [HasStdExtM]
36
37let Predicates = [HasStdExtM, IsRV64] in {
38def MULW    : ALUW_rr<0b0000001, 0b000, "mulw">;
39def DIVW    : ALUW_rr<0b0000001, 0b100, "divw">;
40def DIVUW   : ALUW_rr<0b0000001, 0b101, "divuw">;
41def REMW    : ALUW_rr<0b0000001, 0b110, "remw">;
42def REMUW   : ALUW_rr<0b0000001, 0b111, "remuw">;
43} // Predicates = [HasStdExtM, IsRV64]
44
45//===----------------------------------------------------------------------===//
46// Pseudo-instructions and codegen patterns
47//===----------------------------------------------------------------------===//
48
49let Predicates = [HasStdExtM] in {
50def : PatGprGpr<mul, MUL>;
51def : PatGprGpr<mulhs, MULH>;
52def : PatGprGpr<mulhu, MULHU>;
53// No ISDOpcode for mulhsu
54def : PatGprGpr<sdiv, DIV>;
55def : PatGprGpr<udiv, DIVU>;
56def : PatGprGpr<srem, REM>;
57def : PatGprGpr<urem, REMU>;
58} // Predicates = [HasStdExtM]
59
60let Predicates = [HasStdExtM, IsRV64] in {
61def : Pat<(sext_inreg (mul GPR:$rs1, GPR:$rs2), i32),
62          (MULW GPR:$rs1, GPR:$rs2)>;
63
64def : PatGprGpr<riscv_divw, DIVW>;
65def : PatGprGpr<riscv_divuw, DIVUW>;
66def : PatGprGpr<riscv_remuw, REMUW>;
67
68// Handle the specific cases where using DIVU/REMU would be correct and result
69// in fewer instructions than emitting DIVUW/REMUW then zero-extending the
70// result.
71def : Pat<(zexti32 (riscv_divuw (zexti32 GPR:$rs1), (zexti32 GPR:$rs2))),
72          (DIVU GPR:$rs1, GPR:$rs2)>;
73def : Pat<(zexti32 (riscv_remuw (zexti32 GPR:$rs1), (zexti32 GPR:$rs2))),
74          (REMU GPR:$rs1, GPR:$rs2)>;
75
76// Although the sexti32 operands may not have originated from an i32 srem,
77// this pattern is safe as it is impossible for two sign extended inputs to
78// produce a result where res[63:32]=0 and res[31]=1.
79def : Pat<(srem (sexti32 GPR:$rs1), (sexti32 GPR:$rs2)),
80          (REMW GPR:$rs1, GPR:$rs2)>;
81def : Pat<(sext_inreg (srem (sexti32 GPR:$rs1),
82                            (sexti32 GPR:$rs2)), i32),
83          (REMW GPR:$rs1, GPR:$rs2)>;
84} // Predicates = [HasStdExtM, IsRV64]
85