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