强制 64 位长双打?
Posted
技术标签:
【中文标题】强制 64 位长双打?【英文标题】:Forcing 64-bit long doubles? 【发布时间】:2018-07-31 00:39:54 【问题描述】:我正在为 aarch64
(ARM 64 位)平台上的项目静态构建 musl-libc
。我想避免使用任何软浮点库,例如GCC's soft float library routines。然而,即使我使用-mfloat-abi=hard
,这些仍然出现在图书馆档案中。据我所知,这是因为 ARM 64 位平台将 long double
定义为 128 位。
有没有办法改变这种行为?例如,我可以强制将long double
定义为与double
相同的大小吗?我知道这是 C 标准允许的,但我不确定是否有任何方法可以强制 Clang(我专门为此使用 Clang)使用这样的定义进行编译。
【问题讨论】:
试试-mlong-double-64
。不确定是否适用于 ARM...
@AndrewHenle:我假设软浮点库例程出现只是因为long double
被定义为 128 位(基于__extenddftf2
描述和我知道我的@987654332 的事实@platform 有 64 位 FP 寄存器)。所以虽然是的,vfprintf
依赖于long double
处理,但我想我想知道long double
处理是否又依赖于软浮点库例程。这有意义吗?
@AndrewHenle:换句话说,如果vfprintf
依赖于long double
处理,那么long double
的大小会改变什么 处理吗?如果是这样,我是否可以利用这一事实来强制 long double
的大小适合硬浮点寄存器,而不是不得不求助于软浮点?
我知道这很可怕,但只是为了尝试您的假设,您为什么不在整个库中执行查找替换(将“long double”替换为“double”)?跨度>
@tonysdg 据我所知(这是很久以前的事了),这需要重建编译器。也许 clang 是不同的,但对于 gcc,这是唯一的选择。尽管我们确实非常大声地发誓,该架构定义了 CPU (还)没有的类型和指令。实际上我现在回想起来,我们的问题是双重的。在我们重建 gcc 之后,我们需要有那些 abort-stub 函数,以不生成没有 CPU 实现并且我们没有在内核中模拟的指令(像其他人那样)。
【参考方案1】:
我最终找到了解决方案,但我不一定会向所有人推荐它。它可能会在其他地方引发错误,但它足以满足我的需要。它还涉及从头开始构建 Clang(感谢 @Art 的建议!)。此外,我正在进行的项目使用的是 LLVM/Clang 3.7.1,因此我对其他版本不做任何声明。
据我所知,AArch64 目标的长双精度定义出现在 clang/lib/Basic/Targets.cpp
:
...
MaxAtomicInlineWidth = 128;
MaxAtomicPromoteWidth = 128;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad;
// in inline assembly are neon specifiers, not assembly variant
// specifiers.
...
通过修改内部 2 行,我删除了对我在问题中提到的软 FP 例程的所有引用:
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
我的测试程序 -- SNU's version of the NASA Parallel Benchmarks -- 仍然正确验证,所以我假设我没有严重破坏任何东西。尽管如此,这是一个重要的修改——我不建议大多数人使用它(它可能会导致其他地方的损坏)。
【讨论】:
我有一个类似的案例:ppc32,gcc 将 long double 操作编译成 __gcc_qsub/qmult/etc 调用。 GCC 可以在没有 quadmath 的情况下编译工作,基本上将 long double 减少到 double。截至目前,Clang 不支持这一点。在源中更改它对我有帮助!【参考方案2】:我以前也不得不做类似的事情,弄乱类型(尤其是long
s)。最好的办法是手动手动替换类型,因为这是获得所需内容的最简单、最直接的方法。你可以尝试玩弄宏或按摩编译器,但根据我的经验,你创造的问题比你解决的要多,而且它通常是一个脆弱的解决方案,稍后会中断。
幸运的是,您正在使用的资源看起来维护得很好,而且您正在寻找的更改相当全面。你可以很简单地解决这个问题。假设你正在运行一个类 Unix 系统,你可以从 musl 的基目录运行以下命令:
$ grep -Rl 'long double' * | xargs -tn1 sed -i '' -e 's/long double/double/g'
这个命令:
-
在所有文件中递归查找字符串
long double
,并返回包含该字符串的文件名。
将其传递给xargs
,xargs
针对每个文件名调用sed
命令,同时打印。
当sed
运行时,它会就地修改文件,并将long double
替换为double
。
当我尝试这个命令时,它“正常工作”。我会更仔细地阅读差异,以确保它正确地匹配所有内容并且不会改变库的行为。
【讨论】:
以上是关于强制 64 位长双打?的主要内容,如果未能解决你的问题,请参考以下文章