rust-lang / rust-lang/rust

Possible regression for ui/match/issue-114691.rs

Open
#141,340 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-LLVM C-bug regression-untriaged S-needs-repro T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with tests/ui/match/issue-114691.rs and inspect the LLVM IR for fn test on the custom target after the LLVM 19 update, focusing on foldBoolSelectToLogic. Compare the behavior with the earlier fix and the x86_64 GlobalISel path. Done means explaining why the transformation still runs and confirming the regression is addressed on the affected target.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.