Fallback native-call temporary alignment
Root cause and invariant
The LLVM representation of a Luisa value does not always retain the source
ABI’s alignment. In particular, a matrix is represented by nested arrays of
float: its LLVM ABI alignment is four bytes, while float2x2 requires eight
and float3x3/float4x4 require sixteen bytes. The embedded device library is
compiled against those source types and may use aligned vector loads/stores.
The required invariant for a compiler-created temporary passed to that library
is allocation_alignment >= max(LLVM_alignment, source_ABI_alignment). This
applies to input pointers and output pointers, regardless of whether SROA,
inlining or instruction selection happens to eliminate their storage.
Before the fix, matrix operations and resource-result temporaries used plain
CreateAlloca(mapped_type). The real failing module contained, after inlining:
%tmp = alloca [4 x [4 x float]], align 4
store <4 x float> %column, ptr %tmp, align 16
The observed machine instruction was vmovaps %xmm3, 0x2138(%rsp) with
rsp % 16 == 0; the destination was only eight-byte aligned. This is an
invalid backend ABI promise, not a reason to disable vectorization or blame
the material operation which made the kernel large enough to expose it.
Minimal permanent regression and fix
test_fallback_llvm_abi_alignment generates independent XIR operations for
transpose, inverse, determinant, matrix-matrix and matrix-vector products,
both outer-product forms, and an acceleration-structure instance transform.
It inspects all 53 temporary pointer contracts before optimization. It does
not rely on a lucky stack offset or on a crash being reproducible at one
optimization level. The old code fails for matrix inputs and outputs at
dimensions two, three and four, including the instance-transform result.
_create_abi_temporary now implements the invariant at the native-call
boundary. Matrix, texture, bindless, acceleration-structure and ray-query
result lowering use it. Existing explicitly aligned locals, aggregate
extraction/insertion, bitwise-cast storage and packed capture/print storage
retain their existing rules. No initialization or zero-fill semantics change.
The relocatable shader cache ABI is incremented so old objects are not reused.
Validation
Evidence: /var/tmp/psycles-fallback-codegen-policy-io0puc.
Original complete 311,835-instruction Psycles material kernel: SIGSEGV before, completes its 16x16, 4-sample staged render after the fix. The application binary and shader graph are unchanged; only the backend library changes. It still takes the large-function minimal-IR pipeline.
Exact 53-contract LLVM regression: red before, green after.
All 166 Psycles fallback CTests pass after rebuilding with 32 threads.
Psycles HIP suite: 164/164, and a strict native XIR-to-SPIR-V whole-film Vulkan canary passes. This fix changes no HIP/Vulkan lowering.
The original-module reproduction, LLVM IR, machine assembly and logs are retained with the evidence. Validation of the isolated next candidate uses its codegen and public headers with the existing compatible runtime libraries; it is not a claim that an unrelated dirty SDK tree has been committed.