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