浮点运算控制选项
编译器经过一系列优化后可能出现浮点运算结果不一致,此类情况一般是由以下几个原因导致的:
- 浮点精度有限
- 每个编译器都有影响浮点计算结果的选项
- 选项因编译器而异,并且具有不同的默认值
- 某些选项可以被其它看似无关的选项显式地启用/禁用
- 通过启用/禁用正确的选项,编译器可以控制浮点运算结果
默认选项
毕昇编译器的浮点运算控制选项基于LLVM官方文档,可参阅:https://clang.llvm.org/docs/UsersManual.html#controlling-floating-point-behavior。
-Mflushz
该选项用于控制非规范化的浮点值刷新为零,与其它不安全的浮点优化分开。开源Clang和Flang仅在x86架构支持该选项,毕昇编译器将AArch64架构加入支持范围。使用方式与开源版本相同。
-ffp-contract=style
该选项的值可以是off/on/fast,毕昇编译器将其值默认设为fast,使能浮点数乘加操作,将乘法和加法合并为一条乘加运算从而提升性能。
-faarch64-pow-alt-precision=18/21
Flang选项, 仅对fortran代码起效。用于更改对于pow函数的优化策略,使得pow函数的计算结果与非ARM平台保持一致。
-faarch64-minmax-alt-precision
Flang选项, 仅对fortran代码起效。用于更改对于min/max函数的优化策略,使得min/max函数的计算结果与非ARM平台保持一致。
-mllvm -disable-sincos-opt
llvm选项,更改sin、cos函数的优化策略,使得sin、cos函数的计算结果与非ARM平台保持一致。
-mllvm -aarch64-recip-alt-precision
llc选项,使用软浮点补偿,使得recip倒数指令的计算结果与非ARM平台保持一致。
-mllvm -aarch64-rsqrt-alt-precision
llc选项,使用软浮点补偿,使得rsqrt倒数开方指令的计算结果与非ARM平台保持一致。
-mllvm -enable-alt-precision-math-functions
llvm选项,作用是将数学函数__mth_i_cosd,__mth_i_asind及__pd_powi_1的函数名替换为cosdf,asindf及powr8i4,从而实现控制数学函数精度的效果(需要结合kml数学库使用), 此选项仅在O1及以上优化起效。
-mllvm -enable-18-math-compatibility
llvm选项,作用是将数学函数tgammaf,cbrt,log,log10 等数学函数换作有_18后缀的函数,从而实现控制数学函数精度的效果(需要结合kml数学库使用),此选项仅在O1及以上优化,且开启-mllvm -enable-alt-precision-math-functions 时起效。
-mllvm -enable-80-math-compatibility = <true|false>
llvm选项,作用是将80位精度的长浮点数学函数cosl,sinl,logl,等数学函数换作有_k80后缀的函数,从而实现控制数学函数精度的效果(需要结合kml数学库使用),此选项仅在O1及以上优化,且开启-mllvm -enable-alt-precision-math-functions 时起效,默认开启,指定值为false时关闭转换的使能。
-mllvm -disable-80-math-compatibility = all/func1,func2...
llvm选项,作用是在开启-mllvm -enable-80-math-compatibility的情况下,关闭指定函数到kml中带有_k80后缀函数的转换,从而实现控制数学函数精度的效果(需要结合kml数学库使用),此选项仅在O1及以上优化,且开启-mllvm -enable-alt-precision-math-functions 时起效。
-ffp-compatibility=17/18/21
通用选项,用于统一控制为保持计算结果与非ARM平台保持一致需要打开的所有选项。
-ffma-combine-fdiv
通用选项,用于将表达式 a/b+c 优化为 fma(a, 1/b, c),有利于保持计算结果与非ARM平台保持一致,仅在-ffp-contract=fast时起效。
-ffma-reverse-associative
通用选项,用于将表达式 ab+cd 优化为 fma(a, b, c*d) ,有利于保持计算结果与非ARM平台保持一致,仅在-ffp-contract=fast时起效。
-Hx,124,0xc00000
flang 选项,用于保持使用常量初始化的舍入方式与非ARM计算平台保持一致,仅在fortran起效。