Skip to content

Commit d45d205

Browse files
committed
Auto merge of #86107 - Smittyvb:peephole-optim-eq-bool, r=wesleywiser
Peephole optimize `x == false` and `x != true` This adds peephole optimizations to make `x == false`, `false == x`, `x != true`, and `true != x` get optimized to `!x` in the `instcombine` MIR pass. That pass currently handles `x == true` -> `x` already.
2 parents c838138 + 2f1c219 commit d45d205

6 files changed

+180
-7
lines changed

compiler/rustc_mir/src/transform/instcombine.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::transform::MirPass;
44
use rustc_hir::Mutability;
55
use rustc_middle::mir::{
66
BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
7-
StatementKind,
7+
StatementKind, UnOp,
88
};
99
use rustc_middle::ty::{self, TyCtxt};
1010

@@ -47,28 +47,35 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
4747
Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => {
4848
let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
4949
// Transform "Eq(a, true)" ==> "a"
50-
(BinOp::Eq, _, Some(true)) => Some(a.clone()),
50+
(BinOp::Eq, _, Some(true)) => Some(Rvalue::Use(a.clone())),
5151

5252
// Transform "Ne(a, false)" ==> "a"
53-
(BinOp::Ne, _, Some(false)) => Some(a.clone()),
53+
(BinOp::Ne, _, Some(false)) => Some(Rvalue::Use(a.clone())),
5454

5555
// Transform "Eq(true, b)" ==> "b"
56-
(BinOp::Eq, Some(true), _) => Some(b.clone()),
56+
(BinOp::Eq, Some(true), _) => Some(Rvalue::Use(b.clone())),
5757

5858
// Transform "Ne(false, b)" ==> "b"
59-
(BinOp::Ne, Some(false), _) => Some(b.clone()),
59+
(BinOp::Ne, Some(false), _) => Some(Rvalue::Use(b.clone())),
6060

61-
// FIXME: Consider combining remaining comparisons into logical operations:
6261
// Transform "Eq(false, b)" ==> "Not(b)"
62+
(BinOp::Eq, Some(false), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
63+
6364
// Transform "Ne(true, b)" ==> "Not(b)"
65+
(BinOp::Ne, Some(true), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
66+
6467
// Transform "Eq(a, false)" ==> "Not(a)"
68+
(BinOp::Eq, _, Some(false)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
69+
6570
// Transform "Ne(a, true)" ==> "Not(a)"
71+
(BinOp::Ne, _, Some(true)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
72+
6673
_ => None,
6774
};
6875

6976
if let Some(new) = new {
7077
if self.should_combine(source_info, rvalue) {
71-
*rvalue = Rvalue::Use(new);
78+
*rvalue = new;
7279
}
7380
}
7481
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
- // MIR for `opt1` before InstCombine
2+
+ // MIR for `opt1` after InstCombine
3+
4+
fn opt1(_1: bool) -> u32 {
5+
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:2:9: 2:10
6+
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:2:21: 2:24
7+
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:3:8: 3:17
8+
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:3:8: 3:9
9+
10+
bb0: {
11+
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
12+
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:3:8: 3:9
13+
_3 = _1; // scope 0 at $DIR/bool_compare.rs:3:8: 3:9
14+
- _2 = Ne(move _3, const true); // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
15+
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
16+
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:3:16: 3:17
17+
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
18+
}
19+
20+
bb1: {
21+
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:3:20: 3:21
22+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
23+
}
24+
25+
bb2: {
26+
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:3:31: 3:32
27+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
28+
}
29+
30+
bb3: {
31+
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:3:33: 3:34
32+
return; // scope 0 at $DIR/bool_compare.rs:4:2: 4:2
33+
}
34+
}
35+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
- // MIR for `opt2` before InstCombine
2+
+ // MIR for `opt2` after InstCombine
3+
4+
fn opt2(_1: bool) -> u32 {
5+
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:7:9: 7:10
6+
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:7:21: 7:24
7+
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:8:8: 8:17
8+
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:8:16: 8:17
9+
10+
bb0: {
11+
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
12+
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
13+
_3 = _1; // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
14+
- _2 = Ne(const true, move _3); // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
15+
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
16+
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
17+
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
18+
}
19+
20+
bb1: {
21+
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:8:20: 8:21
22+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
23+
}
24+
25+
bb2: {
26+
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:8:31: 8:32
27+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
28+
}
29+
30+
bb3: {
31+
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:8:33: 8:34
32+
return; // scope 0 at $DIR/bool_compare.rs:9:2: 9:2
33+
}
34+
}
35+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
- // MIR for `opt3` before InstCombine
2+
+ // MIR for `opt3` after InstCombine
3+
4+
fn opt3(_1: bool) -> u32 {
5+
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:12:9: 12:10
6+
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:12:21: 12:24
7+
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:13:8: 13:18
8+
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:13:8: 13:9
9+
10+
bb0: {
11+
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
12+
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:13:8: 13:9
13+
_3 = _1; // scope 0 at $DIR/bool_compare.rs:13:8: 13:9
14+
- _2 = Eq(move _3, const false); // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
15+
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
16+
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:13:17: 13:18
17+
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
18+
}
19+
20+
bb1: {
21+
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:13:21: 13:22
22+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
23+
}
24+
25+
bb2: {
26+
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:13:32: 13:33
27+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
28+
}
29+
30+
bb3: {
31+
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:13:34: 13:35
32+
return; // scope 0 at $DIR/bool_compare.rs:14:2: 14:2
33+
}
34+
}
35+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
- // MIR for `opt4` before InstCombine
2+
+ // MIR for `opt4` after InstCombine
3+
4+
fn opt4(_1: bool) -> u32 {
5+
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:17:9: 17:10
6+
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:17:21: 17:24
7+
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:18:8: 18:18
8+
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:18:17: 18:18
9+
10+
bb0: {
11+
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
12+
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
13+
_3 = _1; // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
14+
- _2 = Eq(const false, move _3); // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
15+
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
16+
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
17+
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
18+
}
19+
20+
bb1: {
21+
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:18:21: 18:22
22+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
23+
}
24+
25+
bb2: {
26+
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:18:32: 18:33
27+
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
28+
}
29+
30+
bb3: {
31+
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:18:34: 18:35
32+
return; // scope 0 at $DIR/bool_compare.rs:19:2: 19:2
33+
}
34+
}
35+

src/test/mir-opt/bool_compare.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// EMIT_MIR bool_compare.opt1.InstCombine.diff
2+
fn opt1(x: bool) -> u32 {
3+
if x != true { 0 } else { 1 }
4+
}
5+
6+
// EMIT_MIR bool_compare.opt2.InstCombine.diff
7+
fn opt2(x: bool) -> u32 {
8+
if true != x { 0 } else { 1 }
9+
}
10+
11+
// EMIT_MIR bool_compare.opt3.InstCombine.diff
12+
fn opt3(x: bool) -> u32 {
13+
if x == false { 0 } else { 1 }
14+
}
15+
16+
// EMIT_MIR bool_compare.opt4.InstCombine.diff
17+
fn opt4(x: bool) -> u32 {
18+
if false == x { 0 } else { 1 }
19+
}
20+
21+
fn main() {
22+
opt1(false);
23+
opt2(false);
24+
opt3(false);
25+
opt4(false);
26+
}

0 commit comments

Comments
 (0)