Optimized the Performance of LLVM Generated by the Compiler
Summary:
Problem:
Small aggregate arguments passed via PassMode::Cast in the Rust ABI (e.g. [u32; 2] cast to i64) are missing noundef in the emitted LLVM IR, even when the type contains no uninit bytes:
#[no_mangle]
pub fn f(v: [u32; 2]) -> u32 { v[0] }
; expected: define i32 @f(i64 noundef %0)
; actual: define i32 @f(i64 %0) ← noundef missing
This blocks LLVM from applying optimizations that require value-defined semantics on function arguments.
Root Cause:
adjust_for_rust_abi calls arg.cast_to(Reg::Integer), which internally creates a CastTarget with ArgAttributes::new() — always empty. Any validity attribute that was present before the cast is silently dropped.
This affects all PassMode::Cast arguments and return values in the Rust ABI: plain arrays, newtype wrappers, and any BackendRepr::Memory type small enough to fit in a register.
A prior attempt (rust-lang/rust#127210) used Ty/repr attributes to detect padding.
Solution:
After adjust_for_rust_abi, iterate all PassMode::Cast args and the return value. For each, call layout_is_noundef on the original layout; if it returns true, set NoUndef on the CastTarget’s attrs.
layout_is_noundef uses only the computed layout — BackendRepr, FieldsShape, Variants, Scalar::is_uninit_valid() — and never touches Ty or repr attributes. Anything it cannot prove returns false.
Covered cases:
-
Scalar / ScalarPair (both halves initialized, fields contiguous)
-
FieldsShape::Array (element type recursively uninit-free)
-
FieldsShape::Arbitrary with Variants::Single (fields cover 0..size with no gaps, each recursively uninit-free) — handles newtype wrappers, multi-field structs, single-variant enums, repr(transparent), repr(C) wrappers