414 lines
12 KiB
LLVM
414 lines
12 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mattr=+simd128 | FileCheck %s
|
|
|
|
;; Test that SIMD bitmask instruction can be selected
|
|
|
|
target triple = "wasm32-unknown-unknown"
|
|
|
|
define i16 @bitmask_v16i8(<16 x i8> %v) {
|
|
; CHECK-LABEL: bitmask_v16i8:
|
|
; CHECK: .functype bitmask_v16i8 (v128) -> (i32)
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: v128.const 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
; CHECK-NEXT: i8x16.eq
|
|
; CHECK-NEXT: i8x16.bitmask
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <16 x i8> %v, zeroinitializer
|
|
%bitmask = bitcast <16 x i1> %cmp to i16
|
|
ret i16 %bitmask
|
|
}
|
|
|
|
define i8 @bitmask_v8i16(<8 x i16> %v) {
|
|
; CHECK-LABEL: bitmask_v8i16:
|
|
; CHECK: .functype bitmask_v8i16 (v128) -> (i32)
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: v128.const 0, 0, 0, 0, 0, 0, 0, 0
|
|
; CHECK-NEXT: i16x8.eq
|
|
; CHECK-NEXT: i16x8.bitmask
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <8 x i16> %v, zeroinitializer
|
|
%bitmask = bitcast <8 x i1> %cmp to i8
|
|
ret i8 %bitmask
|
|
}
|
|
|
|
define i8 @bitmask_v4i32(<4 x i32> %v) {
|
|
; CHECK-LABEL: bitmask_v4i32:
|
|
; CHECK: .functype bitmask_v4i32 (v128) -> (i32)
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: v128.const 0, 0, 0, 0
|
|
; CHECK-NEXT: i32x4.eq
|
|
; CHECK-NEXT: i32x4.bitmask
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <4 x i32> %v, zeroinitializer
|
|
%bitmask = bitcast <4 x i1> %cmp to i4
|
|
%ext = zext i4 %bitmask to i8
|
|
ret i8 %ext
|
|
}
|
|
|
|
define i8 @bitmask_v2i64(<2 x i64> %v) {
|
|
; CHECK-LABEL: bitmask_v2i64:
|
|
; CHECK: .functype bitmask_v2i64 (v128) -> (i32)
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: v128.const 0, 0
|
|
; CHECK-NEXT: i64x2.eq
|
|
; CHECK-NEXT: i64x2.bitmask
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <2 x i64> %v, zeroinitializer
|
|
%bitmask = bitcast <2 x i1> %cmp to i2
|
|
%ext = zext i2 %bitmask to i8
|
|
ret i8 %ext
|
|
}
|
|
|
|
;; Test unusual vectors
|
|
|
|
define i1 @bitmask_v1i8(<1 x i8> %v) {
|
|
; CHECK-LABEL: bitmask_v1i8:
|
|
; CHECK: .functype bitmask_v1i8 (v128) -> (i32)
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 0
|
|
; CHECK-NEXT: i32.eqz
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <1 x i8> %v, zeroinitializer
|
|
%bitmask = bitcast <1 x i1> %cmp to i1
|
|
ret i1 %bitmask
|
|
}
|
|
|
|
define i7 @bitmask_v7i8(<7 x i8> %v) {
|
|
; CHECK-LABEL: bitmask_v7i8:
|
|
; CHECK: .functype bitmask_v7i8 (i32, i32, i32, i32, i32, i32, i32) -> (i32)
|
|
; CHECK-NEXT: .local v128
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: drop
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.splat
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i8x16.replace_lane 1
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i8x16.replace_lane 2
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i8x16.replace_lane 3
|
|
; CHECK-NEXT: local.get 4
|
|
; CHECK-NEXT: i8x16.replace_lane 4
|
|
; CHECK-NEXT: local.get 5
|
|
; CHECK-NEXT: i8x16.replace_lane 5
|
|
; CHECK-NEXT: local.get 6
|
|
; CHECK-NEXT: i8x16.replace_lane 6
|
|
; CHECK-NEXT: v128.const 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
; CHECK-NEXT: i8x16.eq
|
|
; CHECK-NEXT: local.tee 7
|
|
; CHECK-NEXT: i16x8.extract_lane_u 0
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: local.get 7
|
|
; CHECK-NEXT: i16x8.extend_low_i8x16_s
|
|
; CHECK-NEXT: local.tee 7
|
|
; CHECK-NEXT: i16x8.extract_lane_u 1
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 7
|
|
; CHECK-NEXT: i16x8.extract_lane_u 2
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 2
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 7
|
|
; CHECK-NEXT: i16x8.extract_lane_u 3
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 3
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 7
|
|
; CHECK-NEXT: i16x8.extract_lane_u 4
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 4
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 7
|
|
; CHECK-NEXT: i16x8.extract_lane_u 5
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 5
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 7
|
|
; CHECK-NEXT: i16x8.extract_lane_u 6
|
|
; CHECK-NEXT: i32.const 6
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.const 127
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <7 x i8> %v, zeroinitializer
|
|
%bitmask = bitcast <7 x i1> %cmp to i7
|
|
ret i7 %bitmask
|
|
}
|
|
|
|
define i8 @bitmask_v8i8(<8 x i8> %v) {
|
|
; CHECK-LABEL: bitmask_v8i8:
|
|
; CHECK: .functype bitmask_v8i8 (v128) -> (i32)
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: v128.const 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
; CHECK-NEXT: i8x16.eq
|
|
; CHECK-NEXT: i16x8.extend_low_i8x16_s
|
|
; CHECK-NEXT: i16x8.bitmask
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <8 x i8> %v, zeroinitializer
|
|
%bitmask = bitcast <8 x i1> %cmp to i8
|
|
ret i8 %bitmask
|
|
}
|
|
|
|
define i32 @bitmask_v32i8(<32 x i8> %v) {
|
|
; CHECK-LABEL: bitmask_v32i8:
|
|
; CHECK: .functype bitmask_v32i8 (v128, v128) -> (i32)
|
|
; CHECK-NEXT: .local v128
|
|
; CHECK-NEXT: # %bb.0:
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: drop
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: v128.const 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
; CHECK-NEXT: local.tee 2
|
|
; CHECK-NEXT: i8x16.eq
|
|
; CHECK-NEXT: local.tee 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 0
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 1
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 2
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 2
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 3
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 3
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 4
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 4
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 5
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 5
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 6
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 6
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 7
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 7
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 8
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 8
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 9
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 9
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 10
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 10
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 11
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 11
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 12
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 12
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 13
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 13
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 14
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 14
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 15
|
|
; CHECK-NEXT: i32.const 15
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i8x16.eq
|
|
; CHECK-NEXT: local.tee 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 15
|
|
; CHECK-NEXT: i32.const 31
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 14
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 30
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 13
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 29
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 12
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 28
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 11
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 27
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 10
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 26
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 9
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 25
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 8
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 24
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 7
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 23
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 6
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 22
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 5
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 21
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 4
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 20
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 3
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 19
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 2
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 18
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 1
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 17
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i8x16.extract_lane_u 0
|
|
; CHECK-NEXT: i32.const 1
|
|
; CHECK-NEXT: i32.and
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.shl
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: i32.or
|
|
; CHECK-NEXT: # fallthrough-return
|
|
%cmp = icmp eq <32 x i8> %v, zeroinitializer
|
|
%bitmask = bitcast <32 x i1> %cmp to i32
|
|
ret i32 %bitmask
|
|
}
|