@@ -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