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