Skip to content

Wrapper generates more instructions for simple integer operations #119520

Description

@DaniPopes

Code

I tried this code (godbolt):

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Int(u32);

const A: Int = Int(201);
const B: Int = Int(270);
const C: Int = Int(153);

#[inline(never)]
#[rustfmt::skip]
pub fn wrapped(x: Int) -> bool {
    (x >= A && x <= B)
        || x == C
}

#[inline(never)]
#[rustfmt::skip]
pub fn primitive(x: Int) -> bool {
    (x.0 >= A.0 && x.0 <= B.0)
        || x.0 == C.0
}

I expected to see this happen: both functions compile to identical assembly

Instead, this happened: wrapped contains way more instructions:

example::wrapped:
        cmp     edi, 201
        jb      .LBB0_3
        xor     eax, eax
        cmp     edi, 270
        mov     ecx, 255
        setne   al
        cmovae  ecx, eax
        mov     al, 1
        test    cl, cl
        je      .LBB0_4
        movzx   ecx, cl
        cmp     ecx, 255
        jne     .LBB0_3
.LBB0_4:
        ret
.LBB0_3:
        cmp     edi, 153
        sete    al
        ret

example::primitive:
        lea     eax, [rdi - 201]
        cmp     eax, 70
        setb    cl
        cmp     edi, 153
        sete    al
        or      al, cl
        ret

Version it worked on

It most recently worked on: 1.64

Version with regression

rustc --version --verbose:

rustc 1.77.0-nightly (e51e98dde 2023-12-31)
binary: rustc
commit-hash: e51e98dde6a60637b6a71b8105245b629ac3fe77
commit-date: 2023-12-31
host: x86_64-unknown-linux-gnu
release: 1.77.0-nightly
LLVM version: 17.0.6

I have bisected it to between 1.64 and 1.65 on Godbolt, and then further with cargo bisect-rustc which points to nightly-2022-08-17 (4033686...86c6ebe):

Regression in nightly-2022-08-17
...
looking for regression commit between 2022-08-16 and 2022-08-17
...
found 8 bors merge commits in the specified range
  commit[0] 2022-08-15: Auto merge of #100595 - matthiaskrgr:rollup-f1zur58, r=matthiaskrgr
  commit[1] 2022-08-15: Auto merge of #100007 - ChrisDenton:dtor-inline-never, r=michaelwoerister
  commit[2] 2022-08-16: Auto merge of #100237 - cjgillot:no-special-hash-hir, r=nagisa
  commit[3] 2022-08-16: Auto merge of #100611 - matthiaskrgr:rollup-rxj10ur, r=matthiaskrgr
  commit[4] 2022-08-16: Auto merge of #100441 - nnethercote:shrink-ast-Attribute, r=petrochenkov
  commit[5] 2022-08-16: Auto merge of #99612 - yanchen4791:issue-95079-fix, r=compiler-errors
  commit[6] 2022-08-16: Auto merge of #100626 - Dylan-DPC:rollup-mwbm7kj, r=Dylan-DPC
  commit[7] 2022-08-16: Auto merge of #100644 - TaKO8Ki:rollup-n0o6a1t, r=TaKO8Ki

Backtrace

Backtrace

<backtrace>

@rustbot modify labels: +I-slow +regression-from-stable-to-stable -regression-untriaged

Activity

  1. added
    C-bugCategory: This is a bug.
    regression-untriagedUntriaged performance or correctness regression.
    on Jan 2, 2024
  2. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    I-slowIssue: Problems and improvements with respect to performance of generated code.
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    and removed
    regression-untriagedUntriaged performance or correctness regression.
    on Jan 2, 2024
  3. DaniPopes commented on Jan 2, 2024

    @DaniPopes
    ContributorAuthor

    @rustbot modify labels: -needs-triage +A-LLVM

  4. added
    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jan 2, 2024
  5. DaniPopes commented on Jan 2, 2024

    @DaniPopes
    ContributorAuthor
  6. apiraino commented on Jan 4, 2024

    @apiraino
    Contributor

    WG-prioritization assigning priority (Zulip discussion).

    (I wonder if it's in any way related to issue #119014 also about code generation for Partial)

    @rustbot label -I-prioritize +P-medium

  7. added and removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jan 4, 2024
  8. dianqk commented on Jan 5, 2024

    @dianqk
    Member

    Alive2: https://alive2.llvm.org/ce/z/LDK_Rf.
    (I haven't checked where the missing optimizations are.)

  9. 1 remaining item

  10. dianqk commented on Jan 15, 2024

    @dianqk
    Member

    @rustbot claim

  11. dianqk commented on Jan 16, 2024

    @dianqk
    Member

    Upstream issue: llvm/llvm-project#78281

    Even though I created this issue, I think there may be other solutions.
    I might be able to keep the range information in the SROA, and of course for this example, I could use the LazyValueInfo calculation. When I'm sure that this is also a possible way, I'll create a new issue. (Of course, the above issue needs to be resolved as well.)

    But personally, I would like this issue to be solved directly in rust. I write similar code all the time (and I'm sure other projects are similar?). If we wait for an upstream solution, we may be delayed until LLVM 19. Of course, I would also like to see if I can use this to learn the MIR optimization. :)

  12. dianqk commented on Jan 23, 2024

    @dianqk
    Member

    Example of trait removal:

    #![crate_type = "lib"]
    use std::cmp::Ordering::*;
    
    const A: i32 = 201;
    const B: i32 = 270;
    const C: i32 = 153;
    
    #[inline(never)]
    #[no_mangle]
    pub fn foo(x: i32) -> bool {
        matches!(x.partial_cmp(&A), Some(Greater | Equal)) && 
        matches!(x.partial_cmp(&B), Some(Less | Equal)) ||
        x == C
    }

    Godbolt: https://rust.godbolt.org/z/EP9ohq5j3

  13. added 2 commits that reference this issue on Jan 23, 2024
    f893d88
    4b854f3
  14. added a commit that references this issue on Jan 27, 2024
    35c1914
  15. added a commit that references this issue on Jan 27, 2024
    9f41af3
  16. added a commit that references this issue on Feb 14, 2024
    46a599f
  17. added 3 commits that reference this issue on Feb 28, 2024
    b9b7c24
    c1c0824
    aa86e94
  18. added 2 commits that reference this issue on Mar 8, 2024
    ffbf82e
    14fbc3c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.P-mediumMedium priorityregression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions