Skip to content

Commit 18ae990

Browse files
committed
Auto merge of #150925 - dianqk:if-cmp, r=saethlin
Only use SSA locals in SimplifyComparisonIntegral Fixes #150904. The place may be modified from the comparison statement to the switchInt terminator. Best reviewed commit by commit.
2 parents 22c74ba + 5769006 commit 18ae990

23 files changed

Lines changed: 301 additions & 56 deletions

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,12 @@ impl<'tcx> Place<'tcx> {
374374
self.projection.iter().any(|elem| elem.is_indirect())
375375
}
376376

377+
/// Returns `true` if the `Place` always refers to the same memory region
378+
/// whatever the state of the program.
379+
pub fn is_stable_offset(&self) -> bool {
380+
self.projection.iter().all(|elem| elem.is_stable_offset())
381+
}
382+
377383
/// Returns `true` if this `Place`'s first projection is `Deref`.
378384
///
379385
/// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later,

compiler/rustc_mir_transform/src/simplify_comparison_integral.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use rustc_middle::mir::{
99
use rustc_middle::ty::{Ty, TyCtxt};
1010
use tracing::trace;
1111

12+
use crate::ssa::SsaLocals;
13+
1214
/// Pass to convert `if` conditions on integrals into switches on the integral.
1315
/// For an example, it turns something like
1416
///
@@ -27,17 +29,18 @@ pub(super) struct SimplifyComparisonIntegral;
2729

2830
impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
2931
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
30-
sess.mir_opt_level() > 0
32+
sess.mir_opt_level() > 1
3133
}
3234

3335
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
3436
trace!("Running SimplifyComparisonIntegral on {:?}", body.source);
3537

38+
let typing_env = body.typing_env(tcx);
39+
let ssa = SsaLocals::new(tcx, body, typing_env);
3640
let helper = OptimizationFinder { body };
37-
let opts = helper.find_optimizations();
41+
let opts = helper.find_optimizations(&ssa);
3842
let mut storage_deads_to_insert = vec![];
3943
let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![];
40-
let typing_env = body.typing_env(tcx);
4144
for opt in opts {
4245
trace!("SUCCESS: Applying {:?}", opt);
4346
// replace terminator with a switchInt that switches on the integer directly
@@ -132,7 +135,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
132135

133136
let terminator = bb.terminator_mut();
134137
terminator.kind =
135-
TerminatorKind::SwitchInt { discr: Operand::Move(opt.to_switch_on), targets };
138+
TerminatorKind::SwitchInt { discr: Operand::Copy(opt.to_switch_on), targets };
136139
}
137140

