繁体   English   中英

在 arm-none-eabi-gcc 中使用显式字节顺序进行复制的优化

[英]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-Osarm-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM