summaryrefslogtreecommitdiff
path: root/prelude
diff options
context:
space:
mode:
authorsricker-nvidia <115114531+sricker-nvidia@users.noreply.github.com>2025-04-19 04:33:27 -0700
committerGitHub <noreply@github.com>2025-04-19 11:33:27 +0000
commit043278a527ab5744674417a08d924c67a60a486b (patch)
tree19c3ead87def94f2d418926d5f15b9eab1ced440 /prelude
parent6bfabfee317887e678eed9cd6768df2ffd3b9704 (diff)
Implement 64bit countbits intrinsic (#6433) (#6845)
Change modifies the countbits intrinsic to use generics in order to support 64bit countbits on select platforms where this is supported. On platforms where this is not natively supported, we emulate by converting the 64-bit type into a uint2 (metal and spir-v). This should align with the implementation of other uint64_t intrinsics such as abs, min, max and clamp. Added new countbits64 test to verify changes. Updated documentation for 64bit-type-support.html
Diffstat (limited to 'prelude')
-rw-r--r--prelude/slang-cpp-scalar-intrinsics.h25
-rw-r--r--prelude/slang-cuda-prelude.h10
2 files changed, 32 insertions, 3 deletions
diff --git a/prelude/slang-cpp-scalar-intrinsics.h b/prelude/slang-cpp-scalar-intrinsics.h
index 22b5e12e4..0a19eb327 100644
--- a/prelude/slang-cpp-scalar-intrinsics.h
+++ b/prelude/slang-cpp-scalar-intrinsics.h
@@ -661,6 +661,23 @@ SLANG_FORCE_INLINE double I32_asdouble(int32_t low, int32_t hi)
return u.d;
}
+SLANG_FORCE_INLINE uint32_t I32_countbits(int32_t v)
+{
+#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM)
+ return __builtin_popcount(uint32_t(v));
+#elif SLANG_PROCESSOR_X86_64 && SLANG_VC
+ return __popcnt(uint32_t(v));
+#else
+ uint32_t c = 0;
+ while (v)
+ {
+ c++;
+ v &= v - 1;
+ }
+ return c;
+#endif
+}
+
// ----------------------------- U32 -----------------------------------------
SLANG_FORCE_INLINE uint32_t U32_abs(uint32_t f)
@@ -729,9 +746,6 @@ SLANG_FORCE_INLINE uint64_t U64_max(uint64_t a, uint64_t b)
return a > b ? a : b;
}
-// TODO(JS): We don't define countbits for 64bit in the core module currently.
-// It's not clear from documentation if it should return 32 or 64 bits, if it exists.
-// 32 bits can always hold the result, and will be implicitly promoted.
SLANG_FORCE_INLINE uint32_t U64_countbits(uint64_t v)
{
#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM)
@@ -765,6 +779,11 @@ SLANG_FORCE_INLINE int64_t I64_max(int64_t a, int64_t b)
return a > b ? a : b;
}
+SLANG_FORCE_INLINE uint32_t I64_countbits(int64_t v)
+{
+ return U64_countbits(uint64_t(v));
+}
+
// ----------------------------- UPTR -----------------------------------------
SLANG_FORCE_INLINE uintptr_t UPTR_abs(uintptr_t f)
diff --git a/prelude/slang-cuda-prelude.h b/prelude/slang-cuda-prelude.h
index 5585ad6e0..38e018e3e 100644
--- a/prelude/slang-cuda-prelude.h
+++ b/prelude/slang-cuda-prelude.h
@@ -1823,6 +1823,11 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL double I32_asdouble(int32_t low, int32_t hi)
return u.d;
}
+SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I32_countbits(int32_t v)
+{
+ return __popc(uint32_t(v));
+}
+
// ----------------------------- U32 -----------------------------------------
// Unary
@@ -1882,6 +1887,11 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_max(int64_t a, int64_t b)
return a > b ? a : b;
}
+SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I64_countbits(int64_t v)
+{
+ return __popcll(uint64_t(v));
+}
+
// ----------------------------- U64 -----------------------------------------
SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t U64_abs(uint64_t f)