Перейти к содержанию
    

Переупорядочивание инструкций

2 минуты назад, jcxz сказал:

А зачем? В чём вред от того, что внутрь этой последовательности внедрилась посторонняя инструкция?

Вред... Да нет вреда. Просто по моему субъективному мнению, логично было бы не тасовать так инструкции.
Объективно же - только разработчикам компилятора и механизмов оптимизатора известно, чем выгодно иное.

Искать решение, скорее всего, не нужно. Мне было интересно, зачем так делает оптимизатор и можно ли на это повлиять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, Arlleex сказал:

Искать решение, скорее всего, не нужно. Мне было интересно, зачем так делает оптимизатор и можно ли на это повлиять.

Может и можно, но раз разницы нет, то лучше - забить. Есть куда более интересные моменты оптимизации... и - полезные! :wink:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сходу тяжело придумать какой-то осмысленный случай, когда инструкции, не относящиеся к модификации регистров, будут портить малину... Но внутренняя чуйка подсказывает, что все-таки такие ситуации есть. Ну, пример (очень притянутый за уши, костыльный и фекальный): есть какой-нибудь у нас драйвер светодиодов, который управляется хитрыми последовательностями импульсов. МК только и делает, что эти импульсы на ножке формирует. Все ножки заняты, вход драйвера управляется от обычного GPIO и ничего не остается делать, как рулить ногодрыгом. Причем длительность импульсов управления примерно около периода тактовой синхронизации модуля GPIO МК. Вот и пишем некую последовательность установки/сброса пина. Но тут бац - и какая-то зараза (как в моем примере MOVW) из ближайших окрестностей кода встряла в промежутке между сменой уровня на пине. Вот и уехала времянка, бери да пиши на асме, разве что теперь.

Банально, надумано, но пример же:smile:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, Arlleex сказал:

Вот и уехала времянка, бери да пиши на асме, разве что теперь. Банально, надумано, но реально:smile:

В таких крайних случаях так и следует делать.

PS: Боюсь - сейчас набегут местные асмофобы, проклянут и закидают камнями.  :secret:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Arlleex сказал:

Банально, надумано, но пример же:smile:

Приведу более жизненный пример (не совсем про "Переупорядочивание инструкций", скорее про "Переупорядочивание функций", но всё-же...):

Имеем 2 функции:

void f1()
{
  ...
}
void f2()
{
  ...
  f1();  
}

В таком случае оптимизатор IAR (при возможности) в f2() заменяет вызов f1() + возврат из функции, на простой безусловный переход на f1(). Что конечно-же гуд.

Но! Если расположить тело f2() перед f1(), то IAR делает ещё лучше:

void f2()                                                     
{                                                             
  __DSB();                                                    
        _Z2f2v: (+1)                                          
 0xF3BF 0x8F4F      DSB                                       
  __ISB();                                                    
 0xF3BF 0x8F6F      ISB                                       
  f1();                                                       
                    REQUIRE _Z2f1v                            
                    ;; // Fall through to label f1()          
}                                                             
                                                              
void f1()                                              
{                                                             
  __DSB();                                                    
        _Z2f1v: (+1)                                          
 0xF3BF 0x8F4F      DSB                                       
  __ISB();                                                    
 0xF3BF 0x8F6F      ISB                                       
}                                                             
 0x4770             BX       LR               ;; return       

 Инструкции перехода больше нет. Отлично!  :good2:

Но почему компилятор не делает это всегда, самостоятельно переставляя функции в более оптимальном порядке??? Ведь это же ему ничего не стоит (нет противопоказаний). Да и реализовать такое думаю не сложно.

Тем не менее - ему требуется волшебный пендель от программиста.  :sad:

 

PS: Интересно - а есть какие другие компиляторы, умеющие производить подобную оптимизацию (перестановку функций)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, jcxz сказал:

PS: Интересно - а есть какие другие компиляторы, умеющие производить подобную оптимизацию (перестановку функций)?

Есть, например, gcc. У него есть опции, контролирующие это поведение:

Цитата

-fno-toplevel-reorder

Do not reorder top-level functions, variables, and asm statements. Output them in the same order that they appear in the input file. When this option is used, unreferenced static variables are not removed. This option is intended to support existing code that relies on a particular ordering. For new code, it is better to use attributes when possible.

 

-ftoplevel-reorder is the default at -O1 and higher, and also at -O0 if -fsection-anchors is explicitly requested. Additionally -fno-toplevel-reorder implies -fno-section-anchors.

Но иногда это вредно, т.к. не позволяет выполнять такие трюки:

#include <stdint.h>

int function() {
    return 0;
}

int function_end() {
    return 0;
}

int main(void) {
    intptr_t size = (intptr_t) function_end - (intptr_t) function;
}

При этом если будет выполнена перестановка порядка функций, то правильного результата естественно не получить.

PS: На сколько мне известно в стандарте порядок размещения функций жёстко не определен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, AlexRayne сказал:

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

Компилятор может многое. В том числе и сделать слияние, фактически заинлайнив одну функцию в другую, а потом продублировать тело функции для обеспечения успешного разрешения внешних ссылок на эту функцию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в моей практике приходилось заставлять инлайнить. причем на максимальных оптимизациях и иар и гцц.

помог только макрос-дефайн.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На сколько я понимаю, автоматически инлайнятся только небольшие функции, объявленные в модуле как static. Возможно у Вас проблема была в этом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В ARM Compiler 6 тоже такое наблюдал. Но вот прям сходу не смог заставить его повторить.
Он мне короткие тела функций сразу встраивает, подобно inline-функциям. Оптимизация -Os balanced.

P.S. Вроде, повторил. Причем размещать функции можно в любом порядке - результат один (на -Os balanced).
P.S. Интересно, что на -O1 вызов f1() из f2() делается через B (переход по метке) вне зависимости от расположения функций.
P.S. Все-таки, предыдущий тезис относится не только к -O1, но и к -Os balanced (и ко всем остальным уровням, кроме -O0).
P.S. Не, нифига. У ARM Compiler 6 дофига опций: --no_branchnop и --tailreorder как раз для этого. Правда между f1() и f2() NOP вставляется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, makc сказал:

На сколько я понимаю, автоматически инлайнятся только небольшие функции, объявленные в модуле как static. Возможно у Вас проблема была в этом.

нет, мой инлайн состоял из одной строкии - лукап массива по индексу.

почему он его не заинлайнил? упоролся бодаться, но так и не совладал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 часов назад, makc сказал:

Есть, например, gcc. У него есть опции, контролирующие это поведение:

Это вызывает уважение!  :wink:

 

9 часов назад, AlexRayne сказал:

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

А как это может помешать слиянию? Возможность взятия адресов функцию вроде не должна никак зависеть от слиябельности функций.

 

9 часов назад, AlexRayne сказал:

в моей практике приходилось заставлять инлайнить. причем на максимальных оптимизациях и иар и гцц.

Иногда сложнее заставить не инлайнить. Вот где засада! По-крайней мере в IAR....  :russian_ru:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 hours ago, Arlleex said:

Мне было интересно, зачем так делает оптимизатор и можно ли на это повлиять.

Возможно заполняет дырки в пайплайне (обращение в память требуют больше тактов, и если не вставить что нибудь после неё, то процессор просто сам вставит туда nop). Так что влиять на это не стоит - результат будет совсем не таким, какой вы ожидаете

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, jcxz сказал:

Иногда сложнее заставить не инлайнить. Вот где засада! По-крайней мере в IAR....

а какая тут может быть проблема?

если функция не static, по прямо таки интересно - когда он её заинлайнит? 

и зачем с этим бороца?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...