g cc: странный asm, сгенерированный для простого цикла - PullRequest
3 голосов
/ 16 марта 2020
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 %d0andil #65535,%d0movel %d0,c00000. Почему бы просто не clrl и двигаться?

1 Ответ

1 голос
/ 17 марта 2020

Я играл с G CC и генерацией 68k кода и обнаружил, что он просто больше не может генерировать приличный код для семейства 68k, особенно для 68000.

Код является едва ли правильным, но не оптимизированным (или я должен сказать, что он оптимизирован для DE?). Сначала вы должны попытаться использовать -Os вместо -O2. Даже в этом случае вы столкнетесь с множеством бесполезных insns в сгенерированном коде.

Я предполагаю, что хотя фактическая поддержка архитектур в G CC быстро продвигается вперед, бэкэнд для 68k не поддерживается должным образом, а просто сохраняется исправить с минимальными усилиями.

...