Simplify unary operations.
This commit is contained in:
parent
666030c51b
commit
5fc23ad8e6
@ -817,6 +817,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
}
|
||||
Rvalue::UnaryOp(op, ref mut arg) => {
|
||||
let arg = self.simplify_operand(arg, location)?;
|
||||
if let Some(value) = self.simplify_unary(op, arg) {
|
||||
return Some(value);
|
||||
}
|
||||
Value::UnaryOp(op, arg)
|
||||
}
|
||||
Rvalue::Discriminant(ref mut place) => {
|
||||
@ -916,6 +919,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
Some(self.insert(Value::Aggregate(ty, variant_index, fields)))
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn simplify_unary(&mut self, op: UnOp, value: VnIndex) -> Option<VnIndex> {
|
||||
let value = match (op, self.get(value)) {
|
||||
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner),
|
||||
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner),
|
||||
(UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => {
|
||||
Value::BinaryOp(BinOp::Ne, *lhs, *rhs)
|
||||
}
|
||||
(UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
|
||||
Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(self.insert(value))
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn simplify_binary(
|
||||
&mut self,
|
||||
|
@ -8,10 +8,10 @@
|
||||
let mut _3: fn(u8) -> u8;
|
||||
let _5: ();
|
||||
let mut _6: fn(u8) -> u8;
|
||||
let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
let _10: ();
|
||||
let mut _11: fn();
|
||||
let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
let _14: ();
|
||||
let mut _15: fn();
|
||||
scope 1 {
|
||||
@ -19,7 +19,7 @@
|
||||
let _4: fn(u8) -> u8;
|
||||
scope 2 {
|
||||
debug g => _4;
|
||||
let _7: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
scope 3 {
|
||||
debug closure => _7;
|
||||
let _8: fn();
|
||||
@ -62,16 +62,16 @@
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
- StorageLive(_7);
|
||||
- _7 = {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
- _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
- StorageLive(_8);
|
||||
+ nop;
|
||||
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
+ nop;
|
||||
StorageLive(_9);
|
||||
- _9 = _7;
|
||||
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
StorageDead(_9);
|
||||
StorageLive(_10);
|
||||
StorageLive(_11);
|
||||
@ -88,8 +88,8 @@
|
||||
StorageLive(_13);
|
||||
- _13 = _7;
|
||||
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
StorageDead(_13);
|
||||
StorageLive(_14);
|
||||
StorageLive(_15);
|
||||
|
@ -8,10 +8,10 @@
|
||||
let mut _3: fn(u8) -> u8;
|
||||
let _5: ();
|
||||
let mut _6: fn(u8) -> u8;
|
||||
let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
let _10: ();
|
||||
let mut _11: fn();
|
||||
let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
let _14: ();
|
||||
let mut _15: fn();
|
||||
scope 1 {
|
||||
@ -19,7 +19,7 @@
|
||||
let _4: fn(u8) -> u8;
|
||||
scope 2 {
|
||||
debug g => _4;
|
||||
let _7: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
scope 3 {
|
||||
debug closure => _7;
|
||||
let _8: fn();
|
||||
@ -62,16 +62,16 @@
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
- StorageLive(_7);
|
||||
- _7 = {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
- _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
- StorageLive(_8);
|
||||
+ nop;
|
||||
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
+ nop;
|
||||
StorageLive(_9);
|
||||
- _9 = _7;
|
||||
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
StorageDead(_9);
|
||||
StorageLive(_10);
|
||||
StorageLive(_11);
|
||||
@ -88,8 +88,8 @@
|
||||
StorageLive(_13);
|
||||
- _13 = _7;
|
||||
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
|
||||
StorageDead(_13);
|
||||
StorageLive(_14);
|
||||
StorageLive(_15);
|
||||
|
@ -166,6 +166,31 @@ fn repeated_index<T: Copy, const N: usize>(x: T, idx: usize) {
|
||||
opaque(a[idx]);
|
||||
}
|
||||
|
||||
fn unary(x: i64) {
|
||||
// CHECK-LABEL: fn unary(
|
||||
// CHECK: opaque::<i64>(_1)
|
||||
opaque(--x); // This is `x`.
|
||||
|
||||
// CHECK: [[b:_.*]] = Lt(_1, const 13_i64);
|
||||
// CHECK: opaque::<bool>([[b]])
|
||||
let b = x < 13;
|
||||
opaque(!!b); // This is `b`.
|
||||
|
||||
// Both lines should test the same thing.
|
||||
// CHECK: [[c:_.*]] = Ne(_1, const 15_i64);
|
||||
// CHECK: opaque::<bool>([[c]])
|
||||
// CHECK: opaque::<bool>([[c]])
|
||||
opaque(x != 15);
|
||||
opaque(!(x == 15));
|
||||
|
||||
// Both lines should test the same thing.
|
||||
// CHECK: [[d:_.*]] = Eq(_1, const 35_i64);
|
||||
// CHECK: opaque::<bool>([[d]])
|
||||
// CHECK: opaque::<bool>([[d]])
|
||||
opaque(x == 35);
|
||||
opaque(!(x != 35));
|
||||
}
|
||||
|
||||
/// Verify symbolic integer arithmetic simplifications.
|
||||
fn arithmetic(x: u64) {
|
||||
// CHECK-LABEL: fn arithmetic(
|
||||
@ -623,6 +648,7 @@ fn main() {
|
||||
subexpression_elimination(2, 4, 5);
|
||||
wrap_unwrap(5);
|
||||
repeated_index::<u32, 7>(5, 3);
|
||||
unary(i64::MIN);
|
||||
arithmetic(5);
|
||||
comparison(5, 6);
|
||||
arithmetic_checked(5);
|
||||
@ -651,6 +677,7 @@ fn identity<T>(x: T) -> T {
|
||||
// EMIT_MIR gvn.subexpression_elimination.GVN.diff
|
||||
// EMIT_MIR gvn.wrap_unwrap.GVN.diff
|
||||
// EMIT_MIR gvn.repeated_index.GVN.diff
|
||||
// EMIT_MIR gvn.unary.GVN.diff
|
||||
// EMIT_MIR gvn.arithmetic.GVN.diff
|
||||
// EMIT_MIR gvn.comparison.GVN.diff
|
||||
// EMIT_MIR gvn.arithmetic_checked.GVN.diff
|
||||
|
153
tests/mir-opt/gvn.unary.GVN.panic-abort.diff
Normal file
153
tests/mir-opt/gvn.unary.GVN.panic-abort.diff
Normal file
@ -0,0 +1,153 @@
|
||||
- // MIR for `unary` before GVN
|
||||
+ // MIR for `unary` after GVN
|
||||
|
||||
fn unary(_1: i64) -> () {
|
||||
debug x => _1;
|
||||
let mut _0: ();
|
||||
let _2: ();
|
||||
let mut _3: i64;
|
||||
let mut _4: i64;
|
||||
let mut _5: i64;
|
||||
let _6: bool;
|
||||
let mut _7: i64;
|
||||
let _8: ();
|
||||
let mut _9: bool;
|
||||
let mut _10: bool;
|
||||
let mut _11: bool;
|
||||
let _12: ();
|
||||
let mut _13: bool;
|
||||
let mut _14: i64;
|
||||
let _15: ();
|
||||
let mut _16: bool;
|
||||
let mut _17: bool;
|
||||
let mut _18: i64;
|
||||
let _19: ();
|
||||
let mut _20: bool;
|
||||
let mut _21: i64;
|
||||
let _22: ();
|
||||
let mut _23: bool;
|
||||
let mut _24: bool;
|
||||
let mut _25: i64;
|
||||
scope 1 {
|
||||
debug b => _6;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
StorageLive(_5);
|
||||
_5 = _1;
|
||||
- _4 = Neg(move _5);
|
||||
+ _4 = Neg(_1);
|
||||
StorageDead(_5);
|
||||
- _3 = Neg(move _4);
|
||||
+ _3 = _1;
|
||||
StorageDead(_4);
|
||||
- _2 = opaque::<i64>(move _3) -> [return: bb1, unwind unreachable];
|
||||
+ _2 = opaque::<i64>(_1) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
StorageDead(_2);
|
||||
- StorageLive(_6);
|
||||
+ nop;
|
||||
StorageLive(_7);
|
||||
_7 = _1;
|
||||
- _6 = Lt(move _7, const 13_i64);
|
||||
+ _6 = Lt(_1, const 13_i64);
|
||||
StorageDead(_7);
|
||||
StorageLive(_8);
|
||||
StorageLive(_9);
|
||||
StorageLive(_10);
|
||||
StorageLive(_11);
|
||||
_11 = _6;
|
||||
- _10 = Not(move _11);
|
||||
+ _10 = Not(_6);
|
||||
StorageDead(_11);
|
||||
- _9 = Not(move _10);
|
||||
+ _9 = _6;
|
||||
StorageDead(_10);
|
||||
- _8 = opaque::<bool>(move _9) -> [return: bb2, unwind unreachable];
|
||||
+ _8 = opaque::<bool>(_6) -> [return: bb2, unwind unreachable];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageLive(_12);
|
||||
- StorageLive(_13);
|
||||
+ nop;
|
||||
StorageLive(_14);
|
||||
_14 = _1;
|
||||
- _13 = Ne(move _14, const 15_i64);
|
||||
+ _13 = Ne(_1, const 15_i64);
|
||||
StorageDead(_14);
|
||||
- _12 = opaque::<bool>(move _13) -> [return: bb3, unwind unreachable];
|
||||
+ _12 = opaque::<bool>(_13) -> [return: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- StorageDead(_13);
|
||||
+ nop;
|
||||
StorageDead(_12);
|
||||
StorageLive(_15);
|
||||
StorageLive(_16);
|
||||
StorageLive(_17);
|
||||
StorageLive(_18);
|
||||
_18 = _1;
|
||||
- _17 = Eq(move _18, const 15_i64);
|
||||
+ _17 = Eq(_1, const 15_i64);
|
||||
StorageDead(_18);
|
||||
- _16 = Not(move _17);
|
||||
+ _16 = _13;
|
||||
StorageDead(_17);
|
||||
- _15 = opaque::<bool>(move _16) -> [return: bb4, unwind unreachable];
|
||||
+ _15 = opaque::<bool>(_13) -> [return: bb4, unwind unreachable];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_16);
|
||||
StorageDead(_15);
|
||||
StorageLive(_19);
|
||||
- StorageLive(_20);
|
||||
+ nop;
|
||||
StorageLive(_21);
|
||||
_21 = _1;
|
||||
- _20 = Eq(move _21, const 35_i64);
|
||||
+ _20 = Eq(_1, const 35_i64);
|
||||
StorageDead(_21);
|
||||
- _19 = opaque::<bool>(move _20) -> [return: bb5, unwind unreachable];
|
||||
+ _19 = opaque::<bool>(_20) -> [return: bb5, unwind unreachable];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
- StorageDead(_20);
|
||||
+ nop;
|
||||
StorageDead(_19);
|
||||
StorageLive(_22);
|
||||
StorageLive(_23);
|
||||
StorageLive(_24);
|
||||
StorageLive(_25);
|
||||
_25 = _1;
|
||||
- _24 = Ne(move _25, const 35_i64);
|
||||
+ _24 = Ne(_1, const 35_i64);
|
||||
StorageDead(_25);
|
||||
- _23 = Not(move _24);
|
||||
+ _23 = _20;
|
||||
StorageDead(_24);
|
||||
- _22 = opaque::<bool>(move _23) -> [return: bb6, unwind unreachable];
|
||||
+ _22 = opaque::<bool>(_20) -> [return: bb6, unwind unreachable];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_23);
|
||||
StorageDead(_22);
|
||||
_0 = const ();
|
||||
- StorageDead(_6);
|
||||
+ nop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
153
tests/mir-opt/gvn.unary.GVN.panic-unwind.diff
Normal file
153
tests/mir-opt/gvn.unary.GVN.panic-unwind.diff
Normal file
@ -0,0 +1,153 @@
|
||||
- // MIR for `unary` before GVN
|
||||
+ // MIR for `unary` after GVN
|
||||
|
||||
fn unary(_1: i64) -> () {
|
||||
debug x => _1;
|
||||
let mut _0: ();
|
||||
let _2: ();
|
||||
let mut _3: i64;
|
||||
let mut _4: i64;
|
||||
let mut _5: i64;
|
||||
let _6: bool;
|
||||
let mut _7: i64;
|
||||
let _8: ();
|
||||
let mut _9: bool;
|
||||
let mut _10: bool;
|
||||
let mut _11: bool;
|
||||
let _12: ();
|
||||
let mut _13: bool;
|
||||
let mut _14: i64;
|
||||
let _15: ();
|
||||
let mut _16: bool;
|
||||
let mut _17: bool;
|
||||
let mut _18: i64;
|
||||
let _19: ();
|
||||
let mut _20: bool;
|
||||
let mut _21: i64;
|
||||
let _22: ();
|
||||
let mut _23: bool;
|
||||
let mut _24: bool;
|
||||
let mut _25: i64;
|
||||
scope 1 {
|
||||
debug b => _6;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
StorageLive(_5);
|
||||
_5 = _1;
|
||||
- _4 = Neg(move _5);
|
||||
+ _4 = Neg(_1);
|
||||
StorageDead(_5);
|
||||
- _3 = Neg(move _4);
|
||||
+ _3 = _1;
|
||||
StorageDead(_4);
|
||||
- _2 = opaque::<i64>(move _3) -> [return: bb1, unwind continue];
|
||||
+ _2 = opaque::<i64>(_1) -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
StorageDead(_2);
|
||||
- StorageLive(_6);
|
||||
+ nop;
|
||||
StorageLive(_7);
|
||||
_7 = _1;
|
||||
- _6 = Lt(move _7, const 13_i64);
|
||||
+ _6 = Lt(_1, const 13_i64);
|
||||
StorageDead(_7);
|
||||
StorageLive(_8);
|
||||
StorageLive(_9);
|
||||
StorageLive(_10);
|
||||
StorageLive(_11);
|
||||
_11 = _6;
|
||||
- _10 = Not(move _11);
|
||||
+ _10 = Not(_6);
|
||||
StorageDead(_11);
|
||||
- _9 = Not(move _10);
|
||||
+ _9 = _6;
|
||||
StorageDead(_10);
|
||||
- _8 = opaque::<bool>(move _9) -> [return: bb2, unwind continue];
|
||||
+ _8 = opaque::<bool>(_6) -> [return: bb2, unwind continue];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageLive(_12);
|
||||
- StorageLive(_13);
|
||||
+ nop;
|
||||
StorageLive(_14);
|
||||
_14 = _1;
|
||||
- _13 = Ne(move _14, const 15_i64);
|
||||
+ _13 = Ne(_1, const 15_i64);
|
||||
StorageDead(_14);
|
||||
- _12 = opaque::<bool>(move _13) -> [return: bb3, unwind continue];
|
||||
+ _12 = opaque::<bool>(_13) -> [return: bb3, unwind continue];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- StorageDead(_13);
|
||||
+ nop;
|
||||
StorageDead(_12);
|
||||
StorageLive(_15);
|
||||
StorageLive(_16);
|
||||
StorageLive(_17);
|
||||
StorageLive(_18);
|
||||
_18 = _1;
|
||||
- _17 = Eq(move _18, const 15_i64);
|
||||
+ _17 = Eq(_1, const 15_i64);
|
||||
StorageDead(_18);
|
||||
- _16 = Not(move _17);
|
||||
+ _16 = _13;
|
||||
StorageDead(_17);
|
||||
- _15 = opaque::<bool>(move _16) -> [return: bb4, unwind continue];
|
||||
+ _15 = opaque::<bool>(_13) -> [return: bb4, unwind continue];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_16);
|
||||
StorageDead(_15);
|
||||
StorageLive(_19);
|
||||
- StorageLive(_20);
|
||||
+ nop;
|
||||
StorageLive(_21);
|
||||
_21 = _1;
|
||||
- _20 = Eq(move _21, const 35_i64);
|
||||
+ _20 = Eq(_1, const 35_i64);
|
||||
StorageDead(_21);
|
||||
- _19 = opaque::<bool>(move _20) -> [return: bb5, unwind continue];
|
||||
+ _19 = opaque::<bool>(_20) -> [return: bb5, unwind continue];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
- StorageDead(_20);
|
||||
+ nop;
|
||||
StorageDead(_19);
|
||||
StorageLive(_22);
|
||||
StorageLive(_23);
|
||||
StorageLive(_24);
|
||||
StorageLive(_25);
|
||||
_25 = _1;
|
||||
- _24 = Ne(move _25, const 35_i64);
|
||||
+ _24 = Ne(_1, const 35_i64);
|
||||
StorageDead(_25);
|
||||
- _23 = Not(move _24);
|
||||
+ _23 = _20;
|
||||
StorageDead(_24);
|
||||
- _22 = opaque::<bool>(move _23) -> [return: bb6, unwind continue];
|
||||
+ _22 = opaque::<bool>(_20) -> [return: bb6, unwind continue];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_23);
|
||||
StorageDead(_22);
|
||||
_0 = const ();
|
||||
- StorageDead(_6);
|
||||
+ nop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user