Skip to content

Commit 3d52e54

Browse files
committed
Don't need to look at the layout of the types being matched on
We only need to check that the discriminant value is the same
1 parent 4a6b728 commit 3d52e54

6 files changed

+164
-90
lines changed

compiler/rustc_mir/src/transform/early_otherwise_branch.rs

+2-19
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::{
22
transform::{MirPass, MirSource},
33
util::patch::MirPatch,
44
};
5+
use rustc_middle::mir::*;
56
use rustc_middle::ty::{Ty, TyCtxt};
6-
use rustc_middle::{mir::*, ty::ParamEnv};
77
use std::{borrow::Cow, fmt::Debug};
88

99
use super::simplify::simplify_cfg;
@@ -40,7 +40,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
4040
let opts_to_apply: Vec<OptimizationToApply<'tcx>> = bbs_with_switch
4141
.flat_map(|(bb_idx, bb)| {
4242
let switch = bb.terminator();
43-
let helper = Helper { body, tcx, param_env: tcx.param_env(source.def_id()) };
43+
let helper = Helper { body, tcx };
4444
let infos = helper.go(bb, switch)?;
4545
Some(OptimizationToApply { infos, basic_block_first_switch: bb_idx })
4646
})
@@ -170,7 +170,6 @@ fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool {
170170
struct Helper<'a, 'tcx> {
171171
body: &'a Body<'tcx>,
172172
tcx: TyCtxt<'tcx>,
173-
param_env: ParamEnv<'tcx>,
174173
}
175174

176175
#[derive(Debug, Clone)]
@@ -267,22 +266,6 @@ impl<'a, 'tcx> Helper<'a, 'tcx> {
267266
return None;
268267
}
269268

270-
// check that the value being matched on is the same. The
271-
if this_bb_discr_info.targets_with_values.iter().find(|x| x.1 == value).is_none() {
272-
trace!("NO: values being matched on are not the same");
273-
return None;
274-
}
275-
276-
// The layouts of the two ADTs have to be equal for this optimization to apply
277-
let layout_of_adt =
278-
|ty: Ty<'tcx>| self.tcx.layout_of(self.param_env.and(ty)).ok().map(|x| x.layout);
279-
let layout_lhs = layout_of_adt(discr_info.type_adt_matched_on);
280-
let layout_rhs = layout_of_adt(this_bb_discr_info.type_adt_matched_on);
281-
if layout_lhs != layout_rhs {
282-
trace!("NO: Layouts do not match. LHS: {:?}, RHS: {:?}", layout_lhs, layout_rhs);
283-
return None;
284-
}
285-
286269
// If we reach this point, the optimization applies, and we should be able to optimize this case
287270
// store the info that is needed to apply the optimization
288271

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
- // MIR for `opt4` before EarlyOtherwiseBranch
2+
+ // MIR for `opt4` after EarlyOtherwiseBranch
3+
4+
fn opt4(_1: std::result::Result<u32, ()>, _2: Option<u32>) -> u32 {
5+
debug x => _1; // in scope 0 at $DIR/early_otherwise_branch.rs:40:9: 40:10
6+
debug y => _2; // in scope 0 at $DIR/early_otherwise_branch.rs:40:29: 40:30
7+
let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch.rs:40:48: 40:51
8+
let mut _3: (std::result::Result<u32, ()>, std::option::Option<u32>); // in scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17
9+
let mut _4: std::result::Result<u32, ()>; // in scope 0 at $DIR/early_otherwise_branch.rs:41:12: 41:13
10+
let mut _5: std::option::Option<u32>; // in scope 0 at $DIR/early_otherwise_branch.rs:41:15: 41:16
11+
let mut _6: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
12+
let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
13+
+ let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
14+
+ let mut _9: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
15+
16+
bb0: {
17+
StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17
18+
StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch.rs:41:12: 41:13
19+
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:41:12: 41:13
20+
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:41:15: 41:16
21+
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:41:15: 41:16
22+
(_3.0: std::result::Result<u32, ()>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17
23+
(_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17
24+
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:41:16: 41:17
25+
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:41:16: 41:17
26+
_7 = discriminant((_3.0: std::result::Result<u32, ()>)); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
27+
- switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
28+
+ StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
29+
+ _8 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
30+
+ StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
31+
+ _9 = Ne(_8, _7); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
32+
+ StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
33+
+ switchInt(move _9) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
34+
}
35+
36+
bb1: {
37+
+ StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:43:14: 43:15
38+
_0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch.rs:43:14: 43:15
39+
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
40+
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
41+
}
42+
43+
bb2: {
44+
- _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
45+
- switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
46+
+ _0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
47+
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
48+
}
49+
50+
bb3: {
51+
- _0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
52+
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
53+
+ StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
54+
+ return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
55+
}
56+
57+
bb4: {
58+
- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
59+
- return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
60+
+ StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
61+
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
62+
}
63+
}
64+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
- // MIR for `opt5` before EarlyOtherwiseBranch
2+
+ // MIR for `opt5` after EarlyOtherwiseBranch
3+
4+
fn opt5(_1: Option<u32>, _2: Option<bool>) -> u32 {
5+
debug x => _1; // in scope 0 at $DIR/early_otherwise_branch.rs:49:9: 49:10
6+
debug y => _2; // in scope 0 at $DIR/early_otherwise_branch.rs:49:25: 49:26
7+
let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch.rs:49:45: 49:48
8+
let mut _3: (std::option::Option<u32>, std::option::Option<bool>); // in scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17
9+
let mut _4: std::option::Option<u32>; // in scope 0 at $DIR/early_otherwise_branch.rs:50:12: 50:13
10+
let mut _5: std::option::Option<bool>; // in scope 0 at $DIR/early_otherwise_branch.rs:50:15: 50:16
11+
let mut _6: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
12+
let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
13+
let _8: u32; // in scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
14+
let _9: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:51:24: 51:25
15+
+ let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
16+
+ let mut _11: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
17+
scope 1 {
18+
debug a => _8; // in scope 1 at $DIR/early_otherwise_branch.rs:51:15: 51:16
19+
debug b => _9; // in scope 1 at $DIR/early_otherwise_branch.rs:51:24: 51:25
20+
}
21+
22+
bb0: {
23+
StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17
24+
StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch.rs:50:12: 50:13
25+
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:50:12: 50:13
26+
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:50:15: 50:16
27+
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:50:15: 50:16
28+
(_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17
29+
(_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17
30+
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:50:16: 50:17
31+
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:50:16: 50:17
32+
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
33+
- switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
34+
+ StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
35+
+ _10 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
36+
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
37+
+ _11 = Ne(_10, _7); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
38+
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
39+
+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
40+
}
41+
42+
bb1: {
43+
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:52:14: 52:15
44+
_0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch.rs:52:14: 52:15
45+
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6
46+
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6
47+
}
48+
49+
bb2: {
50+
- _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
51+
- switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
52+
- }
53+
-
54+
- bb3: {
55+
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
56+
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
57+
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:51:24: 51:25
58+
_9 = (((_3.1: std::option::Option<bool>) as Some).0: bool); // scope 0 at $DIR/early_otherwise_branch.rs:51:24: 51:25
59+
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:51:31: 51:32
60+
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:51:31: 51:32
61+
StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:51:31: 51:32
62+
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6
63+
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6
64+
}
65+
66+
- bb4: {
67+
+ bb3: {
68+
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:54:1: 54:2
69+
return; // scope 0 at $DIR/early_otherwise_branch.rs:54:2: 54:2
70+
+ }
71+
+
72+
+ bb4: {
73+
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
74+
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
75+
}
76+
}
77+

src/test/mir-opt/early_otherwise_branch.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ enum MyOption2<T> {
2626
None,
2727
}
2828

29-
// must optimize as the tag encoding of the discriminant are the same
29+
// must optimize as the discriminant values are the same
3030
// EMIT_MIR early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
3131
fn opt3(x: MyOption1<u32>, y: MyOption2<u32>) -> u32 {
3232
match (x, y) {
@@ -35,8 +35,28 @@ fn opt3(x: MyOption1<u32>, y: MyOption2<u32>) -> u32 {
3535
}
3636
}
3737

38+
// must optimize as the discriminant values are the same
39+
// EMIT_MIR early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
40+
fn opt4(x: Result<u32, ()>, y: Option<u32>) -> u32 {
41+
match (x, y) {
42+
(Err(_), Some(_)) => 0,
43+
_ => 1,
44+
}
45+
}
46+
47+
// must optimize as the discriminant values are the same
48+
// EMIT_MIR early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff
49+
fn opt5(x: Option<u32>, y: Option<bool>) -> u32 {
50+
match (x, y) {
51+
(Some(a), Some(b)) => 0,
52+
_ => 1,
53+
}
54+
}
55+
3856
fn main() {
3957
opt1(None, Some(0));
4058
opt2(None, Some(0));
4159
opt3(MyOption1::None, MyOption2::Some(0));
60+
opt4(Ok(0), None);
61+
opt5(None, Some(true));
4262
}

src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff

-60
This file was deleted.

src/test/mir-opt/early_otherwise_branch_noopt.rs

-10
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,6 @@ fn noopt1(x: Option<u32>, y: Option<u32>) -> u32 {
1313
}
1414
}
1515

16-
// must not optimize as the tag encodings of the discriminant are not the same
17-
// EMIT_MIR early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff
18-
fn noopt2(x: Option<u32>, y: Option<bool>) -> u32 {
19-
match (x, y) {
20-
(Some(a), Some(b)) => 0,
21-
_ => 1,
22-
}
23-
}
24-
2516
fn main() {
2617
noopt1(None, Some(0));
27-
noopt2(None, Some(true));
2818
}

0 commit comments

Comments
 (0)