Skip to content

Bad size_hint() for Range<i64> on powerpc64le #72023

Closed

Description

@cuviper

I tried this code:

fn main() {
    let range = -2..i64::MAX;
    dbg!(&range);
    // With this assertion, it works as expected!
    // assert!(range.start < range.end);
    dbg!(range.size_hint());
}

I expected to see this, which does work in debug mode:

[src/main.rs:3] &range = -2..9223372036854775807
[src/main.rs:6] range.size_hint() = (
    9223372036854775809,
    Some(
        9223372036854775809,
    ),
)

But in release mode, this happened:

[src/main.rs:3] &range = -2..9223372036854775807
[src/main.rs:6] range.size_hint() = (
    0,
    Some(
        0,
    ),
)

However, it does work in release mode if that start < len assertion is uncommented.

Meta

$ rustc --version --verbose
rustc 1.45.0-nightly (a08c47310 2020-05-07)
binary: rustc
commit-hash: a08c47310c7d49cbdc5d7afb38408ba519967ecd
commit-date: 2020-05-07
host: powerpc64le-unknown-linux-gnu
release: 1.45.0-nightly
LLVM version: 9.0

This is not new -- it comes from a failure noted in rayon-rs/rayon#585 in July 2018, which unfortunately I forgot to followup on until now. It's fine on x86_64, so it seems like an arch-specific codegen issue, most likely down to LLVM.

Activity

  1. added
    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
    A-codegenArea: Code generation
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    O-PowerPCTarget: PowerPC processors
    C-bugCategory: This is a bug.
    on May 8, 2020
  2. cuviper commented on May 8, 2020

    @cuviper
    MemberAuthor

    We have Rust built with LLVM 10 in Fedora 32, but that doesn't fix it:

    $ rustc -Vv
    rustc 1.43.0
    binary: rustc
    commit-hash: unknown
    commit-date: unknown
    host: powerpc64le-unknown-linux-gnu
    release: 1.43.0
    LLVM version: 10.0
    $ cargo run 
       Compiling range_len v0.1.0 (/range_len)
        Finished dev [unoptimized + debuginfo] target(s) in 0.36s
         Running `target/debug/range_len`
    [src/main.rs:3] &range = -2..9223372036854775807
    [src/main.rs:6] range.size_hint() = (
        9223372036854775809,
        Some(
            9223372036854775809,
        ),
    )
    $ cargo run --release
       Compiling range_len v0.1.0 (/range_len)
        Finished release [optimized] target(s) in 0.30s
         Running `target/release/range_len`
    [src/main.rs:3] &range = -2..9223372036854775807
    [src/main.rs:6] range.size_hint() = (
        0,
        Some(
            0,
        ),
    )
    
  3. programmerjake commented on Oct 13, 2020

    @programmerjake
    Member

    I didn't actually run it on a Power processor to test, but AFAICT the bug reduces to this:

    pub fn f(a: i64, b: i64) -> u64 {
        if a < b {
            0
        } else {
            a.wrapping_sub(b) as u64
        }
    }

    LLVM miscompiles it assuming that a.wrapping_sub(b) won't have signed overflow.

    https://rust.godbolt.org/z/49fncx

    Output assembly:

    example::f:
            sub.    3, 3, 4
            isellt  3, 0, 3
            blr
            .long   0
            .quad   0
    

    the sub. sets the condition register CR0 based on sign of wrapped result, not on if r3 is less than, equal to, or greater than r4.

    Will open a LLVM bug report shortly.

  4. programmerjake commented on Oct 13, 2020

    @programmerjake
    Member
  5. ecnelises commented on Dec 20, 2021

    @ecnelises
    Contributor

    It should be fixed by llvm/llvm-project@f6515b0 , @cuviper can you verify it? Thanks.

  6. cuviper commented on Jan 6, 2022

    @cuviper
    MemberAuthor

    Looks like that fix released in LLVM 12. I just tried the reproducer again on Fedora 33, 34, and 35, with LLVM 11, 12, and 13 respectively -- it failed with 11 and passed with 12 and 13. Our minimum is 12 since #90175, so I think we're good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationC-bugCategory: This is a bug.O-PowerPCTarget: PowerPC processorsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions