Simplify unary operations.

This commit is contained in:
Camille GILLOT 2023-03-25 22:33:35 +00:00
parent 666030c51b
commit 5fc23ad8e6
6 changed files with 371 additions and 18 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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

View 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;
}
}

View 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;
}
}