【发布时间】:2019-02-24 23:40:55
【问题描述】:
我正在尝试将大量代码塞进一个相当小的 ARM 微控制器中。我已经在尺寸优化方面做了大量工作,我已经到了需要双重算术的地步,但是__aeabi_ddiv、__aeabi_dadd 和__aeabi_dsub 是整个设备上最大的一些功能.
__aeabi_dadd 和 __aeabi_dsub 都是 ~1700 字节,尽管它们的工作基本相同(双打的最高位是符号位)。两个函数都没有引用另一个。
实际上,我需要做的只是将__aeabi_dsub 替换为:
double __aeabi_dsub(double a, double b) {
// flip top bit of 64 bit number (the sign bit)
((uint32_t*)&b)[1] ^= 0x80000000; // assume little endian
return a + b;
}
我会节省大约 1700 个字节 - 所以翻转第二个参数的符号,然后使用 __aeabi_dadd 添加它们。
我知道这可能不是 100% 与 IEEE 规范兼容,但在这个平台上我可以接受,以便节省 1% 以上的可用闪存。
我的问题是,当我添加该函数时,链接器会抱怨 undefined reference to __aeabi_dsub - 这似乎很奇怪,因为定义它的行为会导致错误。
这似乎与链接时间优化有关 (-flto) - 关闭它意味着它一切正常,但是它增加了 8k 的固件大小使其不再适合可用的闪存!
那么我需要做什么才能在链接时间优化处于活动状态时替换内置函数__aeabi_dsub?
谢谢!
【问题讨论】:
-
试过用
-Os编译它了吗?真的,在破解标准库之前,最好尝试优化代码。此外,如果您的处理器有 FPU,您可以利用它并摆脱这些功能。 -
是的,它已经在使用 -Os,而且我首先进行了许多其他代码优化,包括用较慢但较小的版本替换
sin之类的东西(效果很好)。这个问题是关于 GCC、FLTO 和内置函数的,@toohonestforthissite 你对语言选择的个人看法不应该涉及。该版本适用于 BBC micro:bit,这是一款面向学童的设备。 IMO 绝大多数 10 岁的孩子不会在中断、指针和 Nordic 的蓝牙软设备方面走得太远。 -
这是我在创建引导加载程序时熟悉的活动。你用过
-ffreestanding吗?这通常会消除问题。请同时提供 gcc 版本。 -
谢谢!请问您可以将其发布为答案吗?做到了。添加
-ffreestanding的行为实际上增加了大约 250 字节的固件大小(我猜一些关于内置函数的假设被打破了),但添加我的dsub代码节省了 1680 字节,所以它仍然是一个非常明显的胜利 -
我的回答会比这更多,包括你为什么会遇到这个问题的原因。
-ffreestanding不是唯一的解决方案。有关更多背景信息,请参阅:Static libraries with lto。您链接的-lc或-lgcc可能对 LTO 不友好。我怀疑你的问题会被重新提出;大多数人无法理解你(或者被你想要完成的事情分心);你应该把它作为补充。我几年前用过nsjs,当时不到10万。