231 lines · plain
1; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s2; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}3 4; CHECK-DAG: [[glsl_450_ext:%.+]] = OpExtInstImport "GLSL.std.450"5; CHECK-DAG: OpMemoryModel Logical GLSL4506; CHECK-DAG: [[u32_t:%.+]] = OpTypeInt 32 07; CHECK-DAG: [[u32x2_t:%.+]] = OpTypeVector [[u32_t]] 28; CHECK-DAG: [[u32x3_t:%.+]] = OpTypeVector [[u32_t]] 39; CHECK-DAG: [[u32x4_t:%.+]] = OpTypeVector [[u32_t]] 410; CHECK-DAG: [[const_0:%.*]] = OpConstant [[u32_t]] 011; CHECK-DAG: [[const_0x2:%.*]] = OpConstantComposite [[u32x2_t]] [[const_0]] [[const_0]]12; CHECK-DAG: [[const_1:%.*]] = OpConstant [[u32_t]] 113; CHECK-DAG: [[const_2:%.*]] = OpConstant [[u32_t]] 214; CHECK-DAG: [[const_32:%.*]] = OpConstant [[u32_t]] 3215; CHECK-DAG: [[const_32x2:%.*]] = OpConstantComposite [[u32x2_t]] [[const_32]] [[const_32]]16; CHECK-DAG: [[const_neg1:%.*]] = OpConstant [[u32_t]] 429496729517; CHECK-DAG: [[const_neg1x2:%.*]] = OpConstantComposite [[u32x2_t]] [[const_neg1]] [[const_neg1]]18; CHECK-DAG: [[u16_t:%.+]] = OpTypeInt 16 019; CHECK-DAG: [[u16x2_t:%.+]] = OpTypeVector [[u16_t]] 220; CHECK-DAG: [[u16x3_t:%.+]] = OpTypeVector [[u16_t]] 321; CHECK-DAG: [[u16x4_t:%.+]] = OpTypeVector [[u16_t]] 422; CHECK-DAG: [[u64_t:%.+]] = OpTypeInt 64 023; CHECK-DAG: [[u64x2_t:%.+]] = OpTypeVector [[u64_t]] 224; CHECK-DAG: [[u64x3_t:%.+]] = OpTypeVector [[u64_t]] 325; CHECK-DAG: [[u64x4_t:%.+]] = OpTypeVector [[u64_t]] 426; CHECK-DAG: [[bool_t:%.+]] = OpTypeBool27; CHECK-DAG: [[boolx2_t:%.+]] = OpTypeVector [[bool_t]] 228 29; CHECK-LABEL: Begin function firstbitlow_i3230define noundef i32 @firstbitlow_i32(i32 noundef %a) {31entry:32; CHECK: [[a:%.+]] = OpFunctionParameter [[u32_t]]33; CHECK: [[ret:%.+]] = OpExtInst [[u32_t]] [[glsl_450_ext]] FindILsb [[a]]34; CHECK: OpReturnValue [[ret]]35 %elt.firstbitlow = call i32 @llvm.spv.firstbitlow.i32(i32 %a)36 ret i32 %elt.firstbitlow37}38 39; CHECK-LABEL: Begin function firstbitlow_v2xi3240define noundef <2 x i32> @firstbitlow_v2xi32(<2 x i32> noundef %a) {41entry:42; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x2_t]]43; CHECK: [[ret:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[a]]44; CHECK: OpReturnValue [[ret]]45 %elt.firstbitlow = call <2 x i32> @llvm.spv.firstbitlow.v2i32(<2 x i32> %a)46 ret <2 x i32> %elt.firstbitlow47}48 49; CHECK-LABEL: Begin function firstbitlow_v3xi3250define noundef <3 x i32> @firstbitlow_v3xi32(<3 x i32> noundef %a) {51entry:52; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x3_t]]53; CHECK: [[ret:%.+]] = OpExtInst [[u32x3_t]] [[glsl_450_ext]] FindILsb [[a]]54; CHECK: OpReturnValue [[ret]]55 %elt.firstbitlow = call <3 x i32> @llvm.spv.firstbitlow.v3i32(<3 x i32> %a)56 ret <3 x i32> %elt.firstbitlow57}58 59; CHECK-LABEL: Begin function firstbitlow_v4xi3260define noundef <4 x i32> @firstbitlow_v4xi32(<4 x i32> noundef %a) {61entry:62; CHECK: [[a:%.+]] = OpFunctionParameter [[u32x4_t]]63; CHECK: [[ret:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[a]]64; CHECK: OpReturnValue [[ret]]65 %elt.firstbitlow = call <4 x i32> @llvm.spv.firstbitlow.v4i32(<4 x i32> %a)66 ret <4 x i32> %elt.firstbitlow67}68 69; CHECK-LABEL: Begin function firstbitlow_i1670define noundef i32 @firstbitlow_i16(i16 noundef %a) {71entry:72; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16_t]]73; CHECK: [[a32:%.+]] = OpUConvert [[u32_t]] [[a16]]74; CHECK: [[ret:%.+]] = OpExtInst [[u32_t]] [[glsl_450_ext]] FindILsb [[a32]]75; CHECK: OpReturnValue [[ret]]76 %elt.firstbitlow = call i32 @llvm.spv.firstbitlow.i16(i16 %a)77 ret i32 %elt.firstbitlow78}79 80; CHECK-LABEL: Begin function firstbitlow_v2xi1681define noundef <2 x i32> @firstbitlow_v2xi16(<2 x i16> noundef %a) {82entry:83; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x2_t]]84; CHECK: [[a32:%.+]] = OpUConvert [[u32x2_t]] [[a16]]85; CHECK: [[ret:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[a32]]86; CHECK: OpReturnValue [[ret]]87 %elt.firstbitlow = call <2 x i32> @llvm.spv.firstbitlow.v2i16(<2 x i16> %a)88 ret <2 x i32> %elt.firstbitlow89}90 91; CHECK-LABEL: Begin function firstbitlow_v3xi1692define noundef <3 x i32> @firstbitlow_v3xi16(<3 x i16> noundef %a) {93entry:94; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x3_t]]95; CHECK: [[a32:%.+]] = OpUConvert [[u32x3_t]] [[a16]]96; CHECK: [[ret:%.+]] = OpExtInst [[u32x3_t]] [[glsl_450_ext]] FindILsb [[a32]]97; CHECK: OpReturnValue [[ret]]98 %elt.firstbitlow = call <3 x i32> @llvm.spv.firstbitlow.v3i16(<3 x i16> %a)99 ret <3 x i32> %elt.firstbitlow100}101 102; CHECK-LABEL: Begin function firstbitlow_v4xi16103define noundef <4 x i32> @firstbitlow_v4xi16(<4 x i16> noundef %a) {104entry:105; CHECK: [[a16:%.+]] = OpFunctionParameter [[u16x4_t]]106; CHECK: [[a32:%.+]] = OpUConvert [[u32x4_t]] [[a16]]107; CHECK: [[ret:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[a32]]108; CHECK: OpReturnValue [[ret]]109 %elt.firstbitlow = call <4 x i32> @llvm.spv.firstbitlow.v4i16(<4 x i16> %a)110 ret <4 x i32> %elt.firstbitlow111}112 113; CHECK-LABEL: Begin function firstbitlow_i64114define noundef i32 @firstbitlow_i64(i64 noundef %a) {115entry:116; CHECK: [[a64:%.+]] = OpFunctionParameter [[u64_t]]117; CHECK: [[a32x2:%.+]] = OpBitcast [[u32x2_t]] [[a64]]118; CHECK: [[lsb_bits:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[a32x2]]119; CHECK: [[high_bits:%.+]] = OpVectorExtractDynamic [[u32_t]] [[lsb_bits]] [[const_0]]120; CHECK: [[low_bits:%.+]] = OpVectorExtractDynamic [[u32_t]] [[lsb_bits]] [[const_1]]121; CHECK: [[should_use_high:%.+]] = OpIEqual [[bool_t]] [[low_bits]] [[const_neg1]]122; CHECK: [[ans_bits:%.+]] = OpSelect [[u32_t]] [[should_use_high]] [[high_bits]] [[low_bits]]123; CHECK: [[ans_offset:%.+]] = OpSelect [[u32_t]] [[should_use_high]] [[const_32]] [[const_0]]124; CHECK: [[ret:%.+]] = OpIAdd [[u32_t]] [[ans_offset]] [[ans_bits]]125; CHECK: OpReturnValue [[ret]]126 %elt.firstbitlow = call i32 @llvm.spv.firstbitlow.i64(i64 %a)127 ret i32 %elt.firstbitlow128}129 130; CHECK-LABEL: Begin function firstbitlow_v2xi64131define noundef <2 x i32> @firstbitlow_v2xi64(<2 x i64> noundef %a) {132entry:133; CHECK: [[a64x2:%.+]] = OpFunctionParameter [[u64x2_t]]134; CHECK: [[a32x4:%.+]] = OpBitcast [[u32x4_t]] [[a64x2]]135; CHECK: [[lsb_bits:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[a32x4]]136; CHECK: [[high_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[lsb_bits]] [[lsb_bits]] 0 2137; CHECK: [[low_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[lsb_bits]] [[lsb_bits]] 1 3138; CHECK: [[should_use_high:%.+]] = OpIEqual [[boolx2_t]] [[low_bits]] [[const_neg1x2]]139; CHECK: [[ans_bits:%.+]] = OpSelect [[u32x2_t]] [[should_use_high]] [[high_bits]] [[low_bits]]140; CHECK: [[ans_offset:%.+]] = OpSelect [[u32x2_t]] [[should_use_high]] [[const_32x2]] [[const_0x2]]141; CHECK: [[ret:%.+]] = OpIAdd [[u32x2_t]] [[ans_offset]] [[ans_bits]]142; CHECK: OpReturnValue [[ret]]143 %elt.firstbitlow = call <2 x i32> @llvm.spv.firstbitlow.v2i64(<2 x i64> %a)144 ret <2 x i32> %elt.firstbitlow145}146 147; CHECK-LABEL: Begin function firstbitlow_v3xi64148define noundef <3 x i32> @firstbitlow_v3xi64(<3 x i64> noundef %a) {149entry:150; Preamble151; CHECK: [[a:%.+]] = OpFunctionParameter [[u64x3_t]]152 153; Extract first 2 components from %a154; CHECK: [[pt1:%.+]] = OpVectorShuffle [[u64x2_t]] [[a]] [[a]] 0 1155 156; Do firstbitlow on the first 2 components157; CHECK: [[pt1_cast:%.+]] = OpBitcast [[u32x4_t]] [[pt1]]158; CHECK: [[pt1_lsb_bits:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[pt1_cast]]159; CHECK: [[pt1_high_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[pt1_lsb_bits]] [[pt1_lsb_bits]] 0 2160; CHECK: [[pt1_low_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[pt1_lsb_bits]] [[pt1_lsb_bits]] 1 3161; CHECK: [[pt1_should_use_high:%.+]] = OpIEqual [[boolx2_t]] [[pt1_low_bits]] [[const_neg1x2]]162; CHECK: [[pt1_ans_bits:%.+]] = OpSelect [[u32x2_t]] [[pt1_should_use_high]] [[pt1_high_bits]] [[pt1_low_bits]]163; CHECK: [[pt1_ans_offset:%.+]] = OpSelect [[u32x2_t]] [[pt1_should_use_high]] [[const_32x2]] [[const_0x2]]164; CHECK: [[pt1_res:%.+]] = OpIAdd [[u32x2_t]] [[pt1_ans_offset]] [[pt1_ans_bits]]165 166; Extract the last component from %a167; CHECK: [[pt2:%.+]] = OpVectorExtractDynamic [[u64_t]] [[a]] [[const_2]]168 169; Do firstbitlow on the last component170; CHECK: [[pt2_cast:%.+]] = OpBitcast [[u32x2_t]] [[pt2]]171; CHECK: [[pt2_lsb_bits:%.+]] = OpExtInst [[u32x2_t]] [[glsl_450_ext]] FindILsb [[pt2_cast]]172; CHECK: [[pt2_high_bits:%.+]] = OpVectorExtractDynamic [[u32_t]] [[pt2_lsb_bits]] [[const_0]]173; CHECK: [[pt2_low_bits:%.+]] = OpVectorExtractDynamic [[u32_t]] [[pt2_lsb_bits]] [[const_1]]174; CHECK: [[pt2_should_use_high:%.+]] = OpIEqual [[bool_t]] [[pt2_low_bits]] [[const_neg1]]175; CHECK: [[pt2_ans_bits:%.+]] = OpSelect [[u32_t]] [[pt2_should_use_high]] [[pt2_high_bits]] [[pt2_low_bits]]176; CHECK: [[pt2_ans_offset:%.+]] = OpSelect [[u32_t]] [[pt2_should_use_high]] [[const_32]] [[const_0]]177; CHECK: [[pt2_res:%.+]] = OpIAdd [[u32_t]] [[pt2_ans_offset]] [[pt2_ans_bits]]178 179; Merge the parts into the final i32x3 and return it180; CHECK: [[ret:%.+]] = OpCompositeConstruct [[u32x3_t]] [[pt1_res]] [[pt2_res]]181; CHECK: OpReturnValue [[ret]]182 %elt.firstbitlow = call <3 x i32> @llvm.spv.firstbitlow.v3i64(<3 x i64> %a)183 ret <3 x i32> %elt.firstbitlow184}185 186; CHECK-LABEL: Begin function firstbitlow_v4xi64187define noundef <4 x i32> @firstbitlow_v4xi64(<4 x i64> noundef %a) {188entry:189; Preamble190; CHECK: [[a:%.+]] = OpFunctionParameter [[u64x4_t]]191 192; Extract first 2 components from %a193; CHECK: [[pt1:%.+]] = OpVectorShuffle [[u64x2_t]] [[a]] [[a]] 0 1194 195; Do firstbitlow on the first 2 components196; CHECK: [[pt1_cast:%.+]] = OpBitcast [[u32x4_t]] [[pt1]]197; CHECK: [[pt1_lsb_bits:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[pt1_cast]]198; CHECK: [[pt1_high_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[pt1_lsb_bits]] [[pt1_lsb_bits]] 0 2199; CHECK: [[pt1_low_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[pt1_lsb_bits]] [[pt1_lsb_bits]] 1 3200; CHECK: [[pt1_should_use_high:%.+]] = OpIEqual [[boolx2_t]] [[pt1_low_bits]] [[const_neg1x2]]201; CHECK: [[pt1_ans_bits:%.+]] = OpSelect [[u32x2_t]] [[pt1_should_use_high]] [[pt1_high_bits]] [[pt1_low_bits]]202; CHECK: [[pt1_ans_offset:%.+]] = OpSelect [[u32x2_t]] [[pt1_should_use_high]] [[const_32x2]] [[const_0x2]]203; CHECK: [[pt1_res:%.+]] = OpIAdd [[u32x2_t]] [[pt1_ans_offset]] [[pt1_ans_bits]]204 205; Extract last 2 components from %a206; CHECK: [[pt2:%.+]] = OpVectorShuffle [[u64x2_t]] [[a]] [[a]] 2 3207 208; Do firstbituhigh on the last 2 components209; CHECK: [[pt2_cast:%.+]] = OpBitcast [[u32x4_t]] [[pt2]]210; CHECK: [[pt2_lsb_bits:%.+]] = OpExtInst [[u32x4_t]] [[glsl_450_ext]] FindILsb [[pt2_cast]]211; CHECK: [[pt2_high_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[pt2_lsb_bits]] [[pt2_lsb_bits]] 0 2212; CHECK: [[pt2_low_bits:%.+]] = OpVectorShuffle [[u32x2_t]] [[pt2_lsb_bits]] [[pt2_lsb_bits]] 1 3213; CHECK: [[pt2_should_use_high:%.+]] = OpIEqual [[boolx2_t]] [[pt2_low_bits]] [[const_neg1x2]]214; CHECK: [[pt2_ans_bits:%.+]] = OpSelect [[u32x2_t]] [[pt2_should_use_high]] [[pt2_high_bits]] [[pt2_low_bits]]215; CHECK: [[pt2_ans_offset:%.+]] = OpSelect [[u32x2_t]] [[pt2_should_use_high]] [[const_32x2]] [[const_0x2]]216; CHECK: [[pt2_res:%.+]] = OpIAdd [[u32x2_t]] [[pt2_ans_offset]] [[pt2_ans_bits]]217 218; Merge the parts into the final i32x4 and return it219; CHECK: [[ret:%.+]] = OpCompositeConstruct [[u32x4_t]] [[pt1_res]] [[pt2_res]]220; CHECK: OpReturnValue [[ret]]221 %elt.firstbitlow = call <4 x i32> @llvm.spv.firstbitlow.v4i64(<4 x i64> %a)222 ret <4 x i32> %elt.firstbitlow223}224 225;declare i16 @llvm.spv.firstbitlow.i16(i16)226;declare i32 @llvm.spv.firstbitlow.i32(i32)227;declare i64 @llvm.spv.firstbitlow.i64(i64)228;declare i16 @llvm.spv.firstbitlow.v2i16(<2 x i16>)229;declare i32 @llvm.spv.firstbitlow.v2i32(<2 x i32>)230;declare i64 @llvm.spv.firstbitlow.v2i64(<2 x i64>)231