【发布时间】:2014-06-11 17:40:48
【问题描述】:
在解决 Fastest Cortex M0+ Thumb 32x32=64 multiplication function? 中的问题时,我编写了以下 C 函数以查看它的编译方式:
uint64_t lmul(uint32_t a, uint32_t b){
uint32_t hia = a >> 16,
hib = b >> 16,
loa = (uint32_t)(uint16_t)a,
lob = (uint32_t)(uint16_t)b,
low = loa * lob,
mid1 = hia * lob,
mid2 = loa * hib,
mid = mid1 + mid2,
high = hia * hib;
if (mid < mid1)
high += 0x10000;
return ((uint64_t)high << 32) + ((uint64_t)mid << 16) + low;
}
在使用 ARM GCC 编译器 4.7.3 通过 CodeWarrior(我正在使用的飞思卡尔开发板附带)进行大小优化后,它变成了这样:
00000eac <lmul>:
eac: b570 push {r4, r5, r6, lr}
eae: 0c06 lsrs r6, r0, #16
eb0: b280 uxth r0, r0
eb2: 0c0a lsrs r2, r1, #16
eb4: 1c04 adds r4, r0, #0
eb6: b289 uxth r1, r1
eb8: 434c muls r4, r1
eba: 4350 muls r0, r2
ebc: 4371 muls r1, r6
ebe: 1843 adds r3, r0, r1
ec0: 4356 muls r6, r2
ec2: 428b cmp r3, r1
ec4: d202 bcs.n ecc <lmul+0x20>
ec6: 2580 movs r5, #128 ; 0x80
ec8: 026a lsls r2, r5, #9
eca: 18b6 adds r6, r6, r2
ecc: 0c19 lsrs r1, r3, #16
ece: 0418 lsls r0, r3, #16
ed0: 1c22 adds r2, r4, #0
ed2: 2300 movs r3, #0
ed4: 1c04 adds r4, r0, #0
ed6: 1c0d adds r5, r1, #0
ed8: 18a4 adds r4, r4, r2
eda: 415d adcs r5, r3
edc: 1c31 adds r1, r6, #0
ede: 1c18 adds r0, r3, #0
ee0: 1c22 adds r2, r4, #0
ee2: 1c2b adds r3, r5, #0
ee4: 1812 adds r2, r2, r0
ee6: 414b adcs r3, r1
ee8: 1c10 adds r0, r2, #0
eea: 1c19 adds r1, r3, #0
eec: bd70 pop {r4, r5, r6, pc}
我无法理解编译器在函数的最后 40% 中做了什么。就像它只是为了增加函数的大小而播放音乐寄存器一样。这是众所周知的 ARM 做的事情,还是有一些奇怪的目的,我缺乏 ARM 组装专业知识来理解?
如果我在替换中没有犯任何错误,则函数的后半部分可以表示为:
ecc: 0c19 lsrs r1, r3, #16
ece: 0418 lsls r0, r3, #16
ed2: 2300 movs r3, #0
ed8: 18a4 adds r0, r0, r4
eda: 415d adcs r1, r3
ee6: 414b adds r1, r1, r6
eec: bd70 pop {r4, r5, r6, pc}
【问题讨论】:
-
仅供参考,gcc explorer 上的 gcc 4.5.3 和 4.6.3 似乎没有这样做。
-
LOL +1 只为'音乐寄存器'
-
一件事是我的帖子的前提,但我不完全确定,编译器实际上是来自 ARM 还是只是支持 ARM 的 GCC。我猜是前者,因为它在 CodeWarrior 中被列为“ARM Ltd. GCC Build Tools”,但我可能错了。据我了解,官方 ARM 编译器使用 GCC 前端,但后端不同。
-
有各种 gcc 选项,例如
-dumpspecs提供配置信息。在 gcc explorer 中,大约有 30 条 4.6.3 和-mthumb -mcpu=cortex-m0 -Os的指令。生成的代码看起来很可怕。我猜是演员阵容和一些模糊的溢出标准处理。你试过-ffast-math吗? -
谁能确认这发生在 vanilla GCC 4.7.3(即不是 CodeWarrior 附带的版本)中?
标签: c gcc assembly arm compiler-optimization