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