Skip to content

Commit e46a6aa

Browse files
committed
Implement algebraic simplifications.
1 parent 031bdf9 commit e46a6aa

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,18 +344,45 @@ impl<'a, 'm, 'tcx> ConstAnalysis<'a, 'm, 'tcx> {
344344
) -> (FlatSet<ScalarTy<'tcx>>, FlatSet<bool>) {
345345
let left = self.eval_operand(left, state);
346346
let right = self.eval_operand(right, state);
347+
347348
match (left, right) {
349+
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
350+
// Both sides are known, do the actual computation.
348351
(FlatSet::Elem(left), FlatSet::Elem(right)) => {
349352
match self.ecx.overflowing_binary_op(op, &left, &right) {
350353
Ok((val, overflow, ty)) => (self.wrap_scalar(val, ty), FlatSet::Elem(overflow)),
351354
_ => (FlatSet::Top, FlatSet::Top),
352355
}
353356
}
354-
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
355-
(_, _) => {
356-
// Could attempt some algebraic simplifications here.
357-
(FlatSet::Top, FlatSet::Top)
357+
// Exactly one side is known, attempt some algebraic simplifications.
358+
(FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg)) => {
359+
let layout = const_arg.layout;
360+
if !matches!(layout.abi, rustc_target::abi::Abi::Scalar(..)) {
361+
return (FlatSet::Top, FlatSet::Top);
362+
}
363+
364+
let arg_scalar = const_arg.to_scalar();
365+
let Ok(arg_value) = arg_scalar.to_bits(layout.size) else {
366+
return (FlatSet::Top, FlatSet::Top);
367+
};
368+
369+
match op {
370+
BinOp::BitAnd if arg_value == 0 => {
371+
(self.wrap_scalar(arg_scalar, layout.ty), FlatSet::Bottom)
372+
}
373+
BinOp::BitOr
374+
if arg_value == layout.size.truncate(u128::MAX)
375+
|| (layout.ty.is_bool() && arg_value == 1) =>
376+
{
377+
(self.wrap_scalar(arg_scalar, layout.ty), FlatSet::Bottom)
378+
}
379+
BinOp::Mul if layout.ty.is_integral() && arg_value == 0 => {
380+
(self.wrap_scalar(arg_scalar, layout.ty), FlatSet::Elem(false))
381+
}
382+
_ => (FlatSet::Top, FlatSet::Top),
383+
}
358384
}
385+
(FlatSet::Top, FlatSet::Top) => (FlatSet::Top, FlatSet::Top),
359386
}
360387
}
361388

tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212

1313
bb0: {
1414
StorageLive(_3);
15-
_3 = BitOr(_2, const true);
15+
- _3 = BitOr(_2, const true);
16+
+ _3 = const true;
1617
StorageLive(_5);
17-
_5 = BitAnd(_1, const false);
18-
_0 = BitAnd(move _3, move _5);
18+
- _5 = BitAnd(_1, const false);
19+
- _0 = BitAnd(move _3, move _5);
20+
+ _5 = const false;
21+
+ _0 = const false;
1922
StorageDead(_5);
2023
StorageDead(_3);
2124
return;

tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
bb0: {
1010
StorageLive(_2);
1111
_2 = _1;
12-
_0 = Mul(move _2, const 0_i32);
12+
- _0 = Mul(move _2, const 0_i32);
13+
+ _0 = const 0_i32;
1314
StorageDead(_2);
1415
return;
1516
}

0 commit comments

Comments
 (0)