1 // RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +unimplemented-simd128 -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -fno-lax-vector-conversions -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY32 2 // RUN: %clang_cc1 -triple wasm64-unknown-unknown -target-feature +unimplemented-simd128 -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -fno-lax-vector-conversions -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY64 3 // RUN: not %clang_cc1 -triple wasm64-unknown-unknown -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -fno-lax-vector-conversions -O3 -emit-llvm -o - %s 2>&1 | FileCheck %s -check-prefixes MISSING-SIMD 4 5 // SIMD convenience types 6 typedef char i8x16 __attribute((vector_size(16))); 7 typedef short i16x8 __attribute((vector_size(16))); 8 typedef int i32x4 __attribute((vector_size(16))); 9 typedef long long i64x2 __attribute((vector_size(16))); 10 typedef unsigned char u8x16 __attribute((vector_size(16))); 11 typedef unsigned short u16x8 __attribute((vector_size(16))); 12 typedef unsigned int u32x4 __attribute((vector_size(16))); 13 typedef unsigned long long u64x2 __attribute((vector_size(16))); 14 typedef float f32x4 __attribute((vector_size(16))); 15 typedef double f64x2 __attribute((vector_size(16))); 16 17 __SIZE_TYPE__ memory_size(void) { 18 return __builtin_wasm_memory_size(0); 19 // WEBASSEMBLY32: call {{i.*}} @llvm.wasm.memory.size.i32(i32 0) 20 // WEBASSEMBLY64: call {{i.*}} @llvm.wasm.memory.size.i64(i32 0) 21 } 22 23 __SIZE_TYPE__ memory_grow(__SIZE_TYPE__ delta) { 24 return __builtin_wasm_memory_grow(0, delta); 25 // WEBASSEMBLY32: call i32 @llvm.wasm.memory.grow.i32(i32 0, i32 %{{.*}}) 26 // WEBASSEMBLY64: call i64 @llvm.wasm.memory.grow.i64(i32 0, i64 %{{.*}}) 27 } 28 29 void memory_init(void *dest, int offset, int size) { 30 __builtin_wasm_memory_init(3, 0, dest, offset, size); 31 // WEBASSEMBLY32: call void @llvm.wasm.memory.init(i32 3, i32 0, i8* %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) 32 // WEBASSEMBLY64: call void @llvm.wasm.memory.init(i32 3, i32 0, i8* %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) 33 } 34 35 void data_drop() { 36 __builtin_wasm_data_drop(3); 37 // WEBASSEMBLY32: call void @llvm.wasm.data.drop(i32 3) 38 // WEBASSEMBLY64: call void @llvm.wasm.data.drop(i32 3) 39 } 40 41 void throw(void *obj) { 42 return __builtin_wasm_throw(0, obj); 43 // WEBASSEMBLY32: call void @llvm.wasm.throw(i32 0, i8* %{{.*}}) 44 // WEBASSEMBLY64: call void @llvm.wasm.throw(i32 0, i8* %{{.*}}) 45 } 46 47 void rethrow_in_catch(void) { 48 return __builtin_wasm_rethrow_in_catch(); 49 // WEBASSEMBLY32: call void @llvm.wasm.rethrow.in.catch() 50 // WEBASSEMBLY64: call void @llvm.wasm.rethrow.in.catch() 51 } 52 53 int atomic_wait_i32(int *addr, int expected, long long timeout) { 54 return __builtin_wasm_atomic_wait_i32(addr, expected, timeout); 55 // WEBASSEMBLY32: call i32 @llvm.wasm.atomic.wait.i32(i32* %{{.*}}, i32 %{{.*}}, i64 %{{.*}}) 56 // WEBASSEMBLY64: call i32 @llvm.wasm.atomic.wait.i32(i32* %{{.*}}, i32 %{{.*}}, i64 %{{.*}}) 57 } 58 59 int atomic_wait_i64(long long *addr, long long expected, long long timeout) { 60 return __builtin_wasm_atomic_wait_i64(addr, expected, timeout); 61 // WEBASSEMBLY32: call i32 @llvm.wasm.atomic.wait.i64(i64* %{{.*}}, i64 %{{.*}}, i64 %{{.*}}) 62 // WEBASSEMBLY64: call i32 @llvm.wasm.atomic.wait.i64(i64* %{{.*}}, i64 %{{.*}}, i64 %{{.*}}) 63 } 64 65 unsigned int atomic_notify(int *addr, unsigned int count) { 66 return __builtin_wasm_atomic_notify(addr, count); 67 // WEBASSEMBLY32: call i32 @llvm.wasm.atomic.notify(i32* %{{.*}}, i32 %{{.*}}) 68 // WEBASSEMBLY64: call i32 @llvm.wasm.atomic.notify(i32* %{{.*}}, i32 %{{.*}}) 69 } 70 71 int trunc_saturate_s_i32_f32(float f) { 72 return __builtin_wasm_trunc_saturate_s_i32_f32(f); 73 // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %f) 74 // WEBASSEMBLY-NEXT: ret 75 } 76 77 int trunc_saturate_u_i32_f32(float f) { 78 return __builtin_wasm_trunc_saturate_u_i32_f32(f); 79 // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %f) 80 // WEBASSEMBLY-NEXT: ret 81 } 82 83 int trunc_saturate_s_i32_f64(double f) { 84 return __builtin_wasm_trunc_saturate_s_i32_f64(f); 85 // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %f) 86 // WEBASSEMBLY-NEXT: ret 87 } 88 89 int trunc_saturate_u_i32_f64(double f) { 90 return __builtin_wasm_trunc_saturate_u_i32_f64(f); 91 // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %f) 92 // WEBASSEMBLY-NEXT: ret 93 } 94 95 long long trunc_saturate_s_i64_f32(float f) { 96 return __builtin_wasm_trunc_saturate_s_i64_f32(f); 97 // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %f) 98 // WEBASSEMBLY-NEXT: ret 99 } 100 101 long long trunc_saturate_u_i64_f32(float f) { 102 return __builtin_wasm_trunc_saturate_u_i64_f32(f); 103 // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %f) 104 // WEBASSEMBLY-NEXT: ret 105 } 106 107 long long trunc_saturate_s_i64_f64(double f) { 108 return __builtin_wasm_trunc_saturate_s_i64_f64(f); 109 // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %f) 110 // WEBASSEMBLY-NEXT: ret 111 } 112 113 long long trunc_saturate_u_i64_f64(double f) { 114 return __builtin_wasm_trunc_saturate_u_i64_f64(f); 115 // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %f) 116 // WEBASSEMBLY-NEXT: ret 117 } 118 119 float min_f32(float x, float y) { 120 return __builtin_wasm_min_f32(x, y); 121 // WEBASSEMBLY: call float @llvm.minimum.f32(float %x, float %y) 122 // WEBASSEMBLY-NEXT: ret 123 } 124 125 float max_f32(float x, float y) { 126 return __builtin_wasm_max_f32(x, y); 127 // WEBASSEMBLY: call float @llvm.maximum.f32(float %x, float %y) 128 // WEBASSEMBLY-NEXT: ret 129 } 130 131 double min_f64(double x, double y) { 132 return __builtin_wasm_min_f64(x, y); 133 // WEBASSEMBLY: call double @llvm.minimum.f64(double %x, double %y) 134 // WEBASSEMBLY-NEXT: ret 135 } 136 137 double max_f64(double x, double y) { 138 return __builtin_wasm_max_f64(x, y); 139 // WEBASSEMBLY: call double @llvm.maximum.f64(double %x, double %y) 140 // WEBASSEMBLY-NEXT: ret 141 } 142 143 144 int extract_lane_s_i8x16(i8x16 v) { 145 return __builtin_wasm_extract_lane_s_i8x16(v, 13); 146 // MISSING-SIMD: error: '__builtin_wasm_extract_lane_s_i8x16' needs target feature simd128 147 // WEBASSEMBLY: extractelement <16 x i8> %v, i32 13 148 // WEBASSEMBLY-NEXT: sext 149 // WEBASSEMBLY-NEXT: ret 150 } 151 152 int extract_lane_u_i8x16(i8x16 v) { 153 return __builtin_wasm_extract_lane_u_i8x16(v, 13); 154 // WEBASSEMBLY: extractelement <16 x i8> %v, i32 13 155 // WEBASSEMBLY-NEXT: zext 156 // WEBASSEMBLY-NEXT: ret 157 } 158 159 int extract_lane_s_i16x8(i16x8 v) { 160 return __builtin_wasm_extract_lane_s_i16x8(v, 7); 161 // WEBASSEMBLY: extractelement <8 x i16> %v, i32 7 162 // WEBASSEMBLY-NEXT: sext 163 // WEBASSEMBLY-NEXT: ret 164 } 165 166 int extract_lane_u_i16x8(i16x8 v) { 167 return __builtin_wasm_extract_lane_u_i16x8(v, 7); 168 // WEBASSEMBLY: extractelement <8 x i16> %v, i32 7 169 // WEBASSEMBLY-NEXT: zext 170 // WEBASSEMBLY-NEXT: ret 171 } 172 173 int extract_lane_i32x4(i32x4 v) { 174 return __builtin_wasm_extract_lane_i32x4(v, 3); 175 // WEBASSEMBLY: extractelement <4 x i32> %v, i32 3 176 // WEBASSEMBLY-NEXT: ret 177 } 178 179 long long extract_lane_i64x2(i64x2 v) { 180 return __builtin_wasm_extract_lane_i64x2(v, 1); 181 // WEBASSEMBLY: extractelement <2 x i64> %v, i32 1 182 // WEBASSEMBLY-NEXT: ret 183 } 184 185 float extract_lane_f32x4(f32x4 v) { 186 return __builtin_wasm_extract_lane_f32x4(v, 3); 187 // WEBASSEMBLY: extractelement <4 x float> %v, i32 3 188 // WEBASSEMBLY-NEXT: ret 189 } 190 191 double extract_lane_f64x2(f64x2 v) { 192 return __builtin_wasm_extract_lane_f64x2(v, 1); 193 // WEBASSEMBLY: extractelement <2 x double> %v, i32 1 194 // WEBASSEMBLY-NEXT: ret 195 } 196 197 i8x16 replace_lane_i8x16(i8x16 v, int x) { 198 return __builtin_wasm_replace_lane_i8x16(v, 13, x); 199 // WEBASSEMBLY: trunc i32 %x to i8 200 // WEBASSEMBLY-NEXT: insertelement <16 x i8> %v, i8 %{{.*}}, i32 13 201 // WEBASSEMBLY-NEXT: ret 202 } 203 204 i16x8 replace_lane_i16x8(i16x8 v, int x) { 205 return __builtin_wasm_replace_lane_i16x8(v, 7, x); 206 // WEBASSEMBLY: trunc i32 %x to i16 207 // WEBASSEMBLY-NEXT: insertelement <8 x i16> %v, i16 %{{.*}}, i32 7 208 // WEBASSEMBLY-NEXT: ret 209 } 210 211 i32x4 replace_lane_i32x4(i32x4 v, int x) { 212 return __builtin_wasm_replace_lane_i32x4(v, 3, x); 213 // WEBASSEMBLY: insertelement <4 x i32> %v, i32 %x, i32 3 214 // WEBASSEMBLY-NEXT: ret 215 } 216 217 i64x2 replace_lane_i64x2(i64x2 v, long long x) { 218 return __builtin_wasm_replace_lane_i64x2(v, 1, x); 219 // WEBASSEMBLY: insertelement <2 x i64> %v, i64 %x, i32 1 220 // WEBASSEMBLY-NEXT: ret 221 } 222 223 f32x4 replace_lane_f32x4(f32x4 v, float x) { 224 return __builtin_wasm_replace_lane_f32x4(v, 3, x); 225 // WEBASSEMBLY: insertelement <4 x float> %v, float %x, i32 3 226 // WEBASSEMBLY-NEXT: ret 227 } 228 229 f64x2 replace_lane_f64x2(f64x2 v, double x) { 230 return __builtin_wasm_replace_lane_f64x2(v, 1, x); 231 // WEBASSEMBLY: insertelement <2 x double> %v, double %x, i32 1 232 // WEBASSEMBLY-NEXT: ret 233 } 234 235 i8x16 add_saturate_s_i8x16(i8x16 x, i8x16 y) { 236 return __builtin_wasm_add_saturate_s_i8x16(x, y); 237 // WEBASSEMBLY: call <16 x i8> @llvm.sadd.sat.v16i8( 238 // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) 239 // WEBASSEMBLY-NEXT: ret 240 } 241 242 i8x16 add_saturate_u_i8x16(i8x16 x, i8x16 y) { 243 return __builtin_wasm_add_saturate_u_i8x16(x, y); 244 // WEBASSEMBLY: call <16 x i8> @llvm.uadd.sat.v16i8( 245 // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) 246 // WEBASSEMBLY-NEXT: ret 247 } 248 249 i16x8 add_saturate_s_i16x8(i16x8 x, i16x8 y) { 250 return __builtin_wasm_add_saturate_s_i16x8(x, y); 251 // WEBASSEMBLY: call <8 x i16> @llvm.sadd.sat.v8i16( 252 // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) 253 // WEBASSEMBLY-NEXT: ret 254 } 255 256 i16x8 add_saturate_u_i16x8(i16x8 x, i16x8 y) { 257 return __builtin_wasm_add_saturate_u_i16x8(x, y); 258 // WEBASSEMBLY: call <8 x i16> @llvm.uadd.sat.v8i16( 259 // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) 260 // WEBASSEMBLY-NEXT: ret 261 } 262 263 i8x16 sub_saturate_s_i8x16(i8x16 x, i8x16 y) { 264 return __builtin_wasm_sub_saturate_s_i8x16(x, y); 265 // WEBASSEMBLY: call <16 x i8> @llvm.wasm.sub.saturate.signed.v16i8( 266 // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) 267 // WEBASSEMBLY-NEXT: ret 268 } 269 270 i8x16 sub_saturate_u_i8x16(i8x16 x, i8x16 y) { 271 return __builtin_wasm_sub_saturate_u_i8x16(x, y); 272 // WEBASSEMBLY: call <16 x i8> @llvm.wasm.sub.saturate.unsigned.v16i8( 273 // WEBASSEMBLY-SAME: <16 x i8> %x, <16 x i8> %y) 274 // WEBASSEMBLY-NEXT: ret 275 } 276 277 i16x8 sub_saturate_s_i16x8(i16x8 x, i16x8 y) { 278 return __builtin_wasm_sub_saturate_s_i16x8(x, y); 279 // WEBASSEMBLY: call <8 x i16> @llvm.wasm.sub.saturate.signed.v8i16( 280 // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) 281 // WEBASSEMBLY-NEXT: ret 282 } 283 284 i16x8 sub_saturate_u_i16x8(i16x8 x, i16x8 y) { 285 return __builtin_wasm_sub_saturate_u_i16x8(x, y); 286 // WEBASSEMBLY: call <8 x i16> @llvm.wasm.sub.saturate.unsigned.v8i16( 287 // WEBASSEMBLY-SAME: <8 x i16> %x, <8 x i16> %y) 288 // WEBASSEMBLY-NEXT: ret 289 } 290 291 i32x4 bitselect(i32x4 x, i32x4 y, i32x4 c) { 292 return __builtin_wasm_bitselect(x, y, c); 293 // WEBASSEMBLY: call <4 x i32> @llvm.wasm.bitselect.v4i32( 294 // WEBASSEMBLY-SAME: <4 x i32> %x, <4 x i32> %y, <4 x i32> %c) 295 // WEBASSEMBLY-NEXT: ret 296 } 297 298 int any_true_i8x16(i8x16 x) { 299 return __builtin_wasm_any_true_i8x16(x); 300 // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> %x) 301 // WEBASSEMBLY: ret 302 } 303 304 int any_true_i16x8(i16x8 x) { 305 return __builtin_wasm_any_true_i16x8(x); 306 // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v8i16(<8 x i16> %x) 307 // WEBASSEMBLY: ret 308 } 309 310 int any_true_i32x4(i32x4 x) { 311 return __builtin_wasm_any_true_i32x4(x); 312 // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v4i32(<4 x i32> %x) 313 // WEBASSEMBLY: ret 314 } 315 316 int any_true_i64x2(i64x2 x) { 317 return __builtin_wasm_any_true_i64x2(x); 318 // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v2i64(<2 x i64> %x) 319 // WEBASSEMBLY: ret 320 } 321 322 int all_true_i8x16(i8x16 x) { 323 return __builtin_wasm_all_true_i8x16(x); 324 // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v16i8(<16 x i8> %x) 325 // WEBASSEMBLY: ret 326 } 327 328 int all_true_i16x8(i16x8 x) { 329 return __builtin_wasm_all_true_i16x8(x); 330 // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v8i16(<8 x i16> %x) 331 // WEBASSEMBLY: ret 332 } 333 334 int all_true_i32x4(i32x4 x) { 335 return __builtin_wasm_all_true_i32x4(x); 336 // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v4i32(<4 x i32> %x) 337 // WEBASSEMBLY: ret 338 } 339 340 int all_true_i64x2(i64x2 x) { 341 return __builtin_wasm_all_true_i64x2(x); 342 // WEBASSEMBLY: call i32 @llvm.wasm.alltrue.v2i64(<2 x i64> %x) 343 // WEBASSEMBLY: ret 344 } 345 346 f32x4 abs_f32x4(f32x4 x) { 347 return __builtin_wasm_abs_f32x4(x); 348 // WEBASSEMBLY: call <4 x float> @llvm.fabs.v4f32(<4 x float> %x) 349 // WEBASSEMBLY: ret 350 } 351 352 f64x2 abs_f64x2(f64x2 x) { 353 return __builtin_wasm_abs_f64x2(x); 354 // WEBASSEMBLY: call <2 x double> @llvm.fabs.v2f64(<2 x double> %x) 355 // WEBASSEMBLY: ret 356 } 357 358 f32x4 min_f32x4(f32x4 x, f32x4 y) { 359 return __builtin_wasm_min_f32x4(x, y); 360 // WEBASSEMBLY: call <4 x float> @llvm.minimum.v4f32( 361 // WEBASSEMBLY-SAME: <4 x float> %x, <4 x float> %y) 362 // WEBASSEMBLY-NEXT: ret 363 } 364 365 f32x4 max_f32x4(f32x4 x, f32x4 y) { 366 return __builtin_wasm_max_f32x4(x, y); 367 // WEBASSEMBLY: call <4 x float> @llvm.maximum.v4f32( 368 // WEBASSEMBLY-SAME: <4 x float> %x, <4 x float> %y) 369 // WEBASSEMBLY-NEXT: ret 370 } 371 372 f64x2 min_f64x2(f64x2 x, f64x2 y) { 373 return __builtin_wasm_min_f64x2(x, y); 374 // WEBASSEMBLY: call <2 x double> @llvm.minimum.v2f64( 375 // WEBASSEMBLY-SAME: <2 x double> %x, <2 x double> %y) 376 // WEBASSEMBLY-NEXT: ret 377 } 378 379 f64x2 max_f64x2(f64x2 x, f64x2 y) { 380 return __builtin_wasm_max_f64x2(x, y); 381 // WEBASSEMBLY: call <2 x double> @llvm.maximum.v2f64( 382 // WEBASSEMBLY-SAME: <2 x double> %x, <2 x double> %y) 383 // WEBASSEMBLY-NEXT: ret 384 } 385 386 f32x4 sqrt_f32x4(f32x4 x) { 387 return __builtin_wasm_sqrt_f32x4(x); 388 // WEBASSEMBLY: call <4 x float> @llvm.sqrt.v4f32(<4 x float> %x) 389 // WEBASSEMBLY: ret 390 } 391 392 f64x2 sqrt_f64x2(f64x2 x) { 393 return __builtin_wasm_sqrt_f64x2(x); 394 // WEBASSEMBLY: call <2 x double> @llvm.sqrt.v2f64(<2 x double> %x) 395 // WEBASSEMBLY: ret 396 } 397 398 i32x4 trunc_saturate_s_i32x4_f32x4(f32x4 f) { 399 return __builtin_wasm_trunc_saturate_s_i32x4_f32x4(f); 400 // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %f) 401 // WEBASSEMBLY-NEXT: ret 402 } 403 404 i32x4 trunc_saturate_u_i32x4_f32x4(f32x4 f) { 405 return __builtin_wasm_trunc_saturate_u_i32x4_f32x4(f); 406 // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %f) 407 // WEBASSEMBLY-NEXT: ret 408 } 409 410 i64x2 trunc_saturate_s_i64x2_f64x2(f64x2 f) { 411 return __builtin_wasm_trunc_saturate_s_i64x2_f64x2(f); 412 // WEBASSEMBLY: call <2 x i64> @llvm.wasm.trunc.saturate.signed.v2i64.v2f64(<2 x double> %f) 413 // WEBASSEMBLY-NEXT: ret 414 } 415 416 i64x2 trunc_saturate_u_i64x2_f64x2(f64x2 f) { 417 return __builtin_wasm_trunc_saturate_u_i64x2_f64x2(f); 418 // WEBASSEMBLY: call <2 x i64> @llvm.wasm.trunc.saturate.unsigned.v2i64.v2f64(<2 x double> %f) 419 // WEBASSEMBLY-NEXT: ret 420 } 421