Skip to content

f32::powi on Windows returns different results between 1.44 and 1.45 beta #73420

Closed

Description

@iliekturtles

The issue was noticed because typenum::Pow::powi returns consistent results between rustc versions while f32::powi changes.

Given the following code the "std powi" results differ between stable and beta/nightly. Note that code below will run on https://play.rust-lang.org/ but the issue will not reproduce because the host is not Windows. The playground's output for stable/beta/nightly matches stable on my local machine.

extern crate typenum; // 2.12.0

fn main() {
    let v = 12.046623229980468750000000000000_f32;
    let a = a(v);
    let b = b(v);

    println!("std powi {:.30?}", a);
    println!("typenum  {:.30?}", b);
}

#[inline(never)]
fn a(v: f32) -> f32 {
    v.powi(3)
}

#[inline(never)]
fn b(v: f32) -> f32 {
    typenum::Pow::powi(v, typenum::P3::new())
}

On my Windows 10 machine (and the Travis Win 10 VMs) I get the following results. I'm in the process of bisecting down to a specific nightly right now.

/d/Code/Test/rust/tst (master)$ cargo run; rustc --version --verbose
    Finished dev [unoptimized + debuginfo] target(s) in 0.07s
     Running `target\debug\tst.exe`
std powi 1748.219482421875000000000000000000
typenum  1748.219482421875000000000000000000
rustc 1.44.0 (49cae5576 2020-06-01)
binary: rustc
commit-hash: 49cae55760da0a43428eba73abcb659bb70cf2e4
commit-date: 2020-06-01
host: x86_64-pc-windows-msvc
release: 1.44.0
LLVM version: 9.0
/d/Code/Test/rust/tst (master)$ cargo +beta run; rustc +beta --version --verbose
   Compiling tst v0.1.0 (D:\Code\Test\rust\tst)
    Finished dev [unoptimized + debuginfo] target(s) in 4.95s
     Running `target\debug\tst.exe`
std powi 1748.219604492187500000000000000000
typenum  1748.219482421875000000000000000000
rustc 1.45.0-beta.3359 (b7dc83a3f 2020-06-03)
binary: rustc
commit-hash: b7dc83a3f6ca9746fb3d121761c3605477b77d90
commit-date: 2020-06-03
host: x86_64-pc-windows-msvc
release: 1.45.0-beta.3359
LLVM version: 10.0

1748.2196044921875
1748.219482421875

