xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoM.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric//===-- RISCVInstrInfoM.td - RISC-V 'M' instructions -------*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the RISC-V instructions from the standard 'M', Integer
100b57cec5SDimitry Andric// Multiplication and Division instruction set extension.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric// RISC-V specific DAG Nodes.
160b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric
18fe6060f1SDimitry Andricdef riscv_mulhsu : SDNode<"RISCVISD::MULHSU", SDTIntBinOp>;
19fe6060f1SDimitry Andricdef riscv_divw  : SDNode<"RISCVISD::DIVW",  SDT_RISCVIntBinOpW>;
20fe6060f1SDimitry Andricdef riscv_divuw : SDNode<"RISCVISD::DIVUW", SDT_RISCVIntBinOpW>;
21fe6060f1SDimitry Andricdef riscv_remuw : SDNode<"RISCVISD::REMUW", SDT_RISCVIntBinOpW>;
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
240b57cec5SDimitry Andric// Instructions
250b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
260b57cec5SDimitry Andric
27*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul] in {
2806c3fb27SDimitry Andricdef MUL     : ALU_rr<0b0000001, 0b000, "mul", Commutable=1>,
2913138422SDimitry Andric              Sched<[WriteIMul, ReadIMul, ReadIMul]>;
3006c3fb27SDimitry Andricdef MULH    : ALU_rr<0b0000001, 0b001, "mulh", Commutable=1>,
3113138422SDimitry Andric              Sched<[WriteIMul, ReadIMul, ReadIMul]>;
3213138422SDimitry Andricdef MULHSU  : ALU_rr<0b0000001, 0b010, "mulhsu">,
3313138422SDimitry Andric              Sched<[WriteIMul, ReadIMul, ReadIMul]>;
3406c3fb27SDimitry Andricdef MULHU   : ALU_rr<0b0000001, 0b011, "mulhu", Commutable=1>,
3513138422SDimitry Andric              Sched<[WriteIMul, ReadIMul, ReadIMul]>;
36*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul]
37fcaf7f86SDimitry Andric
38fcaf7f86SDimitry Andriclet Predicates = [HasStdExtM] in {
3913138422SDimitry Andricdef DIV     : ALU_rr<0b0000001, 0b100, "div">,
4013138422SDimitry Andric              Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>;
4113138422SDimitry Andricdef DIVU    : ALU_rr<0b0000001, 0b101, "divu">,
4213138422SDimitry Andric              Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>;
4313138422SDimitry Andricdef REM     : ALU_rr<0b0000001, 0b110, "rem">,
44*0fca6ea1SDimitry Andric              Sched<[WriteIRem, ReadIRem, ReadIRem]>;
4513138422SDimitry Andricdef REMU    : ALU_rr<0b0000001, 0b111, "remu">,
46*0fca6ea1SDimitry Andric              Sched<[WriteIRem, ReadIRem, ReadIRem]>;
470b57cec5SDimitry Andric} // Predicates = [HasStdExtM]
480b57cec5SDimitry Andric
49*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64], IsSignExtendingOpW = 1 in {
5006c3fb27SDimitry Andricdef MULW    : ALUW_rr<0b0000001, 0b000, "mulw", Commutable=1>,
5113138422SDimitry Andric              Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>;
52*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul, IsRV64]
53fcaf7f86SDimitry Andric
54bdd1243dSDimitry Andriclet Predicates = [HasStdExtM, IsRV64], IsSignExtendingOpW = 1 in {
5513138422SDimitry Andricdef DIVW    : ALUW_rr<0b0000001, 0b100, "divw">,
5613138422SDimitry Andric              Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>;
5713138422SDimitry Andricdef DIVUW   : ALUW_rr<0b0000001, 0b101, "divuw">,
5813138422SDimitry Andric              Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>;
5913138422SDimitry Andricdef REMW    : ALUW_rr<0b0000001, 0b110, "remw">,
60*0fca6ea1SDimitry Andric              Sched<[WriteIRem32, ReadIRem32, ReadIRem32]>;
6113138422SDimitry Andricdef REMUW   : ALUW_rr<0b0000001, 0b111, "remuw">,
62*0fca6ea1SDimitry Andric              Sched<[WriteIRem32, ReadIRem32, ReadIRem32]>;
630b57cec5SDimitry Andric} // Predicates = [HasStdExtM, IsRV64]
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
660b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns
670b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
680b57cec5SDimitry Andric
69*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul] in {
700b57cec5SDimitry Andricdef : PatGprGpr<mul, MUL>;
710b57cec5SDimitry Andricdef : PatGprGpr<mulhs, MULH>;
720b57cec5SDimitry Andricdef : PatGprGpr<mulhu, MULHU>;
73fe6060f1SDimitry Andricdef : PatGprGpr<riscv_mulhsu, MULHSU>;
74*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul]
75fcaf7f86SDimitry Andric
76fcaf7f86SDimitry Andriclet Predicates = [HasStdExtM] in {
770b57cec5SDimitry Andricdef : PatGprGpr<sdiv, DIV>;
780b57cec5SDimitry Andricdef : PatGprGpr<udiv, DIVU>;
790b57cec5SDimitry Andricdef : PatGprGpr<srem, REM>;
800b57cec5SDimitry Andricdef : PatGprGpr<urem, REMU>;
810b57cec5SDimitry Andric} // Predicates = [HasStdExtM]
820b57cec5SDimitry Andric
83349cc55cSDimitry Andric// Select W instructions if only the lower 32-bits of the result are used.
84*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64] in
85349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<mul>, MULW>;
860b57cec5SDimitry Andric
87fcaf7f86SDimitry Andriclet Predicates = [HasStdExtM, IsRV64] in {
880b57cec5SDimitry Andricdef : PatGprGpr<riscv_divw, DIVW>;
890b57cec5SDimitry Andricdef : PatGprGpr<riscv_divuw, DIVUW>;
900b57cec5SDimitry Andricdef : PatGprGpr<riscv_remuw, REMUW>;
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric// Handle the specific cases where using DIVU/REMU would be correct and result
930b57cec5SDimitry Andric// in fewer instructions than emitting DIVUW/REMUW then zero-extending the
940b57cec5SDimitry Andric// result.
95e8d8bef9SDimitry Andricdef : Pat<(and (riscv_divuw (assertzexti32 GPR:$rs1),
96e8d8bef9SDimitry Andric                            (assertzexti32 GPR:$rs2)), 0xffffffff),
970b57cec5SDimitry Andric          (DIVU GPR:$rs1, GPR:$rs2)>;
98e8d8bef9SDimitry Andricdef : Pat<(and (riscv_remuw (assertzexti32 GPR:$rs1),
99e8d8bef9SDimitry Andric                            (assertzexti32 GPR:$rs2)), 0xffffffff),
1000b57cec5SDimitry Andric          (REMU GPR:$rs1, GPR:$rs2)>;
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric// Although the sexti32 operands may not have originated from an i32 srem,
1030b57cec5SDimitry Andric// this pattern is safe as it is impossible for two sign extended inputs to
1040b57cec5SDimitry Andric// produce a result where res[63:32]=0 and res[31]=1.
105fe6060f1SDimitry Andricdef : Pat<(srem (sexti32 (i64 GPR:$rs1)), (sexti32 (i64 GPR:$rs2))),
1060b57cec5SDimitry Andric          (REMW GPR:$rs1, GPR:$rs2)>;
1070b57cec5SDimitry Andric} // Predicates = [HasStdExtM, IsRV64]
108fe6060f1SDimitry Andric
109*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64, NotHasStdExtZba] in {
110fe6060f1SDimitry Andric// Special case for calculating the full 64-bit product of a 32x32 unsigned
111fe6060f1SDimitry Andric// multiply where the inputs aren't known to be zero extended. We can shift the
112fe6060f1SDimitry Andric// inputs left by 32 and use a MULHU. This saves two SRLIs needed to finish
113fe6060f1SDimitry Andric// zeroing the upper 32 bits.
114fe6060f1SDimitry Andricdef : Pat<(i64 (mul (and GPR:$rs1, 0xffffffff), (and GPR:$rs2, 0xffffffff))),
115*0fca6ea1SDimitry Andric          (MULHU (i64 (SLLI GPR:$rs1, 32)), (i64 (SLLI GPR:$rs2, 32)))>;
116*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul, IsRV64, NotHasStdExtZba]
1175f757f3fSDimitry Andric
1185f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1195f757f3fSDimitry Andric// Experimental RV64 i32 legalization patterns.
1205f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1215f757f3fSDimitry Andric
122*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64] in {
1235f757f3fSDimitry Andricdef : PatGprGpr<mul, MULW, i32, i32>;
1245f757f3fSDimitry Andric}
1255f757f3fSDimitry Andric
1265f757f3fSDimitry Andriclet Predicates = [HasStdExtM, IsRV64] in {
1275f757f3fSDimitry Andricdef : PatGprGpr<sdiv, DIVW, i32, i32>;
1285f757f3fSDimitry Andricdef : PatGprGpr<udiv, DIVUW, i32, i32>;
1295f757f3fSDimitry Andricdef : PatGprGpr<srem, REMW, i32, i32>;
1305f757f3fSDimitry Andricdef : PatGprGpr<urem, REMUW, i32, i32>;
1315f757f3fSDimitry Andric}
132