Reland "[vm] Recognize int.trailingZeroBitCount/oneBitCount as graph-inlinable"

The previous attempt was reverted because it broke unoptimized JIT
on ARM 32. This reland force-optimizes the two getters.

Stacks on top of the int.{trailingZeroBitCount,oneBitCount} API CL
(commit 754239b077). Both getters route through OTHER_RECOGNIZED_LIST
when a hardware fast path is available; otherwise the newly added
Dart bodies inline at call sites via vm:prefer-inline. The C++
natives are removed.

Backend codegen
---------------
ARM64:     NEON CNT + UADDLV (popcount); RBIT + CLZ (ctz).
ARM:       NEON CNT + VPADDL chain (popcount); RBIT + CLZ on the
           register pair (ctz).
x64:       popcntq when TargetCPUFeatures::popcnt_supported();
           LoadImmediate(64) + rep_bsfq for ctz (decodes as tzcnt
           on BMI1+, preserves dest on zero otherwise).
RISC-V 64: cpop / ctz when RV_baseline includes Zbb.

Per-arch availability is encapsulated in
UnaryInt64OpInstr::IsSupported(Token::Kind).

Apple M-series ARM64, AOT (us/iter, lower is better):
  cardinality.swar              371
  cardinality.accelerated       154    (2.4x)
  forEachSetBit.swar          19031
  forEachSetBit.accelerated    4988    (3.8x)
  select.swar                   199
  select.accelerated             77    (2.6x)
  complementCardinality.swar    399
  complementCardinality.accel   152    (2.6x)

Work towards https://github.com/dart-lang/sdk/issues/6486 (popcount
and ctz intrinsification).

Work towards https://github.com/dart-lang/sdk/issues/1053 (efficient
BitSet implementation).

Fixes https://github.com/dart-lang/sdk/issues/52673
Fixes https://github.com/dart-lang/sdk/issues/38346
Fixes https://github.com/dart-lang/sdk/issues/63436
Issue https://github.com/dart-lang/sdk/issues/10212
Issue https://github.com/dart-lang/sdk/issues/5798
TEST=tests/corelib/int_bit_count_test

Cq-Include-Trybots: luci.dart.try:vm-linux-release-simarm-try,vm-ffi-qemu-linux-release-arm-try,vm-aot-linux-release-simarm_x64-try,vm-aot-linux-debug-simarm_x64-try,dart-sdk-linux-riscv64-try
Change-Id: Ib812cbaec6e371b9720df7a543411f78e524cac1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/506060
Reviewed-by: Martin Kustermann <kustermann@google.com>
Auto-Submit: Modestas Valauskas <valauskasmodestas@gmail.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Modestas Valauskas
2026-05-29 06:01:17 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent abbd9e33ca
commit 415b040d6f
26 changed files with 424 additions and 29 deletions
+15 -4
View File
@@ -163,13 +163,24 @@ abstract final class _IntegerImplementation implements int {
@pragma("vm:external-name", "Integer_equalToInteger")
external bool _equalToInteger(int other);
@pragma("vm:recognized", "other")
@pragma("vm:prefer-inline")
@pragma("vm:exact-result-type", "dart:core#_Smi")
@pragma("vm:external-name", "Integer_trailingZeroBitCount")
external int get trailingZeroBitCount;
int get trailingZeroBitCount {
final int v = this;
return ((v - 1) & ~v).oneBitCount;
}
@pragma("vm:recognized", "other")
@pragma("vm:prefer-inline")
@pragma("vm:exact-result-type", "dart:core#_Smi")
@pragma("vm:external-name", "Integer_oneBitCount")
external int get oneBitCount;
int get oneBitCount {
int v = this;
v = v - ((v >>> 1) & 0x5555555555555555);
v = (v & 0x3333333333333333) + ((v >>> 2) & 0x3333333333333333);
v = (v + (v >>> 4)) & 0x0F0F0F0F0F0F0F0F;
return ((v * 0x0101010101010101) >>> 56);
}
int abs() {
return this < 0 ? -this : this;