Implement algebraic simplifications.
This commit is contained in:
parent
74a967bcec
commit
22986b72e5
5 changed files with 103 additions and 4 deletions
|
@ -309,7 +309,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
||||||
) -> (FlatSet<ScalarInt>, FlatSet<bool>) {
|
) -> (FlatSet<ScalarInt>, FlatSet<bool>) {
|
||||||
let left = self.eval_operand(left, state);
|
let left = self.eval_operand(left, state);
|
||||||
let right = self.eval_operand(right, state);
|
let right = self.eval_operand(right, state);
|
||||||
|
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
|
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
|
||||||
|
// Both sides are known, do the actual computation.
|
||||||
(FlatSet::Elem(left), FlatSet::Elem(right)) => {
|
(FlatSet::Elem(left), FlatSet::Elem(right)) => {
|
||||||
match self.ecx.overflowing_binary_op(op, &left, &right) {
|
match self.ecx.overflowing_binary_op(op, &left, &right) {
|
||||||
Ok((Scalar::Int(val), overflow, _)) => {
|
Ok((Scalar::Int(val), overflow, _)) => {
|
||||||
|
@ -318,11 +321,36 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
||||||
_ => (FlatSet::Top, FlatSet::Top),
|
_ => (FlatSet::Top, FlatSet::Top),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
|
// Exactly one side is known, attempt some algebraic simplifications.
|
||||||
(_, _) => {
|
(FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg)) => {
|
||||||
// Could attempt some algebraic simplifications here.
|
let layout = const_arg.layout;
|
||||||
(FlatSet::Top, FlatSet::Top)
|
if !matches!(layout.abi, rustc_target::abi::Abi::Scalar(..)) {
|
||||||
|
return (FlatSet::Top, FlatSet::Top);
|
||||||
|
}
|
||||||
|
|
||||||
|
let arg_scalar = const_arg.to_scalar();
|
||||||
|
let Ok(arg_scalar) = arg_scalar.try_to_int() else {
|
||||||
|
return (FlatSet::Top, FlatSet::Top);
|
||||||
|
};
|
||||||
|
let Ok(arg_value) = arg_scalar.to_bits(layout.size) else {
|
||||||
|
return (FlatSet::Top, FlatSet::Top);
|
||||||
|
};
|
||||||
|
|
||||||
|
match op {
|
||||||
|
BinOp::BitAnd if arg_value == 0 => (FlatSet::Elem(arg_scalar), FlatSet::Bottom),
|
||||||
|
BinOp::BitOr
|
||||||
|
if arg_value == layout.size.truncate(u128::MAX)
|
||||||
|
|| (layout.ty.is_bool() && arg_value == 1) =>
|
||||||
|
{
|
||||||
|
(FlatSet::Elem(arg_scalar), FlatSet::Bottom)
|
||||||
|
}
|
||||||
|
BinOp::Mul if layout.ty.is_integral() && arg_value == 0 => {
|
||||||
|
(FlatSet::Elem(arg_scalar), FlatSet::Elem(false))
|
||||||
|
}
|
||||||
|
_ => (FlatSet::Top, FlatSet::Top),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
(FlatSet::Top, FlatSet::Top) => (FlatSet::Top, FlatSet::Top),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
tests/mir-opt/dataflow-const-prop/boolean_identities.rs
Normal file
10
tests/mir-opt/dataflow-const-prop/boolean_identities.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// unit-test: DataflowConstProp
|
||||||
|
|
||||||
|
// EMIT_MIR boolean_identities.test.DataflowConstProp.diff
|
||||||
|
pub fn test(x: bool, y: bool) -> bool {
|
||||||
|
(y | true) & (x & false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test(true, false);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
- // MIR for `test` before DataflowConstProp
|
||||||
|
+ // MIR for `test` after DataflowConstProp
|
||||||
|
|
||||||
|
fn test(_1: bool, _2: bool) -> bool {
|
||||||
|
debug x => _1;
|
||||||
|
debug y => _2;
|
||||||
|
let mut _0: bool;
|
||||||
|
let mut _3: bool;
|
||||||
|
let mut _4: bool;
|
||||||
|
let mut _5: bool;
|
||||||
|
let mut _6: bool;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_3);
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = _2;
|
||||||
|
- _3 = BitOr(move _4, const true);
|
||||||
|
+ _3 = const true;
|
||||||
|
StorageDead(_4);
|
||||||
|
StorageLive(_5);
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = _1;
|
||||||
|
- _5 = BitAnd(move _6, const false);
|
||||||
|
+ _5 = const false;
|
||||||
|
StorageDead(_6);
|
||||||
|
- _0 = BitAnd(move _3, move _5);
|
||||||
|
+ _0 = const false;
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageDead(_3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
10
tests/mir-opt/dataflow-const-prop/mult_by_zero.rs
Normal file
10
tests/mir-opt/dataflow-const-prop/mult_by_zero.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// unit-test: DataflowConstProp
|
||||||
|
|
||||||
|
// EMIT_MIR mult_by_zero.test.DataflowConstProp.diff
|
||||||
|
fn test(x : i32) -> i32 {
|
||||||
|
x * 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test(10);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
- // MIR for `test` before DataflowConstProp
|
||||||
|
+ // MIR for `test` after DataflowConstProp
|
||||||
|
|
||||||
|
fn test(_1: i32) -> i32 {
|
||||||
|
debug x => _1;
|
||||||
|
let mut _0: i32;
|
||||||
|
let mut _2: i32;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = _1;
|
||||||
|
- _0 = Mul(move _2, const 0_i32);
|
||||||
|
+ _0 = const 0_i32;
|
||||||
|
StorageDead(_2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue