|
Про IAR компилятор С |
|
|
|
Feb 6 2007, 14:45
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425

|
Здравствуйте. Раньше никогда на C под железо не писал, только на ассемблере. Но жизнь показывает, что для ARM писать все на asm не актуально. Начал смотреть, какой код генерирует компилятор. Вот для примера две строки на C: Код for(waiting_time = 1999; waiting_time >= 0; waiting_time--);
for(waiting_time = 0; waiting_time <= 2000; waiting_time++); Обе эти строки эквивалентны с точки зрения выполнения программы на С (т.е. будет 2000 шагов). Компилятор генерирует следующий код: \ main: \ ??main_0: \ 00000000 CF00A0E3 MOV R0,#+207 \ 00000004 700E80E3 ORR R0,R0,#0x700 \ 00000008 000000EA B ??main_1 \ ??main_2: \ 0000000C 010040E2 SUB R0,R0,#+1 \ ??main_1: \ 00000010 000050E3 CMP R0,#+0 \ 00000014 FCFFFF5A BPL ??main_2 19 20 //AT91C_BASE_PIOB->PIO_CODR = 1 << 22; 21 for(waiting_time = 0; waiting_time < 2000; waiting_time++) ; \ 00000018 0000A0E3 MOV R0,#+0 \ ??main_3: \ 0000001C 7D0E50E3 CMP R0,#+2000 \ 00000020 F6FFFFAA BGE ??main_0 \ 00000024 010080E2 ADD R0,R0,#+1 \ 00000028 FBFFFFEA B ??main_3 Мне кажется, что выделенная строка явно лишняя, так как флаг нулевого значения выставляется и в предыдущей команде. Во-вторых, при декременте (в первом варианте) есть лишний переход. Таким образом, эквивалентность циклов на С достигнута искуственно. Возможно, это сделано специально (а возможно, человек пока способен генерировать все же лучший код)? Возможно, это где-то описанно или отключается?
|
|
|
|
|
Feb 6 2007, 15:08
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 2-03-06
Из: Минск
Пользователь №: 14 879

|
Поиграйтесь с настройками оптимизации. При различном уровне - будет различный код.
|
|
|
|
|
Feb 8 2007, 15:26
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Забавно, а у меня комилятор в обоих случаях сгенерил одно и то же: Код for (i=0; i<2000; i++) __no_operation(); for (i=1999; i>=0; i--) __no_operation();
for (i=0; i<2000; i++) 000195C4 E3A00E7D MOV R0, #0x7D0 __no_operation(); 000195C8 E1A00000 NOP for (i=0; i<2000; i++) 000195CC E2500001 SUBS R0, R0, #0x1 for (i=0; i<2000; i++) 000195D0 1AFFFFFC BNE 0x0195C8 for (i=1999; i>=0; i--) 000195D4 E3A00E7D MOV R0, #0x7D0 __no_operation(); 000195D8 E1A00000 NOP for (i=1999; i>=0; i--) 000195DC E2500001 SUBS R0, R0, #0x1 for (i=1999; i>=0; i--) 000195E0 1AFFFFFC BNE 0x0195D8 Это IAR 4.40, С++, максимальная оптимизация на скорость. Надо сказать, этот компилятор оставляет хорошее впечатление. А вообще лучше не лезть в дела компилятора, а заниматься более интересными вещами, то есть написанием программ. Проверять сгенерированный код надо только тогда, когда не хватает памяти или скорости. Иначе не останется времени на отдых :-)
|
|
|
|
|
Feb 8 2007, 16:02
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425

|
Цитата(scifi @ Feb 8 2007, 15:26)  Примерно о таком коде я и мечтал, если бы еще и NOP выкинуть... Если убрать пустую операцию, то весь цикл попадает под нож оптимизатора при максимальной оптимизации, во всех других режимах оптимизаци цикл сохраняет первозданное уродство с тремя переходами. Вопрос в том, что при желании сделать например, функцию Код SimpleDelay (long d) { for (;d!=0;d--);
} Этот самый Delay будет прямо зависить от режима оптимизации, и вообще улетит при максимальной. Следующий вопрос, а как-нибудь вообще можно объявить функцию на asm как inline? Или сделать макрос на asm для использования в C-коде?
|
|
|
|
|
Feb 8 2007, 17:28
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Dopler @ Feb 8 2007, 15:02)  Если убрать пустую операцию, то весь цикл попадает под нож оптимизатора при максимальной оптимизации Если писать правильно, то не попадает. Цитата(Dopler @ Feb 8 2007, 15:02)  Вопрос в том, что при желании сделать например, функцию Код SimpleDelay (long d) { for (;d!=0;d--); } Этот самый Delay будет прямо зависить от режима оптимизации, и вообще улетит при максимальной. А если так: Код SimpleDelay (long volatile d) { for (;d!=0;d--); } При разном уровне действительно возможно различное время выполнения, но можно ведь для этой конкретной функции выставить желаемый уровень оптимизации с помощью #pragma. Цитата(Dopler @ Feb 8 2007, 15:02)  Следующий вопрос, а как-нибудь вообще можно объявить функцию на asm как inline? Или сделать макрос на asm для использования в C-коде? В gcc вроде да, в IAR - точно нет. Про остальные не знаю.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 8 2007, 22:21
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425

|
Цитата(scifi @ Feb 8 2007, 20:49)  Попробуйте так:
#define DELAY(N) __asm("mov R0,#" #N "\nSUBS R0,R0,#1\nBNE .-4"); И при использовании такого макроса компилятор гарантированно не будет использовать R0 в своих целях? Что-то я ничего внятного в документации IAR по поводу INLINE ASSEMBLER не нашел, кроме того, что его лучше избегать.
|
|
|
|
|
Feb 9 2007, 12:36
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425

|
Цитата(scifi @ Feb 9 2007, 11:37)  Если я правильно понял, нужно получить малые задержки. Предлагаю для этих целей написать функцию на ассемблере и вызывать её из Си. Просто для совсем маленьких функций накладные расходы по вызову и передаче параметров неприятны. Если бы можно было бы функцию на asm сделать inline, было бы здорово.
|
|
|
|
|
Feb 9 2007, 13:13
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(scifi @ Feb 9 2007, 10:37)  Время выполнения кода зависит от модели процессора и задержек при доступе к памяти. Для процессора ARM7TDMI времена выполнения инструкций указаны в "ARM7TDMI Technical Reference Manual": И наличия MAM и наличия Кэш и эффективности работы оных а еще DMA захватит шину  . Короче, лучше навсегда выкиньте из головы желание узнать для более-менее современых контроллеров "точное" время исполнения чего-либо. Цитата(Dopler @ Feb 9 2007, 12:02)  Так #pragma optimize не позволяет повысить уровень оптимизации, что это за лажа такая? Изъясняйтесь конкретнее.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 9 2007, 14:40
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 23-04-05
Из: Таганрог
Пользователь №: 4 425

|
Цитата(zltigo @ Feb 9 2007, 13:13)  Цитата(Dopler @ Feb 9 2007, 12:02)  Так #pragma optimize не позволяет повысить уровень оптимизации, что это за лажа такая?
Изъясняйтесь конкретнее. Я имел в виду, что любимой избранной функции нельзя задать жестко уровень оптимизации. Т.е. нельзя написать какую-нибудь простенькую функцию, определить для нее максимальную оптимизацию и наслаждаться, при условии, что остальной проект выполнен без оптимизации.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|