commit d0e90b94e9cab14cbabab9655e2210f3c620892a (tree)
parent 2d62c61b70e5eecacc6d7988cc084b45f86f449c
Author: Motiejus <motiejus@jakstys.lt>
Date: Sat, 7 Mar 2026 08:07:02 +0000
sema: fix zirBitCount comptime folding to use 128-bit wide values
Replace 64-bit isComptimeInt with 128-bit isComptimeIntWide for CLZ,
CTZ, and POPCOUNT comptime evaluation. Correctly handles integer types
wider than 64 bits (e.g. u128, i128).
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 58 | +++++++++++++++++++++++++++++++++++++--------------------- |
1 file changed, 37 insertions(+), 21 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -1287,41 +1287,57 @@ static AirInstRef zirBitCount(
TypeIndex result_ty = ipIntern(sema->ip, key);
// Comptime folding: if operand is a comptime integer, evaluate now.
- int64_t val;
- if (isComptimeInt(sema, operand, &val)) {
- uint64_t uval = (uint64_t)val;
+ // Use the wide (128-bit) path to handle types wider than 64 bits.
+ uint64_t val_lo, val_hi;
+ bool val_neg;
+ if (isComptimeIntWide(sema, operand, &val_lo, &val_hi, &val_neg)) {
uint64_t result = 0;
switch (air_tag) {
- case AIR_INST_CLZ:
- if (uval == 0 || bits == 0)
+ case AIR_INST_CLZ: {
+ if ((val_lo == 0 && val_hi == 0) || bits == 0) {
result = bits;
- else {
- result = 0;
- uint64_t mask = (uint64_t)1 << (bits - 1);
- while ((uval & mask) == 0) {
+ } else {
+ // Count leading zeros from bit (bits-1) downward.
+ uint16_t b = bits;
+ while (b > 0) {
+ b--;
+ uint64_t word = (b >= 64) ? val_hi : val_lo;
+ uint16_t bit_pos = b % 64;
+ if ((word >> bit_pos) & 1)
+ break;
result++;
- mask >>= 1;
}
}
break;
- case AIR_INST_CTZ:
- if (uval == 0)
+ }
+ case AIR_INST_CTZ: {
+ if (val_lo == 0 && val_hi == 0) {
result = bits;
- else {
- result = 0;
- while ((uval & 1) == 0) {
+ } else {
+ // Count trailing zeros from bit 0 upward.
+ for (uint16_t b = 0; b < bits; b++) {
+ uint64_t word = (b >= 64) ? val_hi : val_lo;
+ uint16_t bit_pos = b % 64;
+ if ((word >> bit_pos) & 1)
+ break;
result++;
- uval >>= 1;
}
}
break;
- case AIR_INST_POPCOUNT:
- result = 0;
- while (uval != 0) {
- result += uval & 1;
- uval >>= 1;
+ }
+ case AIR_INST_POPCOUNT: {
+ // Count all set bits.
+ uint64_t lo = val_lo, hi = val_hi;
+ while (lo) {
+ result += lo & 1;
+ lo >>= 1;
+ }
+ while (hi) {
+ result += hi & 1;
+ hi >>= 1;
}
break;
+ }
default:
break;
}