xref: /llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td (revision 261d4bbb3bb847b90b9734daefe13618dea91613)
1//===-- RISCVInstrInfoZfa.td - RISC-V 'Zfa' 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 'Zfa'
10// additional floating-point extension, version 1.0.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// RISC-V specific DAG Nodes.
16//===----------------------------------------------------------------------===//
17
18def SDT_RISCVFLI
19    : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, XLenVT>]>;
20
21def riscv_fli : SDNode<"RISCVISD::FLI", SDT_RISCVFLI>;
22
23//===----------------------------------------------------------------------===//
24// Operand and SDNode transformation definitions.
25//===----------------------------------------------------------------------===//
26
27// 5-bit floating-point immediate encodings.
28def LoadFPImmOperand : AsmOperandClass {
29  let Name = "LoadFPImm";
30  let ParserMethod = "parseFPImm";
31  let RenderMethod = "addFPImmOperands";
32  let DiagnosticType = "InvalidLoadFPImm";
33}
34
35def loadfpimm : Operand<XLenVT> {
36  let ParserMatchClass = LoadFPImmOperand;
37  let PrintMethod = "printFPImmOperand";
38  let OperandType = "OPERAND_UIMM5";
39  let OperandNamespace = "RISCVOp";
40}
41
42def RTZArg : AsmOperandClass {
43  let Name = "RTZArg";
44  let RenderMethod = "addFRMArgOperands";
45  let DiagnosticType = "InvalidRTZArg";
46  let ParserMethod = "parseFRMArg";
47}
48
49def rtzarg : Operand<XLenVT> {
50  let ParserMatchClass = RTZArg;
51  let PrintMethod = "printFRMArg";
52  let DecoderMethod = "decodeRTZArg";
53  let OperandType = "OPERAND_RTZARG";
54  let OperandNamespace = "RISCVOp";
55}
56
57//===----------------------------------------------------------------------===//
58// Instruction class templates
59//===----------------------------------------------------------------------===//
60
61let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
62class FPBinaryOp_rr<bits<7> funct7, bits<3> funct3, DAGOperand rdty,
63                    DAGOperand rsty, string opcodestr>
64    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd),
65              (ins rsty:$rs1, rsty:$rs2), opcodestr, "$rd, $rs1, $rs2">;
66
67let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
68class FPFLI_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
69              DAGOperand rdty, string opcodestr>
70    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd),
71              (ins loadfpimm:$imm), opcodestr, "$rd, $imm"> {
72  bits<5> imm;
73
74  let rs2 = rs2val;
75  let rs1 = imm;
76}
77
78let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
79    UseNamedOperandTable = 1, hasPostISelHook = 1 in
80class FPUnaryOp_r_rtz<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
81                      DAGOperand rs1ty, string opcodestr>
82    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
83                 (ins rs1ty:$rs1, rtzarg:$frm), opcodestr,
84                  "$rd, $rs1$frm"> {
85  let rs2 = rs2val;
86}
87
88//===----------------------------------------------------------------------===//
89// Instructions
90//===----------------------------------------------------------------------===//
91
92let Predicates = [HasStdExtZfa] in {
93let isReMaterializable = 1, isAsCheapAsAMove = 1 in
94def FLI_S : FPFLI_r<0b1111000, 0b00001, 0b000, FPR32, "fli.s">,
95            Sched<[WriteFLI32]>;
96
97let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
98def FMINM_S: FPALU_rr<0b0010100, 0b010, "fminm.s", FPR32, Commutable=1>;
99def FMAXM_S: FPALU_rr<0b0010100, 0b011, "fmaxm.s", FPR32, Commutable=1>;
100}
101
102def FROUND_S : FPUnaryOp_r_frm<0b0100000, 0b00100, FPR32, FPR32, "fround.s">,
103               Sched<[WriteFRoundF32, ReadFRoundF32]>;
104def FROUNDNX_S : FPUnaryOp_r_frm<0b0100000, 0b00101, FPR32, FPR32, "froundnx.s">,
105                 Sched<[WriteFRoundF32, ReadFRoundF32]>;
106
107let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
108def FLTQ_S : FPCmp_rr<0b1010000, 0b101, "fltq.s", FPR32>;
109def FLEQ_S : FPCmp_rr<0b1010000, 0b100, "fleq.s", FPR32>;
110}
111} // Predicates = [HasStdExtZfa]
112
113let Predicates = [HasStdExtZfa, HasStdExtD] in {
114let isReMaterializable = 1, isAsCheapAsAMove = 1 in
115def FLI_D : FPFLI_r<0b1111001, 0b00001, 0b000, FPR64, "fli.d">,
116            Sched<[WriteFLI64]>;
117
118let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in {
119def FMINM_D: FPALU_rr<0b0010101, 0b010, "fminm.d", FPR64, Commutable=1>;
120def FMAXM_D: FPALU_rr<0b0010101, 0b011, "fmaxm.d", FPR64, Commutable=1>;
121}
122
123def FROUND_D : FPUnaryOp_r_frm<0b0100001, 0b00100, FPR64, FPR64, "fround.d">,
124               Sched<[WriteFRoundF64, ReadFRoundF64]>;
125def FROUNDNX_D : FPUnaryOp_r_frm<0b0100001, 0b00101, FPR64, FPR64, "froundnx.d">,
126                 Sched<[WriteFRoundF64, ReadFRoundF64]>;
127
128let IsSignExtendingOpW = 1 in
129def FCVTMOD_W_D
130    : FPUnaryOp_r_rtz<0b1100001, 0b01000, GPR, FPR64, "fcvtmod.w.d">,
131      Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
132
133let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in {
134def FLTQ_D : FPCmp_rr<0b1010001, 0b101, "fltq.d", FPR64>;
135def FLEQ_D : FPCmp_rr<0b1010001, 0b100, "fleq.d", FPR64>;
136}
137} // Predicates = [HasStdExtZfa, HasStdExtD]
138
139let Predicates = [HasStdExtZfa, HasStdExtD, IsRV32] in {
140let mayRaiseFPException = 0 in {
141def FMVH_X_D : FPUnaryOp_r<0b1110001, 0b00001, 0b000, GPR, FPR64, "fmvh.x.d">,
142               Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>;
143def FMVP_D_X : FPBinaryOp_rr<0b1011001, 0b000, FPR64, GPR, "fmvp.d.x">,
144               Sched<[WriteFMovI64ToF64, ReadFMovI64ToF64]>;
145}
146
147let isCodeGenOnly = 1, mayRaiseFPException = 0 in
148def FMV_X_W_FPR64 : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR64,
149                                "fmv.x.w">,
150                    Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>;
151} // Predicates = [HasStdExtZfa, HasStdExtD, IsRV32]
152
153let Predicates = [HasStdExtZfa, HasStdExtZfhOrZvfh] in
154let isReMaterializable = 1, isAsCheapAsAMove = 1 in
155def FLI_H : FPFLI_r<0b1111010, 0b00001, 0b000, FPR16, "fli.h">,
156            Sched<[WriteFLI16]>;
157
158let Predicates = [HasStdExtZfa, HasStdExtZfh] in {
159let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in {
160def FMINM_H: FPALU_rr<0b0010110, 0b010, "fminm.h", FPR16, Commutable=1>;
161def FMAXM_H: FPALU_rr<0b0010110, 0b011, "fmaxm.h", FPR16, Commutable=1>;
162}
163
164def FROUND_H : FPUnaryOp_r_frm<0b0100010, 0b00100, FPR16, FPR16, "fround.h">,
165               Sched<[WriteFRoundF16, ReadFRoundF16]>;
166def FROUNDNX_H : FPUnaryOp_r_frm<0b0100010, 0b00101, FPR16, FPR16, "froundnx.h">,
167                 Sched<[WriteFRoundF16, ReadFRoundF16]>;
168
169let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in {
170def FLTQ_H : FPCmp_rr<0b1010010, 0b101, "fltq.h", FPR16>;
171def FLEQ_H : FPCmp_rr<0b1010010, 0b100, "fleq.h", FPR16>;
172}
173} // Predicates = [HasStdExtZfa, HasStdExtZfh]
174
175//===----------------------------------------------------------------------===//
176// Pseudo-instructions and codegen patterns
177//===----------------------------------------------------------------------===//
178
179let Predicates = [HasStdExtZfa] in {
180def : InstAlias<"fgtq.s $rd, $rs, $rt",
181                (FLTQ_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
182def : InstAlias<"fgeq.s $rd, $rs, $rt",
183                (FLEQ_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
184}
185
186let Predicates = [HasStdExtZfa, HasStdExtD] in {
187def : InstAlias<"fgtq.d $rd, $rs, $rt",
188                (FLTQ_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>;
189def : InstAlias<"fgeq.d $rd, $rs, $rt",
190                (FLEQ_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>;
191}
192
193let Predicates = [HasStdExtZfa, HasStdExtZfh] in {
194def : InstAlias<"fgtq.h $rd, $rs, $rt",
195                (FLTQ_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>;
196def : InstAlias<"fgeq.h $rd, $rs, $rt",
197                (FLEQ_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>;
198}
199
200//===----------------------------------------------------------------------===//
201// Codegen patterns
202//===----------------------------------------------------------------------===//
203
204let Predicates = [HasStdExtZfa] in {
205def: Pat<(f32 (riscv_fli timm:$imm)), (FLI_S timm:$imm)>;
206
207def: PatFprFpr<fminimum, FMINM_S, FPR32, f32>;
208def: PatFprFpr<fmaximum, FMAXM_S, FPR32, f32>;
209
210// frint rounds according to the current rounding mode and detects
211// inexact conditions.
212def: Pat<(any_frint FPR32:$rs1), (FROUNDNX_S FPR32:$rs1, FRM_DYN)>;
213
214// fnearbyint is like frint but does not detect inexact conditions.
215def: Pat<(any_fnearbyint FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_DYN)>;
216
217def: Pat<(any_fround FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RMM)>;
218def: Pat<(any_froundeven FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RNE)>;
219def: Pat<(any_ffloor FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RDN)>;
220def: Pat<(any_fceil FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RUP)>;
221def: Pat<(any_ftrunc FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RTZ)>;
222
223def: PatSetCC<FPR32, strict_fsetcc, SETLT, FLTQ_S, f32>;
224def: PatSetCC<FPR32, strict_fsetcc, SETOLT, FLTQ_S, f32>;
225def: PatSetCC<FPR32, strict_fsetcc, SETLE, FLEQ_S, f32>;
226def: PatSetCC<FPR32, strict_fsetcc, SETOLE, FLEQ_S, f32>;
227} // Predicates = [HasStdExtZfa]
228
229let Predicates = [HasStdExtZfa, HasStdExtD] in {
230def: Pat<(f64 (riscv_fli timm:$imm)), (FLI_D timm:$imm)>;
231
232def: PatFprFpr<fminimum, FMINM_D, FPR64, f64>;
233def: PatFprFpr<fmaximum, FMAXM_D, FPR64, f64>;
234
235// frint rounds according to the current rounding mode and detects
236// inexact conditions.
237def: Pat<(any_frint FPR64:$rs1), (FROUNDNX_D FPR64:$rs1, FRM_DYN)>;
238
239// fnearbyint is like frint but does not detect inexact conditions.
240def: Pat<(any_fnearbyint FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_DYN)>;
241
242def: Pat<(any_fround FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RMM)>;
243def: Pat<(any_froundeven FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RNE)>;
244def: Pat<(any_ffloor FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RDN)>;
245def: Pat<(any_fceil FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RUP)>;
246def: Pat<(any_ftrunc FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RTZ)>;
247
248def: PatSetCC<FPR64, strict_fsetcc, SETLT, FLTQ_D, f64>;
249def: PatSetCC<FPR64, strict_fsetcc, SETOLT, FLTQ_D, f64>;
250def: PatSetCC<FPR64, strict_fsetcc, SETLE, FLEQ_D, f64>;
251def: PatSetCC<FPR64, strict_fsetcc, SETOLE, FLEQ_D, f64>;
252} // Predicates = [HasStdExtZfa, HasStdExtD]
253
254let Predicates = [HasStdExtZfa, HasStdExtD, IsRV32] in {
255def : Pat<(RISCVBuildPairF64 GPR:$rs1, GPR:$rs2),
256          (FMVP_D_X GPR:$rs1, GPR:$rs2)>;
257}
258
259let Predicates = [HasStdExtZfa, HasStdExtZfh] in {
260def: Pat<(f16 (riscv_fli timm:$imm)), (FLI_H timm:$imm)>;
261
262def: PatFprFpr<fminimum, FMINM_H, FPR16, f16>;
263def: PatFprFpr<fmaximum, FMAXM_H, FPR16, f16>;
264
265// frint rounds according to the current rounding mode and detects
266// inexact conditions.
267def: Pat<(f16 (any_frint FPR16:$rs1)), (FROUNDNX_H FPR16:$rs1, FRM_DYN)>;
268
269// fnearbyint is like frint but does not detect inexact conditions.
270def: Pat<(f16 (any_fnearbyint FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_DYN)>;
271
272def: Pat<(f16 (any_fround FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RMM)>;
273def: Pat<(f16 (any_froundeven FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RNE)>;
274def: Pat<(f16 (any_ffloor FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RDN)>;
275def: Pat<(f16 (any_fceil FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RUP)>;
276def: Pat<(f16 (any_ftrunc FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RTZ)>;
277
278def: PatSetCC<FPR16, strict_fsetcc, SETLT, FLTQ_H, f16>;
279def: PatSetCC<FPR16, strict_fsetcc, SETOLT, FLTQ_H, f16>;
280def: PatSetCC<FPR16, strict_fsetcc, SETLE, FLEQ_H, f16>;
281def: PatSetCC<FPR16, strict_fsetcc, SETOLE, FLEQ_H, f16>;
282} // Predicates = [HasStdExtZfa, HasStdExtZfh]
283