138141
for (idx, bb_idx) in storage_deads_to_remove {
@@ -154,19 +157,18 @@ struct OptimizationFinder<'a, 'tcx> {
154157
}
155158

156159
impl<'tcx> OptimizationFinder<'_, 'tcx> {
157-
fn find_optimizations(&self) -> Vec<OptimizationInfo<'tcx>> {
160+
fn find_optimizations(&self, ssa: &SsaLocals) -> Vec<OptimizationInfo<'tcx>> {
158161
self.body
159162
.basic_blocks
160163
.iter_enumerated()
161164
.filter_map(|(bb_idx, bb)| {
162165
// find switch
163-
let (place_switched_on, targets, place_switched_on_moved) =
164-
match &bb.terminator().kind {
165-
rustc_middle::mir::TerminatorKind::SwitchInt { discr, targets, .. } => {
166-
Some((discr.place()?, targets, discr.is_move()))
167-
}
168-
_ => None,
169-
}?;
166+
let (discr, targets) = bb.terminator().kind.as_switch()?;
167+
let place_switched_on = discr.place()?;
168+
// Make sure that the place is not modified.
169+
if !ssa.is_ssa(place_switched_on.local) || !place_switched_on.is_stable_offset() {
170+
return None;
171+
}
170172

171173
// find the statement that assigns the place being switched on
172174
bb.statements.iter().enumerate().rev().find_map(|(stmt_idx, stmt)| {
@@ -180,12 +182,12 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> {
180182
box (left, right),
181183
) => {
182184
let (branch_value_scalar, branch_value_ty, to_switch_on) =
183-
find_branch_value_info(left, right)?;
185+
find_branch_value_info(left, right, ssa)?;
184186

185187
Some(OptimizationInfo {
186188
bin_op_stmt_idx: stmt_idx,
187189
bb_idx,
188-
can_remove_bin_op_stmt: place_switched_on_moved,
190+
can_remove_bin_op_stmt: discr.is_move(),
189191
to_switch_on,
190192
branch_value_scalar,
191193
branch_value_ty,
@@ -207,13 +209,18 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> {
207209
fn find_branch_value_info<'tcx>(
208210
left: &Operand<'tcx>,
209211
right: &Operand<'tcx>,
212+
ssa: &SsaLocals,
210213
) -> Option<(Scalar, Ty<'tcx>, Place<'tcx>)> {
211214
// check that either left or right is a constant.
212215
// if any are, we can use the other to switch on, and the constant as a value in a switch
213216
use Operand::*;
214217
match (left, right) {
215218
(Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
216219
| (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => {
220+
// Make sure that the place is not modified.
221+
if !ssa.is_ssa(to_switch_on.local) || !to_switch_on.is_stable_offset() {
222+
return None;
223+
}
217224
let branch_value_ty = branch_value.const_.ty();
218225
// we only want to apply this optimization if we are matching on integrals (and chars),
219226
// as it is not possible to switch on floats

tests/debuginfo/dummy_span.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//@ min-lldb-version: 310
22

33
//@ compile-flags:-g
4+
// FIXME: Investigate why test fails without SimplifyComparisonIntegral pass.
5+
//@ compile-flags: -Zmir-enable-passes=+SimplifyComparisonIntegral
46
//@ ignore-backends: gcc
57

68
// === GDB TESTS ===================================================================================

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
7575
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
7676
StorageDead(_23);
77-
switchInt(move _22) -> [0: bb10, otherwise: bb11];
77+
switchInt(copy _22) -> [0: bb10, otherwise: bb11];
7878
}
7979

8080
bb4: {

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
7575
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
7676
StorageDead(_23);
77-
switchInt(move _22) -> [0: bb10, otherwise: bb11];
77+
switchInt(copy _22) -> [0: bb10, otherwise: bb11];
7878
}
7979

8080
bb4: {

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
7575
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
7676
StorageDead(_23);
77-
switchInt(move _22) -> [0: bb10, otherwise: bb11];
77+
switchInt(copy _22) -> [0: bb10, otherwise: bb11];
7878
}
7979

8080
bb4: {

tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
_23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
7575
_22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
7676
StorageDead(_23);
77-
switchInt(move _22) -> [0: bb10, otherwise: bb11];
77+
switchInt(copy _22) -> [0: bb10, otherwise: bb11];
7878
}
7979

8080
bb4: {

tests/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
bb0: {
1010
StorageLive(_2);
1111
_2 = copy _1;
12-
switchInt(move _2) -> [0: bb2, otherwise: bb1];
12+
switchInt(copy _1) -> [0: bb2, otherwise: bb1];
1313
}
1414

1515
bb1: {

tests/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
StorageLive(_2);
1212
StorageLive(_3);
1313
_3 = copy _1;
14-
_2 = Eq(move _3, const -42f32);
14+
_2 = Eq(copy _1, const -42f32);
1515
switchInt(move _2) -> [0: bb2, otherwise: bb1];
1616
}
1717

tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,39 @@
1515
}
1616

1717
bb0: {
18-
StorageLive(_2);
18+
nop;
1919
StorageLive(_3);
2020
_3 = copy _1;
21-
- _2 = Eq(move _3, const 17_i8);
22-
- StorageDead(_3);
21+
_2 = Eq(copy _1, const 17_i8);
22+
StorageDead(_3);
2323
- switchInt(copy _2) -> [0: bb2, otherwise: bb1];
24-
+ _2 = Eq(copy _3, const 17_i8);
25-
+ nop;
26-
+ switchInt(move _3) -> [17: bb1, otherwise: bb2];
24+
+ switchInt(copy _1) -> [17: bb1, otherwise: bb2];
2725
}
2826

2927
bb1: {
30-
+ StorageDead(_3);
3128
StorageLive(_6);
3229
StorageLive(_7);
3330
_7 = copy _2;
34-
_6 = move _7 as i32 (IntToInt);
31+
_6 = copy _2 as i32 (IntToInt);
3532
StorageDead(_7);
3633
_0 = Add(const 100_i32, move _6);
3734
StorageDead(_6);
3835
goto -> bb3;
3936
}
4037

4138
bb2: {
42-
+ StorageDead(_3);
4339
StorageLive(_4);
4440
StorageLive(_5);
4541
_5 = copy _2;
46-
_4 = move _5 as i32 (IntToInt);
42+
_4 = copy _2 as i32 (IntToInt);
4743
StorageDead(_5);
4844
_0 = Add(const 10_i32, move _4);
4945
StorageDead(_4);
5046
goto -> bb3;
5147
}
5248

5349
bb3: {
54-
StorageDead(_2);
50+
nop;
5551
return;
5652
}
5753
}

0 commit comments

Comments
 (0)