blob: 4c5951355b49a1847dcf95c46861b9082ebe80c6 [file] [edit]
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --implicit-check-not="OpTypeInt 128" --implicit-check-not="OpTypeInt 512"
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; Bitcasts between bool vectors and other vectors are decomposed per element,
; without an integer as wide as the whole vector. Constant-index extracts only
; compute the extracted lanes.
; CHECK-DAG: %[[#BOOL:]] = OpTypeBool
; CHECK-DAG: %[[#I8:]] = OpTypeInt 8 0
; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0
; CHECK-DAG: %[[#F32:]] = OpTypeFloat 32
; CHECK-DAG: %[[#V2I8:]] = OpTypeVector %[[#I8]] 2
; CHECK-DAG: %[[#V4I32:]] = OpTypeVector %[[#I32]] 4
; CHECK-DAG: %[[#V16I32:]] = OpTypeVector %[[#I32]] 16
; CHECK-DAG: %[[#V16F32:]] = OpTypeVector %[[#F32]] 16
; CHECK-DAG: %[[#BVEC16:]] = OpTypeVector %[[#BOOL]] 16
; CHECK-DAG: %[[#ZERO8:]] = OpConstantNull %[[#I8]]
; CHECK-DAG: %[[#ONE8:]] = OpConstant %[[#I8]] 1{{$}}
; CHECK-DAG: %[[#TWO8:]] = OpConstant %[[#I8]] 2{{$}}
; CHECK-DAG: %[[#C7_8:]] = OpConstant %[[#I8]] 7{{$}}
; CHECK-DAG: %[[#C128_8:]] = OpConstant %[[#I8]] 128{{$}}
; CHECK-DAG: %[[#ZERO32:]] = OpConstantNull %[[#I32]]
; CHECK-DAG: %[[#ONE32:]] = OpConstant %[[#I32]] 1{{$}}
; CHECK-DAG: %[[#C16_32:]] = OpConstant %[[#I32]] 16{{$}}
; CHECK-DAG: %[[#SIGN32:]] = OpConstant %[[#I32]] 2147483648{{$}}
; bitcast <16 x i32> to <512 x i1>, reading lane 0.
;
; CHECK: OpFunction %[[#BOOL]]
; CHECK: %[[#L0_ARG:]] = OpFunctionParameter %[[#V16I32]]
; CHECK: OpLabel
; CHECK-NEXT:%[[#L0_E:]] = OpCompositeExtract %[[#I32]] %[[#L0_ARG]] 0
; CHECK-NEXT:%[[#L0_A:]] = OpBitwiseAnd %[[#I32]] %[[#L0_E]] %[[#ONE32]]
; CHECK-NEXT:%[[#L0_C:]] = OpINotEqual %[[#BOOL]] %[[#L0_A]] %[[#ZERO32]]
; CHECK-NEXT:OpReturnValue %[[#L0_C]]
; CHECK-NEXT:OpFunctionEnd
define i1 @v16i32_lane0(<16 x i32> %v) {
%b = bitcast <16 x i32> %v to <512 x i1>
%e = extractelement <512 x i1> %b, i64 0
ret i1 %e
}
; bitcast <4 x i32> to <128 x i1>, reading lanes on both sides of element
; boundaries.
;
; CHECK: OpFunction %[[#BOOL]]
; CHECK: %[[#LS_ARG:]] = OpFunctionParameter %[[#V4I32]]
; CHECK: OpLabel
; CHECK-NEXT:%[[#LS_E31:]] = OpCompositeExtract %[[#I32]] %[[#LS_ARG]] 0
; CHECK-NEXT:%[[#LS_A31:]] = OpBitwiseAnd %[[#I32]] %[[#LS_E31]] %[[#SIGN32]]
; CHECK-NEXT:%[[#LS_C31:]] = OpINotEqual %[[#BOOL]] %[[#LS_A31]] %[[#ZERO32]]
; CHECK-NEXT:%[[#LS_E32:]] = OpCompositeExtract %[[#I32]] %[[#LS_ARG]] 1
; CHECK-NEXT:%[[#LS_A32:]] = OpBitwiseAnd %[[#I32]] %[[#LS_E32]] %[[#ONE32]]
; CHECK-NEXT:%[[#LS_C32:]] = OpINotEqual %[[#BOOL]] %[[#LS_A32]] %[[#ZERO32]]
; CHECK-NEXT:%[[#LS_E127:]] = OpCompositeExtract %[[#I32]] %[[#LS_ARG]] 3
; CHECK-NEXT:%[[#LS_A127:]] = OpBitwiseAnd %[[#I32]] %[[#LS_E127]] %[[#SIGN32]]
; CHECK-NEXT:%[[#LS_C127:]] = OpINotEqual %[[#BOOL]] %[[#LS_A127]] %[[#ZERO32]]
; CHECK-NEXT:%[[#LS_X:]] = OpLogicalNotEqual %[[#BOOL]] %[[#LS_C31]] %[[#LS_C32]]
; CHECK-NEXT:%[[#LS_Y:]] = OpLogicalNotEqual %[[#BOOL]] %[[#LS_X]] %[[#LS_C127]]
; CHECK-NEXT:OpReturnValue %[[#LS_Y]]
; CHECK-NEXT:OpFunctionEnd
define i1 @v4i32_lanes(<4 x i32> %v) {
%b = bitcast <4 x i32> %v to <128 x i1>
%e31 = extractelement <128 x i1> %b, i64 31
%e32 = extractelement <128 x i1> %b, i64 32
%e127 = extractelement <128 x i1> %b, i64 127
%x = xor i1 %e31, %e32
%y = xor i1 %x, %e127
ret i1 %y
}
; bitcast <16 x float> to <512 x i1>, reading lane 100: bit 4 of element 3.
;
; CHECK: OpFunction %[[#BOOL]]
; CHECK: %[[#FL_ARG:]] = OpFunctionParameter %[[#V16F32]]
; CHECK: OpLabel
; CHECK-NEXT:%[[#FL_I:]] = OpBitcast %[[#V16I32]] %[[#FL_ARG]]
; CHECK-NEXT:%[[#FL_E:]] = OpCompositeExtract %[[#I32]] %[[#FL_I]] 3
; CHECK-NEXT:%[[#FL_A:]] = OpBitwiseAnd %[[#I32]] %[[#FL_E]] %[[#C16_32]]
; CHECK-NEXT:%[[#FL_C:]] = OpINotEqual %[[#BOOL]] %[[#FL_A]] %[[#ZERO32]]
; CHECK-NEXT:OpReturnValue %[[#FL_C]]
; CHECK-NEXT:OpFunctionEnd
define i1 @v16f32_lane100(<16 x float> %v) {
%b = bitcast <16 x float> %v to <512 x i1>
%e = extractelement <512 x i1> %b, i64 100
ret i1 %e
}
; bitcast <2 x i8> to <16 x i1> with a variable-index extract, which needs all
; lanes, and a constant-index extract of lane 9, which is still computed
; directly.
;
; CHECK: OpFunction %[[#BOOL]]
; CHECK: %[[#DYN_ARG:]] = OpFunctionParameter %[[#V2I8]]
; CHECK: %[[#DYN_IDX:]] = OpFunctionParameter %[[#I32]]
; CHECK: OpLabel
; CHECK: %[[#DYN_VEC:]] = OpCompositeInsert %[[#BVEC16]] %{{.*}} %{{.*}} 15
; CHECK-NEXT:%[[#DYN_E:]] = OpVectorExtractDynamic %[[#BOOL]] %[[#DYN_VEC]] %[[#DYN_IDX]]
; CHECK-NEXT:%[[#DYN_E9:]] = OpCompositeExtract %[[#I8]] %[[#DYN_ARG]] 1
; CHECK-NEXT:%[[#DYN_A9:]] = OpBitwiseAnd %[[#I8]] %[[#DYN_E9]] %[[#TWO8]]
; CHECK-NEXT:%[[#DYN_C9:]] = OpINotEqual %[[#BOOL]] %[[#DYN_A9]] %[[#ZERO8]]
; CHECK-NEXT:%[[#DYN_X:]] = OpLogicalNotEqual %[[#BOOL]] %[[#DYN_E]] %[[#DYN_C9]]
; CHECK-NEXT:OpReturnValue %[[#DYN_X]]
; CHECK-NEXT:OpFunctionEnd
define i1 @v2i8_dynamic_lane(<2 x i8> %v, i32 %i) {
%b = bitcast <2 x i8> %v to <16 x i1>
%e = extractelement <16 x i1> %b, i32 %i
%e9 = extractelement <16 x i1> %b, i32 9
%x = xor i1 %e, %e9
ret i1 %x
}
; bitcast <4 x float> to <128 x i1> and back to <4 x i32>, with all lanes used.
;
; CHECK: OpFunction %[[#V4I32]]
; CHECK: %[[#RT_ARG:]] = OpFunctionParameter
; CHECK: OpLabel
; CHECK: %[[#RT_I:]] = OpBitcast %[[#V4I32]] %[[#RT_ARG]]
; CHECK: OpCompositeExtract %[[#I32]] %[[#RT_I]] 0
; CHECK: OpCompositeExtract %[[#I32]] %[[#RT_I]] 3
; CHECK: OpBitwiseAnd %[[#I32]] %{{.*}} %[[#SIGN32]]
; CHECK: OpLogicalNot
; CHECK: OpCompositeInsert %[[#V4I32]] %{{.*}} %{{.*}} 3
; CHECK: OpReturnValue
; CHECK: OpFunctionEnd
define <4 x i32> @v4f32_roundtrip(<4 x float> %v) {
%b = bitcast <4 x float> %v to <128 x i1>
%n = xor <128 x i1> %b, splat (i1 true)
%r = bitcast <128 x i1> %n to <4 x i32>
ret <4 x i32> %r
}
; bitcast <16 x i32> to <512 x i1> and back, with all lanes used.
;
; CHECK: OpFunction %[[#V16I32]]
; CHECK: %[[#RT512_ARG:]] = OpFunctionParameter %[[#V16I32]]
; CHECK: OpLabel
; CHECK: OpCompositeExtract %[[#I32]] %[[#RT512_ARG]] 15
; CHECK: OpCompositeInsert %[[#V16I32]] %{{.*}} %{{.*}} 15
; CHECK: OpReturnValue
; CHECK: OpFunctionEnd
define <16 x i32> @v16i32_roundtrip(<16 x i32> %v) {
%b = bitcast <16 x i32> %v to <512 x i1>
%n = xor <512 x i1> %b, splat (i1 true)
%r = bitcast <512 x i1> %n to <16 x i32>
ret <16 x i32> %r
}
; bitcast <2 x i8> to <16 x i1>: lanes 0 to 7 are bits of element 0, lanes 8
; to 15 bits of element 1.
;
; CHECK: OpFunction %[[#BVEC16]]
; CHECK: %[[#V2B_ARG:]] = OpFunctionParameter %[[#V2I8]]
; CHECK: OpLabel
; CHECK-NEXT:%[[#V2B_E0:]] = OpCompositeExtract %[[#I8]] %[[#V2B_ARG]] 0
; CHECK-NEXT:%[[#V2B_A0:]] = OpBitwiseAnd %[[#I8]] %[[#V2B_E0]] %[[#ONE8]]
; CHECK-NEXT:%[[#V2B_C0:]] = OpINotEqual %[[#BOOL]] %[[#V2B_A0]] %[[#ZERO8]]
; CHECK-NEXT:%[[#V2B_I0:]] = OpCompositeInsert %[[#BVEC16]] %[[#V2B_C0]] %{{.*}} 0
; CHECK: OpCompositeInsert %[[#BVEC16]] %{{.*}} %{{.*}} 6
; CHECK-NEXT:%[[#V2B_E7:]] = OpCompositeExtract %[[#I8]] %[[#V2B_ARG]] 0
; CHECK-NEXT:%[[#V2B_A7:]] = OpBitwiseAnd %[[#I8]] %[[#V2B_E7]] %[[#C128_8]]
; CHECK-NEXT:%[[#V2B_C7:]] = OpINotEqual %[[#BOOL]] %[[#V2B_A7]] %[[#ZERO8]]
; CHECK-NEXT:%[[#V2B_I7:]] = OpCompositeInsert %[[#BVEC16]] %[[#V2B_C7]] %{{.*}} 7
; CHECK-NEXT:%[[#V2B_E8:]] = OpCompositeExtract %[[#I8]] %[[#V2B_ARG]] 1
; CHECK-NEXT:%[[#V2B_A8:]] = OpBitwiseAnd %[[#I8]] %[[#V2B_E8]] %[[#ONE8]]
; CHECK-NEXT:%[[#V2B_C8:]] = OpINotEqual %[[#BOOL]] %[[#V2B_A8]] %[[#ZERO8]]
; CHECK-NEXT:%[[#V2B_I8:]] = OpCompositeInsert %[[#BVEC16]] %[[#V2B_C8]] %[[#V2B_I7]] 8
; CHECK: %[[#V2B_I14:]] = OpCompositeInsert %[[#BVEC16]] %{{.*}} %{{.*}} 14
; CHECK-NEXT:%[[#V2B_E15:]] = OpCompositeExtract %[[#I8]] %[[#V2B_ARG]] 1
; CHECK-NEXT:%[[#V2B_A15:]] = OpBitwiseAnd %[[#I8]] %[[#V2B_E15]] %[[#C128_8]]
; CHECK-NEXT:%[[#V2B_C15:]] = OpINotEqual %[[#BOOL]] %[[#V2B_A15]] %[[#ZERO8]]
; CHECK-NEXT:%[[#V2B_I15:]] = OpCompositeInsert %[[#BVEC16]] %[[#V2B_C15]] %[[#V2B_I14]] 15
; CHECK-NEXT:OpReturnValue %[[#V2B_I15]]
; CHECK-NEXT:OpFunctionEnd
define <16 x i1> @v2i8_to_boolvec(<2 x i8> %v) {
%b = bitcast <2 x i8> %v to <16 x i1>
ret <16 x i1> %b
}
; bitcast <16 x i1> to <2 x i8>: element 0 is built from lanes 0 to 7, element 1
; from lanes 8 to 15.
;
; CHECK: OpFunction %[[#V2I8]]
; CHECK: %[[#B2V_ARG:]] = OpFunctionParameter %[[#BVEC16]]
; CHECK: OpLabel
; CHECK: OpCompositeExtract %[[#BOOL]] %[[#B2V_ARG]] 6
; CHECK-NEXT:OpSelect
; CHECK-NEXT:OpShiftLeftLogical
; CHECK-NEXT:%[[#B2V_O6:]] = OpBitwiseOr %[[#I8]]
; CHECK-NEXT:%[[#B2V_L7:]] = OpCompositeExtract %[[#BOOL]] %[[#B2V_ARG]] 7
; CHECK-NEXT:%[[#B2V_S7:]] = OpSelect %[[#I8]] %[[#B2V_L7]] %[[#ONE8]] %[[#ZERO8]]
; CHECK-NEXT:%[[#B2V_H7:]] = OpShiftLeftLogical %[[#I8]] %[[#B2V_S7]] %[[#C7_8]]
; CHECK-NEXT:%[[#B2V_O7:]] = OpBitwiseOr %[[#I8]] %[[#B2V_O6]] %[[#B2V_H7]]
; CHECK-NEXT:%[[#B2V_V0:]] = OpCompositeInsert %[[#V2I8]] %[[#B2V_O7]] %{{.*}} 0
; CHECK-NEXT:%[[#B2V_L8:]] = OpCompositeExtract %[[#BOOL]] %[[#B2V_ARG]] 8
; CHECK-NEXT:%[[#B2V_S8:]] = OpSelect %[[#I8]] %[[#B2V_L8]] %[[#ONE8]] %[[#ZERO8]]
; CHECK-NEXT:%[[#B2V_O8:]] = OpBitwiseOr %[[#I8]] %[[#ZERO8]] %[[#B2V_S8]]
; CHECK-NEXT:%[[#B2V_L9:]] = OpCompositeExtract %[[#BOOL]] %[[#B2V_ARG]] 9
; CHECK-NEXT:%[[#B2V_S9:]] = OpSelect %[[#I8]] %[[#B2V_L9]] %[[#ONE8]] %[[#ZERO8]]
; CHECK-NEXT:%[[#B2V_H9:]] = OpShiftLeftLogical %[[#I8]] %[[#B2V_S9]] %[[#ONE8]]
; CHECK-NEXT:%[[#B2V_O9:]] = OpBitwiseOr %[[#I8]] %[[#B2V_O8]] %[[#B2V_H9]]
; CHECK: OpCompositeExtract %[[#BOOL]] %[[#B2V_ARG]] 14
; CHECK-NEXT:OpSelect
; CHECK-NEXT:OpShiftLeftLogical
; CHECK-NEXT:%[[#B2V_O14:]] = OpBitwiseOr %[[#I8]]
; CHECK-NEXT:%[[#B2V_L15:]] = OpCompositeExtract %[[#BOOL]] %[[#B2V_ARG]] 15
; CHECK-NEXT:%[[#B2V_S15:]] = OpSelect %[[#I8]] %[[#B2V_L15]] %[[#ONE8]] %[[#ZERO8]]
; CHECK-NEXT:%[[#B2V_H15:]] = OpShiftLeftLogical %[[#I8]] %[[#B2V_S15]] %[[#C7_8]]
; CHECK-NEXT:%[[#B2V_O15:]] = OpBitwiseOr %[[#I8]] %[[#B2V_O14]] %[[#B2V_H15]]
; CHECK-NEXT:%[[#B2V_V1:]] = OpCompositeInsert %[[#V2I8]] %[[#B2V_O15]] %[[#B2V_V0]] 1
; CHECK-NEXT:OpReturnValue %[[#B2V_V1]]
; CHECK-NEXT:OpFunctionEnd
define <2 x i8> @boolvec_to_v2i8(<16 x i1> %v) {
%b = bitcast <16 x i1> %v to <2 x i8>
ret <2 x i8> %b
}