diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2020-07-24 10:01:32 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-24 10:01:32 -0700 |
| commit | e59effed3037701aadab11d4ea0ddddf2eedbf3b (patch) | |
| tree | 806abbeb804a9e25d08bf88e06182518bb532134 /src/test | |
| parent | 3226d723381a24118f6aaa73b096c8ef4510f189 (diff) | |
| parent | 711a6807a7979715d6b2940db56eaf1585d30a71 (diff) | |
| download | rust-e59effed3037701aadab11d4ea0ddddf2eedbf3b.tar.gz rust-e59effed3037701aadab11d4ea0ddddf2eedbf3b.zip | |
Rollup merge of #74491 - xldenis:constant-binop-opt, r=oli-obk
Optimize away BitAnd and BitOr when possible This PR lets `const_prop` optimize away `a | true == true` , `a & false == false` and `a * 0 = 0`. While I was writing this I've realized that constant propagation misses a lot of opportunities. For example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2a4b45e772f214210a36749b27223bb0 Constant propagation doesn't seem to... propagate constants, additionally the way constant propagation is currently setup makes it tricky to add cases like `a | false == a`. I tried to organize `eval_rvalue_with_identities` to make the pattern of the optimizations easier to see but it still obscurs what should be a simple peephole optmization. cc @oli-obk
Diffstat (limited to 'src/test')
6 files changed, 102 insertions, 3 deletions
diff --git a/src/test/mir-opt/const_prop/boolean_identities.rs b/src/test/mir-opt/const_prop/boolean_identities.rs new file mode 100644 index 00000000000..4e09acbaa53 --- /dev/null +++ b/src/test/mir-opt/const_prop/boolean_identities.rs @@ -0,0 +1,10 @@ +// compile-flags: -O -Zmir-opt-level=3 + +// EMIT_MIR rustc.test.ConstProp.diff +pub fn test(x: bool, y: bool) -> bool { + (y | true) & (x & false) +} + +fn main() { + test(true, false); +} diff --git a/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff new file mode 100644 index 00000000000..b8f0ad4d434 --- /dev/null +++ b/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff @@ -0,0 +1,53 @@ +- // MIR for `test` before ConstProp ++ // MIR for `test` after ConstProp + + fn test(_1: bool, _2: bool) -> bool { + debug x => _1; // in scope 0 at $DIR/boolean_identities.rs:4:13: 4:14 + debug y => _2; // in scope 0 at $DIR/boolean_identities.rs:4:22: 4:23 + let mut _0: bool; // return place in scope 0 at $DIR/boolean_identities.rs:4:34: 4:38 + let mut _3: bool; // in scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 + let mut _4: bool; // in scope 0 at $DIR/boolean_identities.rs:5:6: 5:7 + let mut _5: bool; // in scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 + let mut _6: bool; // in scope 0 at $DIR/boolean_identities.rs:5:19: 5:20 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 + StorageLive(_4); // scope 0 at $DIR/boolean_identities.rs:5:6: 5:7 + _4 = _2; // scope 0 at $DIR/boolean_identities.rs:5:6: 5:7 +- _3 = BitOr(move _4, const true); // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 ++ _3 = const true; // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant +- // + span: $DIR/boolean_identities.rs:5:10: 5:14 ++ // + span: $DIR/boolean_identities.rs:5:5: 5:15 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + StorageDead(_4); // scope 0 at $DIR/boolean_identities.rs:5:14: 5:15 + StorageLive(_5); // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 + StorageLive(_6); // scope 0 at $DIR/boolean_identities.rs:5:19: 5:20 + _6 = _1; // scope 0 at $DIR/boolean_identities.rs:5:19: 5:20 +- _5 = BitAnd(move _6, const false); // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 ++ _5 = const false; // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) + // mir::Constant +- // + span: $DIR/boolean_identities.rs:5:23: 5:28 ++ // + span: $DIR/boolean_identities.rs:5:18: 5:29 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + StorageDead(_6); // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29 +- _0 = BitAnd(move _3, move _5); // scope 0 at $DIR/boolean_identities.rs:5:5: 5:29 ++ _0 = const false; // scope 0 at $DIR/boolean_identities.rs:5:5: 5:29 ++ // ty::Const ++ // + ty: bool ++ // + val: Value(Scalar(0x00)) ++ // mir::Constant ++ // + span: $DIR/boolean_identities.rs:5:5: 5:29 ++ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + StorageDead(_5); // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29 + StorageDead(_3); // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29 + return; // scope 0 at $DIR/boolean_identities.rs:6:2: 6:2 + } + } + diff --git a/src/test/mir-opt/const_prop/mult_by_zero.rs b/src/test/mir-opt/const_prop/mult_by_zero.rs new file mode 100644 index 00000000000..f40faee3110 --- /dev/null +++ b/src/test/mir-opt/const_prop/mult_by_zero.rs @@ -0,0 +1,10 @@ +// compile-flags: -O -Zmir-opt-level=3 + +// EMIT_MIR rustc.test.ConstProp.diff +fn test(x : i32) -> i32 { + x * 0 +} + +fn main() { + test(10); +} diff --git a/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff new file mode 100644 index 00000000000..7b36669bf15 --- /dev/null +++ b/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff @@ -0,0 +1,25 @@ +- // MIR for `test` before ConstProp ++ // MIR for `test` after ConstProp + + fn test(_1: i32) -> i32 { + debug x => _1; // in scope 0 at $DIR/mult_by_zero.rs:4:9: 4:10 + let mut _0: i32; // return place in scope 0 at $DIR/mult_by_zero.rs:4:21: 4:24 + let mut _2: i32; // in scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4 + _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4 +- _0 = Mul(move _2, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:8 ++ _0 = const 0_i32; // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:8 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant +- // + span: $DIR/mult_by_zero.rs:5:7: 5:8 ++ // + span: $DIR/mult_by_zero.rs:5:3: 5:8 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } + StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:5:7: 5:8 + return; // scope 0 at $DIR/mult_by_zero.rs:6:2: 6:2 + } + } + diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs index 2a983e42683..795c5154f81 100644 --- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs +++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs @@ -1,7 +1,7 @@ // build-fail // Regression test for #66975 -#![warn(const_err)] +#![warn(const_err, unconditional_panic)] #![feature(never_type)] struct PrintName<T>(T); @@ -9,6 +9,7 @@ struct PrintName<T>(T); impl<T> PrintName<T> { const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] }; //~^ WARN any use of this value will cause an error + } fn f<T>() { diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr index d78e0da00f5..33e60dd7c91 100644 --- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr +++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr @@ -9,11 +9,11 @@ LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] }; note: the lint level is defined here --> $DIR/index-out-of-bounds-never-type.rs:4:9 | -LL | #![warn(const_err)] +LL | #![warn(const_err, unconditional_panic)] | ^^^^^^^^^ error: erroneous constant encountered - --> $DIR/index-out-of-bounds-never-type.rs:15:13 + --> $DIR/index-out-of-bounds-never-type.rs:16:13 | LL | let _ = PrintName::<T>::VOID; | ^^^^^^^^^^^^^^^^^^^^ |
