8585use  std:: borrow:: Cow ; 
8686
8787use  either:: Either ; 
88+ use  rustc_ast:: attr; 
8889use  rustc_const_eval:: const_eval:: DummyMachine ; 
8990use  rustc_const_eval:: interpret:: { 
9091 ImmTy ,  Immediate ,  InterpCx ,  MemPlaceMeta ,  MemoryKind ,  OpTy ,  Projectable ,  Scalar , 
@@ -101,17 +102,27 @@ use rustc_middle::mir::visit::*;
101102use  rustc_middle:: mir:: * ; 
102103use  rustc_middle:: ty:: layout:: { HasParamEnv ,  LayoutOf } ; 
103104use  rustc_middle:: ty:: { self ,  Ty ,  TyCtxt } ; 
104- use  rustc_span:: DUMMY_SP ; 
105105use  rustc_span:: def_id:: DefId ; 
106+ use  rustc_span:: { DUMMY_SP ,  sym} ; 
106107use  rustc_target:: abi:: { self ,  Abi ,  FIRST_VARIANT ,  FieldIdx ,  Primitive ,  Size ,  VariantIdx } ; 
107108use  smallvec:: SmallVec ; 
108109use  tracing:: { debug,  instrument,  trace} ; 
109110
110111use  crate :: ssa:: { AssignedValue ,  SsaLocals } ; 
111112
112- pub ( super )  struct  GVN ; 
113+ pub ( super )  enum  GVN  { 
114+  Polymorphic , 
115+  PostMono , 
116+ } 
113117
114118impl < ' tcx >  crate :: MirPass < ' tcx >  for  GVN  { 
119+  fn  name ( & self )  -> & ' static  str  { 
120+  match  self  { 
121+  GVN :: Polymorphic  => "GVN" , 
122+  GVN :: PostMono  => "GVN-post-mono" , 
123+  } 
124+  } 
125+ 
115126 fn  is_enabled ( & self ,  sess :  & rustc_session:: Session )  -> bool  { 
116127 sess. mir_opt_level ( )  >= 2 
117128 } 
@@ -125,7 +136,22 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
125136 // Clone dominators because we need them while mutating the body. 
126137 let  dominators = body. basic_blocks . dominators ( ) . clone ( ) ; 
127138
128-  let  mut  state = VnState :: new ( tcx,  body,  param_env,  & ssa,  dominators,  & body. local_decls ) ; 
139+  let  preserve_ub_checks = match  self  { 
140+  GVN :: Polymorphic  => { 
141+  attr:: contains_name ( tcx. hir ( ) . krate_attrs ( ) ,  sym:: rustc_preserve_ub_checks) 
142+  } 
143+  GVN :: PostMono  => false , 
144+  } ; 
145+ 
146+  let  mut  state = VnState :: new ( 
147+  tcx, 
148+  body, 
149+  param_env, 
150+  & ssa, 
151+  dominators, 
152+  & body. local_decls , 
153+  preserve_ub_checks, 
154+  ) ; 
129155 ssa. for_each_assignment_mut ( 
130156 body. basic_blocks . as_mut_preserves_cfg ( ) , 
131157 |local,  value,  location| { 
@@ -260,6 +286,7 @@ struct VnState<'body, 'tcx> {
260286 ssa :  & ' body  SsaLocals , 
261287 dominators :  Dominators < BasicBlock > , 
262288 reused_locals :  BitSet < Local > , 
289+  preserve_ub_checks :  bool , 
263290} 
264291
265292impl < ' body ,  ' tcx >  VnState < ' body ,  ' tcx >  { 
@@ -270,6 +297,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
270297 ssa :  & ' body  SsaLocals , 
271298 dominators :  Dominators < BasicBlock > , 
272299 local_decls :  & ' body  LocalDecls < ' tcx > , 
300+  preserve_ub_checks :  bool , 
273301 )  -> Self  { 
274302 // Compute a rough estimate of the number of values in the body from the number of 
275303 // statements. This is meant to reduce the number of allocations, but it's all right if 
@@ -292,6 +320,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
292320 ssa, 
293321 dominators, 
294322 reused_locals :  BitSet :: new_empty ( local_decls. len ( ) ) , 
323+  preserve_ub_checks, 
295324 } 
296325 } 
297326
@@ -530,7 +559,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
530559 . tcx 
531560 . offset_of_subfield ( self . ecx . param_env ( ) ,  layout,  fields. iter ( ) ) 
532561 . bytes ( ) , 
533-  NullOp :: UbChecks  => return  None , 
562+  NullOp :: UbChecks  => { 
563+  if  self . preserve_ub_checks  { 
564+  return  None ; 
565+  }  else  { 
566+  let  val = ImmTy :: from_bool ( self . tcx . sess . ub_checks ( ) ,  self . tcx ) ; 
567+  return  Some ( val. into ( ) ) ; 
568+  } 
569+  } 
534570 } ; 
535571 let  usize_layout = self . ecx . layout_of ( self . tcx . types . usize ) . unwrap ( ) ; 
536572 let  imm = ImmTy :: from_uint ( val,  usize_layout) ; 
0 commit comments