@@ -65,13 +65,13 @@ trait SimplifyMatch<'tcx> {
65
65
_ => unreachable ! ( ) ,
66
66
} ;
67
67
68
- if !self . can_simplify ( tcx, targets, param_env, bbs) {
68
+ let discr_ty = discr. ty ( local_decls, tcx) ;
69
+ if !self . can_simplify ( tcx, targets, param_env, bbs, discr_ty) {
69
70
return false ;
70
71
}
71
72
72
73
// Take ownership of items now that we know we can optimize.
73
74
let discr = discr. clone ( ) ;
74
- let discr_ty = discr. ty ( local_decls, tcx) ;
75
75
76
76
// Introduce a temporary for the discriminant value.
77
77
let source_info = bbs[ switch_bb_idx] . terminator ( ) . source_info ;
@@ -101,6 +101,7 @@ trait SimplifyMatch<'tcx> {
101
101
targets : & SwitchTargets ,
102
102
param_env : ParamEnv < ' tcx > ,
103
103
bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
104
+ discr_ty : Ty < ' tcx > ,
104
105
) -> bool ;
105
106
106
107
fn new_stmts (
@@ -154,6 +155,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
154
155
targets : & SwitchTargets ,
155
156
param_env : ParamEnv < ' tcx > ,
156
157
bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
158
+ _discr_ty : Ty < ' tcx > ,
157
159
) -> bool {
158
160
if targets. iter ( ) . len ( ) != 1 {
159
161
return false ;
@@ -265,7 +267,7 @@ struct SimplifyToExp {
265
267
enum CompareType < ' tcx , ' a > {
266
268
Same ( & ' a StatementKind < ' tcx > ) ,
267
269
Eq ( & ' a Place < ' tcx > , Ty < ' tcx > , ScalarInt ) ,
268
- Discr ( & ' a Place < ' tcx > , Ty < ' tcx > ) ,
270
+ Discr ( & ' a Place < ' tcx > , Ty < ' tcx > , bool ) ,
269
271
}
270
272
271
273
enum TransfromType {
@@ -279,7 +281,7 @@ impl From<CompareType<'_, '_>> for TransfromType {
279
281
match compare_type {
280
282
CompareType :: Same ( _) => TransfromType :: Same ,
281
283
CompareType :: Eq ( _, _, _) => TransfromType :: Eq ,
282
- CompareType :: Discr ( _, _) => TransfromType :: Discr ,
284
+ CompareType :: Discr ( _, _, _ ) => TransfromType :: Discr ,
283
285
}
284
286
}
285
287
}
@@ -330,6 +332,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
330
332
targets : & SwitchTargets ,
331
333
param_env : ParamEnv < ' tcx > ,
332
334
bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
335
+ discr_ty : Ty < ' tcx > ,
333
336
) -> bool {
334
337
if targets. iter ( ) . len ( ) < 2 || targets. iter ( ) . len ( ) > 64 {
335
338
return false ;
@@ -352,6 +355,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
352
355
return false ;
353
356
}
354
357
358
+ let discr_size = tcx. layout_of ( param_env. and ( discr_ty) ) . unwrap ( ) . size ;
355
359
let first_stmts = & bbs[ first_target] . statements ;
356
360
let ( second_val, second_target) = iter. next ( ) . unwrap ( ) ;
357
361
let second_stmts = & bbs[ second_target] . statements ;
@@ -379,12 +383,30 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
379
383
) {
380
384
( Some ( f) , Some ( s) ) if f == s => CompareType :: Eq ( lhs_f, f_c. const_ . ty ( ) , f) ,
381
385
( Some ( f) , Some ( s) )
382
- if Some ( f) == ScalarInt :: try_from_uint ( first_val, f. size ( ) )
383
- && Some ( s) == ScalarInt :: try_from_uint ( second_val, s. size ( ) ) =>
386
+ if ( ( f_c. const_ . ty ( ) . is_signed ( ) || discr_ty. is_signed ( ) )
387
+ && f. try_to_int ( f. size ( ) ) . unwrap ( )
388
+ == ScalarInt :: try_from_uint ( first_val, discr_size)
389
+ . unwrap ( )
390
+ . try_to_int ( discr_size)
391
+ . unwrap ( )
392
+ && s. try_to_int ( s. size ( ) ) . unwrap ( )
393
+ == ScalarInt :: try_from_uint ( second_val, discr_size)
394
+ . unwrap ( )
395
+ . try_to_int ( discr_size)
396
+ . unwrap ( ) )
397
+ || ( Some ( f) == ScalarInt :: try_from_uint ( first_val, f. size ( ) )
398
+ && Some ( s)
399
+ == ScalarInt :: try_from_uint ( second_val, s. size ( ) ) ) =>
384
400
{
385
- CompareType :: Discr ( lhs_f, f_c. const_ . ty ( ) )
401
+ CompareType :: Discr (
402
+ lhs_f,
403
+ f_c. const_ . ty ( ) ,
404
+ f_c. const_ . ty ( ) . is_signed ( ) || discr_ty. is_signed ( ) ,
405
+ )
406
+ }
407
+ _ => {
408
+ return false ;
386
409
}
387
- _ => return false ,
388
410
}
389
411
}
390
412
@@ -409,15 +431,26 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
409
431
&& s_c. const_ . ty ( ) == f_ty
410
432
&& s_c. const_ . try_eval_scalar_int ( tcx, param_env) == Some ( val) => { }
411
433
(
412
- CompareType :: Discr ( lhs_f, f_ty) ,
434
+ CompareType :: Discr ( lhs_f, f_ty, is_signed ) ,
413
435
StatementKind :: Assign ( box ( lhs_s, Rvalue :: Use ( Operand :: Constant ( s_c) ) ) ) ,
414
436
) if lhs_f == lhs_s && s_c. const_ . ty ( ) == f_ty => {
415
437
let Some ( f) = s_c. const_ . try_eval_scalar_int ( tcx, param_env) else {
416
438
return false ;
417
439
} ;
418
- if Some ( f) != ScalarInt :: try_from_uint ( other_val, f. size ( ) ) {
419
- return false ;
440
+ if is_signed
441
+ && s_c. const_ . ty ( ) . is_signed ( )
442
+ && f. try_to_int ( f. size ( ) ) . unwrap ( )
443
+ == ScalarInt :: try_from_uint ( other_val, discr_size)
444
+ . unwrap ( )
445
+ . try_to_int ( discr_size)
446
+ . unwrap ( )
447
+ {
448
+ continue ;
449
+ }
450
+ if Some ( f) == ScalarInt :: try_from_uint ( other_val, f. size ( ) ) {
451
+ continue ;
420
452
}
453
+ return false ;
421
454
}
422
455
_ => return false ,
423
456
}
0 commit comments