Skip to content

Bad native codegen (2017-12-25 Nightly) #47015

Closed
@leonardo-m

Description

@leonardo-m

Given this small program:

#[inline(never)]
fn e97() -> u64 {
    // Input.
    const BASE: f64 = 28_433.0;
    const EXP: u64 = 7_830_457;
    const BIG: f64 = 1e10;

    let mut b = EXP.next_power_of_two();

    let mut n = 1.0;
    while b > 0 {
        if EXP & b != 0 {
            n = (n * n * 2.0) % BIG;
        } else {
            n = (n * n) % BIG;
        }
        b >>= 1;
    }

    ((n * BASE + 1.0) % BIG) as u64
}

fn main() {
    assert_eq!(e97(), 8_739_992_577);
}

I am using:

rustc 1.24.0-nightly (4a7c072fa 2017-12-25)
commit-hash: 4a7c072fa61b42f96d8b75c37fc1edfd71172695
host: x86_64-pc-windows-gnu

If I compile that program with this it works correctly:
rustc -C opt-level=1 test.rs

If I compile it with a native CPU target it asserts:
rustc -C opt-level=1 -C target-cpu=native test.rs

The llvm-ir of the e97 function produced with a default CPU target:

; test::e97
; Function Attrs: noinline norecurse nounwind readnone uwtable
define internal fastcc i64 @_ZN4test3e9717h2a230e2896608cc2E() unnamed_addr #3 {
start:
  br label %bb4

bb3:                                              ; preds = %bb4
  %0 = fmul double %n.1.1, 2.843300e+04
  %1 = fadd double %0, 1.000000e+00
  %2 = frem double %1, 1.000000e+10
  %3 = fptoui double %2 to i64
  ret i64 %3

bb4:                                              ; preds = %bb4, %start
  %b.08 = phi i64 [ 8388608, %start ], [ %12, %bb4 ]
  %n.07 = phi double [ 1.000000e+00, %start ], [ %n.1.1, %bb4 ]
  %4 = and i64 %b.08, 7830457
  %5 = icmp eq i64 %4, 0
  %6 = fmul double %n.07, %n.07
  %7 = fmul double %6, 2.000000e+00
  %n.1.in = select i1 %5, double %6, double %7
  %n.1 = frem double %n.1.in, 1.000000e+10
  %8 = and i64 %b.08, 15660914
  %9 = icmp eq i64 %8, 0
  %10 = fmul double %n.1, %n.1
  %11 = fmul double %10, 2.000000e+00
  %n.1.in.1 = select i1 %9, double %10, double %11
  %n.1.1 = frem double %n.1.in.1, 1.000000e+10
  %12 = lshr i64 %b.08, 2
  %13 = icmp eq i64 %12, 0
  br i1 %13, label %bb3, label %bb4
}

And the llvm-ir using the native CPU target:

; test::e97
; Function Attrs: noinline norecurse nounwind readnone uwtable
define internal fastcc i64 @_ZN4test3e9717h2a230e2896608cc2E() unnamed_addr #3 {
start:
  br label %bb4

bb3:                                              ; preds = %bb4
  %0 = fmul double %n.1.3, 2.843300e+04
  %1 = fadd double %0, 1.000000e+00
  %2 = frem double %1, 1.000000e+10
  %3 = fptoui double %2 to i64
  ret i64 %3

bb4:                                              ; preds = %bb4, %start
  %b.08 = phi i64 [ 8388608, %start ], [ %20, %bb4 ]
  %n.07 = phi double [ 1.000000e+00, %start ], [ %n.1.3, %bb4 ]
  %4 = and i64 %b.08, 7830457
  %5 = icmp eq i64 %4, 0
  %6 = fmul double %n.07, %n.07
  %7 = fmul double %6, 2.000000e+00
  %n.1.in = select i1 %5, double %6, double %7
  %n.1 = frem double %n.1.in, 1.000000e+10
  %8 = and i64 %b.08, 15660914
  %9 = icmp eq i64 %8, 0
  %10 = fmul double %n.1, %n.1
  %11 = fmul double %10, 2.000000e+00
  %n.1.in.1 = select i1 %9, double %10, double %11
  %n.1.1 = frem double %n.1.in.1, 1.000000e+10
  %12 = and i64 %b.08, 31321828
  %13 = icmp eq i64 %12, 0
  %14 = fmul double %n.1.1, %n.1.1
  %15 = fmul double %14, 2.000000e+00
  %n.1.in.2 = select i1 %13, double %14, double %15
  %n.1.2 = frem double %n.1.in.2, 1.000000e+10
  %16 = and i64 %b.08, 62643656
  %17 = icmp eq i64 %16, 0
  %18 = fmul double %n.1.2, %n.1.2
  %19 = fmul double %18, 2.000000e+00
  %n.1.in.3 = select i1 %17, double %18, double %19
  %n.1.3 = frem double %n.1.in.3, 1.000000e+10
  %20 = lshr i64 %b.08, 4
  %21 = icmp eq i64 %20, 0
  br i1 %21, label %bb3, label %bb4
}

Their diff:

8c8
<   %0 = fmul double %n.1.1, 2.843300e+04
---
>   %0 = fmul double %n.1.3, 2.843300e+04
15,16c15,16
<   %b.08 = phi i64 [ 8388608, %start ], [ %12, %bb4 ]
<   %n.07 = phi double [ 1.000000e+00, %start ], [ %n.1.1, %bb4 ]
---
>   %b.08 = phi i64 [ 8388608, %start ], [ %20, %bb4 ]
>   %n.07 = phi double [ 1.000000e+00, %start ], [ %n.1.3, %bb4 ]
29,31c29,43
<   %12 = lshr i64 %b.08, 2
<   %13 = icmp eq i64 %12, 0
<   br i1 %13, label %bb3, label %bb4
---
>   %12 = and i64 %b.08, 31321828
>   %13 = icmp eq i64 %12, 0
>   %14 = fmul double %n.1.1, %n.1.1
>   %15 = fmul double %14, 2.000000e+00
>   %n.1.in.2 = select i1 %13, double %14, double %15
>   %n.1.2 = frem double %n.1.in.2, 1.000000e+10
>   %16 = and i64 %b.08, 62643656
>   %17 = icmp eq i64 %16, 0
>   %18 = fmul double %n.1.2, %n.1.2
>   %19 = fmul double %18, 2.000000e+00
>   %n.1.in.3 = select i1 %17, double %18, double %19
>   %n.1.3 = frem double %n.1.in.3, 1.000000e+10
>   %20 = lshr i64 %b.08, 4
>   %21 = icmp eq i64 %20, 0
>   br i1 %21, label %bb3, label %bb4

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.I-slowIssue: Problems and improvements with respect to performance of generated code.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions