Skip to content

Commit

Permalink
Rollup merge of rust-lang#125893 - cjgillot:gvn-newops, r=oli-obk
Browse files Browse the repository at this point in the history
Handle all GVN binops in a single place.

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->

Addresses https://github.com/rust-lang/rust/pull/125359/files#r1608185319
r? ``@oli-obk``
  • Loading branch information
matthiaskrgr authored Jun 3, 2024
2 parents 374460d + c3de4b3 commit 4483fc6
Showing 1 changed file with 40 additions and 30 deletions.
70 changes: 40 additions & 30 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ enum Value<'tcx> {
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
UnaryOp(UnOp, VnIndex),
BinaryOp(BinOp, VnIndex, VnIndex),
CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead
Cast {
kind: CastKind,
value: VnIndex,
Expand Down Expand Up @@ -508,17 +507,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?;
val.into()
}
CheckedBinaryOp(bin_op, lhs, rhs) => {
let lhs = self.evaluated[lhs].as_ref()?;
let lhs = self.ecx.read_immediate(lhs).ok()?;
let rhs = self.evaluated[rhs].as_ref()?;
let rhs = self.ecx.read_immediate(rhs).ok()?;
let val = self
.ecx
.binary_op(bin_op.wrapping_to_overflowing().unwrap(), &lhs, &rhs)
.ok()?;
val.into()
}
Cast { kind, value, from: _, to } => match kind {
CastKind::IntToInt | CastKind::IntToFloat => {
let value = self.evaluated[value].as_ref()?;
Expand Down Expand Up @@ -829,17 +817,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
let lhs = lhs?;
let rhs = rhs?;

if let Some(op) = op.overflowing_to_wrapping() {
if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
return Some(value);
}
Value::CheckedBinaryOp(op, lhs, rhs)
} else {
if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
return Some(value);
}
Value::BinaryOp(op, lhs, rhs)
if let Some(value) = self.simplify_binary(op, ty, lhs, rhs) {
return Some(value);
}
Value::BinaryOp(op, lhs, rhs)
}
Rvalue::UnaryOp(op, ref mut arg) => {
let arg = self.simplify_operand(arg, location)?;
Expand Down Expand Up @@ -970,7 +951,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
fn simplify_binary(
&mut self,
op: BinOp,
checked: bool,
lhs_ty: Ty<'tcx>,
lhs: VnIndex,
rhs: VnIndex,
Expand Down Expand Up @@ -999,22 +979,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
use Either::{Left, Right};
let a = as_bits(lhs).map_or(Right(lhs), Left);
let b = as_bits(rhs).map_or(Right(rhs), Left);

let result = match (op, a, b) {
// Neutral elements.
(BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p))
(
BinOp::Add
| BinOp::AddWithOverflow
| BinOp::AddUnchecked
| BinOp::BitOr
| BinOp::BitXor,
Left(0),
Right(p),
)
| (
BinOp::Add
| BinOp::AddWithOverflow
| BinOp::AddUnchecked
| BinOp::BitOr
| BinOp::BitXor
| BinOp::Sub
| BinOp::SubWithOverflow
| BinOp::SubUnchecked
| BinOp::Offset
| BinOp::Shl
| BinOp::Shr,
Right(p),
Left(0),
)
| (BinOp::Mul, Left(1), Right(p))
| (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p,
| (BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked, Left(1), Right(p))
| (
BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::Div,
Right(p),
Left(1),
) => p,
// Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size.
(BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p))
if ones == layout.size.truncate(u128::MAX)
Expand All @@ -1023,10 +1020,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
p
}
// Absorbing elements.
(BinOp::Mul | BinOp::BitAnd, _, Left(0))
(
BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::BitAnd,
_,
Left(0),
)
| (BinOp::Rem, _, Left(1))
| (
BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr,
BinOp::Mul
| BinOp::MulWithOverflow
| BinOp::MulUnchecked
| BinOp::Div
| BinOp::Rem
| BinOp::BitAnd
| BinOp::Shl
| BinOp::Shr,
Left(0),
_,
) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty),
Expand All @@ -1038,7 +1046,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty)
}
// Sub/Xor with itself.
(BinOp::Sub | BinOp::BitXor, a, b) if a == b => {
(BinOp::Sub | BinOp::SubWithOverflow | BinOp::SubUnchecked | BinOp::BitXor, a, b)
if a == b =>
{
self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty)
}
// Comparison:
Expand All @@ -1052,7 +1062,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
_ => return None,
};

if checked {
if op.is_overflowing() {
let false_val = self.insert_bool(false);
Some(self.insert_tuple(vec![result, false_val]))
} else {
Expand Down

0 comments on commit 4483fc6

Please sign in to comment.