From 2f1c2193d1e9a01adbf5b7886eee229242407dcb Mon Sep 17 00:00:00 2001 From: Smitty Date: Mon, 7 Jun 2021 12:33:00 -0400 Subject: [PATCH] Peephole optimize `x == false` and `x != true` --- .../rustc_mir/src/transform/instcombine.rs | 21 +++++++---- .../bool_compare.opt1.InstCombine.diff | 35 +++++++++++++++++++ .../bool_compare.opt2.InstCombine.diff | 35 +++++++++++++++++++ .../bool_compare.opt3.InstCombine.diff | 35 +++++++++++++++++++ .../bool_compare.opt4.InstCombine.diff | 35 +++++++++++++++++++ src/test/mir-opt/bool_compare.rs | 26 ++++++++++++++ 6 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 src/test/mir-opt/bool_compare.opt1.InstCombine.diff create mode 100644 src/test/mir-opt/bool_compare.opt2.InstCombine.diff create mode 100644 src/test/mir-opt/bool_compare.opt3.InstCombine.diff create mode 100644 src/test/mir-opt/bool_compare.opt4.InstCombine.diff create mode 100644 src/test/mir-opt/bool_compare.rs diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index 7aaf0224164..b64189a7f3c 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -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; } } } diff --git a/src/test/mir-opt/bool_compare.opt1.InstCombine.diff b/src/test/mir-opt/bool_compare.opt1.InstCombine.diff new file mode 100644 index 00000000000..a14f64467a6 --- /dev/null +++ b/src/test/mir-opt/bool_compare.opt1.InstCombine.diff @@ -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 + } + } + diff --git a/src/test/mir-opt/bool_compare.opt2.InstCombine.diff b/src/test/mir-opt/bool_compare.opt2.InstCombine.diff new file mode 100644 index 00000000000..4e9c255ad62 --- /dev/null +++ b/src/test/mir-opt/bool_compare.opt2.InstCombine.diff @@ -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 + } + } + diff --git a/src/test/mir-opt/bool_compare.opt3.InstCombine.diff b/src/test/mir-opt/bool_compare.opt3.InstCombine.diff new file mode 100644 index 00000000000..2048c97a9e1 --- /dev/null +++ b/src/test/mir-opt/bool_compare.opt3.InstCombine.diff @@ -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 + } + } + diff --git a/src/test/mir-opt/bool_compare.opt4.InstCombine.diff b/src/test/mir-opt/bool_compare.opt4.InstCombine.diff new file mode 100644 index 00000000000..efcaa2766a9 --- /dev/null +++ b/src/test/mir-opt/bool_compare.opt4.InstCombine.diff @@ -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 + } + } + diff --git a/src/test/mir-opt/bool_compare.rs b/src/test/mir-opt/bool_compare.rs new file mode 100644 index 00000000000..3ff046325dc --- /dev/null +++ b/src/test/mir-opt/bool_compare.rs @@ -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); +}