[英]Optimization of copying with an explicit byte order in arm-none-eabi-gcc
在用 C 为数据结构编写部分反序列化程序时,我需要一种读取 16 位和 32 位整数的方法。 鉴于此代码有可能被编译并用于可能不是小端字节序的体系结构,我决定编写辅助函数来显式解码小端字节序:
#include <stdint.h>
void read_16(uint8_t *data, uint16_t *value) {
*value = data[0] | (data[1] << 8);
}
void read_32(uint8_t *data, uint32_t *value) {
*value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
}
我很好奇这如何在原生小端架构上编译。 带有-mcpu=cortex-a9
和-Os
的arm-none-eabi-gcc
给出以下输出:
00000000 <read_16>:
0: e5d02001 ldrb r2, [r0, #1]
4: e5d03000 ldrb r3, [r0]
8: e1833402 orr r3, r3, r2, lsl #8
c: e1c130b0 strh r3, [r1]
10: e12fff1e bx lr
00000014 <read_32>:
14: e5903000 ldr r3, [r0]
18: e5813000 str r3, [r1]
1c: e12fff1e bx lr
问题:为什么优化器会简化为 32 位的加载然后存储而不是 16 位的原因,假设这样的操作是有效的,会更短更快,并且启用了大小优化?
具体来说,我希望read_16
有以下程序集:
ldrh r3, [r0]
strh r3, [r1]
bx lr
这似乎是一个错过的优化机会——如果你向函数引入一个临时的uint32_t
变量:
void read_16(uint8_t *data, uint16_t *value) {
// to the future maintainers: 'tmp' makes this function faster
uint32_t tmp = data[0] | (data[1] << 8);
*value = (uint16_t)tmp;
}
具有讽刺意味的是,您在 -O2 和 -O3 处获得了预期的版本:
ldrh r3, [r0] @ unaligned
strh r3, [r1] @ movhi
bx lr
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.