Skip to content

Commit 5fc23ad

Browse files
committed
Simplify unary operations.
1 parent 666030c commit 5fc23ad

File tree

6 files changed

+371
-18
lines changed

6 files changed

+371
-18
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+20
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
817817
}
818818
Rvalue::UnaryOp(op, ref mut arg) => {
819819
let arg = self.simplify_operand(arg, location)?;
820+
if let Some(value) = self.simplify_unary(op, arg) {
821+
return Some(value);
822+
}
820823
Value::UnaryOp(op, arg)
821824
}
822825
Rvalue::Discriminant(ref mut place) => {
@@ -916,6 +919,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
916919
Some(self.insert(Value::Aggregate(ty, variant_index, fields)))
917920
}
918921

922+
#[instrument(level = "trace", skip(self), ret)]
923+
fn simplify_unary(&mut self, op: UnOp, value: VnIndex) -> Option<VnIndex> {
924+
let value = match (op, self.get(value)) {
925+
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner),
926+
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner),
927+
(UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => {
928+
Value::BinaryOp(BinOp::Ne, *lhs, *rhs)
929+
}
930+
(UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
931+
Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
932+
}
933+
_ => return None,
934+
};
935+
936+
Some(self.insert(value))
937+
}
938+
919939
#[instrument(level = "trace", skip(self), ret)]
920940
fn simplify_binary(
921941
&mut self,

tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff

+9-9
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
let mut _3: fn(u8) -> u8;
99
let _5: ();
1010
let mut _6: fn(u8) -> u8;
11-
let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21};
11+
let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
1212
let _10: ();
1313
let mut _11: fn();
14-
let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21};
14+
let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
1515
let _14: ();
1616
let mut _15: fn();
1717
scope 1 {
1818
debug f => _1;
1919
let _4: fn(u8) -> u8;
2020
scope 2 {
2121
debug g => _4;
22-
let _7: {closure@$DIR/gvn.rs:585:19: 585:21};
22+
let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
2323
scope 3 {
2424
debug closure => _7;
2525
let _8: fn();
@@ -62,16 +62,16 @@
6262
StorageDead(_6);
6363
StorageDead(_5);
6464
- StorageLive(_7);
65-
- _7 = {closure@$DIR/gvn.rs:585:19: 585:21};
65+
- _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
6666
- StorageLive(_8);
6767
+ nop;
68-
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
68+
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
6969
+ nop;
7070
StorageLive(_9);
7171
- _9 = _7;
7272
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73-
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
74-
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73+
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
74+
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
7575
StorageDead(_9);
7676
StorageLive(_10);
7777
StorageLive(_11);
@@ -88,8 +88,8 @@
8888
StorageLive(_13);
8989
- _13 = _7;
9090
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91-
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
92-
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91+
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
92+
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
9393
StorageDead(_13);
9494
StorageLive(_14);
9595
StorageLive(_15);

tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff

+9-9
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
let mut _3: fn(u8) -> u8;
99
let _5: ();
1010
let mut _6: fn(u8) -> u8;
11-
let mut _9: {closure@$DIR/gvn.rs:585:19: 585:21};
11+
let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
1212
let _10: ();
1313
let mut _11: fn();
14-
let mut _13: {closure@$DIR/gvn.rs:585:19: 585:21};
14+
let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
1515
let _14: ();
1616
let mut _15: fn();
1717
scope 1 {
1818
debug f => _1;
1919
let _4: fn(u8) -> u8;
2020
scope 2 {
2121
debug g => _4;
22-
let _7: {closure@$DIR/gvn.rs:585:19: 585:21};
22+
let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
2323
scope 3 {
2424
debug closure => _7;
2525
let _8: fn();
@@ -62,16 +62,16 @@
6262
StorageDead(_6);
6363
StorageDead(_5);
6464
- StorageLive(_7);
65-
- _7 = {closure@$DIR/gvn.rs:585:19: 585:21};
65+
- _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
6666
- StorageLive(_8);
6767
+ nop;
68-
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
68+
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
6969
+ nop;
7070
StorageLive(_9);
7171
- _9 = _7;
7272
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73-
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
74-
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73+
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
74+
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
7575
StorageDead(_9);
7676
StorageLive(_10);
7777
StorageLive(_11);
@@ -88,8 +88,8 @@
8888
StorageLive(_13);
8989
- _13 = _7;
9090
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91-
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21};
92-
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:585:19: 585:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91+
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
92+
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
9393
StorageDead(_13);
9494
StorageLive(_14);
9595
StorageLive(_15);

tests/mir-opt/gvn.rs

+27
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,31 @@ fn repeated_index<T: Copy, const N: usize>(x: T, idx: usize) {
166166
opaque(a[idx]);
167167
}
168168

169+
fn unary(x: i64) {
170+
// CHECK-LABEL: fn unary(
171+
// CHECK: opaque::<i64>(_1)
172+
opaque(--x); // This is `x`.
173+
174+
// CHECK: [[b:_.*]] = Lt(_1, const 13_i64);
175+
// CHECK: opaque::<bool>([[b]])
176+
let b = x < 13;
177+
opaque(!!b); // This is `b`.
178+
179+
// Both lines should test the same thing.
180+
// CHECK: [[c:_.*]] = Ne(_1, const 15_i64);
181+
// CHECK: opaque::<bool>([[c]])
182+
// CHECK: opaque::<bool>([[c]])
183+
opaque(x != 15);
184+
opaque(!(x == 15));
185+
186+
// Both lines should test the same thing.
187+
// CHECK: [[d:_.*]] = Eq(_1, const 35_i64);
188+
// CHECK: opaque::<bool>([[d]])
189+
// CHECK: opaque::<bool>([[d]])
190+
opaque(x == 35);
191+
opaque(!(x != 35));
192+
}
193+
169194
/// Verify symbolic integer arithmetic simplifications.
170195
fn arithmetic(x: u64) {
171196
// CHECK-LABEL: fn arithmetic(
@@ -623,6 +648,7 @@ fn main() {
623648
subexpression_elimination(2, 4, 5);
624649
wrap_unwrap(5);
625650
repeated_index::<u32, 7>(5, 3);
651+
unary(i64::MIN);
626652
arithmetic(5);
627653
comparison(5, 6);
628654
arithmetic_checked(5);
@@ -651,6 +677,7 @@ fn identity<T>(x: T) -> T {
651677
// EMIT_MIR gvn.subexpression_elimination.GVN.diff
652678
// EMIT_MIR gvn.wrap_unwrap.GVN.diff
653679
// EMIT_MIR gvn.repeated_index.GVN.diff
680+
// EMIT_MIR gvn.unary.GVN.diff
654681
// EMIT_MIR gvn.arithmetic.GVN.diff
655682
// EMIT_MIR gvn.comparison.GVN.diff
656683
// EMIT_MIR gvn.arithmetic_checked.GVN.diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
- // MIR for `unary` before GVN
2+
+ // MIR for `unary` after GVN
3+
4+
fn unary(_1: i64) -> () {
5+
debug x => _1;
6+
let mut _0: ();
7+
let _2: ();
8+
let mut _3: i64;
9+
let mut _4: i64;
10+
let mut _5: i64;
11+
let _6: bool;
12+
let mut _7: i64;
13+
let _8: ();
14+
let mut _9: bool;
15+
let mut _10: bool;
16+
let mut _11: bool;
17+
let _12: ();
18+
let mut _13: bool;
19+
let mut _14: i64;
20+
let _15: ();
21+
let mut _16: bool;
22+
let mut _17: bool;
23+
let mut _18: i64;
24+
let _19: ();
25+
let mut _20: bool;
26+
let mut _21: i64;
27+
let _22: ();
28+
let mut _23: bool;
29+
let mut _24: bool;
30+
let mut _25: i64;
31+
scope 1 {
32+
debug b => _6;
33+
}
34+
35+
bb0: {
36+
StorageLive(_2);
37+
StorageLive(_3);
38+
StorageLive(_4);
39+
StorageLive(_5);
40+
_5 = _1;
41+
- _4 = Neg(move _5);
42+
+ _4 = Neg(_1);
43+
StorageDead(_5);
44+
- _3 = Neg(move _4);
45+
+ _3 = _1;
46+
StorageDead(_4);
47+
- _2 = opaque::<i64>(move _3) -> [return: bb1, unwind unreachable];
48+
+ _2 = opaque::<i64>(_1) -> [return: bb1, unwind unreachable];
49+
}
50+
51+
bb1: {
52+
StorageDead(_3);
53+
StorageDead(_2);
54+
- StorageLive(_6);
55+
+ nop;
56+
StorageLive(_7);
57+
_7 = _1;
58+
- _6 = Lt(move _7, const 13_i64);
59+
+ _6 = Lt(_1, const 13_i64);
60+
StorageDead(_7);
61+
StorageLive(_8);
62+
StorageLive(_9);
63+
StorageLive(_10);
64+
StorageLive(_11);
65+
_11 = _6;
66+
- _10 = Not(move _11);
67+
+ _10 = Not(_6);
68+
StorageDead(_11);
69+
- _9 = Not(move _10);
70+
+ _9 = _6;
71+
StorageDead(_10);
72+
- _8 = opaque::<bool>(move _9) -> [return: bb2, unwind unreachable];
73+
+ _8 = opaque::<bool>(_6) -> [return: bb2, unwind unreachable];
74+
}
75+
76+
bb2: {
77+
StorageDead(_9);
78+
StorageDead(_8);
79+
StorageLive(_12);
80+
- StorageLive(_13);
81+
+ nop;
82+
StorageLive(_14);
83+
_14 = _1;
84+
- _13 = Ne(move _14, const 15_i64);
85+
+ _13 = Ne(_1, const 15_i64);
86+
StorageDead(_14);
87+
- _12 = opaque::<bool>(move _13) -> [return: bb3, unwind unreachable];
88+
+ _12 = opaque::<bool>(_13) -> [return: bb3, unwind unreachable];
89+
}
90+
91+
bb3: {
92+
- StorageDead(_13);
93+
+ nop;
94+
StorageDead(_12);
95+
StorageLive(_15);
96+
StorageLive(_16);
97+
StorageLive(_17);
98+
StorageLive(_18);
99+
_18 = _1;
100+
- _17 = Eq(move _18, const 15_i64);
101+
+ _17 = Eq(_1, const 15_i64);
102+
StorageDead(_18);
103+
- _16 = Not(move _17);
104+
+ _16 = _13;
105+
StorageDead(_17);
106+
- _15 = opaque::<bool>(move _16) -> [return: bb4, unwind unreachable];
107+
+ _15 = opaque::<bool>(_13) -> [return: bb4, unwind unreachable];
108+
}
109+
110+
bb4: {
111+
StorageDead(_16);
112+
StorageDead(_15);
113+
StorageLive(_19);
114+
- StorageLive(_20);
115+
+ nop;
116+
StorageLive(_21);
117+
_21 = _1;
118+
- _20 = Eq(move _21, const 35_i64);
119+
+ _20 = Eq(_1, const 35_i64);
120+
StorageDead(_21);
121+
- _19 = opaque::<bool>(move _20) -> [return: bb5, unwind unreachable];
122+
+ _19 = opaque::<bool>(_20) -> [return: bb5, unwind unreachable];
123+
}
124+
125+
bb5: {
126+
- StorageDead(_20);
127+
+ nop;
128+
StorageDead(_19);
129+
StorageLive(_22);
130+
StorageLive(_23);
131+
StorageLive(_24);
132+
StorageLive(_25);
133+
_25 = _1;
134+
- _24 = Ne(move _25, const 35_i64);
135+
+ _24 = Ne(_1, const 35_i64);
136+
StorageDead(_25);
137+
- _23 = Not(move _24);
138+
+ _23 = _20;
139+
StorageDead(_24);
140+
- _22 = opaque::<bool>(move _23) -> [return: bb6, unwind unreachable];
141+
+ _22 = opaque::<bool>(_20) -> [return: bb6, unwind unreachable];
142+
}
143+
144+
bb6: {
145+
StorageDead(_23);
146+
StorageDead(_22);
147+
_0 = const ();
148+
- StorageDead(_6);
149+
+ nop;
150+
return;
151+
}
152+
}
153+

0 commit comments

Comments
 (0)