почему "осторожно делать" лучше, чем "переходить на середину" в asm - PullRequest
3 голосов
/ 13 июля 2020

Я читал учебник, в котором описаны два способа перевода while l oop в машинный код:

//jump to middle
   goto test;
loop:
   body-statement
test:
   t = test-expr;
   if (t)
       goto loop;

и

//guarded do

t = test-expr;
if (!t)
   goto done;
loop:
   body-statement
   t = test-expr;
   if (t)
      goto loop;
done:

Я не знаю, зачем использовать второй подход, компилятор может оптимизировать начальный тест?

1 Ответ

1 голос
/ 13 июля 2020

Я не знаю, почему при использовании подхода secoond компилятор может оптимизировать начальный тест?

Вот как может выглядеть код asm / machine после компилятор завершает работу, используя C в качестве псевдокода для asm . (Бесполезно писать C таким образом.) После того, как мы перейдем к этому шагу, дальнейшая оптимизация / компиляция не происходит.

Фактически C вы должны просто написать while(t) или for(int i=0 ; i<n ; i++) как нормальный человек (идиоматия c C l oop), и пусть компилятор создает идиоматию c asm l oop (условная ветвь внизу). Для этого нужны компиляторы.

Связано: Почему циклы всегда компилируются в стиле «do ... while» (прыжок хвостом)?

Основной недостаток прыжков в середину заключается в том, что он добавляет дополнительный безусловный переход на всех путях прохождения функции. (Независимо от того, выполняет ли l oop нулевые итерации или нет).

Очистка теста перед первой итерацией, чтобы сделать if(run_at_all) do_loop, избежать этого скачка, дублируя тестовый код, вместо перехода к его единственная копия.

Иногда его можно оптимизировать: многие циклы имеют известное число отключений или, по крайней мере, известное ненулевое значение, если компилятор может доказать что-либо о t для первая итерация.

...