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 folder contains tests for MIR optimizations.
The mir-opt
test format emits MIR to extra files that you can automatically update by specifying
--bless
on the command line (just like ui
tests updating .stderr
files).
--bless
able test format
By default 32 bit and 64 bit targets use the same dump files, which can be problematic in the presence of pointers in constants or other bit width dependent things. In that case you can add
// EMIT_MIR_FOR_EACH_BIT_WIDTH
to your test, causing separate files to be generated for 32bit and 64bit systems.
Unit testing
If you are only testing the behavior of a particular mir-opt pass on some specific input (as is usually the case), you should add
// unit-test: PassName
to the top of the file. This makes sure that other passes don't run which means you'll get the input you expected and your test won't break when other code changes.
Emit a diff of the mir for a specific optimization
This is what you want most often when you want to see how an optimization changes the MIR.
// EMIT_MIR $file_name_of_some_mir_dump.diff
Emit mir after a specific optimization
Use this if you are just interested in the final state after an optimization.
// EMIT_MIR $file_name_of_some_mir_dump.after.mir
Emit mir before a specific optimization
This exists mainly for completeness and is rarely useful.
// EMIT_MIR $file_name_of_some_mir_dump.before.mir