mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
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.
This commit is contained in:
commit
d45d205d59
@ -4,7 +4,7 @@ use crate::transform::MirPass;
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_middle::mir::{
|
||||
BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
|
||||
StatementKind,
|
||||
StatementKind, UnOp,
|
||||
};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
||||
@ -47,28 +47,35 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
|
||||
Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => {
|
||||
let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
|
||||
// Transform "Eq(a, true)" ==> "a"
|
||||
(BinOp::Eq, _, Some(true)) => Some(a.clone()),
|
||||
(BinOp::Eq, _, Some(true)) => Some(Rvalue::Use(a.clone())),
|
||||
|
||||
// Transform "Ne(a, false)" ==> "a"
|
||||
(BinOp::Ne, _, Some(false)) => Some(a.clone()),
|
||||
(BinOp::Ne, _, Some(false)) => Some(Rvalue::Use(a.clone())),
|
||||
|
||||
// Transform "Eq(true, b)" ==> "b"
|
||||
(BinOp::Eq, Some(true), _) => Some(b.clone()),
|
||||
(BinOp::Eq, Some(true), _) => Some(Rvalue::Use(b.clone())),
|
||||
|
||||
// Transform "Ne(false, b)" ==> "b"
|
||||
(BinOp::Ne, Some(false), _) => Some(b.clone()),
|
||||
(BinOp::Ne, Some(false), _) => Some(Rvalue::Use(b.clone())),
|
||||
|
||||
// FIXME: Consider combining remaining comparisons into logical operations:
|
||||
// Transform "Eq(false, b)" ==> "Not(b)"
|
||||
(BinOp::Eq, Some(false), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
|
||||
|
||||
// Transform "Ne(true, b)" ==> "Not(b)"
|
||||
(BinOp::Ne, Some(true), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
|
||||
|
||||
// Transform "Eq(a, false)" ==> "Not(a)"
|
||||
(BinOp::Eq, _, Some(false)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
|
||||
|
||||
// Transform "Ne(a, true)" ==> "Not(a)"
|
||||
(BinOp::Ne, _, Some(true)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(new) = new {
|
||||
if self.should_combine(source_info, rvalue) {
|
||||
*rvalue = Rvalue::Use(new);
|
||||
*rvalue = new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
35
src/test/mir-opt/bool_compare.opt1.InstCombine.diff
Normal file
35
src/test/mir-opt/bool_compare.opt1.InstCombine.diff
Normal file
@ -0,0 +1,35 @@
|
||||
- // MIR for `opt1` before InstCombine
|
||||
+ // MIR for `opt1` after InstCombine
|
||||
|
||||
fn opt1(_1: bool) -> u32 {
|
||||
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:2:9: 2:10
|
||||
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:2:21: 2:24
|
||||
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:3:8: 3:17
|
||||
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:3:8: 3:9
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
|
||||
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:3:8: 3:9
|
||||
_3 = _1; // scope 0 at $DIR/bool_compare.rs:3:8: 3:9
|
||||
- _2 = Ne(move _3, const true); // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
|
||||
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
|
||||
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:3:16: 3:17
|
||||
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:3:20: 3:21
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:3:31: 3:32
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:3:33: 3:34
|
||||
return; // scope 0 at $DIR/bool_compare.rs:4:2: 4:2
|
||||
}
|
||||
}
|
||||
|
35
src/test/mir-opt/bool_compare.opt2.InstCombine.diff
Normal file
35
src/test/mir-opt/bool_compare.opt2.InstCombine.diff
Normal file
@ -0,0 +1,35 @@
|
||||
- // MIR for `opt2` before InstCombine
|
||||
+ // MIR for `opt2` after InstCombine
|
||||
|
||||
fn opt2(_1: bool) -> u32 {
|
||||
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:7:9: 7:10
|
||||
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:7:21: 7:24
|
||||
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:8:8: 8:17
|
||||
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:8:16: 8:17
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
|
||||
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
|
||||
_3 = _1; // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
|
||||
- _2 = Ne(const true, move _3); // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
|
||||
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
|
||||
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
|
||||
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:8:20: 8:21
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:8:31: 8:32
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:8:33: 8:34
|
||||
return; // scope 0 at $DIR/bool_compare.rs:9:2: 9:2
|
||||
}
|
||||
}
|
||||
|
35
src/test/mir-opt/bool_compare.opt3.InstCombine.diff
Normal file
35
src/test/mir-opt/bool_compare.opt3.InstCombine.diff
Normal file
@ -0,0 +1,35 @@
|
||||
- // MIR for `opt3` before InstCombine
|
||||
+ // MIR for `opt3` after InstCombine
|
||||
|
||||
fn opt3(_1: bool) -> u32 {
|
||||
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:12:9: 12:10
|
||||
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:12:21: 12:24
|
||||
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:13:8: 13:18
|
||||
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:13:8: 13:9
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
|
||||
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:13:8: 13:9
|
||||
_3 = _1; // scope 0 at $DIR/bool_compare.rs:13:8: 13:9
|
||||
- _2 = Eq(move _3, const false); // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
|
||||
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
|
||||
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:13:17: 13:18
|
||||
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:13:21: 13:22
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:13:32: 13:33
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:13:34: 13:35
|
||||
return; // scope 0 at $DIR/bool_compare.rs:14:2: 14:2
|
||||
}
|
||||
}
|
||||
|
35
src/test/mir-opt/bool_compare.opt4.InstCombine.diff
Normal file
35
src/test/mir-opt/bool_compare.opt4.InstCombine.diff
Normal file
@ -0,0 +1,35 @@
|
||||
- // MIR for `opt4` before InstCombine
|
||||
+ // MIR for `opt4` after InstCombine
|
||||
|
||||
fn opt4(_1: bool) -> u32 {
|
||||
debug x => _1; // in scope 0 at $DIR/bool_compare.rs:17:9: 17:10
|
||||
let mut _0: u32; // return place in scope 0 at $DIR/bool_compare.rs:17:21: 17:24
|
||||
let mut _2: bool; // in scope 0 at $DIR/bool_compare.rs:18:8: 18:18
|
||||
let mut _3: bool; // in scope 0 at $DIR/bool_compare.rs:18:17: 18:18
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
|
||||
StorageLive(_3); // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
|
||||
_3 = _1; // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
|
||||
- _2 = Eq(const false, move _3); // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
|
||||
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
|
||||
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
|
||||
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const 0_u32; // scope 0 at $DIR/bool_compare.rs:18:21: 18:22
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_0 = const 1_u32; // scope 0 at $DIR/bool_compare.rs:18:32: 18:33
|
||||
goto -> bb3; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_2); // scope 0 at $DIR/bool_compare.rs:18:34: 18:35
|
||||
return; // scope 0 at $DIR/bool_compare.rs:19:2: 19:2
|
||||
}
|
||||
}
|
||||
|
26
src/test/mir-opt/bool_compare.rs
Normal file
26
src/test/mir-opt/bool_compare.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// EMIT_MIR bool_compare.opt1.InstCombine.diff
|
||||
fn opt1(x: bool) -> u32 {
|
||||
if x != true { 0 } else { 1 }
|
||||
}
|
||||
|
||||
// EMIT_MIR bool_compare.opt2.InstCombine.diff
|
||||
fn opt2(x: bool) -> u32 {
|
||||
if true != x { 0 } else { 1 }
|
||||
}
|
||||
|
||||
// EMIT_MIR bool_compare.opt3.InstCombine.diff
|
||||
fn opt3(x: bool) -> u32 {
|
||||
if x == false { 0 } else { 1 }
|
||||
}
|
||||
|
||||
// EMIT_MIR bool_compare.opt4.InstCombine.diff
|
||||
fn opt4(x: bool) -> u32 {
|
||||
if false == x { 0 } else { 1 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
opt1(false);
|
||||
opt2(false);
|
||||
opt3(false);
|
||||
opt4(false);
|
||||
}
|
Loading…
Reference in New Issue
Block a user