Move aarch64 Node16 SIMD index loads into assembly #76

Merged
andrew merged 2 commits from weaselbot/conflict-set:weaselbot/issue-68 into main 2026-08-03 13:42:51 +00:00
Showing only changes of commit e02dd41f74 - Show all commits
+11 -9
View File
@@ -1,8 +1,8 @@
// SIMD operations on potentially-indeterminate Node16::index[16] bytes.
// Written in assembly so msan doesn't track the loads, and so that loading
// and operating on indeterminate values is well-defined (unlike C++). The
// caller is responsible for masking the returned bitfield to [0, numChildren)
// before using it.
// Written in assembly because loading and operating on indeterminate values
Outdated
Review

It's not so msan doesn't track the loads, it's because it's not UB in asm

It's not so msan doesn't track the loads, it's because it's not UB in asm
// is undefined behavior in C++ ([basic.indet]) but well-defined in assembly.
// The caller is responsible for masking the returned bitfield to
// [0, numChildren) before using it.
//
// Unlike x86-64 (which has pmovmskb), AArch64 has no single instruction that
// produces a 1-bit-per-byte mask. Each function therefore returns a 64-bit
@@ -16,6 +16,10 @@
// w1 = uint8_t key (find_eq_16, find_ge_16)
// w1 = uint8_t begin (mask_in_range_16)
// w2 = uint8_t end (mask_in_range_16)
//
// These functions are only ever called directly (never indirectly), so they
// do not need BTI landing pads; the object is still marked BTI/PAC/GCS-aware
// below so a -z force-bti link keeps BTI enabled for the whole binary.
.text
1
@@ -24,7 +28,6 @@
.globl find_eq_16
.type find_eq_16, %function
find_eq_16:
hint 34 // bti c
dup v1.16b, w1 // broadcast key
ldr q0, [x0] // load 16 bytes (may be indeterminate)
cmeq v0.16b, v0.16b, v1.16b // 0xff for each match
@@ -39,7 +42,6 @@ find_eq_16:
.globl find_ge_16
.type find_ge_16, %function
find_ge_16:
hint 34 // bti c
dup v1.16b, w1 // broadcast child
ldr q0, [x0] // load 16 bytes
cmhs v0.16b, v0.16b, v1.16b // 0xff where idx[i] >= child (unsigned)
@@ -56,7 +58,6 @@ find_ge_16:
.globl mask_in_range_16
.type mask_in_range_16, %function
mask_in_range_16:
hint 34 // bti c
dup v1.16b, w1 // broadcast begin
dup v2.16b, w2 // broadcast end
ldr q0, [x0] // load 16 bytes
@@ -71,8 +72,9 @@ mask_in_range_16:
// Declare AArch64 branch-protection compatibility, matching what the
// compiler emits for -mbranch-protection=standard (BTI + PAC + GCS). This
// keeps the object indistinguishable from C/C++ translation units for
// linkers enforcing BTI (-z force-bti); the functions above only use
// `bti c` and no stack, so PAC/GCS compatibility holds trivially.
// linkers enforcing BTI (-z force-bti). The functions above are only ever
// called directly, so they need no BTI landing pads; PAC/GCS compatibility
// holds trivially since they use no stack.
.aeabi_subsection aeabi_feature_and_bits, optional, ULEB128
.aeabi_attribute Tag_Feature_BTI, 1