Activity

  1. added
    A-floating-pointArea: Floating point numbers and arithmetic
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jun 16, 2020
  2. iliekturtles commented on Jun 16, 2020

    @iliekturtles
    ContributorAuthor

    Issue first appears in nightly-2020-05-22-x86_64-pc-windows-msvc - rustc 1.45.0-nightly (9310e3b 2020-05-21)

    Commit comparison with the previous nightly: 0aa6751...9310e3b

    I'm guessing 9f12823 (Update LLVM submodule) is the culprit since the f32::powi code just lowers to an LLVM intrisic.

        Finished dev [unoptimized + debuginfo] target(s) in 2.74s
         Running `target\debug\tst.exe`
    std powi 1748.219482421875000000000000000000
    typenum  1748.219482421875000000000000000000
    rustc 1.45.0-nightly (0aa6751c1 2020-05-20)
    binary: rustc
    commit-hash: 0aa6751c19d3ba80df5b0b02c00bf44e13c97e80
    commit-date: 2020-05-20
    host: x86_64-pc-windows-msvc
    release: 1.45.0-nightly
    LLVM version: 9.0
    
        Finished dev [unoptimized + debuginfo] target(s) in 9.16s
         Running `target\debug\tst.exe`
    std powi 1748.219604492187500000000000000000
    typenum  1748.219482421875000000000000000000
    rustc 1.45.0-nightly (9310e3bd4 2020-05-21)
    binary: rustc
    commit-hash: 9310e3bd4f425f84fc27878ebf2bda1f30935a63
    commit-date: 2020-05-21
    host: x86_64-pc-windows-msvc
    release: 1.45.0-nightly
    LLVM version: 10.0
    
  3. ecstatic-morse commented on Jun 16, 2020

    @ecstatic-morse
    Contributor

    I'm guessing that LLVM 10 started using the MSVC implementation of the powi intrinsic, which uses a higher precision for intermediate results. The result you see is equivalent to the one you would get from casting to and f64, multiplying and then casting back to and f32.

  4. ollie27 commented on Jun 16, 2020

    @ollie27
    Contributor

    Looking at the changes in assembly for powi on 1.44.0 we have:

    	callq	__powisf2

    but on beta that's replaced with:

    	cvtsi2ss	%edx, %xmm1
    	callq	powf

    So LLVM has switched from calling the __powisf2 intrinsic from compiler-rt/compiler-builtins to calling powf. This looks like an intentional change from https://reviews.llvm.org/D69013 but it's not clear to me why that change was made.

  5. added
    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
    on Jun 16, 2020
  6. mati865 commented on Jun 16, 2020

    @mati865
  7. added
    O-windowsOperating system: Windows
    and removed
    O-windows-msvcToolchain: MSVC, Operating system: Windows
    on Jun 16, 2020
  8. iliekturtles commented on Jun 17, 2020

    @iliekturtles
    ContributorAuthor

    Thanks for digging into the details. Sounds like this issue should be closed as working as intended then?

  9. ollie27 commented on Jun 17, 2020

    @ollie27
    Contributor

    Sounds like this issue should be closed as working as intended then?

    I don't know. I think minor changes to the output of float operations between versions are technically allowed breakage but it would be nice to know why this change was made.

    Given that powi seemed to be working fine before, does anyone know why https://reviews.llvm.org/D69013 was done?

  10. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jun 17, 2020
  11. 10 remaining items

  12. ollie27 commented on Jun 25, 2020

    @ollie27
    Contributor

    Did anyone actually figure out why this change was made?

  13. Mark-Simulacrum commented on Jun 25, 2020

    @Mark-Simulacrum
    Member

    My impression is no. I don't think we should close this out before it's a compat note in relnotes and we have some sense of why this is happening (beyond "LLVM patch"), if only to hopefully be better able to explain to users why things broke for them.

  14. eddyb commented on Jun 25, 2020

    @eddyb
    Contributor

    Looks like the intention was to avoid calling __powidf2 as it's (sometimes?) not available in MSVC (so this might be for compiling without compiler-rt?), and they assumed the expansion would be compatible. I'm not sure they were aware it might have a different result, or what the deal is with usecases that involve compiler-rt.

  15. spastorino commented on Jul 15, 2020

    @spastorino
    Member

    Given that this was added to release notes, I think this should be closed now?.

  16. spastorino commented on Jul 16, 2020

    @spastorino
    Member

    Tagging as P-low until we find some answers for @Mark-Simulacrum's questions

  17. added a commit that references this issue on Aug 6, 2020
  18. added
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    and removed on Aug 21, 2020
  19. iliekturtles commented on Apr 13, 2022

    @iliekturtles
    ContributorAuthor

    @Mark-Simulacrum @spastorino With this documented in the 1.45.0 compatability notes are there still open questions that need action or are we good to close this issue?

  20. Mark-Simulacrum commented on Apr 13, 2022

    @Mark-Simulacrum
    Member

    I think we can close. I'm not fully happy about the explanation we have, but it seems good enough for the time being.

  21. added a commit that references this issue on May 11, 2026
  22. added a commit that references this issue on May 14, 2026
  23. added a commit that references this issue on Oct 17, 2026
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-floating-pointArea: Floating point numbers and arithmeticC-bugCategory: This is a bug.O-windowsOperating system: WindowsP-lowLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.relnotesMarks issues that should be documented in the release notes of the next release.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions