`adjust_for_rust_abi` was casting small aggregates to an integer register
without propagating `noundef`, causing a performance regression (#123183)
— LLVM could no longer assume the bits were fully defined.
Add `layout_is_noundef` (conservative) + `fields_are_noundef` helper,
then use `cast_to_with_attrs` to forward `NoUndef` when proven:
Scalar → `!is_uninit_valid()`
ScalarPair → both scalars valid + `s1.size + s2.size == layout.size`
(size equality rejects layouts with inter-scalar padding)
Array → recurse into element; empty arrays unconditionally noundef
Arbitrary → `Variants::Single` required; walk fields in offset order —
any gap, non-noundef field, or trailing pad returns false
Union / Primitive / Simd → false (conservative)
Bless `pass-indirectly-attr.stderr` and `debuginfo-dse.rs` for the new
attribute on Cast args. Add `tests/codegen-llvm/abi-noundef-cast.rs`
covering positive Cast cases (arrays, plain structs, single-variant enum)
and negative Cast cases (MaybeUninit, multi-variant enum, field/pair gap,
trailing padding).
Fixes#123183.
Co-authored-by: Ralf Jung <post@ralfj.de>
If the `LocalRef` is `LocalRef::Place`, we can refer to it directly,
because the local of place is an indirect pointer.
Such a statement is `_1 = &(_2.1)`.
If the `LocalRef` is `LocalRef::Operand`,
the `OperandRef` should provide the pointer of the reference.
Such a statement is `_1 = &((*_2).1)`.
But there is a special case that hasn't been handled, scalar pairs like `(&[i32; 16], i32)`.