1//=-- LoongArchInstrInfoD.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<0b00000001000000010, "fadd.d", FPR64>; 21def FSUB_D : FP_ALU_3R<0b00000001000000110, "fsub.d", FPR64>; 22def FMUL_D : FP_ALU_3R<0b00000001000001010, "fmul.d", FPR64>; 23def FDIV_D : FP_ALU_3R<0b00000001000001110, "fdiv.d", FPR64>; 24def FMADD_D : FP_ALU_4R<0b000010000010, "fmadd.d", FPR64>; 25def FMSUB_D : FP_ALU_4R<0b000010000110, "fmsub.d", FPR64>; 26def FNMADD_D : FP_ALU_4R<0b000010001010, "fnmadd.d", FPR64>; 27def FNMSUB_D : FP_ALU_4R<0b000010001110, "fnmsub.d", FPR64>; 28def FMAX_D : FP_ALU_3R<0b00000001000010010, "fmax.d", FPR64>; 29def FMIN_D : FP_ALU_3R<0b00000001000010110, "fmin.d", FPR64>; 30def FMAXA_D : FP_ALU_3R<0b00000001000011010, "fmaxa.d", FPR64>; 31def FMINA_D : FP_ALU_3R<0b00000001000011110, "fmina.d", FPR64>; 32def FABS_D : FP_ALU_2R<0b0000000100010100000010, "fabs.d", FPR64>; 33def FNEG_D : FP_ALU_2R<0b0000000100010100000110, "fneg.d", FPR64>; 34def FSQRT_D : FP_ALU_2R<0b0000000100010100010010, "fsqrt.d", FPR64>; 35def FRECIP_D : FP_ALU_2R<0b0000000100010100010110, "frecip.d", FPR64>; 36def FRSQRT_D : FP_ALU_2R<0b0000000100010100011010, "frsqrt.d", FPR64>; 37def FSCALEB_D : FP_ALU_3R<0b00000001000100010, "fscaleb.d", FPR64>; 38def FLOGB_D : FP_ALU_2R<0b0000000100010100001010, "flogb.d", FPR64>; 39def FCOPYSIGN_D : FP_ALU_3R<0b00000001000100110, "fcopysign.d", FPR64>; 40def FCLASS_D : FP_ALU_2R<0b0000000100010100001110, "fclass.d", FPR64>; 41 42// Comparison Instructions 43def FCMP_CAF_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CAF, "fcmp.caf.d", FPR64>; 44def FCMP_CUN_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUN, "fcmp.cun.d", FPR64>; 45def FCMP_CEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CEQ, "fcmp.ceq.d", FPR64>; 46def FCMP_CUEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUEQ, "fcmp.cueq.d", FPR64>; 47def FCMP_CLT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CLT, "fcmp.clt.d", FPR64>; 48def FCMP_CULT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CULT, "fcmp.cult.d", FPR64>; 49def FCMP_CLE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CLE, "fcmp.cle.d", FPR64>; 50def FCMP_CULE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CULE, "fcmp.cule.d", FPR64>; 51def FCMP_CNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CNE, "fcmp.cne.d", FPR64>; 52def FCMP_COR_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_COR, "fcmp.cor.d", FPR64>; 53def FCMP_CUNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUNE, "fcmp.cune.d", FPR64>; 54def FCMP_SAF_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SAF, "fcmp.saf.d", FPR64>; 55def FCMP_SUN_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUN, "fcmp.sun.d", FPR64>; 56def FCMP_SEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SEQ, "fcmp.seq.d", FPR64>; 57def FCMP_SUEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUEQ, "fcmp.sueq.d", FPR64>; 58def FCMP_SLT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SLT, "fcmp.slt.d", FPR64>; 59def FCMP_SULT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SULT, "fcmp.sult.d", FPR64>; 60def FCMP_SLE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SLE, "fcmp.sle.d", FPR64>; 61def FCMP_SULE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SULE, "fcmp.sule.d", FPR64>; 62def FCMP_SNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SNE, "fcmp.sne.d", FPR64>; 63def FCMP_SOR_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SOR, "fcmp.sor.d", FPR64>; 64def FCMP_SUNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUNE, "fcmp.sune.d", FPR64>; 65 66// Conversion Instructions 67def FFINT_S_L : FP_CONV<0b0000000100011101000110, "ffint.s.l", FPR32, FPR64>; 68def FTINT_L_S : FP_CONV<0b0000000100011011001001, "ftint.l.s", FPR64, FPR32>; 69def FTINTRM_L_S : FP_CONV<0b0000000100011010001001, "ftintrm.l.s", FPR64, 70 FPR32>; 71def FTINTRP_L_S : FP_CONV<0b0000000100011010011001, "ftintrp.l.s", FPR64, 72 FPR32>; 73def FTINTRZ_L_S : FP_CONV<0b0000000100011010101001, "ftintrz.l.s", FPR64, 74 FPR32>; 75def FTINTRNE_L_S : FP_CONV<0b0000000100011010111001, "ftintrne.l.s", FPR64, 76 FPR32>; 77def FCVT_S_D : FP_CONV<0b0000000100011001000110, "fcvt.s.d", FPR32, FPR64>; 78def FCVT_D_S : FP_CONV<0b0000000100011001001001, "fcvt.d.s", FPR64, FPR32>; 79def FFINT_D_W : FP_CONV<0b0000000100011101001000, "ffint.d.w", FPR64, FPR32>; 80def FFINT_D_L : FP_CONV<0b0000000100011101001010, "ffint.d.l", FPR64, FPR64>; 81def FTINT_W_D : FP_CONV<0b0000000100011011000010, "ftint.w.d", FPR32, FPR64>; 82def FTINT_L_D : FP_CONV<0b0000000100011011001010, "ftint.l.d", FPR64, FPR64>; 83def FTINTRM_W_D : FP_CONV<0b0000000100011010000010, "ftintrm.w.d", FPR32, 84 FPR64>; 85def FTINTRM_L_D : FP_CONV<0b0000000100011010001010, "ftintrm.l.d", FPR64, 86 FPR64>; 87def FTINTRP_W_D : FP_CONV<0b0000000100011010010010, "ftintrp.w.d", FPR32, 88 FPR64>; 89def FTINTRP_L_D : FP_CONV<0b0000000100011010011010, "ftintrp.l.d", FPR64, 90 FPR64>; 91def FTINTRZ_W_D : FP_CONV<0b0000000100011010100010, "ftintrz.w.d", FPR32, 92 FPR64>; 93def FTINTRZ_L_D : FP_CONV<0b0000000100011010101010, "ftintrz.l.d", FPR64, 94 FPR64>; 95def FTINTRNE_W_D : FP_CONV<0b0000000100011010110010, "ftintrne.w.d", FPR32, 96 FPR64>; 97def FTINTRNE_L_D : FP_CONV<0b0000000100011010111010, "ftintrne.l.d", FPR64, 98 FPR64>; 99def FRINT_D : FP_CONV<0b0000000100011110010010, "frint.d", FPR64, FPR64>; 100 101// Move Instructions 102def FMOV_D : FP_MOV<0b0000000100010100100110, "fmov.d", FPR64, FPR64>; 103def MOVFRH2GR_S : FP_MOV<0b0000000100010100101111, "movfrh2gr.s", GPR, FPR64>; 104let isCodeGenOnly = 1 in { 105def MOVFR2GR_S_64 : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR64>; 106def FSEL_D : FP_SEL<0b00001101000000, "fsel", FPR64>; 107} // isCodeGenOnly = 1 108let Constraints = "$dst = $out" in { 109def MOVGR2FRH_W : FPFmtMOV<0b0000000100010100101011, (outs FPR64:$out), 110 (ins FPR64:$dst, GPR:$src), "movgr2frh.w", 111 "$dst, $src">; 112} // Constraints = "$dst = $out" 113 114// Common Memory Access Instructions 115def FLD_D : FP_LOAD_2RI12<0b0010101110, "fld.d", FPR64>; 116def FST_D : FP_STORE_2RI12<0b0010101111, "fst.d", FPR64>; 117def FLDX_D : FP_LOAD_3R<0b00111000001101000, "fldx.d", FPR64>; 118def FSTX_D : FP_STORE_3R<0b00111000001111000, "fstx.d", FPR64>; 119 120// Bound Check Memory Access Instructions 121def FLDGT_D : FP_LOAD_3R<0b00111000011101001, "fldgt.d", FPR64>; 122def FLDLE_D : FP_LOAD_3R<0b00111000011101011, "fldle.d", FPR64>; 123def FSTGT_D : FP_STORE_3R<0b00111000011101101, "fstgt.d", FPR64>; 124def FSTLE_D : FP_STORE_3R<0b00111000011101111, "fstle.d", FPR64>; 125 126} // Predicates = [HasBasicD] 127 128// Instructions only available on LA64 129let Predicates = [HasBasicD, IsLA64] in { 130def MOVGR2FR_D : FP_MOV<0b0000000100010100101010, "movgr2fr.d", FPR64, GPR>; 131def MOVFR2GR_D : FP_MOV<0b0000000100010100101110, "movfr2gr.d", GPR, FPR64>; 132} // Predicates = [HasBasicD, IsLA64] 133 134// Instructions only available on LA32 135let Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 in { 136def MOVGR2FR_W_64 : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR64, GPR>; 137} // Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 138 139//===----------------------------------------------------------------------===// 140// Pseudo-instructions and codegen patterns 141//===----------------------------------------------------------------------===// 142 143let Predicates = [HasBasicD] in { 144 145/// Float arithmetic operations 146 147def : PatFprFpr<fadd, FADD_D, FPR64>; 148def : PatFprFpr<fsub, FSUB_D, FPR64>; 149def : PatFprFpr<fmul, FMUL_D, FPR64>; 150def : PatFprFpr<fdiv, FDIV_D, FPR64>; 151def : PatFpr<fneg, FNEG_D, FPR64>; 152 153/// Setcc 154 155// Match non-signaling comparison 156 157// TODO: Change setcc to any_fsetcc after call is supported because 158// we need to call llvm.experimental.constrained.fcmp.f64 in testcase. 159// See RISCV float-fcmp-strict.ll for reference. 160 161// SETOGT/SETOGE/SETUGT/SETUGE will expand into SETOLT/SETOLE/SETULT/SETULE. 162def : PatFPSetcc<SETOEQ, FCMP_CEQ_D, FPR64>; 163def : PatFPSetcc<SETOLT, FCMP_CLT_D, FPR64>; 164def : PatFPSetcc<SETOLE, FCMP_CLE_D, FPR64>; 165def : PatFPSetcc<SETONE, FCMP_CNE_D, FPR64>; 166def : PatFPSetcc<SETO, FCMP_COR_D, FPR64>; 167def : PatFPSetcc<SETUEQ, FCMP_CUEQ_D, FPR64>; 168def : PatFPSetcc<SETULT, FCMP_CULT_D, FPR64>; 169def : PatFPSetcc<SETULE, FCMP_CULE_D, FPR64>; 170def : PatFPSetcc<SETUNE, FCMP_CUNE_D, FPR64>; 171def : PatFPSetcc<SETUO, FCMP_CUN_D, FPR64>; 172def : PatFPSetcc<SETLT, FCMP_CLT_D, FPR64>; 173 174// TODO: Match signaling comparison strict_fsetccs with FCMP_S*_D instructions. 175 176/// Select 177 178def : Pat<(select GPR:$cc, FPR64:$fk, FPR64:$fj), 179 (FSEL_D FPR64:$fj, FPR64:$fk, (MOVGR2CF GPR:$cc))>; 180 181/// Selectcc 182 183def : PatFPSelectcc<SETOEQ, FCMP_CEQ_D, FSEL_D, FPR64>; 184def : PatFPSelectcc<SETOLT, FCMP_CLT_D, FSEL_D, FPR64>; 185def : PatFPSelectcc<SETOLE, FCMP_CLE_D, FSEL_D, FPR64>; 186def : PatFPSelectcc<SETONE, FCMP_CNE_D, FSEL_D, FPR64>; 187def : PatFPSelectcc<SETO, FCMP_COR_D, FSEL_D, FPR64>; 188def : PatFPSelectcc<SETUEQ, FCMP_CUEQ_D, FSEL_D, FPR64>; 189def : PatFPSelectcc<SETULT, FCMP_CULT_D, FSEL_D, FPR64>; 190def : PatFPSelectcc<SETULE, FCMP_CULE_D, FSEL_D, FPR64>; 191def : PatFPSelectcc<SETUNE, FCMP_CUNE_D, FSEL_D, FPR64>; 192def : PatFPSelectcc<SETUO, FCMP_CUN_D, FSEL_D, FPR64>; 193 194/// Loads 195 196defm : LdPat<load, FLD_D, f64>; 197 198/// Stores 199 200defm : StPat<store, FST_D, FPR64, f64>; 201 202/// FP conversion operations 203 204def : Pat<(loongarch_ftint FPR64:$src), (FTINTRZ_W_D FPR64:$src)>; 205def : Pat<(f64 (loongarch_ftint FPR64:$src)), (FTINTRZ_L_D FPR64:$src)>; 206def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_L_S FPR32:$src)>; 207 208// f64 -> f32 209def : Pat<(f32 (fpround FPR64:$src)), (FCVT_S_D FPR64:$src)>; 210// f32 -> f64 211def : Pat<(f64 (fpextend FPR32:$src)), (FCVT_D_S FPR32:$src)>; 212} // Predicates = [HasBasicD] 213 214/// Floating point constants 215 216let Predicates = [HasBasicD, IsLA64] in { 217def : Pat<(f64 fpimm0), (MOVGR2FR_D R0)>; 218def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FR_D R0))>; 219def : Pat<(f64 fpimm1), (FFINT_D_L (MOVGR2FR_D (ADDI_D R0, 1)))>; 220 221// Convert int to FP 222def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))), 223 (FFINT_D_W (MOVGR2FR_W GPR:$src))>; 224def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>; 225 226def : Pat<(f64 (uint_to_fp (i64 (zexti32 (i64 GPR:$src))))), 227 (FFINT_D_W (MOVGR2FR_W GPR:$src))>; 228 229def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>; 230 231// Convert FP to int 232def : Pat<(bitconvert FPR64:$src), (MOVFR2GR_D FPR64:$src)>; 233} // Predicates = [HasBasicD, IsLA64] 234 235let Predicates = [HasBasicD, IsLA32] in { 236def : Pat<(f64 fpimm0), (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0)>; 237def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0))>; 238def : Pat<(f64 fpimm1), (FCVT_D_S (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1))))>; 239 240// Convert int to FP 241def : Pat<(f64 (sint_to_fp (i32 GPR:$src))), (FFINT_D_W (MOVGR2FR_W GPR:$src))>; 242} // Predicates = [HasBasicD, IsLA32] 243