Скомпилированный код AtmelStudio: как оптимизировать компилятор

Для кода:

uint8_t count;

ISR(TIMER1_OVF_vect, ISR_NAKED)
{
    count++;
    reti();
}

Сгенерированная сборка:

--- F:\atmel-prj\compiler-test2\compiler-test2\Debug/.././compiler-test2.c -----
{
00000048  PUSH R1       Push register on stack 
00000049  PUSH R0       Push register on stack 
0000004A  IN R0,0x3F        In from I/O location 
0000004B  PUSH R0       Push register on stack 
0000004C  CLR R1        Clear Register 
0000004D  PUSH R24      Push register on stack 
    count++;
0000004E  LDS R24,0x0100        Load direct from data space 
00000050  SUBI R24,0xFF     Subtract immediate 
00000051  STS 0x0100,R24        Store direct to data space 
}
00000053  POP R24       Pop register from stack 
00000054  POP R0        Pop register from stack 
00000055  OUT 0x3F,R0       Out to I/O location 
00000056  POP R0        Pop register from stack 
00000057  POP R1        Pop register from stack 
00000058  RETI      Interrupt return 

Теперь, насколько я понимаю, можно исключить как минимум одну, а то и две пары push-pop:

  1. чтобы сохранить один push-pop, устраните r24, используя вместо него r0

    PUSH R1     Push register on stack 
    PUSH R0     Push register on stack 
    IN R0,0x3F      In from I/O location 
    PUSH R0     Push register on stack 
    CLR R1      Clear Register 
    count++;
    LDS R0,0x0100       Load direct from data space 
    SUBI R0,0xFF        Subtract immediate 
    STS 0x0100,R0       Store direct to data space 
    ...
    
  2. Обратите внимание, что ни один код не использует r1 для значения 0, поэтому используйте только r1 для всех целей.

    PUSH R1     Push register on stack 
    IN R1,0x3F      In from I/O location 
    PUSH R1     Push register on stack 
    CLR R1      Clear Register 
    count++;
    LDS R0,0x0100       Load direct from data space 
    SUBI R0,0xFF        Subtract immediate 
    STS 0x0100,R0       Store direct to data space 
    ...
    

Любой из них экономит нам драгоценные байты и микросекунды.

Есть ли способ, которым я могу каким-то образом поместить эти или подобные оптимизации в цепочку инструментов/библиотеки atmel studio, чтобы мой скомпилированный код генерировался немного лучше?
Много кода, связанного с прерываниями и вызовами функций, а также некоторые переводы с языка C на ассемблер можно многое оптимизировать.


person GPS    schedule 12.11.2015    source источник
comment
Это для архитектуры Atmel AVR? gcc может ориентироваться на AVR. Это одна из доступных целей на gcc.godbolt.org. Я понятия не имею, насколько хорошо компилятор Atmel оптимизирует другой код и есть ли у него опции для включения оптимизации.   -  person Peter Cordes    schedule 12.11.2015
comment
У меня есть Atmel Studio 6, и, похоже, в нем есть компилятор gcc. В любом случае, спасибо за предложение, я посмотрю gcc для цели avr.   -  person GPS    schedule 12.11.2015
comment
Вы включили оптимизацию? Многие IDE по умолчанию используют какой-либо профиль для отладки с отключенной оптимизацией.   -  person Marco van de Voort    schedule 13.11.2015
comment
да. Это с -O3. -O1 тоже самое. Также протестировано с отключенными параметрами отладки.   -  person GPS    schedule 14.11.2015
comment
В ответ на Питер, документация gcc на gcc.gnu.org/wiki/avr-gcc и документы, поставляемые с Atmel Studio, имеют одинаковый текст. Это должно быть одно и то же программное обеспечение. В любом случае, я вижу, что некоторые довольно очевидные оптимизации не были сделаны. Итак, либо я плохо понимаю генерацию кода и оптимизацию, либо в наборе инструментов не существует некоторых очевидных оптимизаций. Мой вопрос в первую очередь заключается в том, чтобы выяснить, можно ли каким-то образом изменить пролог и эпилог, построенные компилятором, без перевода всего моего собственного кода на ассемблер.   -  person GPS    schedule 14.11.2015


Ответы (1)


Я также обнаружил, что сгенерированный ассемблерный код можно оптимизировать. К тому времени я не использовал опцию -On. Я обнаружил, что код вызываемой функции (которая принимает параметр в регистре); копирует его в стек (чтобы сохранить чистую копию как «автоматическую» переменную C... что в большинстве случаев бесполезно) И, ДАЛЕЕ, копирует это значение обратно в исходный регистр !!! Тогда как этот регистр был только что прочитан ранее, и GCC должен это знать.

Если вы используете Atmel Studio с компилятором по умолчанию, которым является GCC, оптимизация вашего двоичного кода зависит от поведения цепочки инструментов (и, следовательно, параметров, указанных в его командной строке).

Чтобы получить наилучший результат, вы можете попытаться скомпилировать исходное дерево напрямую с помощью avr-gcc (чтобы установить параметры, которые Atmel Studio не может установить для вас).

Использование другой цепочки инструментов — еще один способ получить (теоретически) наилучшие результаты. В любом случае, я сомневаюсь, что какой-либо другой инструментарий даст (в целом) лучший результат, чем GCC.

person SKZ 81    schedule 14.01.2016
comment
Я, наверное, не слышал о clang к тому времени! Не уверен, что у clang есть бэкэнд AVR... - person SKZ 81; 07.06.2019