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