1 // LoongArchFloat64InstrInfo.td - Double-Precision Float instr --*- tablegen -*-
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
7 //===----------------------------------------------------------------------===//
9 // This file describes the basic double-precision floating-point instructions.
11 //===----------------------------------------------------------------------===//
13 //===----------------------------------------------------------------------===//
15 //===----------------------------------------------------------------------===//
17 let Predicates = [HasBasicD] in {
19 // Arithmetic Operation Instructions
20 def FADD_D : FP_ALU_3R<0x01010000, FPR64>;
21 def FSUB_D : FP_ALU_3R<0x01030000, FPR64>;
22 def FMUL_D : FP_ALU_3R<0x01050000, FPR64>;
23 def FDIV_D : FP_ALU_3R<0x01070000, FPR64>;
24 def FMADD_D : FP_ALU_4R<0x08200000, FPR64>;
25 def FMSUB_D : FP_ALU_4R<0x08600000, FPR64>;
26 def FNMADD_D : FP_ALU_4R<0x08a00000, FPR64>;
27 def FNMSUB_D : FP_ALU_4R<0x08e00000, FPR64>;
28 def FMAX_D : FP_ALU_3R<0x01090000, FPR64>;
29 def FMIN_D : FP_ALU_3R<0x010b0000, FPR64>;
30 def FMAXA_D : FP_ALU_3R<0x010d0000, FPR64>;
31 def FMINA_D : FP_ALU_3R<0x010f0000, FPR64>;
32 def FABS_D : FP_ALU_2R<0x01140800, FPR64>;
33 def FNEG_D : FP_ALU_2R<0x01141800, FPR64>;
34 def FSQRT_D : FP_ALU_2R<0x01144800, FPR64>;
35 def FRECIP_D : FP_ALU_2R<0x01145800, FPR64>;
36 def FRSQRT_D : FP_ALU_2R<0x01146800, FPR64>;
37 def FRECIPE_D : FP_ALU_2R<0x01147800, FPR64>;
38 def FRSQRTE_D : FP_ALU_2R<0x01148800, FPR64>;
39 def FSCALEB_D : FP_ALU_3R<0x01110000, FPR64>;
40 def FLOGB_D : FP_ALU_2R<0x01142800, FPR64>;
41 def FCOPYSIGN_D : FP_ALU_3R<0x01130000, FPR64>;
42 def FCLASS_D : FP_ALU_2R<0x01143800, FPR64>;
44 // Comparison Instructions
45 def FCMP_CAF_D : FP_CMP<0x0c200000, FPR64>;
46 def FCMP_CUN_D : FP_CMP<0x0c240000, FPR64>;
47 def FCMP_CEQ_D : FP_CMP<0x0c220000, FPR64>;
48 def FCMP_CUEQ_D : FP_CMP<0x0c260000, FPR64>;
49 def FCMP_CLT_D : FP_CMP<0x0c210000, FPR64>;
50 def FCMP_CULT_D : FP_CMP<0x0c250000, FPR64>;
51 def FCMP_CLE_D : FP_CMP<0x0c230000, FPR64>;
52 def FCMP_CULE_D : FP_CMP<0x0c270000, FPR64>;
53 def FCMP_CNE_D : FP_CMP<0x0c280000, FPR64>;
54 def FCMP_COR_D : FP_CMP<0x0c2a0000, FPR64>;
55 def FCMP_CUNE_D : FP_CMP<0x0c2c0000, FPR64>;
56 def FCMP_SAF_D : FP_CMP<0x0c208000, FPR64>;
57 def FCMP_SUN_D : FP_CMP<0x0c248000, FPR64>;
58 def FCMP_SEQ_D : FP_CMP<0x0c228000, FPR64>;
59 def FCMP_SUEQ_D : FP_CMP<0x0c268000, FPR64>;
60 def FCMP_SLT_D : FP_CMP<0x0c218000, FPR64>;
61 def FCMP_SULT_D : FP_CMP<0x0c258000, FPR64>;
62 def FCMP_SLE_D : FP_CMP<0x0c238000, FPR64>;
63 def FCMP_SULE_D : FP_CMP<0x0c278000, FPR64>;
64 def FCMP_SNE_D : FP_CMP<0x0c288000, FPR64>;
65 def FCMP_SOR_D : FP_CMP<0x0c2a8000, FPR64>;
66 def FCMP_SUNE_D : FP_CMP<0x0c2c8000, FPR64>;
68 // Conversion Instructions
69 def FFINT_S_L : FP_CONV<0x011d1800, FPR32, FPR64>;
70 def FTINT_L_S : FP_CONV<0x011b2400, FPR64, FPR32>;
71 def FTINTRM_L_S : FP_CONV<0x011a2400, FPR64, FPR32>;
72 def FTINTRP_L_S : FP_CONV<0x011a6400, FPR64, FPR32>;
73 def FTINTRZ_L_S : FP_CONV<0x011aa400, FPR64, FPR32>;
74 def FTINTRNE_L_S : FP_CONV<0x011ae400, FPR64, FPR32>;
75 def FCVT_S_D : FP_CONV<0x01191800, FPR32, FPR64>;
76 def FCVT_D_S : FP_CONV<0x01192400, FPR64, FPR32>;
77 def FFINT_D_W : FP_CONV<0x011d2000, FPR64, FPR32>;
78 def FFINT_D_L : FP_CONV<0x011d2800, FPR64, FPR64>;
79 def FTINT_W_D : FP_CONV<0x011b0800, FPR32, FPR64>;
80 def FTINT_L_D : FP_CONV<0x011b2800, FPR64, FPR64>;
81 def FTINTRM_W_D : FP_CONV<0x011a0800, FPR32, FPR64>;
82 def FTINTRM_L_D : FP_CONV<0x011a2800, FPR64, FPR64>;
83 def FTINTRP_W_D : FP_CONV<0x011a4800, FPR32, FPR64>;
84 def FTINTRP_L_D : FP_CONV<0x011a6800, FPR64, FPR64>;
85 def FTINTRZ_W_D : FP_CONV<0x011a8800, FPR32, FPR64>;
86 def FTINTRZ_L_D : FP_CONV<0x011aa800, FPR64, FPR64>;
87 def FTINTRNE_W_D : FP_CONV<0x011ac800, FPR32, FPR64>;
88 def FTINTRNE_L_D : FP_CONV<0x011ae800, FPR64, FPR64>;
89 def FRINT_D : FP_CONV<0x011e4800, FPR64, FPR64>;
92 def FMOV_D : FP_MOV<0x01149800, FPR64, FPR64>;
93 def MOVFRH2GR_S : FP_MOV<0x0114bc00, GPR, FPR64>;
94 let isCodeGenOnly = 1 in {
95 def MOVFR2GR_S_64 : FP_MOV<0x0114b400, GPR, FPR64>;
96 def FSEL_xD : FP_SEL<0x0d000000, FPR64>;
97 } // isCodeGenOnly = 1
98 let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Constraints = "$dst = $out" in {
99 def MOVGR2FRH_W : FPFmtMOV<0x0114ac00, (outs FPR64:$out),
100 (ins FPR64:$dst, GPR:$src),
102 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0, Constraints = "$dst = $out"
104 // Common Memory Access Instructions
105 def FLD_D : FP_LOAD_2RI12<0x2b800000, FPR64>;
106 def FST_D : FP_STORE_2RI12<0x2bc00000, FPR64>;
107 def FLDX_D : FP_LOAD_3R<0x38340000, FPR64>;
108 def FSTX_D : FP_STORE_3R<0x383c0000, FPR64>;
110 // Bound Check Memory Access Instructions
111 def FLDGT_D : FP_LOAD_3R<0x38748000, FPR64>;
112 def FLDLE_D : FP_LOAD_3R<0x38758000, FPR64>;
113 def FSTGT_D : FP_STORE_3R<0x38768000, FPR64>;
114 def FSTLE_D : FP_STORE_3R<0x38778000, FPR64>;
116 } // Predicates = [HasBasicD]
118 // Instructions only available on LA64
119 let Predicates = [HasBasicD, IsLA64] in {
120 def MOVGR2FR_D : FP_MOV<0x0114a800, FPR64, GPR>;
121 def MOVFR2GR_D : FP_MOV<0x0114b800, GPR, FPR64>;
122 } // Predicates = [HasBasicD, IsLA64]
124 // Instructions only available on LA32
125 let Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 in {
126 def MOVGR2FR_W_64 : FP_MOV<0x0114a400, FPR64, GPR>;
127 } // Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1
129 //===----------------------------------------------------------------------===//
130 // Pseudo-instructions and codegen patterns
131 //===----------------------------------------------------------------------===//
133 let Predicates = [HasBasicD] in {
135 /// Float arithmetic operations
137 def : PatFprFpr<fadd, FADD_D, FPR64>;
138 def : PatFprFpr<fsub, FSUB_D, FPR64>;
139 def : PatFprFpr<fmul, FMUL_D, FPR64>;
140 def : PatFprFpr<fdiv, FDIV_D, FPR64>;
141 def : PatFprFpr<fcopysign, FCOPYSIGN_D, FPR64>;
142 def : PatFprFpr<fmaxnum_ieee, FMAX_D, FPR64>;
143 def : PatFprFpr<fminnum_ieee, FMIN_D, FPR64>;
144 def : PatFpr<fneg, FNEG_D, FPR64>;
145 def : PatFpr<fabs, FABS_D, FPR64>;
146 def : PatFpr<fsqrt, FSQRT_D, FPR64>;
147 def : Pat<(fdiv fpimm1, (fsqrt FPR64:$fj)), (FRSQRT_D FPR64:$fj)>;
148 def : Pat<(fcopysign FPR64:$fj, FPR32:$fk),
149 (FCOPYSIGN_D FPR64:$fj, (FCVT_D_S FPR32:$fk))>;
150 def : Pat<(fcopysign FPR32:$fj, FPR64:$fk),
151 (FCOPYSIGN_S FPR32:$fj, (FCVT_S_D FPR64:$fk))>;
152 def : Pat<(fcanonicalize FPR64:$fj), (FMAX_D $fj, $fj)>;
153 let Predicates = [IsLA32] in {
154 def : Pat<(is_fpclass FPR64:$fj, (i32 timm:$mask)),
155 (SLTU R0, (ANDI (MOVFR2GR_S_64 (FCLASS_D FPR64:$fj)),
156 (to_fclass_mask timm:$mask)))>;
157 } // Predicates = [IsLA32]
158 let Predicates = [IsLA64] in {
159 def : Pat<(is_fpclass FPR64:$fj, (i32 timm:$mask)),
160 (SLTU R0, (ANDI (MOVFR2GR_D (FCLASS_D FPR64:$fj)),
161 (to_fclass_mask timm:$mask)))>;
162 } // Predicates = [IsLA64]
166 // Match non-signaling comparison
168 // SETOGT/SETOGE/SETUGT/SETUGE/SETGE/SETNE/SETGT will expand into
169 // SETOLT/SETOLE/SETULT/SETULE/SETLE/SETEQ/SETLT.
170 def : PatFPSetcc<SETOEQ, FCMP_CEQ_D, FPR64>;
171 def : PatFPSetcc<SETEQ, FCMP_CEQ_D, FPR64>;
172 def : PatFPSetcc<SETOLT, FCMP_CLT_D, FPR64>;
173 def : PatFPSetcc<SETOLE, FCMP_CLE_D, FPR64>;
174 def : PatFPSetcc<SETLE, FCMP_CLE_D, FPR64>;
175 def : PatFPSetcc<SETONE, FCMP_CNE_D, FPR64>;
176 def : PatFPSetcc<SETO, FCMP_COR_D, FPR64>;
177 def : PatFPSetcc<SETUEQ, FCMP_CUEQ_D, FPR64>;
178 def : PatFPSetcc<SETULT, FCMP_CULT_D, FPR64>;
179 def : PatFPSetcc<SETULE, FCMP_CULE_D, FPR64>;
180 def : PatFPSetcc<SETUNE, FCMP_CUNE_D, FPR64>;
181 def : PatFPSetcc<SETUO, FCMP_CUN_D, FPR64>;
182 def : PatFPSetcc<SETLT, FCMP_CLT_D, FPR64>;
184 defm : PatFPBrcond<SETOEQ, FCMP_CEQ_D, FPR64>;
185 defm : PatFPBrcond<SETOLT, FCMP_CLT_D, FPR64>;
186 defm : PatFPBrcond<SETOLE, FCMP_CLE_D, FPR64>;
187 defm : PatFPBrcond<SETONE, FCMP_CNE_D, FPR64>;
188 defm : PatFPBrcond<SETO, FCMP_COR_D, FPR64>;
189 defm : PatFPBrcond<SETUEQ, FCMP_CUEQ_D, FPR64>;
190 defm : PatFPBrcond<SETULT, FCMP_CULT_D, FPR64>;
191 defm : PatFPBrcond<SETULE, FCMP_CULE_D, FPR64>;
192 defm : PatFPBrcond<SETUNE, FCMP_CUNE_D, FPR64>;
193 defm : PatFPBrcond<SETUO, FCMP_CUN_D, FPR64>;
194 defm : PatFPBrcond<SETLT, FCMP_CLT_D, FPR64>;
196 // Match signaling comparison
198 def : PatStrictFsetccs<SETOEQ, FCMP_SEQ_D, FPR64>;
199 def : PatStrictFsetccs<SETOLT, FCMP_SLT_D, FPR64>;
200 def : PatStrictFsetccs<SETOLE, FCMP_SLE_D, FPR64>;
201 def : PatStrictFsetccs<SETONE, FCMP_SNE_D, FPR64>;
202 def : PatStrictFsetccs<SETO, FCMP_SOR_D, FPR64>;
203 def : PatStrictFsetccs<SETUEQ, FCMP_SUEQ_D, FPR64>;
204 def : PatStrictFsetccs<SETULT, FCMP_SULT_D, FPR64>;
205 def : PatStrictFsetccs<SETULE, FCMP_SULE_D, FPR64>;
206 def : PatStrictFsetccs<SETUNE, FCMP_SUNE_D, FPR64>;
207 def : PatStrictFsetccs<SETUO, FCMP_SUN_D, FPR64>;
208 def : PatStrictFsetccs<SETLT, FCMP_SLT_D, FPR64>;
212 def : Pat<(select CFR:$cc, FPR64:$fk, FPR64:$fj),
213 (FSEL_xD FPR64:$fj, FPR64:$fk, CFR:$cc)>;
217 def : PatFPSelectcc<SETOEQ, FCMP_CEQ_D, FSEL_xD, FPR64>;
218 def : PatFPSelectcc<SETOLT, FCMP_CLT_D, FSEL_xD, FPR64>;
219 def : PatFPSelectcc<SETOLE, FCMP_CLE_D, FSEL_xD, FPR64>;
220 def : PatFPSelectcc<SETONE, FCMP_CNE_D, FSEL_xD, FPR64>;
221 def : PatFPSelectcc<SETO, FCMP_COR_D, FSEL_xD, FPR64>;
222 def : PatFPSelectcc<SETUEQ, FCMP_CUEQ_D, FSEL_xD, FPR64>;
223 def : PatFPSelectcc<SETULT, FCMP_CULT_D, FSEL_xD, FPR64>;
224 def : PatFPSelectcc<SETULE, FCMP_CULE_D, FSEL_xD, FPR64>;
225 def : PatFPSelectcc<SETUNE, FCMP_CUNE_D, FSEL_xD, FPR64>;
226 def : PatFPSelectcc<SETUO, FCMP_CUN_D, FSEL_xD, FPR64>;
230 defm : LdPat<load, FLD_D, f64>;
231 def : RegRegLdPat<load, FLDX_D, f64>;
235 defm : StPat<store, FST_D, FPR64, f64>;
236 def : RegRegStPat<store, FSTX_D, FPR64, f64>;
238 /// FP conversion operations
240 def : Pat<(loongarch_ftint FPR64:$src), (FTINTRZ_W_D FPR64:$src)>;
241 def : Pat<(f64 (loongarch_ftint FPR64:$src)), (FTINTRZ_L_D FPR64:$src)>;
242 def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_L_S FPR32:$src)>;
245 def : Pat<(f32 (fpround FPR64:$src)), (FCVT_S_D FPR64:$src)>;
247 def : Pat<(f64 (fpextend FPR32:$src)), (FCVT_D_S FPR32:$src)>;
249 // FP reciprocal operation
250 def : Pat<(fdiv fpimm1, FPR64:$src), (FRECIP_D $src)>;
252 let Predicates = [HasFrecipe] in {
253 // FP approximate reciprocal operation
254 def : Pat<(int_loongarch_frecipe_d FPR64:$src), (FRECIPE_D FPR64:$src)>;
255 def : Pat<(int_loongarch_frsqrte_d FPR64:$src), (FRSQRTE_D FPR64:$src)>;
258 // fmadd.d: fj * fk + fa
259 def : Pat<(fma FPR64:$fj, FPR64:$fk, FPR64:$fa), (FMADD_D $fj, $fk, $fa)>;
261 // fmsub.d: fj * fk - fa
262 def : Pat<(fma FPR64:$fj, FPR64:$fk, (fneg FPR64:$fa)),
263 (FMSUB_D FPR64:$fj, FPR64:$fk, FPR64:$fa)>;
265 // fnmadd.d: -(fj * fk + fa)
266 def : Pat<(fneg (fma FPR64:$fj, FPR64:$fk, FPR64:$fa)),
267 (FNMADD_D FPR64:$fj, FPR64:$fk, FPR64:$fa)>;
269 // fnmadd.d: -fj * fk - fa (the nsz flag on the FMA)
270 def : Pat<(fma_nsz (fneg FPR64:$fj), FPR64:$fk, (fneg FPR64:$fa)),
271 (FNMADD_D FPR64:$fj, FPR64:$fk, FPR64:$fa)>;
273 // fnmsub.d: -(fj * fk - fa)
274 def : Pat<(fneg (fma FPR64:$fj, FPR64:$fk, (fneg FPR64:$fa))),
275 (FNMSUB_D FPR64:$fj, FPR64:$fk, FPR64:$fa)>;
277 // fnmsub.d: -fj * fk + fa (the nsz flag on the FMA)
278 def : Pat<(fma_nsz (fneg FPR64:$fj), FPR64:$fk, FPR64:$fa),
279 (FNMSUB_D FPR64:$fj, FPR64:$fk, FPR64:$fa)>;
280 } // Predicates = [HasBasicD]
282 /// Floating point constants
284 let Predicates = [HasBasicD, IsLA64] in {
285 def : Pat<(f64 fpimm0), (MOVGR2FR_D R0)>;
286 def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FR_D R0))>;
287 def : Pat<(f64 fpimm1), (FFINT_D_L (MOVGR2FR_D (ADDI_D R0, 1)))>;
288 } // Predicates = [HasBasicD, IsLA64]
289 let Predicates = [HasBasicD, IsLA32] in {
290 def : Pat<(f64 fpimm0), (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0)>;
291 def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0))>;
292 def : Pat<(f64 fpimm1), (FCVT_D_S (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1))))>;
293 } // Predicates = [HasBasicD, IsLA32]
295 /// Convert int to FP
297 let Predicates = [HasBasicD, IsLA64] in {
298 def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_L (MOVGR2FR_D GPR:$src))>;
299 def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
300 (FFINT_D_W (MOVGR2FR_W GPR:$src))>;
301 def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>;
303 def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>;
304 } // Predicates = [HasBasicD, IsLA64]
305 let Predicates = [HasBasicD, IsLA32] in {
306 def : Pat<(f64 (sint_to_fp (i32 GPR:$src))), (FFINT_D_W (MOVGR2FR_W GPR:$src))>;
307 } // Predicates = [HasBasicD, IsLA32]
310 let Predicates = [HasBasicD, IsLA64] in {
311 def : Pat<(bitconvert FPR64:$src), (MOVFR2GR_D FPR64:$src)>;
312 } // Predicates = [HasBasicD, IsLA64]
315 let Predicates = [HasBasicD, IsLA64] in {
316 def : PatFpr<frint, FRINT_D, FPR64>;
317 } // Predicates = [HasBasicD, IsLA64]