We are experimenting with addinge f128
support to the Rust frontend, but some weird results are popping up:
10.0: 0x40024000000000000000000000000000
1.0: 0x3fff0000000000000000000000000000
3.4: 0x4000b333333333333333333333333333
4.5: 0x40012000000000000000000000000000
-inf: 0xffff0000000000000000000000000000
log10(10) = 0 0x0000000000000000fff0000000000000
3.4^4.5 = 3.4 0x4000b333333333333333333333333333
sqrt(-inf) = -inf 0xffff0000000000000000000000000000
The results should be more like 1.0, 245.4, and NaN.
The IR (below) looks like it should be ok, so I am a bit confused as to what is going on. Is this a form of unsupported math showing up from this table Math Functions — The LLVM C Library? Or a weird x87 extended precision artifact? Or am I just overlooking something in codegen.
(in the above example log10(10) = 0
isn’t actually 0
but I’m using double’s printing).
; ModuleID = 'test_f128.7c43ebc7dc3975e3-cgu.0'
source_filename = "test_f128.7c43ebc7dc3975e3-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: mustprogress nofree nosync nounwind nonlazybind willreturn memory(none) uwtable
define noundef fp128 @log10_f128(fp128 noundef %a) unnamed_addr #0 {
start:
%0 = tail call fp128 @llvm.log10.f128(fp128 %a)
ret fp128 %0
}
; Function Attrs: mustprogress nofree nosync nounwind nonlazybind willreturn memory(none) uwtable
define noundef fp128 @powf_f128(fp128 noundef %a, fp128 noundef %b) unnamed_addr #0 {
start:
%0 = tail call fp128 @llvm.pow.f128(fp128 %a, fp128 %b)
ret fp128 %0
}
; Function Attrs: mustprogress nofree nosync nounwind nonlazybind willreturn memory(none) uwtable
define noundef fp128 @sqrt_f128(fp128 noundef %a) unnamed_addr #0 {
start:
%0 = tail call fp128 @llvm.sqrt.f128(fp128 %a)
ret fp128 %0
}
; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare fp128 @llvm.log10.f128(fp128) #1
; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare fp128 @llvm.pow.f128(fp128, fp128) #1
; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare fp128 @llvm.sqrt.f128(fp128) #1
attributes #0 = { mustprogress nofree nosync nounwind nonlazybind willreturn memory(none) uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #1 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}
!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}
!2 = !{!"rustc version 1.73.0-dev"}
For further reference:
The generated assembly
.text
.file "test_f128.7c43ebc7dc3975e3-cgu.0"
.section .text.log10_f128,"ax",@progbits
.globl log10_f128
.p2align 4, 0x90
.type log10_f128,@function
log10_f128:
.cfi_startproc
jmpq *log10l@GOTPCREL(%rip)
.Lfunc_end0:
.size log10_f128, .Lfunc_end0-log10_f128
.cfi_endproc
.section .text.powf_f128,"ax",@progbits
.globl powf_f128
.p2align 4, 0x90
.type powf_f128,@function
powf_f128:
.cfi_startproc
jmpq *powl@GOTPCREL(%rip)
.Lfunc_end1:
.size powf_f128, .Lfunc_end1-powf_f128
.cfi_endproc
.section .text.sqrt_f128,"ax",@progbits
.globl sqrt_f128
.p2align 4, 0x90
.type sqrt_f128,@function
sqrt_f128:
.cfi_startproc
jmpq *sqrtl@GOTPCREL(%rip)
.Lfunc_end2:
.size sqrt_f128, .Lfunc_end2-sqrt_f128
.cfi_endproc
.ident "rustc version 1.73.0-dev"
.section ".note.GNU-stack","",@progbits
The rust source
I excluded main
and built as a lib to generate the above code.
You will need my branch from Add `f16` and `f128` by tgross35 · Pull Request #114607 · rust-lang/rust · GitHub if you want to build this
#![feature(f128)]
#[no_mangle]
pub fn log10_f128(a: f128) -> f128 {
a.log10()
}
#[no_mangle]
pub fn powf_f128(a: f128, b: f128) -> f128 {
a.powf(b)
}
#[no_mangle]
pub fn sqrt_f128(a: f128) -> f128 {
a.sqrt()
}
fn main() {
let ten: f128 = 10.0;
let one: f128 = 1.0;
let three_four: f128 = 3.4;
let four_five: f128 = 4.5;
let neg_inf: f128 = -1.0 / 0.0;
let log10ten = log10_f128(ten);
let three_pow_four = powf_f128(three_four, four_five);
let sqrt_neginf = sqrt_f128(neg_inf);
println!(
"10.0: {:#034x}\n 1.0: {:#034x}\n 3.4: {:#034x}\n 4.5: {:#034x}\n-inf: {:#034x}",
ten.to_bits(), one.to_bits(), three_four.to_bits(), four_five.to_bits(), neg_inf.to_bits(),
);
println!("log10({}) = {} {:#034x}", ten, log10ten, log10ten.to_bits());
println!("{}^{} = {} {:#034x}", three_four, four_five, three_pow_four, three_pow_four.to_bits());
println!("sqrt({}) = {} {:#034x}", neg_inf, sqrt_neginf, sqrt_neginf.to_bits());
}
Full IR with main (opt-level=3): test-f128-main-opt3.ll - Pastebin.com
Full assembly with main (opt-level=3): test-f128-main-opt3.s - Pastebin.com