LINUX.ORG.RU

История изменений

Исправление wandrien, (текущая версия) :

Но даже так, для цикла можно выделять регистры, а при вызове функций внутри цикла сохранять их в память а при выходе восстанавливать. Это лучше чем постоянно читать/писать память.

Ну это естественный ход улучшения программы:

  • Простейший кодогенератор вообще ничего не умеет оптимизировать и тупо использует один регистр для вычислений. Такое написать можно за день.
  • Потом мы учим его простейшим вещам, ну хотя бы константы более эффективно обрабатывать.
  • Потом учим всё более и более сложным.

В текущем виде функция, которые подбирает оптимальный способ вычисления выражения, учитывая возможность переупорядочивания операндов и содержимого регистров, уже выглядит как адок на 800 строк кода. Но зато творит чудесные вещи, с учётом того, что она вообще не пытается проанализировать программу в глубину, а тупо исходит из сохранённого состояния здесь и сейчас.

Ну и в итоге вот такой кусок исходника:

while P < nDICT do
  if Dict[P].Name.Hash != hash then
    P = Dict[P].pNext;
    continue;
...

Превращается во вполне осмысленный цикл:

@10499: 
        mov     EAX,  dword [EBP-8]
        cmp     EAX,  100000
        jae     @10500
                                         ; #line compiler_dict.qdi:199
        imul    EAX,  92
        mov     EDX,  dword [@@DATA+EAX+777192]
        cmp     EDX,  dword [EBP-4]
        je      @10503
                                         ; #line compiler_dict.qdi:200
        mov     ECX,  dword [@@DATA+EAX+777204]
        mov     dword [EBP-8], ECX
        jmp     @10499

И вот когда мы такое имеем, отсюда уже близко до распределения регистров с учётом более сложного контекста, нежели просто «текущая арифметическая операция». Вот сюда уже проще всунуть преаллокацию регистров по эвристикам анализа кода.

Исходная версия wandrien, :

Но даже так, для цикла можно выделять регистры, а при вызове функций внутри цикла сохранять их в память а при выходе восстанавливать. Это лучше чем постоянно читать/писать память.

Ну это естественный ход улучшения программы:

  • Простейший кодогенератор вообще ничего не умеет оптимизировать и тупо использует один регистр для вычислений. Такое написать можно за день.
  • Потом мы учим его простейшим вещам, ну хотя бы константы более эффективно обрабатывать.
  • Потом учим всё более и более сложным.

В текущем виде функция, которые подбирает оптимальный способ вычисления выражения, учитывая возможность переупорядочивания операндов и содержимого регистров, уже выглядит как адок на 800 строк кода. Но зато творит чудесные вещи, с учётом того, что она вообще не пытается проанализировать программу в глубину, а тупо исходит из сохранённого состояния здесь и сейчас.

Ну и в итоге вот такой кусок исходника:

while P < nDICT do
  if Dict[P].Name.Hash != hash then /* optimized for better code layout */
    P = Dict[P].pNext;
    continue;
...

Превращается во вполне осмысленный цикл:

@10499: 
        mov     EAX,  dword [EBP-8]
        cmp     EAX,  100000
        jae     @10500
                                         ; #line compiler_dict.qdi:199
        imul    EAX,  92
        mov     EDX,  dword [@@DATA+EAX+777192]
        cmp     EDX,  dword [EBP-4]
        je      @10503
                                         ; #line compiler_dict.qdi:200
        mov     ECX,  dword [@@DATA+EAX+777204]
        mov     dword [EBP-8], ECX
        jmp     @10499

И вот когда мы такое имеем, отсюда уже близко до распределения регистров с учётом более сложного контекста, нежели просто «текущая арифметическая операция». Вот сюда уже проще всунуть преаллокацию регистров по эвристикам анализа кода.