xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoM.td (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
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<(zexti32 (riscv_divuw (zexti32 GPR:$rs1), (zexti32 GPR:$rs2))),
85          (DIVU GPR:$rs1, GPR:$rs2)>;
86def : Pat<(zexti32 (riscv_remuw (zexti32 GPR:$rs1), (zexti32 GPR:$rs2))),
87          (REMU GPR:$rs1, GPR:$rs2)>;
88
89// Although the sexti32 operands may not have originated from an i32 srem,
90// this pattern is safe as it is impossible for two sign extended inputs to
91// produce a result where res[63:32]=0 and res[31]=1.
92def : Pat<(srem (sexti32 GPR:$rs1), (sexti32 GPR:$rs2)),
93          (REMW GPR:$rs1, GPR:$rs2)>;
94def : Pat<(sext_inreg (srem (sexti32 GPR:$rs1),
95                            (sexti32 GPR:$rs2)), i32),
96          (REMW GPR:$rs1, GPR:$rs2)>;
97} // Predicates = [HasStdExtM, IsRV64]
98