about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-06-09 06:06:06 +0000
committerbors <bors@rust-lang.org>2021-06-09 06:06:06 +0000
commitd45d205d59bd9eaca352e3a8f18c625f47f5838b (patch)
tree0f893fbff81c786d9deea4c34cf594f1b3ecd2ec
parentc8381389ee10e3c0505ccb5bac05382de1b9f99d (diff)
parent2f1c2193d1e9a01adbf5b7886eee229242407dcb (diff)
downloadrust-d45d205d59bd9eaca352e3a8f18c625f47f5838b.tar.gz
rust-d45d205d59bd9eaca352e3a8f18c625f47f5838b.zip
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.
-rw-r--r--compiler/rustc_mir/src/transform/instcombine.rs21
-rw-r--r--src/test/mir-opt/bool_compare.opt1.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.opt2.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.opt3.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.opt4.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.rs26
6 files changed, 180 insertions, 7 deletions
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);
+}