@@ -39,26 +39,26 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
3939 attr:: contains_name ( tcx. hir_krate_attrs ( ) , sym:: rustc_preserve_ub_checks) ;
4040 for block in body. basic_blocks . as_mut ( ) {
4141 for statement in block. statements . iter_mut ( ) {
42- match statement. kind {
43- StatementKind :: Assign ( box ( _place, ref mut rvalue) ) => {
44- if !preserve_ub_checks {
45- ctx. simplify_ub_check ( rvalue) ;
46- }
47- ctx. simplify_bool_cmp ( rvalue) ;
48- ctx. simplify_ref_deref ( rvalue) ;
49- ctx. simplify_ptr_aggregate ( rvalue) ;
50- ctx. simplify_cast ( rvalue) ;
51- ctx. simplify_repeated_aggregate ( rvalue) ;
52- ctx. simplify_repeat_once ( rvalue) ;
53- }
54- _ => { }
42+ let StatementKind :: Assign ( box ( .., rvalue) ) = & mut statement. kind else {
43+ continue ;
44+ } ;
45+
46+ if !preserve_ub_checks {
47+ ctx. simplify_ub_check ( rvalue) ;
5548 }
49+ ctx. simplify_bool_cmp ( rvalue) ;
50+ ctx. simplify_ref_deref ( rvalue) ;
51+ ctx. simplify_ptr_aggregate ( rvalue) ;
52+ ctx. simplify_cast ( rvalue) ;
53+ ctx. simplify_repeated_aggregate ( rvalue) ;
54+ ctx. simplify_repeat_once ( rvalue) ;
5655 }
5756
58- ctx. simplify_primitive_clone ( block. terminator . as_mut ( ) . unwrap ( ) , & mut block. statements ) ;
59- ctx. simplify_intrinsic_assert ( block. terminator . as_mut ( ) . unwrap ( ) ) ;
60- ctx. simplify_nounwind_call ( block. terminator . as_mut ( ) . unwrap ( ) ) ;
61- simplify_duplicate_switch_targets ( block. terminator . as_mut ( ) . unwrap ( ) ) ;
57+ let terminator = block. terminator . as_mut ( ) . unwrap ( ) ;
58+ ctx. simplify_primitive_clone ( terminator, & mut block. statements ) ;
59+ ctx. simplify_intrinsic_assert ( terminator) ;
60+ ctx. simplify_nounwind_call ( terminator) ;
61+ simplify_duplicate_switch_targets ( terminator) ;
6262 }
6363 }
6464
@@ -105,43 +105,34 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
105105
106106 /// Transform boolean comparisons into logical operations.
107107 fn simplify_bool_cmp ( & self , rvalue : & mut Rvalue < ' tcx > ) {
108- match rvalue {
109- Rvalue :: BinaryOp ( op @ ( BinOp :: Eq | BinOp :: Ne ) , box ( a, b) ) => {
110- let new = match ( op, self . try_eval_bool ( a) , self . try_eval_bool ( b) ) {
111- // Transform "Eq(a, true)" ==> "a"
112- ( BinOp :: Eq , _, Some ( true ) ) => Some ( Rvalue :: Use ( a. clone ( ) ) ) ,
108+ let Rvalue :: BinaryOp ( op @ ( BinOp :: Eq | BinOp :: Ne ) , box ( a, b) ) = & * rvalue else { return } ;
109+ * rvalue = match ( op, self . try_eval_bool ( a) , self . try_eval_bool ( b) ) {
110+ // Transform "Eq(a, true)" ==> "a"
111+ ( BinOp :: Eq , _, Some ( true ) ) => Rvalue :: Use ( a. clone ( ) ) ,
113112
114- // Transform "Ne(a, false)" ==> "a"
115- ( BinOp :: Ne , _, Some ( false ) ) => Some ( Rvalue :: Use ( a. clone ( ) ) ) ,
113+ // Transform "Ne(a, false)" ==> "a"
114+ ( BinOp :: Ne , _, Some ( false ) ) => Rvalue :: Use ( a. clone ( ) ) ,
116115
117- // Transform "Eq(true, b)" ==> "b"
118- ( BinOp :: Eq , Some ( true ) , _) => Some ( Rvalue :: Use ( b. clone ( ) ) ) ,
116+ // Transform "Eq(true, b)" ==> "b"
117+ ( BinOp :: Eq , Some ( true ) , _) => Rvalue :: Use ( b. clone ( ) ) ,
119118
120- // Transform "Ne(false, b)" ==> "b"
121- ( BinOp :: Ne , Some ( false ) , _) => Some ( Rvalue :: Use ( b. clone ( ) ) ) ,
119+ // Transform "Ne(false, b)" ==> "b"
120+ ( BinOp :: Ne , Some ( false ) , _) => Rvalue :: Use ( b. clone ( ) ) ,
122121
123- // Transform "Eq(false, b)" ==> "Not(b)"
124- ( BinOp :: Eq , Some ( false ) , _) => Some ( Rvalue :: UnaryOp ( UnOp :: Not , b. clone ( ) ) ) ,
122+ // Transform "Eq(false, b)" ==> "Not(b)"
123+ ( BinOp :: Eq , Some ( false ) , _) => Rvalue :: UnaryOp ( UnOp :: Not , b. clone ( ) ) ,
125124
126- // Transform "Ne(true, b)" ==> "Not(b)"
127- ( BinOp :: Ne , Some ( true ) , _) => Some ( Rvalue :: UnaryOp ( UnOp :: Not , b. clone ( ) ) ) ,
125+ // Transform "Ne(true, b)" ==> "Not(b)"
126+ ( BinOp :: Ne , Some ( true ) , _) => Rvalue :: UnaryOp ( UnOp :: Not , b. clone ( ) ) ,
128127
129- // Transform "Eq(a, false)" ==> "Not(a)"
130- ( BinOp :: Eq , _, Some ( false ) ) => Some ( Rvalue :: UnaryOp ( UnOp :: Not , a. clone ( ) ) ) ,
128+ // Transform "Eq(a, false)" ==> "Not(a)"
129+ ( BinOp :: Eq , _, Some ( false ) ) => Rvalue :: UnaryOp ( UnOp :: Not , a. clone ( ) ) ,
131130
132- // Transform "Ne(a, true)" ==> "Not(a)"
133- ( BinOp :: Ne , _, Some ( true ) ) => Some ( Rvalue :: UnaryOp ( UnOp :: Not , a. clone ( ) ) ) ,
134-
135- _ => None ,
136- } ;
137-
138- if let Some ( new) = new {
139- * rvalue = new;
140- }
141- }
131+ // Transform "Ne(a, true)" ==> "Not(a)"
132+ ( BinOp :: Ne , _, Some ( true ) ) => Rvalue :: UnaryOp ( UnOp :: Not , a. clone ( ) ) ,
142133
143- _ => { }
144- }
134+ _ => return ,
135+ } ;
145136 }
146137
147138 fn try_eval_bool ( & self , a : & Operand < ' _ > ) -> Option < bool > {
@@ -151,64 +142,58 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
151142
152143 /// Transform `&(*a)` ==> `a`.
153144 fn simplify_ref_deref ( & self , rvalue : & mut Rvalue < ' tcx > ) {
154- if let Rvalue :: Ref ( _, _, place) | Rvalue :: RawPtr ( _, place) = rvalue {
155- if let Some ( ( base, ProjectionElem :: Deref ) ) = place. as_ref ( ) . last_projection ( ) {
156- if rvalue. ty ( self . local_decls , self . tcx ) != base. ty ( self . local_decls , self . tcx ) . ty {
157- return ;
158- }
159-
160- * rvalue = Rvalue :: Use ( Operand :: Copy ( Place {
161- local : base. local ,
162- projection : self . tcx . mk_place_elems ( base. projection ) ,
163- } ) ) ;
164- }
145+ if let Rvalue :: Ref ( _, _, place) | Rvalue :: RawPtr ( _, place) = rvalue
146+ && let Some ( ( base, ProjectionElem :: Deref ) ) = place. as_ref ( ) . last_projection ( )
147+ && rvalue. ty ( self . local_decls , self . tcx ) == base. ty ( self . local_decls , self . tcx ) . ty
148+ {
149+ * rvalue = Rvalue :: Use ( Operand :: Copy ( Place {
150+ local : base. local ,
151+ projection : self . tcx . mk_place_elems ( base. projection ) ,
152+ } ) ) ;
165153 }
166154 }
167155
168156 /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`.
169157 fn simplify_ptr_aggregate ( & self , rvalue : & mut Rvalue < ' tcx > ) {
170158 if let Rvalue :: Aggregate ( box AggregateKind :: RawPtr ( pointee_ty, mutability) , fields) = rvalue
159+ && let meta_ty = fields. raw [ 1 ] . ty ( self . local_decls , self . tcx )
160+ && meta_ty. is_unit ( )
171161 {
172- let meta_ty = fields. raw [ 1 ] . ty ( self . local_decls , self . tcx ) ;
173- if meta_ty. is_unit ( ) {
174- // The mutable borrows we're holding prevent printing `rvalue` here
175- let mut fields = std:: mem:: take ( fields) ;
176- let _meta = fields. pop ( ) . unwrap ( ) ;
177- let data = fields. pop ( ) . unwrap ( ) ;
178- let ptr_ty = Ty :: new_ptr ( self . tcx , * pointee_ty, * mutability) ;
179- * rvalue = Rvalue :: Cast ( CastKind :: PtrToPtr , data, ptr_ty) ;
180- }
162+ // The mutable borrows we're holding prevent printing `rvalue` here
163+ let mut fields = std:: mem:: take ( fields) ;
164+ let _meta = fields. pop ( ) . unwrap ( ) ;
165+ let data = fields. pop ( ) . unwrap ( ) ;
166+ let ptr_ty = Ty :: new_ptr ( self . tcx , * pointee_ty, * mutability) ;
167+ * rvalue = Rvalue :: Cast ( CastKind :: PtrToPtr , data, ptr_ty) ;
181168 }
182169 }
183170
184171 fn simplify_ub_check ( & self , rvalue : & mut Rvalue < ' tcx > ) {
185- if let Rvalue :: NullaryOp ( NullOp :: UbChecks , _) = * rvalue {
186- let const_ = Const :: from_bool ( self . tcx , self . tcx . sess . ub_checks ( ) ) ;
187- let constant = ConstOperand { span : DUMMY_SP , const_ , user_ty : None } ;
188- * rvalue = Rvalue :: Use ( Operand :: Constant ( Box :: new ( constant ) ) ) ;
189- }
172+ let Rvalue :: NullaryOp ( NullOp :: UbChecks , _) = * rvalue else { return } ;
173+
174+ let const_ = Const :: from_bool ( self . tcx , self . tcx . sess . ub_checks ( ) ) ;
175+ let constant = ConstOperand { span : DUMMY_SP , const_ , user_ty : None } ;
176+ * rvalue = Rvalue :: Use ( Operand :: Constant ( Box :: new ( constant ) ) ) ;
190177 }
191178
192179 fn simplify_cast ( & self , rvalue : & mut Rvalue < ' tcx > ) {
193- if let Rvalue :: Cast ( kind, operand, cast_ty) = rvalue {
194- let operand_ty = operand. ty ( self . local_decls , self . tcx ) ;
195- if operand_ty == * cast_ty {
196- * rvalue = Rvalue :: Use ( operand. clone ( ) ) ;
197- } else if * kind == CastKind :: Transmute {
198- // Transmuting an integer to another integer is just a signedness cast
199- if let ( ty:: Int ( int) , ty:: Uint ( uint) ) | ( ty:: Uint ( uint) , ty:: Int ( int) ) =
200- ( operand_ty. kind ( ) , cast_ty. kind ( ) )
201- && int. bit_width ( ) == uint. bit_width ( )
202- {
203- // The width check isn't strictly necessary, as different widths
204- // are UB and thus we'd be allowed to turn it into a cast anyway.
205- // But let's keep the UB around for codegen to exploit later.
206- // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
207- // then the width check is necessary for big-endian correctness.)
208- * kind = CastKind :: IntToInt ;
209- return ;
210- }
211- }
180+ let Rvalue :: Cast ( kind, operand, cast_ty) = rvalue else { return } ;
181+
182+ let operand_ty = operand. ty ( self . local_decls , self . tcx ) ;
183+ if operand_ty == * cast_ty {
184+ * rvalue = Rvalue :: Use ( operand. clone ( ) ) ;
185+ } else if * kind == CastKind :: Transmute
186+ // Transmuting an integer to another integer is just a signedness cast
187+ && let ( ty:: Int ( int) , ty:: Uint ( uint) ) | ( ty:: Uint ( uint) , ty:: Int ( int) ) =
188+ ( operand_ty. kind ( ) , cast_ty. kind ( ) )
189+ && int. bit_width ( ) == uint. bit_width ( )
190+ {
191+ // The width check isn't strictly necessary, as different widths
192+ // are UB and thus we'd be allowed to turn it into a cast anyway.
193+ // But let's keep the UB around for codegen to exploit later.
194+ // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
195+ // then the width check is necessary for big-endian correctness.)
196+ * kind = CastKind :: IntToInt ;
212197 }
213198 }
214199
@@ -277,7 +262,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
277262 }
278263
279264 fn simplify_nounwind_call ( & self , terminator : & mut Terminator < ' tcx > ) {
280- let TerminatorKind :: Call { func, unwind, .. } = & mut terminator. kind else {
265+ let TerminatorKind :: Call { ref func, ref mut unwind, .. } = terminator. kind else {
281266 return ;
282267 } ;
283268
@@ -290,7 +275,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
290275 ty:: FnDef ( ..) => body_ty. fn_sig ( self . tcx ) . abi ( ) ,
291276 ty:: Closure ( ..) => ExternAbi :: RustCall ,
292277 ty:: Coroutine ( ..) => ExternAbi :: Rust ,
293- _ => bug ! ( "unexpected body ty: {:?}" , body_ty ) ,
278+ _ => bug ! ( "unexpected body ty: {body_ty :?}" ) ,
294279 } ;
295280
296281 if !layout:: fn_can_unwind ( self . tcx , Some ( def_id) , body_abi) {
@@ -299,23 +284,20 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
299284 }
300285
301286 fn simplify_intrinsic_assert ( & self , terminator : & mut Terminator < ' tcx > ) {
302- let TerminatorKind :: Call { func, target, .. } = & mut terminator. kind else {
303- return ;
304- } ;
305- let Some ( target_block) = target else {
287+ let TerminatorKind :: Call { ref func, target : ref mut target @ Some ( target_block) , .. } =
288+ terminator. kind
289+ else {
306290 return ;
307291 } ;
308292 let func_ty = func. ty ( self . local_decls , self . tcx ) ;
309293 let Some ( ( intrinsic_name, args) ) = resolve_rust_intrinsic ( self . tcx , func_ty) else {
310294 return ;
311295 } ;
312296 // The intrinsics we are interested in have one generic parameter
313- if args. is_empty ( ) {
314- return ;
315- }
297+ let [ arg, ..] = args[ ..] else { return } ;
316298
317299 let known_is_valid =
318- intrinsic_assert_panics ( self . tcx , self . typing_env , args [ 0 ] , intrinsic_name) ;
300+ intrinsic_assert_panics ( self . tcx , self . typing_env , arg , intrinsic_name) ;
319301 match known_is_valid {
320302 // We don't know the layout or it's not validity assertion at all, don't touch it
321303 None => { }
@@ -325,7 +307,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
325307 }
326308 Some ( false ) => {
327309 // If we know the assert does not panic, turn the call into a Goto
328- terminator. kind = TerminatorKind :: Goto { target : * target_block } ;
310+ terminator. kind = TerminatorKind :: Goto { target : target_block } ;
329311 }
330312 }
331313 }
@@ -346,9 +328,7 @@ fn resolve_rust_intrinsic<'tcx>(
346328 tcx : TyCtxt < ' tcx > ,
347329 func_ty : Ty < ' tcx > ,
348330) -> Option < ( Symbol , GenericArgsRef < ' tcx > ) > {
349- if let ty:: FnDef ( def_id, args) = * func_ty. kind ( ) {
350- let intrinsic = tcx. intrinsic ( def_id) ?;
351- return Some ( ( intrinsic. name , args) ) ;
352- }
353- None
331+ let ty:: FnDef ( def_id, args) = * func_ty. kind ( ) else { return None } ;
332+ let intrinsic = tcx. intrinsic ( def_id) ?;
333+ Some ( ( intrinsic. name , args) )
354334}
0 commit comments