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

Странности при оптимизации

А есть ли возможность указать компилятору в данном конкретном примере какой-нибудь командой #cmdxxx НЕ ОПТИМИЗИРОВАТЬ например именно строчку где a=2; ?

#pragma optimize = none

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


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

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

Про "оптимизирующий" код линкер это достойно назаборной письменности.

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


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

Про "оптимизирующий" код линкер это достойно назаборной письменности.

 

К примеру, начиная с MSVC++ 7.0 линкер имеет опцию /ltcg - "link time code generation" и это позволяет "отодвинуть" вопрос о встраивании функции или использовании обычного вызова на этап линковки. Про это достаточно подробно Г.Саттер "Новые сложные задачи на С++", Вильямс, 2005 стр.164-174. Нечто подобное поддерживает компилятор от HP.

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


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

К примеру

К "примеру" Вы уже говорили:

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

А вот это:

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

уже не имеет нималейшего отношения ни к обсуждаемой "проблеме", ни к Вашим предыдущим словам. Не говоря уже о том, что это вполне бесполезный трюк, ибо не позволяет произвести сквозную оптимизацию "склееенного" кода, а только грошовую экономию вызова. Любой компилятор сделает СВОЮ работу по inline несораизмеримо лучше, при этом КОМПИЛЯТОР должен предавительно изменить calling conversion для тех функций которые предполагается потом возможно склеить.

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


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

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

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


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

Я не являюсь разрабочиком компиляторов и линкеров.
Я являюсь :)

 

