@@ -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,61 @@ 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- } ) ) ;
145+ if let Rvalue :: Ref ( _, _, place) | Rvalue :: RawPtr ( _, place) = rvalue
146+ && let Some ( ( base, ProjectionElem :: Deref ) ) = place. as_ref ( ) . last_projection ( )
147+ {
148+ if rvalue. ty ( self . local_decls , self . tcx ) != base. ty ( self . local_decls , self . tcx ) . ty {
149+ return ;
164150 }
151+
152+ * rvalue = Rvalue :: Use ( Operand :: Copy ( Place {
153+ local : base. local ,
154+ projection : self . tcx . mk_place_elems ( base. projection ) ,
155+ } ) ) ;
165156 }
166157 }
167158
168159 /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`.
169160 fn simplify_ptr_aggregate ( & self , rvalue : & mut Rvalue < ' tcx > ) {
170161 if let Rvalue :: Aggregate ( box AggregateKind :: RawPtr ( pointee_ty, mutability) , fields) = rvalue
162+ && let meta_ty = fields. raw [ 1 ] . ty ( self . local_decls , self . tcx )
163+ && meta_ty. is_unit ( )
171164 {
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- }
165+ // The mutable borrows we're holding prevent printing `rvalue` here
166+ let mut fields = std:: mem:: take ( fields) ;
167+ let _meta = fields. pop ( ) . unwrap ( ) ;
168+ let data = fields. pop ( ) . unwrap ( ) ;
169+ let ptr_ty = Ty :: new_ptr ( self . tcx , * pointee_ty, * mutability) ;
170+ * rvalue = Rvalue :: Cast ( CastKind :: PtrToPtr , data, ptr_ty) ;
181171 }
182172 }
183173
184174 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- }
175+ let Rvalue :: NullaryOp ( NullOp :: UbChecks , _) = * rvalue else { return } ;
176+
177+ let const_ = Const :: from_bool ( self . tcx , self . tcx . sess . ub_checks ( ) ) ;
178+ let constant = ConstOperand { span : DUMMY_SP , const_ , user_ty : None } ;
179+ * rvalue = Rvalue :: Use ( Operand :: Constant ( Box :: new ( constant ) ) ) ;
190180 }
191181
192182 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- }
183+ let Rvalue :: Cast ( kind, operand, cast_ty) = rvalue else { return } ;
184+
185+ let operand_ty = operand. ty ( self . local_decls , self . tcx ) ;
186+ if operand_ty == * cast_ty {
187+ * rvalue = Rvalue :: Use ( operand. clone ( ) ) ;
188+ } else if * kind == CastKind :: Transmute
189+ // Transmuting an integer to another integer is just a signedness cast
190+ && let ( ty:: Int ( int) , ty:: Uint ( uint) ) | ( ty:: Uint ( uint) , ty:: Int ( int) ) =
191+ ( operand_ty. kind ( ) , cast_ty. kind ( ) )
192+ && int. bit_width ( ) == uint. bit_width ( )
193+ {
194+ // The width check isn't strictly necessary, as different widths
195+ // are UB and thus we'd be allowed to turn it into a cast anyway.
196+ // But let's keep the UB around for codegen to exploit later.
197+ // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
198+ // then the width check is necessary for big-endian correctness.)
199+ * kind = CastKind :: IntToInt ;
212200 }
213201 }
214202
@@ -277,7 +265,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
277265 }
278266
279267 fn simplify_nounwind_call ( & self , terminator : & mut Terminator < ' tcx > ) {
280- let TerminatorKind :: Call { func, unwind, .. } = & mut terminator. kind else {
268+ let TerminatorKind :: Call { ref func, ref mut unwind, .. } = terminator. kind else {
281269 return ;
282270 } ;
283271
@@ -290,7 +278,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
290278 ty:: FnDef ( ..) => body_ty. fn_sig ( self . tcx ) . abi ( ) ,
291279 ty:: Closure ( ..) => ExternAbi :: RustCall ,
292280 ty:: Coroutine ( ..) => ExternAbi :: Rust ,
293- _ => bug ! ( "unexpected body ty: {:?}" , body_ty ) ,
281+ _ => bug ! ( "unexpected body ty: {body_ty :?}" ) ,
294282 } ;
295283
296284 if !layout:: fn_can_unwind ( self . tcx , Some ( def_id) , body_abi) {
@@ -299,23 +287,20 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
299287 }
300288
301289 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 {
290+ let TerminatorKind :: Call { ref func, target : ref mut target @ Some ( target_block) , .. } =
291+ terminator. kind
292+ else {
306293 return ;
307294 } ;
308295 let func_ty = func. ty ( self . local_decls , self . tcx ) ;
309296 let Some ( ( intrinsic_name, args) ) = resolve_rust_intrinsic ( self . tcx , func_ty) else {
310297 return ;
311298 } ;
312299 // The intrinsics we are interested in have one generic parameter
313- if args. is_empty ( ) {
314- return ;
315- }
300+ let [ arg, ..] = args[ ..] else { return } ;
316301
317302 let known_is_valid =
318- intrinsic_assert_panics ( self . tcx , self . typing_env , args [ 0 ] , intrinsic_name) ;
303+ intrinsic_assert_panics ( self . tcx , self . typing_env , arg , intrinsic_name) ;
319304 match known_is_valid {
320305 // We don't know the layout or it's not validity assertion at all, don't touch it
321306 None => { }
@@ -325,7 +310,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
325310 }
326311 Some ( false ) => {
327312 // If we know the assert does not panic, turn the call into a Goto
328- terminator. kind = TerminatorKind :: Goto { target : * target_block } ;
313+ terminator. kind = TerminatorKind :: Goto { target : target_block } ;
329314 }
330315 }
331316 }
@@ -346,9 +331,7 @@ fn resolve_rust_intrinsic<'tcx>(
346331 tcx : TyCtxt < ' tcx > ,
347332 func_ty : Ty < ' tcx > ,
348333) -> 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
334+ let ty:: FnDef ( def_id, args) = * func_ty. kind ( ) else { return None } ;
335+ let intrinsic = tcx. intrinsic ( def_id) ?;
336+ Some ( ( intrinsic. name , args) )
354337}
0 commit comments