Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 22986b7

Browse files
committed
Implement algebraic simplifications.
1 parent 74a967b commit 22986b7

File tree

5 files changed

+103
-4
lines changed

5 files changed

+103
-4
lines changed

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
309309
) -> (FlatSet<ScalarInt>, FlatSet<bool>) {
310310
let left = self.eval_operand(left, state);
311311
let right = self.eval_operand(right, state);
312+
312313
match (left, right) {
314+
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
315+
// Both sides are known, do the actual computation.
313316
(FlatSet::Elem(left), FlatSet::Elem(right)) => {
314317
match self.ecx.overflowing_binary_op(op, &left, &right) {
315318
Ok((Scalar::Int(val), overflow, _)) => {
@@ -318,11 +321,36 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
318321
_ => (FlatSet::Top, FlatSet::Top),
319322
}
320323
}
321-
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
322-
(_, _) => {
323-
// Could attempt some algebraic simplifications here.
324-
(FlatSet::Top, FlatSet::Top)
324+
// Exactly one side is known, attempt some algebraic simplifications.
325+
(FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg)) => {
326+
let layout = const_arg.layout;
327+
if !matches!(layout.abi, rustc_target::abi::Abi::Scalar(..)) {
328+
return (FlatSet::Top, FlatSet::Top);
329+
}
330+
331+
let arg_scalar = const_arg.to_scalar();
332+
let Ok(arg_scalar) = arg_scalar.try_to_int() else {
333+
return (FlatSet::Top, FlatSet::Top);
334+
};
335+
let Ok(arg_value) = arg_scalar.to_bits(layout.size) else {
336+
return (FlatSet::Top, FlatSet::Top);
337+
};
338+
339+
match op {
340+
BinOp::BitAnd if arg_value == 0 => (FlatSet::Elem(arg_scalar), FlatSet::Bottom),
341+
BinOp::BitOr
342+
if arg_value == layout.size.truncate(u128::MAX)
343+
|| (layout.ty.is_bool() && arg_value == 1) =>
344+
{
345+
(FlatSet::Elem(arg_scalar), FlatSet::Bottom)
346+
}
347+
BinOp::Mul if layout.ty.is_integral() && arg_value == 0 => {
348+
(FlatSet::Elem(arg_scalar), FlatSet::Elem(false))
349+
}
350+
_ => (FlatSet::Top, FlatSet::Top),
351+
}
325352
}
353+
(FlatSet::Top, FlatSet::Top) => (FlatSet::Top, FlatSet::Top),
326354
}
327355
}
328356

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// unit-test: DataflowConstProp
2+
3+
// EMIT_MIR boolean_identities.test.DataflowConstProp.diff
4+
pub fn test(x: bool, y: bool) -> bool {
5+
(y | true) & (x & false)
6+
}
7+
8+
fn main() {
9+
test(true, false);
10+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
- // MIR for `test` before DataflowConstProp
2+
+ // MIR for `test` after DataflowConstProp
3+
4+
fn test(_1: bool, _2: bool) -> bool {
5+
debug x => _1;
6+
debug y => _2;
7+
let mut _0: bool;
8+
let mut _3: bool;
9+
let mut _4: bool;
10+
let mut _5: bool;
11+
let mut _6: bool;
12+
13+
bb0: {
14+
StorageLive(_3);
15+
StorageLive(_4);
16+
_4 = _2;
17+
- _3 = BitOr(move _4, const true);
18+
+ _3 = const true;
19+
StorageDead(_4);
20+
StorageLive(_5);
21+
StorageLive(_6);
22+
_6 = _1;
23+
- _5 = BitAnd(move _6, const false);
24+
+ _5 = const false;
25+
StorageDead(_6);
26+
- _0 = BitAnd(move _3, move _5);
27+
+ _0 = const false;
28+
StorageDead(_5);
29+
StorageDead(_3);
30+
return;
31+
}
32+
}
33+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// unit-test: DataflowConstProp
2+
3+
// EMIT_MIR mult_by_zero.test.DataflowConstProp.diff
4+
fn test(x : i32) -> i32 {
5+
x * 0
6+
}
7+
8+
fn main() {
9+
test(10);
10+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
- // MIR for `test` before DataflowConstProp
2+
+ // MIR for `test` after DataflowConstProp
3+
4+
fn test(_1: i32) -> i32 {
5+
debug x => _1;
6+
let mut _0: i32;
7+
let mut _2: i32;
8+
9+
bb0: {
10+
StorageLive(_2);
11+
_2 = _1;
12+
- _0 = Mul(move _2, const 0_i32);
13+
+ _0 = const 0_i32;
14+
StorageDead(_2);
15+
return;
16+
}
17+
}
18+

0 commit comments

Comments
 (0)