Closed
Description
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