Auto merge of #111568 - scottmcm:undo-opt, r=WaffleLapkin

Stop turning transmutes into discriminant reads in mir-opt

Partially reverts #109612, as after #109993 these aren't actually equivalent any more, and I'm no longer confident this was ever an improvement in the first place.

Having this "simplification" meant that similar-looking code actually did somewhat different things.  For example,
```rust
pub unsafe fn demo1(x: std::cmp::Ordering) -> u8 {
    std::mem::transmute(x)
}
pub unsafe fn demo2(x: std::cmp::Ordering) -> i8 {
    std::mem::transmute(x)
}
```
in nightly today is generating <https://rust.godbolt.org/z/dPK58zW18>
```llvm
define noundef i8 `@_ZN7example5demo117h341ef313673d2ee6E(i8` noundef %x) unnamed_addr #0 {
  %0 = icmp uge i8 %x, -1
  %1 = icmp ule i8 %x, 1
  %2 = or i1 %0, %1
  call void `@llvm.assume(i1` %2)
  ret i8 %x
}

define noundef i8 `@_ZN7example5demo217h5ad29f361a3f5700E(i8` noundef %0) unnamed_addr #0 {
  %x = alloca i8, align 1
  store i8 %0, ptr %x, align 1
  %1 = load i8, ptr %x, align 1, !range !2, !noundef !3
  ret i8 %1
}
```

Which feels too different when the original code is essentially identical.

---

Aside: that example is different *after* optimizations too:
```llvm
define noundef i8 `@_ZN7example5demo117h341ef313673d2ee6E(i8` noundef returned %x) unnamed_addr #0 {
  %0 = add i8 %x, 1
  %1 = icmp ult i8 %0, 3
  tail call void `@llvm.assume(i1` %1)
  ret i8 %x
}

define noundef i8 `@_ZN7example5demo217h5ad29f361a3f5700E(i8` noundef returned %0) unnamed_addr #1 {
  ret i8 %0
}
```
so turning the `Transmute` into a `Discriminant` was arguably just making things worse, so leaving it alone instead -- and thus having less code in rustc -- seems clearly better.
This commit is contained in:
bors 2023-05-17 18:53:26 +00:00
commit e9e1bbc7a8
3 changed files with 49 additions and 152 deletions

View file

@ -5,7 +5,6 @@ use crate::MirPass;
use rustc_hir::Mutability;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
use rustc_span::symbol::Symbol;
use rustc_target::abi::FieldIdx;
@ -163,18 +162,6 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
return;
}
// Transmuting a fieldless enum to its repr is a discriminant read
if let ty::Adt(adt_def, ..) = operand_ty.kind()
&& adt_def.is_enum()
&& adt_def.is_payloadfree()
&& let Some(place) = operand.place()
&& let Some(repr_int) = adt_def.repr().int
&& repr_int.to_ty(self.tcx) == *cast_ty
{
*rvalue = Rvalue::Discriminant(place);
return;
}
// Transmuting a transparent struct/union to a field's type is a projection
if let ty::Adt(adt_def, substs) = operand_ty.kind()
&& adt_def.repr().transparent()