Skip to content

Promoted constants lead to poor MIR from comparisons #139093

Closed

Description

@scottmcm

Follow-along at https://rust.godbolt.org/z/Trzrobvo5

Consider these two functions that ought to be equivalent:

use std::cmp::Ordering;

#[no_mangle]
pub fn direct(e: Option<Ordering>) -> bool {
    e == Some(Ordering::Equal)
}

#[no_mangle]
pub fn with_let(e: Option<Ordering>) -> bool {
    let eq = Ordering::Equal;
    e == Some(eq)
}

The latter ends up with about the MIR you'd expect: it checks for Some, then for Equal

    bb0: {
        StorageLive(_2);
        _2 = discriminant(_1);
        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4];
    }

    bb1: {
        _0 = const false;
        goto -> bb3;
    }

    bb2: {
        StorageLive(_3);
        _3 = discriminant(((_1 as Some).0: std::cmp::Ordering));
        _0 = Eq(copy _3, const 0_i8);
        StorageDead(_3);
        goto -> bb3;
    }

    bb3: {
        StorageDead(_2);
        return;
    }

    bb4: {
        unreachable;
    }

The former, though, ends up with way more MIR because of the promoted const:

    bb0: {
        _2 = const direct::promoted[0];
        StorageLive(_5);
        StorageLive(_4);
        StorageLive(_3);
        _3 = discriminant(_1);
        switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb6];
    }

    bb1: {
        _4 = discriminant((*_2));
        _0 = Eq(copy _4, const 0_isize);
        goto -> bb5;
    }

    bb2: {
        _5 = discriminant((*_2));
        switchInt(move _5) -> [0: bb3, 1: bb4, otherwise: bb6];
    }

    bb3: {
        _0 = const false;
        goto -> bb5;
    }

    bb4: {
        StorageLive(_6);
        StorageLive(_7);
        _6 = discriminant(((_1 as Some).0: std::cmp::Ordering));
        _7 = discriminant((((*_2) as Some).0: std::cmp::Ordering));
        _0 = Eq(copy _6, copy _7);
        StorageDead(_7);
        StorageDead(_6);
        goto -> bb5;
    }

    bb5: {
        StorageDead(_3);
        StorageDead(_4);
        StorageDead(_5);
        return;
    }

    bb6: {
        unreachable;
    }

Apparently we can't even tell what the discriminant is of that const direct::promoted[0], so we end up emitting even LLVM IR checks on the value of the constant, which it then has to turn around and optimize away again.

Can we maybe just unilaterally un-promote simple (Copy + NoCell + Scalar/ScalarPair) constants like this?

Activity

  1. added
    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html
    A-mir-optArea: MIR optimizations
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    WG-mir-optWorking group: MIR optimizations
    on Mar 29, 2025
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Mar 29, 2025
  3. added
    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing such
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on May 1, 2025
  4. cjgillot commented on Jul 20, 2025

    @cjgillot
    Contributor

    Current MIR is identical for both versions.

  5. added
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Jul 20, 2025
  6. borsakv commented on Aug 6, 2025

    @borsakv
    Member

    @rustbot claim

  7. added a commit that references this issue on Aug 20, 2025
  8. added a commit that references this issue on Oct 10, 2025
    486fae1
  9. added a commit that references this issue on Oct 11, 2025
    2ba4428
  10. added a commit that references this issue on Oct 12, 2025
    bb62518
  11. added a commit that references this issue on Oct 18, 2025
    a40a1cf
  12. added 3 commits that reference this issue on Nov 8, 2025
    6eae704
    799d58f
    a2b1879
  13. added a commit that references this issue on Dec 29, 2025
    b1ad983
  14. added a commit that references this issue on Mar 27, 2026
    90c72f1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-mir-optArea: MIR optimizationsC-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.WG-mir-optWorking group: MIR optimizations

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions