xref: /llvm-project/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td (revision e9eec14bb3566f6578950797559de98678f16985)
1// LoongArchFloat32InstrInfo.td - Single-Precision Float instr --*- 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 baisc single-precision floating-point instructions.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// LoongArch specific DAG Nodes.
15//===----------------------------------------------------------------------===//
16
17def SDT_LoongArchMOVGR2FR_W_LA64
18    : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;
19def SDT_LoongArchMOVFR2GR_S_LA64
20    : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>;
21def SDT_LoongArchFTINT : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>;
22def SDT_LoongArchFRECIPE : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>;
23def SDT_LoongArchFRSQRTE : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>;
24
25def loongarch_movgr2fr_w_la64
26    : SDNode<"LoongArchISD::MOVGR2FR_W_LA64", SDT_LoongArchMOVGR2FR_W_LA64>;
27def loongarch_movfr2gr_s_la64
28    : SDNode<"LoongArchISD::MOVFR2GR_S_LA64", SDT_LoongArchMOVFR2GR_S_LA64>;
29def loongarch_ftint : SDNode<"LoongArchISD::FTINT", SDT_LoongArchFTINT>;
30def loongarch_frecipe : SDNode<"LoongArchISD::FRECIPE", SDT_LoongArchFRECIPE>;
31def loongarch_frsqrte : SDNode<"LoongArchISD::FRSQRTE", SDT_LoongArchFRSQRTE>;
32
33//===----------------------------------------------------------------------===//
34// Instructions
35//===----------------------------------------------------------------------===//
36
37let Predicates = [HasBasicF] in {
38
39// Arithmetic Operation Instructions
40def FADD_S : FP_ALU_3R<0x01008000>;
41def FSUB_S : FP_ALU_3R<0x01028000>;
42def FMUL_S : FP_ALU_3R<0x01048000>;
43def FDIV_S : FP_ALU_3R<0x01068000>;
44def FMADD_S  : FP_ALU_4R<0x08100000>;
45def FMSUB_S  : FP_ALU_4R<0x08500000>;
46def FNMADD_S : FP_ALU_4R<0x08900000>;
47def FNMSUB_S : FP_ALU_4R<0x08d00000>;
48def FMAX_S  : FP_ALU_3R<0x01088000>;
49def FMIN_S  : FP_ALU_3R<0x010a8000>;
50def FMAXA_S : FP_ALU_3R<0x010c8000>;
51def FMINA_S : FP_ALU_3R<0x010e8000>;
52def FABS_S   : FP_ALU_2R<0x01140400>;
53def FNEG_S   : FP_ALU_2R<0x01141400>;
54def FSQRT_S  : FP_ALU_2R<0x01144400>;
55def FRECIP_S : FP_ALU_2R<0x01145400>;
56def FRSQRT_S : FP_ALU_2R<0x01146400>;
57def FRECIPE_S : FP_ALU_2R<0x01147400>;
58def FRSQRTE_S : FP_ALU_2R<0x01148400>;
59def FSCALEB_S : FP_ALU_3R<0x01108000>;
60def FLOGB_S   : FP_ALU_2R<0x01142400>;
61def FCOPYSIGN_S : FP_ALU_3R<0x01128000>;
62def FCLASS_S  : FP_ALU_2R<0x01143400>;
63
64
65// Comparison Instructions
66def FCMP_CAF_S  : FP_CMP<0x0c100000>;
67def FCMP_CUN_S  : FP_CMP<0x0c140000>;
68def FCMP_CEQ_S  : FP_CMP<0x0c120000>;
69def FCMP_CUEQ_S : FP_CMP<0x0c160000>;
70def FCMP_CLT_S  : FP_CMP<0x0c110000>;
71def FCMP_CULT_S : FP_CMP<0x0c150000>;
72def FCMP_CLE_S  : FP_CMP<0x0c130000>;
73def FCMP_CULE_S : FP_CMP<0x0c170000>;
74def FCMP_CNE_S  : FP_CMP<0x0c180000>;
75def FCMP_COR_S  : FP_CMP<0x0c1a0000>;
76def FCMP_CUNE_S : FP_CMP<0x0c1c0000>;
77def FCMP_SAF_S  : FP_CMP<0x0c108000>;
78def FCMP_SUN_S  : FP_CMP<0x0c148000>;
79def FCMP_SEQ_S  : FP_CMP<0x0c128000>;
80def FCMP_SUEQ_S : FP_CMP<0x0c168000>;
81def FCMP_SLT_S  : FP_CMP<0x0c118000>;
82def FCMP_SULT_S : FP_CMP<0x0c158000>;
83def FCMP_SLE_S  : FP_CMP<0x0c138000>;
84def FCMP_SULE_S : FP_CMP<0x0c178000>;
85def FCMP_SNE_S  : FP_CMP<0x0c188000>;
86def FCMP_SOR_S  : FP_CMP<0x0c1a8000>;
87def FCMP_SUNE_S : FP_CMP<0x0c1c8000>;
88
89// Conversion Instructions
90def FFINT_S_W    : FP_CONV<0x011d1000>;
91def FTINT_W_S    : FP_CONV<0x011b0400>;
92def FTINTRM_W_S  : FP_CONV<0x011a0400>;
93def FTINTRP_W_S  : FP_CONV<0x011a4400>;
94def FTINTRZ_W_S  : FP_CONV<0x011a8400>;
95def FTINTRNE_W_S : FP_CONV<0x011ac400>;
96def FRINT_S      : FP_CONV<0x011e4400>;
97
98// Move Instructions
99def FSEL_xS    : FP_SEL<0x0d000000>;
100def FMOV_S     : FP_MOV<0x01149400>;
101def MOVGR2FR_W : FP_MOV<0x0114a400, FPR32, GPR>;
102def MOVFR2GR_S : FP_MOV<0x0114b400, GPR, FPR32>;
103let hasSideEffects = 1 in {
104def MOVGR2FCSR : FP_MOV<0x0114c000, FCSR, GPR>;
105def MOVFCSR2GR : FP_MOV<0x0114c800, GPR, FCSR>;
106} // hasSideEffects = 1
107def MOVFR2CF_xS : FP_MOV<0x0114d000, CFR, FPR32>;
108def MOVCF2FR_xS : FP_MOV<0x0114d400, FPR32, CFR>;
109def MOVGR2CF    : FP_MOV<0x0114d800, CFR, GPR>;
110def MOVCF2GR    : FP_MOV<0x0114dc00, GPR, CFR>;
111
112// Branch Instructions
113def BCEQZ : FP_BRANCH<0x48000000>;
114def BCNEZ : FP_BRANCH<0x48000100>;
115
116// Common Memory Access Instructions
117def FLD_S : FP_LOAD_2RI12<0x2b000000>;
118def FST_S : FP_STORE_2RI12<0x2b400000>;
119def FLDX_S : FP_LOAD_3R<0x38300000>;
120def FSTX_S : FP_STORE_3R<0x38380000>;
121
122// Bound Check Memory Access Instructions
123def FLDGT_S : FP_LOAD_3R<0x38740000>;
124def FLDLE_S : FP_LOAD_3R<0x38750000>;
125def FSTGT_S : FP_STORE_3R<0x38760000>;
126def FSTLE_S : FP_STORE_3R<0x38770000>;
127
128// Pseudo instructions for spill/reload CFRs.
129let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
130def PseudoST_CFR : Pseudo<(outs),
131                          (ins CFR:$ccd, GPR:$rj, grlenimm:$imm)>;
132let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
133def PseudoLD_CFR : Pseudo<(outs CFR:$ccd),
134                          (ins GPR:$rj, grlenimm:$imm)>;
135
136// SET_CFR_{FALSE,TRUE}
137// These instructions are defined in order to avoid expensive check error if
138// regular instruction patterns are used.
139// fcmp.caf.s $dst, $fa0, $fa0
140def SET_CFR_FALSE : SET_CFR<0x0c100000, "fcmp.caf.s">;
141// fcmp.cueq.s $dst, $fa0, $fa0
142def SET_CFR_TRUE  : SET_CFR<0x0c160000, "fcmp.cueq.s">;
143
144// Pseudo instruction for copying CFRs.
145def PseudoCopyCFR : Pseudo<(outs CFR:$dst), (ins CFR:$src)> {
146  let mayLoad = 0;
147  let mayStore = 0;
148  let hasSideEffects = 0;
149  let Size = 12;
150}
151
152} // Predicates = [HasBasicF]
153
154//===----------------------------------------------------------------------===//
155// Pseudo-instructions and codegen patterns
156//===----------------------------------------------------------------------===//
157
158/// Generic pattern classes
159
160class PatFpr<SDPatternOperator OpNode, LAInst Inst, RegisterClass RegTy>
161    : Pat<(OpNode RegTy:$fj), (Inst $fj)>;
162class PatFprFpr<SDPatternOperator OpNode, LAInst Inst, RegisterClass RegTy>
163    : Pat<(OpNode RegTy:$fj, RegTy:$fk), (Inst $fj, $fk)>;
164
165let Predicates = [HasBasicF] in {
166
167/// Float arithmetic operations
168
169def : PatFprFpr<fadd, FADD_S, FPR32>;
170def : PatFprFpr<fsub, FSUB_S, FPR32>;
171def : PatFprFpr<fmul, FMUL_S, FPR32>;
172def : PatFprFpr<fdiv, FDIV_S, FPR32>;
173def : PatFprFpr<fcopysign, FCOPYSIGN_S, FPR32>;
174def : PatFprFpr<fmaxnum_ieee, FMAX_S, FPR32>;
175def : PatFprFpr<fminnum_ieee, FMIN_S, FPR32>;
176def : PatFpr<fneg, FNEG_S, FPR32>;
177def : PatFpr<fabs, FABS_S, FPR32>;
178def : PatFpr<fsqrt, FSQRT_S, FPR32>;
179def : Pat<(fdiv fpimm1, (fsqrt FPR32:$fj)), (FRSQRT_S FPR32:$fj)>;
180def : Pat<(fcanonicalize FPR32:$fj), (FMAX_S $fj, $fj)>;
181def : Pat<(is_fpclass FPR32:$fj, (i32 timm:$mask)),
182          (SLTU R0, (ANDI (MOVFR2GR_S (FCLASS_S FPR32:$fj)),
183                          (to_fclass_mask timm:$mask)))>;
184
185/// Setcc
186
187// Match non-signaling comparison
188
189class PatFPSetcc<CondCode cc, LAInst CmpInst, RegisterClass RegTy>
190    : Pat<(any_fsetcc RegTy:$fj, RegTy:$fk, cc),
191          (CmpInst RegTy:$fj, RegTy:$fk)>;
192// SETOGT/SETOGE/SETUGT/SETUGE/SETGE/SETNE/SETGT will expand into
193// SETOLT/SETOLE/SETULT/SETULE/SETLE/SETEQ/SETLT.
194def : PatFPSetcc<SETOEQ, FCMP_CEQ_S,  FPR32>;
195def : PatFPSetcc<SETEQ,  FCMP_CEQ_S,  FPR32>;
196def : PatFPSetcc<SETOLT, FCMP_CLT_S,  FPR32>;
197def : PatFPSetcc<SETOLE, FCMP_CLE_S,  FPR32>;
198def : PatFPSetcc<SETLE,  FCMP_CLE_S,  FPR32>;
199def : PatFPSetcc<SETONE, FCMP_CNE_S,  FPR32>;
200def : PatFPSetcc<SETO,   FCMP_COR_S,  FPR32>;
201def : PatFPSetcc<SETUEQ, FCMP_CUEQ_S, FPR32>;
202def : PatFPSetcc<SETULT, FCMP_CULT_S, FPR32>;
203def : PatFPSetcc<SETULE, FCMP_CULE_S, FPR32>;
204def : PatFPSetcc<SETUNE, FCMP_CUNE_S, FPR32>;
205def : PatFPSetcc<SETUO,  FCMP_CUN_S,  FPR32>;
206def : PatFPSetcc<SETLT,  FCMP_CLT_S,  FPR32>;
207
208multiclass PatFPBrcond<CondCode cc, LAInst CmpInst, RegisterClass RegTy> {
209  def : Pat<(brcond (xor (GRLenVT (setcc RegTy:$fj, RegTy:$fk, cc)), -1),
210                     bb:$imm21),
211            (BCEQZ (CmpInst RegTy:$fj, RegTy:$fk), bb:$imm21)>;
212  def : Pat<(brcond (GRLenVT (setcc RegTy:$fj, RegTy:$fk, cc)), bb:$imm21),
213            (BCNEZ (CmpInst RegTy:$fj, RegTy:$fk), bb:$imm21)>;
214}
215
216defm : PatFPBrcond<SETOEQ, FCMP_CEQ_S, FPR32>;
217defm : PatFPBrcond<SETOLT, FCMP_CLT_S, FPR32>;
218defm : PatFPBrcond<SETOLE, FCMP_CLE_S, FPR32>;
219defm : PatFPBrcond<SETONE, FCMP_CNE_S, FPR32>;
220defm : PatFPBrcond<SETO,   FCMP_COR_S, FPR32>;
221defm : PatFPBrcond<SETUEQ, FCMP_CUEQ_S, FPR32>;
222defm : PatFPBrcond<SETULT, FCMP_CULT_S, FPR32>;
223defm : PatFPBrcond<SETULE, FCMP_CULE_S, FPR32>;
224defm : PatFPBrcond<SETUNE, FCMP_CUNE_S, FPR32>;
225defm : PatFPBrcond<SETUO,  FCMP_CUN_S, FPR32>;
226defm : PatFPBrcond<SETLT,  FCMP_CLT_S, FPR32>;
227
228// Match signaling comparison
229
230class PatStrictFsetccs<CondCode cc, LAInst CmpInst, RegisterClass RegTy>
231    : Pat<(strict_fsetccs RegTy:$fj, RegTy:$fk, cc),
232          (CmpInst RegTy:$fj, RegTy:$fk)>;
233def : PatStrictFsetccs<SETOEQ, FCMP_SEQ_S,  FPR32>;
234def : PatStrictFsetccs<SETOLT, FCMP_SLT_S,  FPR32>;
235def : PatStrictFsetccs<SETOLE, FCMP_SLE_S,  FPR32>;
236def : PatStrictFsetccs<SETONE, FCMP_SNE_S,  FPR32>;
237def : PatStrictFsetccs<SETO,   FCMP_SOR_S,  FPR32>;
238def : PatStrictFsetccs<SETUEQ, FCMP_SUEQ_S, FPR32>;
239def : PatStrictFsetccs<SETULT, FCMP_SULT_S, FPR32>;
240def : PatStrictFsetccs<SETULE, FCMP_SULE_S, FPR32>;
241def : PatStrictFsetccs<SETUNE, FCMP_SUNE_S, FPR32>;
242def : PatStrictFsetccs<SETUO,  FCMP_SUN_S,  FPR32>;
243def : PatStrictFsetccs<SETLT,  FCMP_SLT_S,  FPR32>;
244
245/// Select
246
247def : Pat<(select CFR:$cc, FPR32:$fk, FPR32:$fj),
248          (FSEL_xS FPR32:$fj, FPR32:$fk, CFR:$cc)>;
249
250/// Selectcc
251
252class PatFPSelectcc<CondCode cc, LAInst CmpInst, LAInst SelInst,
253                    RegisterClass RegTy>
254    : Pat<(select (GRLenVT (setcc RegTy:$a, RegTy:$b, cc)), RegTy:$t, RegTy:$f),
255          (SelInst RegTy:$f, RegTy:$t, (CmpInst RegTy:$a, RegTy:$b))>;
256def : PatFPSelectcc<SETOEQ, FCMP_CEQ_S,  FSEL_xS, FPR32>;
257def : PatFPSelectcc<SETOLT, FCMP_CLT_S,  FSEL_xS, FPR32>;
258def : PatFPSelectcc<SETOLE, FCMP_CLE_S,  FSEL_xS, FPR32>;
259def : PatFPSelectcc<SETONE, FCMP_CNE_S,  FSEL_xS, FPR32>;
260def : PatFPSelectcc<SETO,   FCMP_COR_S,  FSEL_xS, FPR32>;
261def : PatFPSelectcc<SETUEQ, FCMP_CUEQ_S, FSEL_xS, FPR32>;
262def : PatFPSelectcc<SETULT, FCMP_CULT_S, FSEL_xS, FPR32>;
263def : PatFPSelectcc<SETULE, FCMP_CULE_S, FSEL_xS, FPR32>;
264def : PatFPSelectcc<SETUNE, FCMP_CUNE_S, FSEL_xS, FPR32>;
265def : PatFPSelectcc<SETUO,  FCMP_CUN_S,  FSEL_xS, FPR32>;
266
267/// Loads
268
269defm : LdPat<load, FLD_S, f32>;
270def : RegRegLdPat<load, FLDX_S, f32>;
271
272/// Stores
273
274defm : StPat<store, FST_S, FPR32, f32>;
275def : RegRegStPat<store, FSTX_S, FPR32, f32>;
276
277/// Floating point constants
278
279def : Pat<(f32 fpimm0), (MOVGR2FR_W R0)>;
280def : Pat<(f32 fpimm0neg), (FNEG_S (MOVGR2FR_W R0))>;
281def : Pat<(f32 fpimm1), (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1)))>;
282
283// FP Conversion
284def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_W_S FPR32:$src)>;
285
286// FP reciprocal operation
287def : Pat<(fdiv fpimm1, FPR32:$src), (FRECIP_S $src)>;
288
289let Predicates = [HasFrecipe] in {
290// FP approximate reciprocal operation
291def : Pat<(int_loongarch_frecipe_s FPR32:$src), (FRECIPE_S FPR32:$src)>;
292def : Pat<(int_loongarch_frsqrte_s FPR32:$src), (FRSQRTE_S FPR32:$src)>;
293def : Pat<(loongarch_frecipe FPR32:$src), (FRECIPE_S FPR32:$src)>;
294def : Pat<(loongarch_frsqrte FPR32:$src), (FRSQRTE_S FPR32:$src)>;
295}
296
297// fmadd.s: fj * fk + fa
298def : Pat<(fma FPR32:$fj, FPR32:$fk, FPR32:$fa), (FMADD_S $fj, $fk, $fa)>;
299
300// fmsub.s: fj * fk - fa
301def : Pat<(fma FPR32:$fj, FPR32:$fk, (fneg FPR32:$fa)),
302          (FMSUB_S FPR32:$fj, FPR32:$fk, FPR32:$fa)>;
303
304// fnmadd.s: -(fj * fk + fa)
305def : Pat<(fneg (fma FPR32:$fj, FPR32:$fk, FPR32:$fa)),
306          (FNMADD_S FPR32:$fj, FPR32:$fk, FPR32:$fa)>;
307
308// fnmadd.s: -fj * fk - fa (the nsz flag on the FMA)
309def : Pat<(fma_nsz (fneg FPR32:$fj), FPR32:$fk, (fneg FPR32:$fa)),
310          (FNMADD_S FPR32:$fj, FPR32:$fk, FPR32:$fa)>;
311
312// fnmsub.s: -(fj * fk - fa)
313def : Pat<(fneg (fma FPR32:$fj, FPR32:$fk, (fneg FPR32:$fa))),
314          (FNMSUB_S FPR32:$fj, FPR32:$fk, FPR32:$fa)>;
315
316// fnmsub.s: -fj * fk + fa (the nsz flag on the FMA)
317def : Pat<(fma_nsz (fneg FPR32:$fj), FPR32:$fk, FPR32:$fa),
318          (FNMSUB_S FPR32:$fj, FPR32:$fk, FPR32:$fa)>;
319} // Predicates = [HasBasicF]
320
321let Predicates = [HasBasicF, IsLA64] in {
322// GPR -> FPR
323def : Pat<(loongarch_movgr2fr_w_la64 GPR:$src), (MOVGR2FR_W GPR:$src)>;
324// FPR -> GPR
325def : Pat<(loongarch_movfr2gr_s_la64 FPR32:$src),
326          (MOVFR2GR_S FPR32:$src)>;
327// int -> f32
328def : Pat<(f32 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
329          (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
330// uint -> f32
331def : Pat<(f32 (uint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
332          (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
333} // Predicates = [HasBasicF, IsLA64]
334
335// FP Rounding
336let Predicates = [HasBasicF, IsLA64] in {
337def : PatFpr<frint, FRINT_S, FPR32>;
338} // Predicates = [HasBasicF, IsLA64]
339
340let Predicates = [HasBasicF, IsLA32] in {
341// GPR -> FPR
342def : Pat<(bitconvert (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>;
343// FPR -> GPR
344def : Pat<(i32 (bitconvert FPR32:$src)), (MOVFR2GR_S FPR32:$src)>;
345// int -> f32
346def : Pat<(f32 (sint_to_fp (i32 GPR:$src))), (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
347} // Predicates = [HasBasicF, IsLA32]
348