LoongArchFloat64InstrInfo.td 14 KB

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