1//=-- LoongArchInstrInfoF.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>]>;
22
23def loongarch_movgr2fr_w_la64
24    : SDNode<"LoongArchISD::MOVGR2FR_W_LA64", SDT_LoongArchMOVGR2FR_W_LA64>;
25def loongarch_movfr2gr_s_la64
26    : SDNode<"LoongArchISD::MOVFR2GR_S_LA64", SDT_LoongArchMOVFR2GR_S_LA64>;
27def loongarch_ftint : SDNode<"LoongArchISD::FTINT", SDT_LoongArchFTINT>;
28
29//===----------------------------------------------------------------------===//
30// Instructions
31//===----------------------------------------------------------------------===//
32
33let Predicates = [HasBasicF] in {
34
35// Arithmetic Operation Instructions
36def FADD_S : FP_ALU_3R<0b00000001000000001, "fadd.s", FPR32>;
37def FSUB_S : FP_ALU_3R<0b00000001000000101, "fsub.s", FPR32>;
38def FMUL_S : FP_ALU_3R<0b00000001000001001, "fmul.s", FPR32>;
39def FDIV_S : FP_ALU_3R<0b00000001000001101, "fdiv.s", FPR32>;
40def FMADD_S  : FP_ALU_4R<0b000010000001, "fmadd.s", FPR32>;
41def FMSUB_S  : FP_ALU_4R<0b000010000101, "fmsub.s", FPR32>;
42def FNMADD_S : FP_ALU_4R<0b000010001001, "fnmadd.s", FPR32>;
43def FNMSUB_S : FP_ALU_4R<0b000010001101, "fnmsub.s", FPR32>;
44def FMAX_S  : FP_ALU_3R<0b00000001000010001, "fmax.s", FPR32>;
45def FMIN_S  : FP_ALU_3R<0b00000001000010101, "fmin.s", FPR32>;
46def FMAXA_S : FP_ALU_3R<0b00000001000011001, "fmaxa.s", FPR32>;
47def FMINA_S : FP_ALU_3R<0b00000001000011101, "fmina.s", FPR32>;
48def FABS_S   : FP_ALU_2R<0b0000000100010100000001, "fabs.s", FPR32>;
49def FNEG_S   : FP_ALU_2R<0b0000000100010100000101, "fneg.s", FPR32>;
50def FSQRT_S  : FP_ALU_2R<0b0000000100010100010001, "fsqrt.s", FPR32>;
51def FRECIP_S : FP_ALU_2R<0b0000000100010100010101, "frecip.s", FPR32>;
52def FRSQRT_S : FP_ALU_2R<0b0000000100010100011001, "frsqrt.s", FPR32>;
53def FSCALEB_S : FP_ALU_3R<0b00000001000100001, "fscaleb.s", FPR32>;
54def FLOGB_S   : FP_ALU_2R<0b0000000100010100001001, "flogb.s", FPR32>;
55def FCOPYSIGN_S : FP_ALU_3R<0b00000001000100101, "fcopysign.s", FPR32>;
56def FCLASS_S  : FP_ALU_2R<0b0000000100010100001101, "fclass.s", FPR32>;
57
58
59// Comparison Instructions
60def FCMP_CAF_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CAF, "fcmp.caf.s", FPR32>;
61def FCMP_CUN_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUN, "fcmp.cun.s", FPR32>;
62def FCMP_CEQ_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CEQ, "fcmp.ceq.s", FPR32>;
63def FCMP_CUEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUEQ, "fcmp.cueq.s", FPR32>;
64def FCMP_CLT_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CLT, "fcmp.clt.s", FPR32>;
65def FCMP_CULT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CULT, "fcmp.cult.s", FPR32>;
66def FCMP_CLE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CLE, "fcmp.cle.s", FPR32>;
67def FCMP_CULE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CULE, "fcmp.cule.s", FPR32>;
68def FCMP_CNE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CNE, "fcmp.cne.s", FPR32>;
69def FCMP_COR_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_COR, "fcmp.cor.s", FPR32>;
70def FCMP_CUNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUNE, "fcmp.cune.s", FPR32>;
71def FCMP_SAF_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SAF, "fcmp.saf.s", FPR32>;
72def FCMP_SUN_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUN, "fcmp.sun.s", FPR32>;
73def FCMP_SEQ_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SEQ, "fcmp.seq.s", FPR32>;
74def FCMP_SUEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUEQ, "fcmp.sueq.s", FPR32>;
75def FCMP_SLT_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SLT, "fcmp.slt.s", FPR32>;
76def FCMP_SULT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SULT, "fcmp.sult.s", FPR32>;
77def FCMP_SLE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SLE, "fcmp.sle.s", FPR32>;
78def FCMP_SULE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SULE, "fcmp.sule.s", FPR32>;
79def FCMP_SNE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SNE, "fcmp.sne.s", FPR32>;
80def FCMP_SOR_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SOR, "fcmp.sor.s", FPR32>;
81def FCMP_SUNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUNE, "fcmp.sune.s", FPR32>;
82
83// Conversion Instructions
84def FFINT_S_W    : FP_CONV<0b0000000100011101000100, "ffint.s.w", FPR32, FPR32>;
85def FTINT_W_S    : FP_CONV<0b0000000100011011000001, "ftint.w.s", FPR32, FPR32>;
86def FTINTRM_W_S  : FP_CONV<0b0000000100011010000001, "ftintrm.w.s", FPR32,
87                           FPR32>;
88def FTINTRP_W_S  : FP_CONV<0b0000000100011010010001, "ftintrp.w.s", FPR32,
89                           FPR32>;
90def FTINTRZ_W_S  : FP_CONV<0b0000000100011010100001, "ftintrz.w.s", FPR32,
91                           FPR32>;
92def FTINTRNE_W_S : FP_CONV<0b0000000100011010110001, "ftintrne.w.s", FPR32,
93                           FPR32>;
94def FRINT_S      : FP_CONV<0b0000000100011110010001, "frint.s", FPR32, FPR32>;
95
96// Move Instructions
97def FSEL_S : FP_SEL<0b00001101000000, "fsel", FPR32>;
98def FMOV_S     : FP_MOV<0b0000000100010100100101, "fmov.s", FPR32, FPR32>;
99def MOVGR2FR_W : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR32, GPR>;
100def MOVFR2GR_S : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR32>;
101def MOVGR2FCSR : FP_MOV<0b0000000100010100110000, "movgr2fcsr", FCSR, GPR>;
102def MOVFCSR2GR : FP_MOV<0b0000000100010100110010, "movfcsr2gr", GPR, FCSR>;
103def MOVFR2CF_S : FP_MOV<0b0000000100010100110100, "movfr2cf", CFR, FPR32>;
104def MOVCF2FR_S : FP_MOV<0b0000000100010100110101, "movcf2fr", FPR32, CFR>;
105def MOVGR2CF   : FP_MOV<0b0000000100010100110110, "movgr2cf", CFR, GPR>;
106def MOVCF2GR   : FP_MOV<0b0000000100010100110111, "movcf2gr", GPR, CFR>;
107
108// Branch Instructions
109def BCEQZ : FP_BRANCH<0b01001000, "bceqz">;
110def BCNEZ : FP_BRANCH<0b01001001, "bcnez">;
111
112// Common Memory Access Instructions
113def FLD_S : FP_LOAD_2RI12<0b0010101100, "fld.s", FPR32>;
114def FST_S : FP_STORE_2RI12<0b0010101101, "fst.s", FPR32>;
115def FLDX_S : FP_LOAD_3R<0b00111000001100000, "fldx.s", FPR32>;
116def FSTX_S : FP_STORE_3R<0b00111000001110000, "fstx.s", FPR32>;
117
118// Bound Check Memory Access Instructions
119def FLDGT_S : FP_LOAD_3R<0b00111000011101000, "fldgt.s", FPR32>;
120def FLDLE_S : FP_LOAD_3R<0b00111000011101010, "fldle.s", FPR32>;
121def FSTGT_S : FP_STORE_3R<0b00111000011101100, "fstgt.s", FPR32>;
122def FSTLE_S : FP_STORE_3R<0b00111000011101110, "fstle.s", FPR32>;
123
124} // Predicates = [HasBasicF]
125
126//===----------------------------------------------------------------------===//
127// Pseudo-instructions and codegen patterns
128//===----------------------------------------------------------------------===//
129
130/// Generic pattern classes
131
132class PatFpr<SDPatternOperator OpNode, LAInst Inst, RegisterClass RegTy>
133    : Pat<(OpNode RegTy:$fj), (Inst $fj)>;
134class PatFprFpr<SDPatternOperator OpNode, LAInst Inst, RegisterClass RegTy>
135    : Pat<(OpNode RegTy:$fj, RegTy:$fk), (Inst $fj, $fk)>;
136
137let Predicates = [HasBasicF] in {
138
139/// Float arithmetic operations
140
141def : PatFprFpr<fadd, FADD_S, FPR32>;
142def : PatFprFpr<fsub, FSUB_S, FPR32>;
143def : PatFprFpr<fmul, FMUL_S, FPR32>;
144def : PatFprFpr<fdiv, FDIV_S, FPR32>;
145def : PatFpr<fneg, FNEG_S, FPR32>;
146
147/// Setcc
148
149// Match non-signaling comparison
150
151// TODO: change setcc to any_fsetcc after call is supported because
152// we need to call llvm.experimental.constrained.fcmp.f32 in testcase.
153// See RISCV float-fcmp-strict.ll for reference.
154class PatFPSetcc<CondCode cc, LAInst CmpInst, RegisterClass RegTy>
155    : Pat<(setcc RegTy:$fj, RegTy:$fk, cc),
156          (MOVCF2GR (CmpInst RegTy:$fj, RegTy:$fk))>;
157// SETOGT/SETOGE/SETUGT/SETUGE will expand into SETOLT/SETOLE/SETULT/SETULE.
158def : PatFPSetcc<SETOEQ, FCMP_CEQ_S,  FPR32>;
159def : PatFPSetcc<SETOLT, FCMP_CLT_S,  FPR32>;
160def : PatFPSetcc<SETOLE, FCMP_CLE_S,  FPR32>;
161def : PatFPSetcc<SETONE, FCMP_CNE_S,  FPR32>;
162def : PatFPSetcc<SETO,   FCMP_COR_S,  FPR32>;
163def : PatFPSetcc<SETUEQ, FCMP_CUEQ_S, FPR32>;
164def : PatFPSetcc<SETULT, FCMP_CULT_S, FPR32>;
165def : PatFPSetcc<SETULE, FCMP_CULE_S, FPR32>;
166def : PatFPSetcc<SETUNE, FCMP_CUNE_S, FPR32>;
167def : PatFPSetcc<SETUO,  FCMP_CUN_S,  FPR32>;
168def : PatFPSetcc<SETLT,  FCMP_CLT_S,  FPR32>;
169
170// TODO: Match signaling comparison strict_fsetccs with FCMP_S*_S instructions.
171
172/// Select
173
174def : Pat<(select GPR:$cc, FPR32:$fk, FPR32:$fj),
175          (FSEL_S FPR32:$fj, FPR32:$fk, (MOVGR2CF GPR:$cc))>;
176
177/// Selectcc
178
179class PatFPSelectcc<CondCode cc, LAInst CmpInst, LAInst SelInst,
180                    RegisterClass RegTy>
181    : Pat<(select (GRLenVT (setcc RegTy:$a, RegTy:$b, cc)), RegTy:$t, RegTy:$f),
182          (SelInst RegTy:$f, RegTy:$t, (CmpInst RegTy:$a, RegTy:$b))>;
183def : PatFPSelectcc<SETOEQ, FCMP_CEQ_S,  FSEL_S, FPR32>;
184def : PatFPSelectcc<SETOLT, FCMP_CLT_S,  FSEL_S, FPR32>;
185def : PatFPSelectcc<SETOLE, FCMP_CLE_S,  FSEL_S, FPR32>;
186def : PatFPSelectcc<SETONE, FCMP_CNE_S,  FSEL_S, FPR32>;
187def : PatFPSelectcc<SETO,   FCMP_COR_S,  FSEL_S, FPR32>;
188def : PatFPSelectcc<SETUEQ, FCMP_CUEQ_S, FSEL_S, FPR32>;
189def : PatFPSelectcc<SETULT, FCMP_CULT_S, FSEL_S, FPR32>;
190def : PatFPSelectcc<SETULE, FCMP_CULE_S, FSEL_S, FPR32>;
191def : PatFPSelectcc<SETUNE, FCMP_CUNE_S, FSEL_S, FPR32>;
192def : PatFPSelectcc<SETUO,  FCMP_CUN_S,  FSEL_S, FPR32>;
193
194/// Loads
195
196defm : LdPat<load, FLD_S, f32>;
197
198/// Stores
199
200defm : StPat<store, FST_S, FPR32, f32>;
201
202/// Floating point constants
203
204def : Pat<(f32 fpimm0), (MOVGR2FR_W R0)>;
205def : Pat<(f32 fpimm0neg), (FNEG_S (MOVGR2FR_W R0))>;
206def : Pat<(f32 fpimm1), (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1)))>;
207
208// FP Conversion
209def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_W_S FPR32:$src)>;
210} // Predicates = [HasBasicF]
211
212let Predicates = [HasBasicF, IsLA64] in {
213// GPR -> FPR
214def : Pat<(loongarch_movgr2fr_w_la64 GPR:$src), (MOVGR2FR_W GPR:$src)>;
215// FPR -> GPR
216def : Pat<(loongarch_movfr2gr_s_la64 FPR32:$src),
217          (MOVFR2GR_S FPR32:$src)>;
218// int -> f32
219def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
220} // Predicates = [HasBasicF, IsLA64]
221
222let Predicates = [HasBasicF, IsLA32] in {
223// GPR -> FPR
224def : Pat<(bitconvert (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>;
225// FPR -> GPR
226def : Pat<(i32 (bitconvert FPR32:$src)), (MOVFR2GR_S FPR32:$src)>;
227// int -> f32
228def : Pat<(f32 (sint_to_fp (i32 GPR:$src))), (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
229} // Predicates = [HasBasicF, IsLA64]
230