1 //===-- WebAssemblyInstrConv.td-WebAssembly Conversion support -*- tablegen -*-= 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// WebAssembly datatype conversions, truncations, reinterpretations, 12 /// promotions, and demotions operand code-gen constructs. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 let Defs = [ARGUMENTS] in { 17 18 defm I32_WRAP_I64 : I<(outs I32:$dst), (ins I64:$src), (outs), (ins), 19 [(set I32:$dst, (trunc I64:$src))], 20 "i32.wrap/i64\t$dst, $src", "i32.wrap/i64", 0xa7>; 21 22 defm I64_EXTEND_S_I32 : I<(outs I64:$dst), (ins I32:$src), (outs), (ins), 23 [(set I64:$dst, (sext I32:$src))], 24 "i64.extend_s/i32\t$dst, $src", "i64.extend_s/i32", 25 0xac>; 26 defm I64_EXTEND_U_I32 : I<(outs I64:$dst), (ins I32:$src), (outs), (ins), 27 [(set I64:$dst, (zext I32:$src))], 28 "i64.extend_u/i32\t$dst, $src", "i64.extend_u/i32", 29 0xad>; 30 31 let Predicates = [HasSignExt] in { 32 defm I32_EXTEND8_S_I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins), 33 [(set I32:$dst, (sext_inreg I32:$src, i8))], 34 "i32.extend8_s\t$dst, $src", "i32.extend8_s", 35 0xc0>; 36 defm I32_EXTEND16_S_I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins), 37 [(set I32:$dst, (sext_inreg I32:$src, i16))], 38 "i32.extend16_s\t$dst, $src", "i32.extend16_s", 39 0xc1>; 40 defm I64_EXTEND8_S_I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins), 41 [(set I64:$dst, (sext_inreg I64:$src, i8))], 42 "i64.extend8_s\t$dst, $src", "i64.extend8_s", 43 0xc2>; 44 defm I64_EXTEND16_S_I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins), 45 [(set I64:$dst, (sext_inreg I64:$src, i16))], 46 "i64.extend16_s\t$dst, $src", "i64.extend16_s", 47 0xc3>; 48 defm I64_EXTEND32_S_I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins), 49 [(set I64:$dst, (sext_inreg I64:$src, i32))], 50 "i64.extend32_s\t$dst, $src", "i64.extend32_s", 51 0xc4>; 52 } // Predicates = [HasSignExt] 53 54 } // defs = [ARGUMENTS] 55 56 // Expand a "don't care" extend into zero-extend (chosen over sign-extend 57 // somewhat arbitrarily, although it favors popular hardware architectures 58 // and is conceptually a simpler operation). 59 def : Pat<(i64 (anyext I32:$src)), (I64_EXTEND_U_I32 I32:$src)>; 60 61 let Defs = [ARGUMENTS] in { 62 63 // Conversion from floating point to integer instructions which don't trap on 64 // overflow or invalid. 65 defm I32_TRUNC_S_SAT_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), 66 [(set I32:$dst, (fp_to_sint F32:$src))], 67 "i32.trunc_s:sat/f32\t$dst, $src", 68 "i32.trunc_s:sat/f32", 0xfc00>, 69 Requires<[HasNontrappingFPToInt]>; 70 defm I32_TRUNC_U_SAT_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), 71 [(set I32:$dst, (fp_to_uint F32:$src))], 72 "i32.trunc_u:sat/f32\t$dst, $src", 73 "i32.trunc_u:sat/f32", 0xfc01>, 74 Requires<[HasNontrappingFPToInt]>; 75 defm I64_TRUNC_S_SAT_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), 76 [(set I64:$dst, (fp_to_sint F32:$src))], 77 "i64.trunc_s:sat/f32\t$dst, $src", 78 "i64.trunc_s:sat/f32", 0xfc04>, 79 Requires<[HasNontrappingFPToInt]>; 80 defm I64_TRUNC_U_SAT_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), 81 [(set I64:$dst, (fp_to_uint F32:$src))], 82 "i64.trunc_u:sat/f32\t$dst, $src", 83 "i64.trunc_u:sat/f32", 0xfc05>, 84 Requires<[HasNontrappingFPToInt]>; 85 defm I32_TRUNC_S_SAT_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), 86 [(set I32:$dst, (fp_to_sint F64:$src))], 87 "i32.trunc_s:sat/f64\t$dst, $src", 88 "i32.trunc_s:sat/f64", 0xfc02>, 89 Requires<[HasNontrappingFPToInt]>; 90 defm I32_TRUNC_U_SAT_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), 91 [(set I32:$dst, (fp_to_uint F64:$src))], 92 "i32.trunc_u:sat/f64\t$dst, $src", 93 "i32.trunc_u:sat/f64", 0xfc03>, 94 Requires<[HasNontrappingFPToInt]>; 95 defm I64_TRUNC_S_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), 96 [(set I64:$dst, (fp_to_sint F64:$src))], 97 "i64.trunc_s:sat/f64\t$dst, $src", 98 "i64.trunc_s:sat/f64", 0xfc06>, 99 Requires<[HasNontrappingFPToInt]>; 100 defm I64_TRUNC_U_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), 101 [(set I64:$dst, (fp_to_uint F64:$src))], 102 "i64.trunc_u:sat/f64\t$dst, $src", 103 "i64.trunc_u:sat/f64", 0xfc07>, 104 Requires<[HasNontrappingFPToInt]>; 105 106 // Conversion from floating point to integer pseudo-instructions which don't 107 // trap on overflow or invalid. 108 let usesCustomInserter = 1, isCodeGenOnly = 1 in { 109 defm FP_TO_SINT_I32_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), 110 [(set I32:$dst, (fp_to_sint F32:$src))], "", "", 0>, 111 Requires<[NotHasNontrappingFPToInt]>; 112 defm FP_TO_UINT_I32_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), 113 [(set I32:$dst, (fp_to_uint F32:$src))], "", "", 0>, 114 Requires<[NotHasNontrappingFPToInt]>; 115 defm FP_TO_SINT_I64_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), 116 [(set I64:$dst, (fp_to_sint F32:$src))], "", "", 0>, 117 Requires<[NotHasNontrappingFPToInt]>; 118 defm FP_TO_UINT_I64_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), 119 [(set I64:$dst, (fp_to_uint F32:$src))], "", "", 0>, 120 Requires<[NotHasNontrappingFPToInt]>; 121 defm FP_TO_SINT_I32_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), 122 [(set I32:$dst, (fp_to_sint F64:$src))], "", "", 0>, 123 Requires<[NotHasNontrappingFPToInt]>; 124 defm FP_TO_UINT_I32_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), 125 [(set I32:$dst, (fp_to_uint F64:$src))], "", "", 0>, 126 Requires<[NotHasNontrappingFPToInt]>; 127 defm FP_TO_SINT_I64_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), 128 [(set I64:$dst, (fp_to_sint F64:$src))], "", "", 0>, 129 Requires<[NotHasNontrappingFPToInt]>; 130 defm FP_TO_UINT_I64_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), 131 [(set I64:$dst, (fp_to_uint F64:$src))], "", "", 0>, 132 Requires<[NotHasNontrappingFPToInt]>; 133 } // usesCustomInserter, isCodeGenOnly = 1 134 135 // Conversion from floating point to integer traps on overflow and invalid. 136 let hasSideEffects = 1 in { 137 defm I32_TRUNC_S_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), 138 [], "i32.trunc_s/f32\t$dst, $src", "i32.trunc_s/f32", 139 0xa8>; 140 defm I32_TRUNC_U_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), 141 [], "i32.trunc_u/f32\t$dst, $src", "i32.trunc_u/f32", 142 0xa9>; 143 defm I64_TRUNC_S_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), 144 [], "i64.trunc_s/f32\t$dst, $src", "i64.trunc_s/f32", 145 0xae>; 146 defm I64_TRUNC_U_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), 147 [], "i64.trunc_u/f32\t$dst, $src", "i64.trunc_u/f32", 148 0xaf>; 149 defm I32_TRUNC_S_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), 150 [], "i32.trunc_s/f64\t$dst, $src", "i32.trunc_s/f64", 151 0xaa>; 152 defm I32_TRUNC_U_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), 153 [], "i32.trunc_u/f64\t$dst, $src", "i32.trunc_u/f64", 154 0xab>; 155 defm I64_TRUNC_S_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), 156 [], "i64.trunc_s/f64\t$dst, $src", "i64.trunc_s/f64", 157 0xb0>; 158 defm I64_TRUNC_U_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), 159 [], "i64.trunc_u/f64\t$dst, $src", "i64.trunc_u/f64", 160 0xb1>; 161 } // hasSideEffects = 1 162 163 defm F32_CONVERT_S_I32 : I<(outs F32:$dst), (ins I32:$src), (outs), (ins), 164 [(set F32:$dst, (sint_to_fp I32:$src))], 165 "f32.convert_s/i32\t$dst, $src", "f32.convert_s/i32", 166 0xb2>; 167 defm F32_CONVERT_U_I32 : I<(outs F32:$dst), (ins I32:$src), (outs), (ins), 168 [(set F32:$dst, (uint_to_fp I32:$src))], 169 "f32.convert_u/i32\t$dst, $src", "f32.convert_u/i32", 170 0xb3>; 171 defm F64_CONVERT_S_I32 : I<(outs F64:$dst), (ins I32:$src), (outs), (ins), 172 [(set F64:$dst, (sint_to_fp I32:$src))], 173 "f64.convert_s/i32\t$dst, $src", "f64.convert_s/i32", 174 0xb7>; 175 defm F64_CONVERT_U_I32 : I<(outs F64:$dst), (ins I32:$src), (outs), (ins), 176 [(set F64:$dst, (uint_to_fp I32:$src))], 177 "f64.convert_u/i32\t$dst, $src", "f64.convert_u/i32", 178 0xb8>; 179 defm F32_CONVERT_S_I64 : I<(outs F32:$dst), (ins I64:$src), (outs), (ins), 180 [(set F32:$dst, (sint_to_fp I64:$src))], 181 "f32.convert_s/i64\t$dst, $src", "f32.convert_s/i64", 182 0xb4>; 183 defm F32_CONVERT_U_I64 : I<(outs F32:$dst), (ins I64:$src), (outs), (ins), 184 [(set F32:$dst, (uint_to_fp I64:$src))], 185 "f32.convert_u/i64\t$dst, $src", "f32.convert_u/i64", 186 0xb5>; 187 defm F64_CONVERT_S_I64 : I<(outs F64:$dst), (ins I64:$src), (outs), (ins), 188 [(set F64:$dst, (sint_to_fp I64:$src))], 189 "f64.convert_s/i64\t$dst, $src", "f64.convert_s/i64", 190 0xb9>; 191 defm F64_CONVERT_U_I64 : I<(outs F64:$dst), (ins I64:$src), (outs), (ins), 192 [(set F64:$dst, (uint_to_fp I64:$src))], 193 "f64.convert_u/i64\t$dst, $src", "f64.convert_u/i64", 194 0xba>; 195 196 defm F64_PROMOTE_F32 : I<(outs F64:$dst), (ins F32:$src), (outs), (ins), 197 [(set F64:$dst, (fpextend F32:$src))], 198 "f64.promote/f32\t$dst, $src", "f64.promote/f32", 199 0xbb>; 200 defm F32_DEMOTE_F64 : I<(outs F32:$dst), (ins F64:$src), (outs), (ins), 201 [(set F32:$dst, (fpround F64:$src))], 202 "f32.demote/f64\t$dst, $src", "f32.demote/f64", 203 0xb6>; 204 205 defm I32_REINTERPRET_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), 206 [(set I32:$dst, (bitconvert F32:$src))], 207 "i32.reinterpret/f32\t$dst, $src", 208 "i32.reinterpret/f32", 0xbc>; 209 defm F32_REINTERPRET_I32 : I<(outs F32:$dst), (ins I32:$src), (outs), (ins), 210 [(set F32:$dst, (bitconvert I32:$src))], 211 "f32.reinterpret/i32\t$dst, $src", 212 "f32.reinterpret/i32", 0xbe>; 213 defm I64_REINTERPRET_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), 214 [(set I64:$dst, (bitconvert F64:$src))], 215 "i64.reinterpret/f64\t$dst, $src", 216 "i64.reinterpret/f64", 0xbd>; 217 defm F64_REINTERPRET_I64 : I<(outs F64:$dst), (ins I64:$src), (outs), (ins), 218 [(set F64:$dst, (bitconvert I64:$src))], 219 "f64.reinterpret/i64\t$dst, $src", 220 "f64.reinterpret/i64", 0xbf>; 221 222 } // Defs = [ARGUMENTS] 223