kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit d74fc43d6c6e0e04eae4ea221404d54a769acf28
parent 2dadd8b01a1000932423b27d2625bf5b2ca8098d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 16 Jun 2026 09:38:06 -0700

test/opt: o1p_rider structural+correctness guard for L7/L8 (O1-PATTERNS)

Adds test/opt/o1p_rider.sh. L7: a+(b<<k) emits add/sub/and xD,xB,xS,lsl #k with
no standalone lsl; L8: signed/unsigned int array access emits ldr/str [xB, wI,
sxtw/uxtw #scale] with no standalone sxtw/uxtw. Both sections RED-GREEN against
$KIT_BASE when present, include a multiply-used / value-reused negative case
that must NOT fold, and an O0==O1 correctness program covering negative-index
sign-extension. Structural disasm checks gate on an arm64 host (the aa64 folded
forms); correctness builds everywhere and execs on arm64. Run via
KIT=build/kit bash test/opt/o1p_rider.sh. Not wired into mk/test.mk.

Diffstat:
Atest/opt/o1p_rider.sh | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 215 insertions(+), 0 deletions(-)

diff --git a/test/opt/o1p_rider.sh b/test/opt/o1p_rider.sh @@ -0,0 +1,215 @@ +#!/usr/bin/env bash +# Structural + correctness guards for the two -O1 operand-rider folds from +# doc/plan/O1-PATTERNS.md §2 (L7, L8). Both extend the optimizer Operand model +# with a rider field consumed only by a backend that advertises the matching +# NativeTarget capability hook (aa64 today; x64/rv64 keep the unfolded form): +# +# L7 shift rider on a register ALU operand +# a + (b<<k) -> add xD,xB,xS,lsl #k (no separate `lsl`) +# src/opt/pass_combine.c try_fold_shift_into_alu + aa64 aa_binop +# +# L8 extend rider on a load/store index operand +# a[i] (signed int i) -> ldr wD,[xB, wI, sxtw #2] (no sxtw+add) +# src/opt/pass_combine.c try_addr_synth (L8 block) + aa64 aa_emit_mem +# +# Each section is GREEN-only against the candidate kit ($KIT): it asserts the +# folded idiom is PRESENT and the unfolded scaffolding (separate lsl / sxtw+add) +# is GONE, that a multiply-used producer is NOT folded (negative case), and that +# the program computes the identical correct result at -O0 and -O1. When a +# baseline ($KIT_BASE) is present the structural assertions are additionally +# checked RED on it (the baseline must still emit the unfolded form). The folded +# forms are aa64-specific, so the structural disasm checks only run on an +# arm64/Darwin host; correctness runs wherever the host can execute the output. +set -uo pipefail + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +KIT="${KIT:-$ROOT/build/kit}" +KIT_BASE="${KIT_BASE:-$ROOT/build/kit_base}" +WORK="$ROOT/build/test/opt/o1p_rider" +mkdir -p "$WORK" +SYS="$(xcrun --sdk macosx --show-sdk-path 2>/dev/null || echo)" + +# Structural disasm checks only make sense for the aa64 folded forms; gate them +# on an arm64 host (the only place this worktree natively runs the output too). +HOST_ARCH="$(uname -m 2>/dev/null || echo unknown)" +do_struct=1 +case "$HOST_ARCH" in + arm64 | aarch64) ;; + *) do_struct=0 ;; +esac + +fail() { + printf 'o1p_rider FAILED: %s\n' "$1" >&2 + shift || true + for f in "$@"; do + printf ' --- %s ---\n' "$f" >&2 + sed 's/^/ | /' "$f" >&2 + done + exit 1 +} + +have_base=1 +[ -x "$KIT_BASE" ] || { + have_base=0 + printf 'o1p_rider: note: no %s — RED baseline checks skipped (GREEN-only)\n' \ + "$KIT_BASE" >&2 +} + +# count_re FILE REGEX -> number of matching disasm lines +count_re() { grep -cE "$2" "$1" || true; } + +# ---------------------------------------------------------------------------- +# L7 — fold a single-use shift into the consuming ALU op +# ---------------------------------------------------------------------------- +echo "== L7 shift-into-ALU ==" +cat > "$WORK/l7.c" <<'EOF' +long add_shl(long a, long b) { return a + (b << 3); } +long sub_shl(long a, long b) { return a - (b << 2); } +long and_shl(long a, long b) { return a & (b << 1); } +EOF +cat > "$WORK/l7_neg.c" <<'EOF' +extern long g; +/* shift result used twice (stored AND added): must NOT fold; lsl stays. */ +long multi_use(long a, long b) { long s = b << 3; g = s; return a + s; } +EOF + +if [ "$do_struct" = 1 ] && [ -n "$SYS" ]; then + "$KIT" cc -O1 --sysroot "$SYS" -c "$WORK/l7.c" -o "$WORK/l7.o" \ + > "$WORK/l7.cc" 2>&1 || fail "L7 candidate compile failed" "$WORK/l7.cc" + "$KIT" objdump -d "$WORK/l7.o" > "$WORK/l7.dis" 2>&1 + # GREEN: at least three shifted-register ALU ops (add/sub/and ...,lsl #k), + # and zero standalone `lsl xN,xM,#k` left behind. + SR="$(count_re "$WORK/l7.dis" '\b(add|sub|and|orr|eor)\b[^;]*,[[:space:]]*lsl[[:space:]]+#[1-4]\b')" + # A STANDALONE lsl is the instruction mnemonic (`lsl xN,xM,#k`), distinct from + # the `lsl #k` shift modifier inside a shifted-register ALU op. Match the + # mnemonic position (after the tab, immediately followed by a register). + LSL="$(count_re "$WORK/l7.dis" $'\tlsl[[:space:]]+[wx][0-9]+,')" + [ "$SR" -ge 3 ] || fail "L7: expected >=3 shifted-reg ALU ops, got $SR" "$WORK/l7.dis" + [ "$LSL" -eq 0 ] || fail "L7: standalone lsl should be folded away, got $LSL" "$WORK/l7.dis" + printf ' L7: shifted-reg ALU ops=%s, standalone lsl=%s (GREEN)\n' "$SR" "$LSL" + + # Negative: multiply-used shift keeps its lsl and a plain add. + "$KIT" cc -O1 --sysroot "$SYS" -c "$WORK/l7_neg.c" -o "$WORK/l7n.o" \ + > "$WORK/l7n.cc" 2>&1 || fail "L7 neg compile failed" "$WORK/l7n.cc" + "$KIT" objdump -d "$WORK/l7n.o" > "$WORK/l7n.dis" 2>&1 + NEG_LSL="$(count_re "$WORK/l7n.dis" $'\tlsl[[:space:]]+[wx][0-9]+,')" + NEG_SR="$(count_re "$WORK/l7n.dis" '\badd\b[^;]*,[[:space:]]*lsl[[:space:]]+#[1-4]\b')" + [ "$NEG_LSL" -ge 1 ] || fail "L7 neg: multiply-used lsl must remain, got $NEG_LSL" "$WORK/l7n.dis" + [ "$NEG_SR" -eq 0 ] || fail "L7 neg: must NOT fold a multiply-used shift, got $NEG_SR" "$WORK/l7n.dis" + printf ' L7 neg: multiply-used lsl kept=%s, folded=%s (correctly NOT folded)\n' \ + "$NEG_LSL" "$NEG_SR" + + if [ "$have_base" = 1 ]; then + "$KIT_BASE" cc -O1 --sysroot "$SYS" -c "$WORK/l7.c" -o "$WORK/l7.base.o" \ + > "$WORK/l7.base.cc" 2>&1 || fail "L7 baseline compile failed" "$WORK/l7.base.cc" + "$KIT_BASE" objdump -d "$WORK/l7.base.o" > "$WORK/l7.base.dis" 2>&1 + BSR="$(count_re "$WORK/l7.base.dis" '\b(add|sub|and|orr|eor)\b[^;]*,[[:space:]]*lsl[[:space:]]+#[1-4]\b')" + [ "$BSR" -eq 0 ] || fail "L7 RED precondition: baseline already folds (sr=$BSR)" "$WORK/l7.base.dis" + printf ' L7: baseline shifted-reg ALU ops=%s (RED) -> candidate=%s (GREEN)\n' "$BSR" "$SR" + fi +else + printf ' L7: structural disasm checks skipped (non-aa64 host or no SDK)\n' +fi + +# ---------------------------------------------------------------------------- +# L8 — fold a sxtw/uxtw index into the load/store addressing mode +# ---------------------------------------------------------------------------- +echo "== L8 extend-into-addr ==" +cat > "$WORK/l8.c" <<'EOF' +int load_signed(int* a, int i) { return a[i]; } +void store_signed(long* a, int i, long v) { a[i] = v; } +unsigned load_unsigned(unsigned* a, unsigned ui) { return a[ui]; } +EOF +cat > "$WORK/l8_neg.c" <<'EOF' +extern long g; +/* widened index used twice (stored AND used as index): the sxtw must remain. */ +long shared(long* a, int i) { long w = (long)i; g = w; return a[w]; } +EOF + +if [ "$do_struct" = 1 ] && [ -n "$SYS" ]; then + "$KIT" cc -O1 --sysroot "$SYS" -c "$WORK/l8.c" -o "$WORK/l8.o" \ + > "$WORK/l8.cc" 2>&1 || fail "L8 candidate compile failed" "$WORK/l8.cc" + "$KIT" objdump -d "$WORK/l8.o" > "$WORK/l8.dis" 2>&1 + # GREEN: the load/store carry the folded extended-register index, and there + # is no standalone `sxtw`/`uxtw` left to widen it. + FOLD="$(count_re "$WORK/l8.dis" '\b(ldr|str)\b[^;]*\[[^]]*,[[:space:]]*w[0-9]+,[[:space:]]*(sxtw|uxtw)[[:space:]]+#[0-3]\]')" + # Standalone sxtw/uxtw is the mnemonic `sxtw xN,wM` — distinct from the + # `sxtw #k` extend modifier inside a folded addressing mode. + STX="$(count_re "$WORK/l8.dis" $'\t(sxtw|uxtw)[[:space:]]+[wx][0-9]+,')" + [ "$FOLD" -ge 2 ] || fail "L8: expected >=2 folded sxtw/uxtw addressing modes, got $FOLD" "$WORK/l8.dis" + [ "$STX" -eq 0 ] || fail "L8: standalone sxtw/uxtw should be folded away, got $STX" "$WORK/l8.dis" + printf ' L8: folded extend addressing modes=%s, standalone sxtw/uxtw=%s (GREEN)\n' "$FOLD" "$STX" + + # Negative: a widened value reused beyond the index keeps its sxtw. + "$KIT" cc -O1 --sysroot "$SYS" -c "$WORK/l8_neg.c" -o "$WORK/l8n.o" \ + > "$WORK/l8n.cc" 2>&1 || fail "L8 neg compile failed" "$WORK/l8n.cc" + "$KIT" objdump -d "$WORK/l8n.o" > "$WORK/l8n.dis" 2>&1 + NEG_SXTW="$(count_re "$WORK/l8n.dis" $'\tsxtw[[:space:]]+x[0-9]+,')" + [ "$NEG_SXTW" -ge 1 ] || fail "L8 neg: reused sxtw must remain, got $NEG_SXTW" "$WORK/l8n.dis" + printf ' L8 neg: reused sxtw kept=%s (the stored widened value stays live)\n' "$NEG_SXTW" + + if [ "$have_base" = 1 ]; then + "$KIT_BASE" cc -O1 --sysroot "$SYS" -c "$WORK/l8.c" -o "$WORK/l8.base.o" \ + > "$WORK/l8.base.cc" 2>&1 || fail "L8 baseline compile failed" "$WORK/l8.base.cc" + "$KIT_BASE" objdump -d "$WORK/l8.base.o" > "$WORK/l8.base.dis" 2>&1 + BFOLD="$(count_re "$WORK/l8.base.dis" '\b(ldr|str)\b[^;]*\[[^]]*,[[:space:]]*w[0-9]+,[[:space:]]*(sxtw|uxtw)[[:space:]]+#[0-3]\]')" + [ "$BFOLD" -eq 0 ] || fail "L8 RED precondition: baseline already folds (fold=$BFOLD)" "$WORK/l8.base.dis" + printf ' L8: baseline folded addressing modes=%s (RED) -> candidate=%s (GREEN)\n' "$BFOLD" "$FOLD" + fi +else + printf ' L8: structural disasm checks skipped (non-aa64 host or no SDK)\n' +fi + +# ---------------------------------------------------------------------------- +# Correctness: O0 must equal O1, exercising both folds (incl. negative index +# sign-extension and the multiply-used / value-reused non-fold paths). +# ---------------------------------------------------------------------------- +echo "== rider correctness (O0 == O1) ==" +cat > "$WORK/run.c" <<'EOF' +long g; +long add_shl(long a, long b) { return a + (b << 3); } +long sub_shl(long a, long b) { return a - (b << 2); } +long multi_use(long a, long b) { long s = b << 3; g = s; return a + s; } +long load_neg(long* a, int i) { return a[i]; } /* sxtw: i may be negative */ +unsigned load_u(unsigned* a, unsigned ui) { return a[ui]; } +long shared(long* a, int i) { long w = (long)i; g = w; return a[w]; } +int sum(int* a, int n) { int s = 0; for (int i = 0; i < n; i++) s += a[i] + (i << 2); return s; } + +int main(void) { + long la[5] = {7, 8, 9, 11, 13}; + unsigned ua[5] = {100, 200, 300, 400, 500}; + int ia[6] = {1, 2, 3, 4, 5, 6}; + long acc = 0; + acc += add_shl(100, 5); /* 140 */ + acc += sub_shl(100, 5); /* 80 */ + acc += multi_use(100, 5); /* 140; g=40 */ + acc += g; /* +40 */ + acc += load_neg(la + 2, -2); /* la[0] = 7 (negative index) */ + acc += (long)load_u(ua, 3); /* 400 */ + acc += shared(la, 4); /* la[4]=13; g=4 */ + acc += g; /* +4 */ + acc += sum(ia, 6); /* 21 + 60 = 81 */ + /* total = 140+80+140+40+7+400+13+4+81 = 905 */ + return (int)(acc - 905); /* 0 on success */ +} +EOF +if [ -n "$SYS" ]; then + "$KIT" cc -O0 --sysroot "$SYS" "$WORK/run.c" -o "$WORK/run_o0" -lc \ + > "$WORK/run0.cc" 2>&1 || fail "rider O0 link failed" "$WORK/run0.cc" + "$KIT" cc -O1 --sysroot "$SYS" "$WORK/run.c" -o "$WORK/run_o1" -lc \ + > "$WORK/run1.cc" 2>&1 || fail "rider O1 link failed" "$WORK/run1.cc" + if [ "$do_struct" = 1 ]; then + "$WORK/run_o0"; rc0=$? + "$WORK/run_o1"; rc1=$? + [ "$rc0" -eq 0 ] || fail "rider O0 run wrong result rc=$rc0" + [ "$rc1" -eq 0 ] || fail "rider O1 run wrong result rc=$rc1" + [ "$rc0" -eq "$rc1" ] || fail "rider O0 ($rc0) != O1 ($rc1)" + printf ' rider: O0==O1 (rc=%s) — both folds correct incl. negative index\n' "$rc0" + else + printf ' rider: built O0/O1 OK; exec skipped (non-aa64 host)\n' + fi +else + printf ' rider: correctness skipped (no SDK)\n' +fi + +echo "o1p_rider: OK"