[llvm] [SPIRV]Implementing PopCount for 16 and 64 bits (PR #191283)

Steven Perron via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 07:22:07 PDT 2026


=?utf-8?q?João?= Saffran <joaosaffranllvm at gmail.com>,Joao Saffran
 <joaosaffranllvm at gmail.com>,Joao Saffran <joaosaffranllvm at gmail.com>,Joao
 Saffran <joaosaffranllvm at gmail.com>,Joao Saffran <joaosaffranllvm at gmail.com>,Joao
 Saffran <joaosaffranllvm at gmail.com>,Joao Saffran <joaosaffranllvm at gmail.com>,Joao
 Saffran <joaosaffranllvm at gmail.com>,Joao Saffran <joaosaffranllvm at gmail.com>,Joao
 Saffran <joaosaffranllvm at gmail.com>,Joao Saffran <joaosaffranllvm at gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/191283 at github.com>


================
@@ -0,0 +1,144 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-unknown %s -o - -filetype=obj | spirv-val %}
+
+
+; CHECK-DAG: [[i8_t:%.+]]  = OpTypeInt 8 0
+; CHECK-DAG: [[i16_t:%.+]] = OpTypeInt 16 0
+; CHECK-DAG: [[i32_t:%.+]] = OpTypeInt 32 0
+; CHECK-DAG: [[i64_t:%.+]] = OpTypeInt 64 0
+; CHECK-DAG: [[i32x2_t:%.+]] = OpTypeVector [[i32_t]] 2
+; CHECK-DAG: [[i32x3_t:%.+]] = OpTypeVector [[i32_t]] 3
+; CHECK-DAG: [[i32x4_t:%.+]] = OpTypeVector [[i32_t]] 4
+; CHECK-DAG: [[i64x2_t:%.+]] = OpTypeVector [[i64_t]] 2
+; CHECK-DAG: [[i64x3_t:%.+]] = OpTypeVector [[i64_t]] 3
+; CHECK-DAG: [[i64x4_t:%.+]] = OpTypeVector [[i64_t]] 4
+; CHECK-DAG: [[i16x3_t:%.+]] = OpTypeVector [[i16_t]] 3
+
+; CHECK-DAG: [[zero:%.*]] = OpConstant [[i32_t]] 0
+; CHECK-DAG: [[one:%.*]] = OpConstant [[i32_t]] 1
+; CHECK-DAG: [[two:%.*]] = OpConstant [[i64_t]] 2
+
+; CHECK-LABEL:  ; -- Begin function test
+
+; CHECK: [[p8:%.+]] = OpFunctionParameter [[i8_t]]
+; CHECK: [[p16:%.+]] = OpFunctionParameter [[i16_t]]
+; CHECK: [[p32:%.+]] = OpFunctionParameter [[i32_t]]
+; CHECK: [[p64:%.+]] = OpFunctionParameter [[i64_t]]
+; CHECK: [[p32x2:%.+]] = OpFunctionParameter [[i32x2_t]]
+; CHECK: [[p64x2:%.+]] = OpFunctionParameter [[i64x2_t]]
+; CHECK: [[p64x3:%.+]] = OpFunctionParameter [[i64x3_t]]
+; CHECK: [[p64x4:%.+]] = OpFunctionParameter [[i64x4_t]]
+; CHECK: [[p16x3:%.+]] = OpFunctionParameter [[i16x3_t]]
+
+; p8
+; CHECK: [[p8_conversion_in:%.+]] = OpUConvert [[i32_t]] [[p8]]
+; CHECK: [[p8_bitcount:%.+]] = OpBitCount [[i32_t]] [[p8_conversion_in]]
+; CHECK: %[[#]] = OpUConvert [[i8_t]] [[p8_bitcount]]
+
+; p16
+; CHECK: [[p16_conversion_in:%.+]] = OpUConvert [[i32_t]] [[p16]]
+; CHECK: [[p16_bitcount:%.+]] = OpBitCount [[i32_t]] [[p16_conversion_in]]
+; CHECK: %[[#]] = OpUConvert [[i16_t]] [[p16_bitcount]]
+
+; p32
+; CHECK: [[p32_bitcount:%.+]] = OpBitCount [[i32_t]] [[p32]]
+
+; p64
+; CHECK: [[p64_bitcast:%.+]] = OpBitcast [[i32x2_t]] [[p64]]
+; CHECK: [[p64_bitcount:%.+]] = OpBitCount [[i32x2_t]] [[p64_bitcast]]
+; CHECK: [[index_one:%.+]] = OpVectorExtractDynamic [[i32_t]] [[p64_bitcount]] [[one]]
+; CHECK: [[index_zero:%.+]] = OpVectorExtractDynamic [[i32_t]] [[p64_bitcount]] [[zero]]
+; CHECK: [[add:%.+]] = OpIAdd [[i32_t]] [[index_one]] [[index_zero]]
+; CHECK: [[#]] = OpUConvert [[i64_t]] [[add]]
+
+; p32x2
+; CHECK: [[#]] = OpBitCount [[i32x2_t]] [[p32x2]]
+
+; p64x2
+; CHECK: [[p64x2_bitcast:%.+]] = OpBitcast [[i32x4_t]] [[p64x2]]
+; CHECK: [[p64x2_bitcount:%.+]] = OpBitCount [[i32x4_t]] [[p64x2_bitcast]]
+; CHECK: [[odd_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 1 3
+; CHECK: [[even_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 0 2
+; CHECK: [[add:%.+]] = OpIAdd [[i32x2_t]] [[odd_indexes]] [[even_indexes]]
+; CHECK: [[#]] = OpUConvert [[i64x2_t]] [[add]]
+
+; p64x3
+; CHECK: [[first_half:%.+]] = OpVectorShuffle [[i64x2_t]] [[p64x3]] [[p64x3]] 0 1
+; CHECK: [[p64x2_bitcast:%.+]] = OpBitcast [[i32x4_t]] [[first_half]]
+; CHECK: [[p64x2_bitcount:%.+]] = OpBitCount [[i32x4_t]] [[p64x2_bitcast]]
+; CHECK: [[odd_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 1 3
+; CHECK: [[even_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 0 2
+; CHECK: [[add:%.+]] = OpIAdd [[i32x2_t]] [[odd_indexes]] [[even_indexes]]
+; CHECK: [[first_half_result:%.+]] = OpUConvert [[i64x2_t]] [[add]]
+
+; CHECK: [[second_half:%.+]] = OpVectorExtractDynamic [[i64_t]] [[p64x3]] [[two]]
+; CHECK: [[p64_bitcast:%.+]] = OpBitcast [[i32x2_t]] [[second_half]]
+; CHECK: [[p64_bitcount:%.+]] = OpBitCount [[i32x2_t]] [[p64_bitcast]]
+; CHECK: [[index_one:%.+]] = OpVectorExtractDynamic [[i32_t]] [[p64_bitcount]] [[one]]
+; CHECK: [[index_zero:%.+]] = OpVectorExtractDynamic [[i32_t]] [[p64_bitcount]] [[zero]]
+; CHECK: [[add:%.+]] = OpIAdd [[i32_t]] [[index_one]] [[index_zero]]
+; CHECK: [[second_half_result:%.+]] = OpUConvert [[i64_t]] [[add]]
+; CHECK: %[[#]] = OpCompositeConstruct [[i64x3_t]] [[first_half_result]] [[second_half_result]]
+
+; p64x4
+; CHECK: [[first_half:%.+]] = OpVectorShuffle [[i64x2_t]] [[p64x4]] [[p64x4]] 0 1
+; CHECK: [[p64x2_bitcast:%.+]] = OpBitcast [[i32x4_t]] [[first_half]]
+; CHECK: [[p64x2_bitcount:%.+]] = OpBitCount [[i32x4_t]] [[p64x2_bitcast]]
+; CHECK: [[odd_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 1 3
+; CHECK: [[even_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 0 2
+; CHECK: [[add:%.+]] = OpIAdd [[i32x2_t]] [[odd_indexes]] [[even_indexes]]
+; CHECK: [[first_half_result:%.+]] = OpUConvert [[i64x2_t]] [[add]]
+
+; CHECK: [[second_half:%.+]] = OpVectorShuffle [[i64x2_t]] [[p64x4]] [[p64x4]] 2 3
+; CHECK: [[p64x2_bitcast:%.+]] = OpBitcast [[i32x4_t]] [[second_half]]
+; CHECK: [[p64x2_bitcount:%.+]] = OpBitCount [[i32x4_t]] [[p64x2_bitcast]]
+; CHECK: [[odd_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 1 3
+; CHECK: [[even_indexes:%.+]] = OpVectorShuffle [[i32x2_t]] [[p64x2_bitcount]] [[p64x2_bitcount]] 0 2
+; CHECK: [[add:%.+]] = OpIAdd [[i32x2_t]] [[odd_indexes]] [[even_indexes]]
+; CHECK: [[second_half_result:%.+]] = OpUConvert [[i64x2_t]] [[add]]
+
+; CHECK: %[[#]] = OpCompositeConstruct [[i64x4_t]] [[first_half_result]] [[second_half_result]]
+
+; p16x3
+; CHECK: [[p16_conversion_in:%.+]] = OpUConvert [[i32x3_t]] [[p16x3]]
+; CHECK: [[p16_bitcount:%.+]] = OpBitCount [[i32x3_t]] [[p16_conversion_in]]
+; CHECK: %[[#]] = OpUConvert [[i16x3_t]] [[p16_bitcount]]
+
+ at g1 = addrspace(1) global i8  0, align 4
+ at g2 = addrspace(1) global i16 0, align 4
+ at g3 = addrspace(1) global i32 0, align 4
+ at g4 = addrspace(1) global i64 0, align 8
+ at g5 = addrspace(1) global <2 x i32> zeroinitializer, align 4
+ at g6 = addrspace(1) global <2 x i64> zeroinitializer, align 8
+ at g7 = addrspace(1) global <3 x i64> zeroinitializer, align 8
+ at g8 = addrspace(1) global <4 x i64> zeroinitializer, align 8
+ at g9 = addrspace(1) global <3 x i16> zeroinitializer, align 4
----------------
s-perron wrote:

```suggestion
@g1 = private global i8  0, align 4
@g2 = private global i16 0, align 4
@g3 = private global i32 0, align 4
@g4 = private global i64 0, align 8
@g5 = private global <2 x i32> zeroinitializer, align 4
@g6 = private global <2 x i64> zeroinitializer, align 8
@g7 = private global <3 x i64> zeroinitializer, align 8
@g8 = private global <4 x i64> zeroinitializer, align 8
@g9 = private global <3 x i16> zeroinitializer, align 4
```

https://github.com/llvm/llvm-project/pull/191283


More information about the llvm-commits mailing list