【发布时间】:2019-09-04 01:09:00
【问题描述】:
当尝试处理 uint64 中的单个字节时,AVR gcc⁽¹⁾ 给了我一个奇怪的序言/尾声,而使用 uint32_t 编写的相同函数给了我一个 ret(示例函数是没有)。
为什么 gcc 会这样做?如何删除它?
You can see the code here, in Compiler Explorer.
⁽¹⁾ gcc 5.4.0 来自 Arduino 1.8.9 发行版,参数=-O3 -std=c++11。
源代码:
#include <stdint.h>
uint32_t f_u32(uint32_t x) {
union y {
uint8_t p[4];
uint32_t w;
};
return y{ .p = {
y{ .w = x }.p[0],
y{ .w = x }.p[1],
y{ .w = x }.p[2],
y{ .w = x }.p[3]
} }.w;
}
uint64_t f_u64(uint64_t x) {
union y {
uint8_t p[8];
uint64_t w;
};
return y{ .p = {
y{ .w = x }.p[0],
y{ .w = x }.p[1],
y{ .w = x }.p[2],
y{ .w = x }.p[3],
y{ .w = x }.p[4],
y{ .w = x }.p[5],
y{ .w = x }.p[6],
y{ .w = x }.p[7]
} }.w;
}
为uint32_t 版本生成的程序集:
f_u32(unsigned long):
ret
为uint64_t 版本生成的程序集:
f_u64(unsigned long long):
push r28
push r29
in r28,__SP_L__
in r29,__SP_H__
subi r28,72
sbc r29,__zero_reg__
in __tmp_reg__,__SREG__
cli
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
subi r28,-72
sbci r29,-1
in __tmp_reg__,__SREG__
cli
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
pop r29
pop r28
ret
【问题讨论】:
-
你的问题在哪里?
-
@DavidGrayson 我现在添加了它。
-
看起来像一些参数传递开销,因为 32 位 int 在寄存器中传递,但没有 64 位寄存器。但我不能肯定。
-
这些函数被很好地优化掉了,因为它们没有被使用。通过堆栈仅返回 64 位值,因此第二个函数在堆栈上分配 8 个字节。如果要删除此功能,请删除此功能。去掉优化选项就可以看到函数的完整实现了。
-
很难知道你在找什么。您的问题的答案很简单:(1)gcc 这样做是因为它的优化器不够强大,无法将
f_u64()减少为 NOP,并且(2)您可以通过删除函数来删除它或尝试将其实现为return x;。如果这些不是您要寻找的答案,也许您可以改写问题或在评论中详细说明?
标签: c++ arduino compiler-optimization avr avr-gcc