kit

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

zero_arg.sh (2272B)


      1 #!/usr/bin/env bash
      2 # Behavioral check for the O1 "zero through a temp" call-arg wart (PERCALL.md
      3 # item 3). A pointer-typed null argument (`(void*)0`) introduces an int->ptr
      4 # IR_CONVERT between the constant's `load_imm` and the call arg. At -O1 the
      5 # arg-register hint reaches the convert's def but not its load_imm source, so
      6 # the source lands in a scratch (x8) and the convert emits `mov x0, x8` --
      7 # routing each zero through a temp:
      8 #
      9 #   movz x8, 0x0 ; mov x0, x8 ; movz x8, 0x0 ; mov x1, x8     (4 insns)
     10 #
     11 # Optimal is `movz x0, 0x0 ; movz x1, 0x0` (2 insns, no temp). This test
     12 # asserts the args are materialized directly into the arg registers.
     13 set -euo pipefail
     14 
     15 ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
     16 KIT="${KIT:-$ROOT/build/kit}"
     17 WORK="$ROOT/build/test/opt/zero_arg"
     18 mkdir -p "$WORK"
     19 
     20 SRC="$WORK/leaf.c"
     21 cat > "$SRC" <<'EOF'
     22 #define NULL ((void*)0)
     23 typedef struct tn { struct tn* l; struct tn* r; } treeNode;
     24 treeNode* NewTreeNode(treeNode* left, treeNode* right);
     25 treeNode* leaf(void) { return NewTreeNode(NULL, NULL); }
     26 EOF
     27 
     28 "$KIT" cc -target aarch64-linux-gnu -O1 -std=c99 -c "$SRC" \
     29   -o "$WORK/leaf.o" > "$WORK/cc.out" 2>&1
     30 "$KIT" objdump -d "$WORK/leaf.o" > "$WORK/dis.out" 2>&1
     31 
     32 # Slice out the leaf() function body.
     33 awk '
     34   /^[0-9a-f]+ <leaf>:/ { in_fn = 1; next }
     35   /^[0-9a-f]+ </ { in_fn = 0 }
     36   in_fn { print }
     37 ' "$WORK/dis.out" > "$WORK/leaf.dis"
     38 
     39 fail() {
     40   printf 'zero-arg check FAILED: %s\n' "$1" >&2
     41   sed 's/^/  | /' "$WORK/leaf.dis" >&2
     42   exit 1
     43 }
     44 
     45 # The wart: a register-to-register move into an arg register (the zero routed
     46 # through a scratch temp). Optimal codegen materializes the constant straight
     47 # into the arg reg, so there must be no `mov x0, x<n>` / `mov x1, x<n>`.
     48 # (`movz x0, ...` is a separate mnemonic and is not matched by `\bmov x`.)
     49 if grep -Eq '\bmov[[:space:]]+x[01],[[:space:]]*x[0-9]' "$WORK/leaf.dis"; then
     50   fail 'arg zero routed through a scratch temp (mov x0/x1, x<n>)'
     51 fi
     52 
     53 # Both args must be loaded directly with movz into x0 and x1.
     54 if ! grep -Eq '\bmovz[[:space:]]+x0,' "$WORK/leaf.dis"; then
     55   fail 'arg x0 not materialized directly (movz x0, ...)'
     56 fi
     57 if ! grep -Eq '\bmovz[[:space:]]+x1,' "$WORK/leaf.dis"; then
     58   fail 'arg x1 not materialized directly (movz x1, ...)'
     59 fi
     60 
     61 printf 'zero-arg: ok\n'