| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: llc < %s -fast-isel -fast-isel-abort=0 -mattr=+simd128 -verify-machineinstrs | FileCheck %s | |
| ; RUN: llc < %s -mtriple=wasm64 -fast-isel -fast-isel-abort=0 -mattr=+simd128 -verify-machineinstrs | FileCheck %s | |
| target triple = "wasm32-unknown-unknown" | |
| define i8 @pr165438(<4 x i32> %0) { | |
| ; CHECK-LABEL: pr165438: | |
| ; CHECK: .functype pr165438 (v128) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: i8x16.shuffle 0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| ; CHECK-NEXT: i8x16.extract_lane_u 0 | |
| ; CHECK-NEXT: # fallthrough-return | |
| entry: | |
| %conv = trunc <4 x i32> %0 to <4 x i8> | |
| br label %cond.true | |
| cond.true: ; preds = %entry | |
| %vecext = extractelement <4 x i8> %conv, i32 0 | |
| ret i8 %vecext | |
| } | |
| ; selectICmp classifies any non-i64 operand as i32 and selectFCmp any | |
| ; non-f64 operand as f32, so without the vector bail-out a vector | |
| ; compare takes the FastISel path and emits a scalar i32.eq/f32.eq over | |
| ; v128 registers, failing module validation. FastISel has no vector | |
| ; compare lowering of its own, so a valid SIMD compare can only come | |
| ; from the SelectionDAG fallback; the wasm64 RUN re-runs the same checks | |
| ; under the triple the mis-lowering was found with. The scalar eq_i32 | |
| ; guards that the bail-out is vector-only. | |
| declare i1 @any16(<16 x i1>) | |
| declare i1 @any4(<4 x i1>) | |
| define i32 @eq_i8x16(<16 x i8> %a, <16 x i8> %b) { | |
| ; CHECK-LABEL: eq_i8x16: | |
| ; CHECK: .functype eq_i8x16 (v128, v128) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: local.get 1 | |
| ; CHECK-NEXT: i8x16.ne | |
| ; CHECK-NEXT: call any16 | |
| ; CHECK-NEXT: i32.const 1 | |
| ; CHECK-NEXT: i32.and | |
| ; CHECK-NEXT: # fallthrough-return | |
| entry: | |
| %c = icmp ne <16 x i8> %a, %b | |
| %r = call i1 @any16(<16 x i1> %c) | |
| %z = zext i1 %r to i32 | |
| ret i32 %z | |
| } | |
| define i32 @eq_f32x4(<4 x float> %a, <4 x float> %b) { | |
| ; CHECK-LABEL: eq_f32x4: | |
| ; CHECK: .functype eq_f32x4 (v128, v128) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: local.get 1 | |
| ; CHECK-NEXT: f32x4.eq | |
| ; CHECK-NEXT: call any4 | |
| ; CHECK-NEXT: i32.const 1 | |
| ; CHECK-NEXT: i32.and | |
| ; CHECK-NEXT: # fallthrough-return | |
| entry: | |
| %c = fcmp oeq <4 x float> %a, %b | |
| %r = call i1 @any4(<4 x i1> %c) | |
| %z = zext i1 %r to i32 | |
| ret i32 %z | |
| } | |
| define i32 @eq_i32(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: eq_i32: | |
| ; CHECK: .functype eq_i32 (i32, i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: local.get 1 | |
| ; CHECK-NEXT: i32.eq | |
| ; CHECK-NEXT: i32.const 1 | |
| ; CHECK-NEXT: i32.and | |
| ; CHECK-NEXT: # fallthrough-return | |
| entry: | |
| %c = icmp eq i32 %a, %b | |
| %z = zext i1 %c to i32 | |
| ret i32 %z | |
| } |