簡體   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