85
85
use std:: borrow:: Cow ;
86
86
87
87
use either:: Either ;
88
+ use rustc_ast:: attr;
88
89
use rustc_const_eval:: const_eval:: DummyMachine ;
89
90
use rustc_const_eval:: interpret:: {
90
91
ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
@@ -101,17 +102,27 @@ use rustc_middle::mir::visit::*;
101
102
use rustc_middle:: mir:: * ;
102
103
use rustc_middle:: ty:: layout:: { HasParamEnv , LayoutOf } ;
103
104
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
104
- use rustc_span:: DUMMY_SP ;
105
105
use rustc_span:: def_id:: DefId ;
106
+ use rustc_span:: { DUMMY_SP , sym} ;
106
107
use rustc_target:: abi:: { self , Abi , FIRST_VARIANT , FieldIdx , Primitive , Size , VariantIdx } ;
107
108
use smallvec:: SmallVec ;
108
109
use tracing:: { debug, instrument, trace} ;
109
110
110
111
use crate :: ssa:: { AssignedValue , SsaLocals } ;
111
112
112
- pub ( super ) struct GVN ;
113
+ pub ( super ) enum GVN {
114
+ Polymorphic ,
115
+ PostMono ,
116
+ }
113
117
114
118
impl < ' 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
+
115
126
fn is_enabled ( & self , sess : & rustc_session:: Session ) -> bool {
116
127
sess. mir_opt_level ( ) >= 2
117
128
}
@@ -125,7 +136,22 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
125
136
// Clone dominators because we need them while mutating the body.
126
137
let dominators = body. basic_blocks . dominators ( ) . clone ( ) ;
127
138
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
+ ) ;
129
155
ssa. for_each_assignment_mut (
130
156
body. basic_blocks . as_mut_preserves_cfg ( ) ,
131
157
|local, value, location| {
@@ -260,6 +286,7 @@ struct VnState<'body, 'tcx> {
260
286
ssa : & ' body SsaLocals ,
261
287
dominators : Dominators < BasicBlock > ,
262
288
reused_locals : BitSet < Local > ,
289
+ preserve_ub_checks : bool ,
263
290
}
264
291
265
292
impl < ' body , ' tcx > VnState < ' body , ' tcx > {
@@ -270,6 +297,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
270
297
ssa : & ' body SsaLocals ,
271
298
dominators : Dominators < BasicBlock > ,
272
299
local_decls : & ' body LocalDecls < ' tcx > ,
300
+ preserve_ub_checks : bool ,
273
301
) -> Self {
274
302
// Compute a rough estimate of the number of values in the body from the number of
275
303
// 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> {
292
320
ssa,
293
321
dominators,
294
322
reused_locals : BitSet :: new_empty ( local_decls. len ( ) ) ,
323
+ preserve_ub_checks,
295
324
}
296
325
}
297
326
@@ -530,7 +559,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
530
559
. tcx
531
560
. offset_of_subfield ( self . ecx . param_env ( ) , layout, fields. iter ( ) )
532
561
. 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
+ }
534
570
} ;
535
571
let usize_layout = self . ecx . layout_of ( self . tcx . types . usize ) . unwrap ( ) ;
536
572
let imm = ImmTy :: from_uint ( val, usize_layout) ;
0 commit comments