m68k-linux-gnu-gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
CFLAGS = -Wall -Werror -ffreestanding -nostdlib -O2 -m68000 -mshort
Я очень смущен, почему g cc генерирует такой (казалось бы) неоптимальный код для простого для l oop над константным массивом.
const unsigned int pallet[16] = {
0x0000,
0x00E0,
0x000E,
...
0x0000
};
...
volatile unsigned long * const VDP_DATA = (unsigned long *) 0x00C00000;
...
for(int i = 0; i < 16; i++) {
*VDP_DATA = pallet[i];
}
В результате:
296: 41f9 0000 037e lea 37e <pallet+0x2>,%a0
29c: 223c 0000 039c movel #924,%d1
2a2: 4240 clrw %d0
2a4: 0280 0000 ffff andil #65535,%d0
2aa: 23c0 00c0 0000 movel %d0,c00000 <_etext+0xbffc2c>
2b0: b288 cmpl %a0,%d1
2b2: 6712 beqs 2c6 <main+0x46>
2b4: 3018 movew %a0@+,%d0
2b6: 0280 0000 ffff andil #65535,%d0
2bc: 23c0 00c0 0000 movel %d0,c00000 <_etext+0xbffc2c>
2c2: b288 cmpl %a0,%d1
2c4: 66ee bnes 2b4 <main+0x34>
Моя главная проблема:
Почему бесполезный первый элемент сравнивается с 2b0
? Это никогда не ударит и никогда не разветвится. Он просто оказывается дублирующим кодом для первой итерации.
- Есть ли лучший способ написать этот простой-простой l oop такой, что g cc не произведет этот странный код?
- Есть ли какие-нибудь флаги / оптимизации компилятора, которыми я могу воспользоваться?
O3
просто развертывает l oop, что мне тоже не нужно, так как в этой части кода пробел важнее, чем скорость. - Может быть, я слишком скрупулезен, но я просто Я подумал, что это будет не самый сложный код для генерации. Я ожидал чего-то более похожего (вероятно, неправильно, но вы поняли):
lea pallet,%a0
movel #7,%d0
1:
movel %a0@+,c00000
dbra %d0,1
Я понял, что мне нужно быть немного более явным в своем коде, чтобы заставить его писать длинными кусками. Мой главный вопрос заключается в том, почему g cc не может понять мои намерения, т.е. я просто хочу отправить эти данные в этот адрес.
Еще одно наблюдение:
clrw %d0
→ andil #65535,%d0
→ movel %d0,c00000
. Почему бы просто не clrl
и двигаться?