Все вышесказанное привел только для иллюстрации того, что на сегодняшний день не только компилятор, но и линкер совместно оптимизируют генерируемый код.
Это не совсем точное высказывание :( Код может оптимизироваться на этапе линковки, но занимается этим не линкер, а все таки компилятор. И тот 'код', который оптимизируется, на самом делен не код, а промежуточное представление компилятора.

 

Это может кому-то нравится, а кому-то нет.
Вне зависимости от того, нравится это или нет, оптимизациями занимается компилятор, когда бы он не запускался :1111493779:

 

Пример: Hi-TECH PICC-18 Pro. Результатом независимой компиляции модуля (.c) является файл (.p1) с промежуточным представлением С'ной программы. На этапе сборки (линковки) они ВМЕСТЕ обрабатываются компилятором, который и генерит выходной код.

 

Другой пример: Intel C компилятор. Опция -ipo (или -fast) переводит компилятор в режим компиляции всей программы. При этом, компиляция собственно модулей (.c) производит .obj файлы, в которых НЕТ кода, зато есть секции с промежуточным представлением программы. На этапе линковки снова вызывается компилятор, который читает все это из .obj файлов и генерирует код (в виде одного .obj файла, на этот раз с кодом) который уже и отправляется линкеру.

 

Что касается опции 'MSVC++ 7.0 /ltcg' то сдается мне, что это не опция линкера, а опция ВСЕГО проекта, и подавать ее надо везде. Реализация (скорее всего) будет очень похожа на реализацию в Intel компиляторе

 

Единственная известная мне 'оптимизация' именно ЛИНКЕРА - это выкидывание неиспользуемых кодов и данных из исполняемого файла. Но у меня язык не повернется назвать это 'оптимизацией' :(

Изменено пользователем XVR

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


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

Вне зависимости от того, нравится это или нет, оптимизациями занимается компилятор, когда бы он не запускался :1111493779:
Не во всех компиляторах. В avr-gcc вызов линкера с опцией --relax приводит к замене пар call/ret на jmp, а jmp (там, где длина перехода позволяет) - на rjmp. Это вполне себе оптимизация и занимается ей именно линкер.

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


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

#pragma optimize = none

Спасибо. Это как раз и было нужно. А опять включить ?

Или можно поменять степень оптимизации на ходу?

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


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

Спасибо. Это как раз и было нужно. А опять включить ?

Или можно поменять степень оптимизации на ходу?

Вы двигаетесь в неправильном направлении. Правильно написанная программа должна работать при любом уровне оптимизации.

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


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

Вы двигаетесь в неправильном направлении. Правильно написанная программа должна работать при любом уровне оптимизации.

Согласен. Но в данном случае вы неправы. Бывают разные ситуации. Я, например в данном случае пытаюсь добиться результатов после дилетанта-программиста. Возможности переписать ВСЮ прогу просто нет, отключаю оптимизацию=прога не влазит в кристалл. Программист в прерываниях использует почти все модули и я исправляю ошибки доступа, что бы основная прога не вешалась. Так что в данном случае мой вопрос правилен.

Лично я пишу, правильно разбивая ресурсы/переменные и лично у меня проблем с оптимизацией не было.

Просто исправлять за кем-то - неблагодарное и трудное занятие. Но необходимое (в моём случае)

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


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

Ещё вопросик:

Например, компилятор HiTech предупреждает при:

while(1)  { .... }
while(1)  { .... }

типа warning: infinity loop, а вот ИАР не предупреждает, а молча делает... :)

Но это лирика...

 

У меня (в данном случае ИАР) ругается на переменные, когда я их обзываю volatile на то, что он не может просчитать их значение, т.к. не проинициализированы.

А инитить я их не хочу, т.к. эти переменные лежат в озу и должны быть валидны и просле ресета (я их инициализю отдельно, считая их CRC или анализируя флаг сброса по питанию)

Вот тут и грабли... (Опять повторю, прогу полностью переписать не cмогу(высшая математика), исправляю за самоучками :( )

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


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

DenisIV, а такой вариант объявления

__no_init volatile unsigned a, b, c;

не проходит? У меня IAR только "варнингами" ругается, но ошибок не выдает.

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


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

DenisIV, а такой вариант объявления

__no_init volatile unsigned a, b, c;

не проходит? У меня IAR только "варнингами" ругается, но ошибок не выдает.

Проходит,ошибок нет, вот по этому и спрашиваю, как обойти... Варнинги достали (>100) :(

Мож #pragma optimize =none ?

Ток я не знаю, как потом включить и будут ли варнинги дальше?

А у меня варнинг-указание на засаду в проге. Игнорировать и отключать не хочется... Потом можно 3 дня глюк ловить... И не поймать... :(

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


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

типа warning: infinity loop, а вот ИАР не предупреждает, а молча делает... :)

Но это лирика...

Это не лирика, это где-то у вас преднамеренно отключены предупреждения (Project->Options->C/C++ compiler->Diagnostics):
void Test()
{
    while(1) { __no_operation();}
    while(1) { __no_operation();}
}

Warning[Pe128]: loop is not reachable from preceding code D:\****\loader.cpp 75

У меня (в данном случае ИАР) ругается на переменные, когда я их обзываю volatile на то, что он не может просчитать их значение, т.к. не проинициализированы.
Давайте так: Есть непонятка, выкладываете код, выкладываете полный текст предупреждения на языке оригинала, будем смотреть.
volatile int a;
volatile int b;
volatile int c;
void Test()
{
    int Tmp = a;
    b = Tmp;
    Tmp = b;
    c = Tmp;
}

Done. 0 error(s), 0 warning(s) 

   \                                 In segment DATA_Z, align 4, align-sorted
     72          volatile int a;
   \                     a:
   \   00000000                      DS8 4
     73          volatile int b;
   \                     `b`:
   \   00000004                      DS8 4
     74          volatile int c;
   \                     c:
   \   00000008                      DS8 4

   \                                 In segment CODE, align 4, keep-with-next
     75          void Test()
     76          {
     77              int Tmp = a;
   \                     ??Test:
   \   00000000   0248               LDR         R0,??Test_1      ;; a
   \   00000002   0168               LDR         R1,[R0, #+0]
     78              b = Tmp;
   \   00000004   4160               STR         R1,[R0, #+0x4]
     79              Tmp = b;
   \   00000006   4168               LDR         R1,[R0, #+0x4]
     80              c = Tmp;
   \   00000008   8160               STR         R1,[R0, #+0x8]
     81          }
   \   0000000A   7047               BX          LR            ;; return
   \                     ??Test_1:
   \   0000000C   ........           DC32        a

Как видите, никакой ругани, делает все, как просилось.

Я могу предположить, что ругань выглядит так:

Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement D:\*****\loader.cpp 77
Но она означает вовсе не "не может проинициализировать", а "не определен порядок обращения к volatile-переменным". И вызывает его примерно такой код:
int a;
volatile int b;
volatile int c;
void Test()
{
    a = b + c;
}

И это предупреждение совершенно справедливо: стандарт позволяет компилятору изменять порядок вычисления подвыражений. А поскольку одно из свойств volatile-переменных состоит в том, что чтение может изменять ее значение (а таким свойством обладают многие sfr-регистры), то изменение порядка чтения двух volatile-переменных может привести к неожиданным для вас результатам. Поэтому для разрешения неоднозначности надо разделить чтения точками последовательности, т.е. ";" или оператором "запятая", введя временную переменную как я сделал в примере выше.

Но это лишь гадание.Если бы вы представили минимальный необходимый для воспроизведения ситуации код - вы бы получили более точный и быстрый ответ.

 

Варнинги достали (>100) :(
Поэтому бороться надо с их причиной, а не следствием.

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


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

Это не лирика, это где-то у вас преднамеренно отключены предупреждения (Project->Options->C/C++ compiler->Diagnostics)

Угу, и у тебя тоже :) не все включено, ибо еще, если мне не изменяет склероз, должено быть что-то типа Еxpression is constant.

while(1) { .... }

Вобще-то сие однозначно со всех точек зрения пишется так:

 
for(;; )  { .... }

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


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

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

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

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

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

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

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

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

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

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