Description
Copied code for the test in question here:
//@ run-pass
// This test used to be miscompiled by LLVM 17.
#![allow(dead_code)]
enum Pass {
Opaque {
clear_color: [f32; 4],
with_depth_pre_pass: bool,
},
Transparent,
}
enum LoadOp {
Clear,
Load,
}
#[inline(never)]
fn check(x: Option<LoadOp>) {
assert!(x.is_none());
}
#[inline(never)]
fn test(mode: Pass) {
check(match mode {
Pass::Opaque {
with_depth_pre_pass: true,
..
}
| Pass::Transparent => None,
_ => Some(LoadOp::Clear),
});
}
fn main() {
println!("Hello, world!");
test(Pass::Transparent);
}
This test is regressing for us with a custom target, because the problematic transformation foldBoolSelectToLogic
still runs on the IR for fn test
. This is after updating to LLVM 19.
To me, it's clear to see why the transformation is invalid, but for seemingly different reasons than the above fix addresses. The IR is:
; main::test
; Function Attrs: noinline nounwind
define internal fastcc void @_ZN4main4test17h24436c5bdc3836e4E(i8 %mode.0.val, i8 %mode.1.val) unnamed_addr #2 {
start:
%trunc = trunc nuw i8 %mode.0.val to i1
%0 = trunc nuw i8 %mode.1.val to i1
%1 = select i1 %trunc, i1 true, i1 %0
%.sink = select i1 %1, i8 2, i8 0
; call main::check
tail call fastcc void @_ZN4main5check17h13ab3f87dc46addbE(i8 noundef %.sink) #5
ret void
}
Which represents a logical, short-circuiting or
operation on %mode.0.val
and %mode.1.val
. And since %mode.1.val
is not marked as noundef
, it shouldn't be valid to transform that operation into a bitwise or
, since %mode.1.val
being undefined now has an effect on the result regardless of whether %mode.0.val
is true or not.
Does anyone have a theory as to why this fix used to work, but seems to no longer work? Frustratingly, the testcase still passes for x86_64, but that doesn't mean anything about this fix because they have switched to using GlobalISel.
Relates to issue #114691
Activity
apiraino commentedon May 26, 2025
@lewis1revill what is the custom target you're mentioning? Can we reproduce the issue? Can you help bisecting with cargo-bisect-rustc?
For easier linking, we updated to LLVM 19 in #127513. I infer this is when that test started regressing for you?
@rustbot label E-needs-bisection
nikic commentedon May 26, 2025
Can you try using LLVM 20 instead? LLVM 20 fixed the underlying issue. It's possible that the previous workaround in prior versions is insufficient if
trunc nuw
is used.workingjubilee commentedon May 26, 2025
"they" have switched to using GlobalISel? Oh, LLVM has switched to using GlobalISel with x86 by default? neat?
nikic commentedon May 26, 2025
It hasn't.