@@ -570,9 +570,19 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
570570 _ if ty. is_zst ( ) => ImmTy :: uninit ( ty) . into ( ) ,
571571
572572 Opaque ( _) => return None ,
573- // Do not bother evaluating repeat expressions. This would uselessly consume memory.
574- Repeat ( ..) => return None ,
575573
574+ // In general, evaluating repeat expressions just consumes a lot of memory.
575+ // But in the special case that the element is just Immediate::Uninit, we can evaluate
576+ // it without extra memory! If we don't propagate uninit values like this, LLVM can get
577+ // very confused: https://github.com/rust-lang/rust/issues/139355
578+ Repeat ( value, _count) => {
579+ let value = self . eval_to_const ( value) ?;
580+ if value. is_immediate_uninit ( ) {
581+ ImmTy :: uninit ( ty) . into ( )
582+ } else {
583+ return None ;
584+ }
585+ }
576586 Constant { ref value, disambiguator : _ } => {
577587 self . ecx . eval_mir_constant ( value, DUMMY_SP , None ) . discard_err ( ) ?
578588 }
@@ -608,8 +618,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
608618 }
609619 Union ( active_field, field) => {
610620 let field = self . eval_to_const ( field) ?;
611- if matches ! ( ty. backend_repr, BackendRepr :: Scalar ( ..) | BackendRepr :: ScalarPair ( ..) )
612- {
621+ if field. layout . layout . is_zst ( ) {
622+ ImmTy :: from_immediate ( Immediate :: Uninit , ty) . into ( )
623+ } else if matches ! (
624+ ty. backend_repr,
625+ BackendRepr :: Scalar ( ..) | BackendRepr :: ScalarPair ( ..)
626+ ) {
613627 let dest = self . ecx . allocate ( ty, MemoryKind :: Stack ) . discard_err ( ) ?;
614628 let field_dest = self . ecx . project_field ( & dest, active_field) . discard_err ( ) ?;
615629 self . ecx . copy_op ( field, & field_dest) . discard_err ( ) ?;
@@ -1711,7 +1725,11 @@ fn op_to_prop_const<'tcx>(
17111725
17121726 // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to
17131727 // avoid.
1714- if !matches ! ( op. layout. backend_repr, BackendRepr :: Scalar ( ..) | BackendRepr :: ScalarPair ( ..) ) {
1728+ // But we *do* want to synthesize any size constant if it is entirely uninit because that
1729+ // benefits codegen, which has special handling for them.
1730+ if !op. is_immediate_uninit ( )
1731+ && !matches ! ( op. layout. backend_repr, BackendRepr :: Scalar ( ..) | BackendRepr :: ScalarPair ( ..) )
1732+ {
17151733 return None ;
17161734 }
17171735
0 commit comments