jcxz 243 14 мая, 2019 Опубликовано 14 мая, 2019 · Жалоба Имеется код: ... if (n >= 4) continue; if ((u32)(j - pcv->min) > pcv->range) e |= 1u << FaultState::GF_volt << n; } while ((int)--n >= 0); После компиляции IAR_v7.80.4 с максимальной оптимизацией, Balanced, получаю: ... 000001C6 0x2D04 CMP R5,#+4 000001C8 0xBF3F ITTTT CC 000001CA 0x8899 LDRHCC R1,[R3, #+4] 000001CC 0xF8B3 0x9002 LDRHCC R9,[R3, #+2] 000001D0 0xEBA0 0x0009 SUBCC R0,R0,R9 000001D4 0x4281 CMPCC R1,R0 000001D6 0xBF3C ITT CC 000001D8 0xFA08 0xF005 LSLCC R0,R8,R5 000001DC 0x4302 ORRCC R2,R0,R2 000001DE 0x1E6D SUBS R5,R5,#+1 000001E0 0x1E7F SUBS R7,R7,#+1 000001E2 0x2D00 CMP R5,#+0 000001E4 0xF1AC 0x0C02 SUB R12,R12,#+2 000001E8 0xD5CB BPL.N ??ProcessAdcV_7 Видно, что вместо того, чтобы по адресу 0x1C8 поставить инструкцию BCS на адрес 0x1DE, компилятор использовал инструкцию IT. Интересно - почему так? Ведь цена инструкции BCS здесь будет меньше (потребуется меньше тактов в случае сработавшего перехода)? А в данном случае, процессор пропустит последующие 7 инструкций по условию CS. И это потребует намного больше тактов. Просто интересно.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 14 мая, 2019 Опубликовано 14 мая, 2019 · Жалоба 11 минут назад, jcxz сказал: Просто интересно.... Цитата The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors (Joseph Yiu): Third EditionIn many cases, the IT instruction can help improve the performance of program code significantly because it avoids some of the branch penalty, as well as reducing the number of branch instructions. For example, a short IF-THEN-ELSE program sequence that normally requires one conditional branch and an unconditional branch can be replaced by a single IT instruction. In some other cases, traditional branch methods can be better than the IT instruction because a conditional failed instruction in an IT instruction sequence will still take a cycle to run. So if you specified ITTTT <cond> and the condition failed due to the APSR value in run-time, it could be quicker to use a conditional branch (three cycles) than using IT instruction block (up to five cycles in this case, including the IT instruction itself). В случае коротких IT выигрыш есть, в вашем же случае выигрыша нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 14 мая, 2019 Опубликовано 14 мая, 2019 · Жалоба 3 минуты назад, adnega сказал: В случае коротких IT выигрыш есть, в вашем же случае выигрыша нет. Вот именно, я об этом. Поэтому и удивляюсь зачем IAR так делает? Даже не то что нет выигрыша, а даже есть проигрыш. Надо наверное в поддержку писать, ибо похоже на баг оптимизатора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 14 мая, 2019 Опубликовано 14 мая, 2019 · Жалоба А с оптимизацией speed что будет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба В 14.05.2019 в 20:07, VladislavS сказал: А с оптимизацией speed что будет? Проверил - то же самое. Те же 7 пропускаемых инструкций после условной IT. Только регистры другие. При оптимизации "size" количество условных команд (с префиксом) стало меньше, но баг тем не менее всё равно присутствует. Даже, пожалуй, усугубился: if (n >= VOLT_CH_MON_n) continue; 000001D4 0x2B04 CMP R3,#+4 000001D6 0xBF3F ITTTT CC 000001D8 0x88B9 LDRHCC R1,[R7, #+4] 000001DA 0xF8B7 0xE002 LDRHCC LR,[R7, #+2] 000001DE 0xEBA0 0x000E SUBCC R0,R0,LR 000001E2 0x4281 CMPCC R1,R0 if ((u32)(j - pcv->min) > pcv->range) e |= 1u << FaultState::GF_volt << n; 000001E4 0xD203 BCS.N ??ProcessAdcV_10 000001E6 0xF44F 0x5000 MOV R0,#+8192 000001EA 0x4098 LSLS R0,R0,R3 000001EC 0x4302 ORRS R2,R0,R2 } while ((int)--n >= 0); ??ProcessAdcV_10: (+1) 000001EE 0x1E5B SUBS R3,R3,#+1 000001F0 0xD5CB BPL.N ??ProcessAdcV_9 PS: Только заметил Ваше сообщение.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба К сожалению, мне трудно воспроизвести этот код, а так бы попробовал на крайней версии компилятора. Можно также посмотреть как тот же gcc с этим справится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба On 5/14/2019 at 5:35 PM, jcxz said: А в данном случае, процессор пропустит последующие 7 инструкций по условию CS. И это потребует намного больше тактов. Просто интересно.... А Вы попробуйте этот код побенчмаркать на настоящем МК. Только не в ОЗУ, а во флеше. Какой-нибудь акселератор доступа во флеш вполне может давать куда более вменяемые результаты при последовательном доступе, нежели при переходе. Возможно, именно некой среднепотолочной статистикой работы различных акселераторов в различных МК и обусловлено такое поведение оптимизатора. Возможно, кстати, что компиляция функции с модификатором __ramfunc изменит поведение оптимизатора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба 30 минут назад, VladislavS сказал: К сожалению, мне трудно воспроизвести этот код, а так бы попробовал на крайней версии компилятора. Не утруждайтесь: только что проверил на IAR-8.32.1 - результат точно тот же. Те же 7 команд. Что balanced что speed. Конечно 8.32.1 - не самый край, но всё же.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба Да я и не утруждаюсь, просто любопытство. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба 19 минут назад, Rst7 сказал: А Вы попробуйте этот код побенчмаркать на настоящем МК. Только не в ОЗУ, а во флеше. Какой-нибудь акселератор доступа во флеш вполне может давать куда более вменяемые результаты при последовательном доступе, нежели при переходе. Возможно, именно некой среднепотолочной статистикой работы различных акселераторов в различных МК и обусловлено такое поведение оптимизатора. Я считал, что штатные 4 условные инструкции (включённые в возможности инструкции IT) уже как раз и включают особенности работы усреднённого кеша инструкций. Да и если просто взять: 144МГц(макс.тактовая ядра)/30МГц(частота флешь?) = ~4.8 инструкций - как раз примерно соответствует возможностям команды IT. Т.е. - при кеш-промахе (переходе) потребуется ~5 тактов на чтение новой порции кода, а не 7. Цитата Возможно, кстати, что компиляция функции с модификатором __ramfunc изменит поведение оптимизатора. Не изменяет. Проверил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба 1 час назад, VladislavS сказал: К сожалению, мне трудно воспроизвести этот код, а так бы попробовал на крайней версии компилятора. Можно также посмотреть как тот же gcc с этим справится. Если ещё интересно - я выхолостил функцию. Так что она должна компилиться без привязки к остальной программе. Вот её код: Спойлер u32 Z1() { enum {VOLT_CH_n = 5}; struct VoltCfg { u16 scale; //масштабирующие коэфф. для приведения данных АЦП к напряжению в V/VOLT_PNT в формате UQ12.20 u16 min, range; //ADC_VOLT_..._MIN, ADC_VOLT_..._MAX - ADC_VOLT_..._MIN } static const voltCfg[VOLT_CH_n] = { {0x7FFF, 0x100, 0x1010}, {0x7F3F, 0x112, 0x1450}, {0x7F56, 0x101, 0x1023}, {0x7012, 0x140, 0x1440}, {0x7342, 0x103, 0x1555}}; static u8 const toAdcVolt[VOLT_CH_n] = {34, 36, 24, 18, 10}; u32 j, e = 0; VoltCfg const *pcv = &voltCfg[0] + VOLT_CH_n; u32 const *p = (u32 *)0x20004000; u32 const *pa = (u32 *)0x20001230; u32 *pc = (u32 *)0x20005600; u16 *pr = (u16 *)0x20002200; uint n = VOLT_CH_n - 1; do { u64 q = (j = *p++) * 2 * (u64)(1 << 15); pc[n] = j += *(u16 *)((u8 *)pa + toAdcVolt[n]) - (u32)(q >> 32) - ((u32)q >> 31); q = j * 2 * (u64)(1 << 15); j = __USAT((u32)(q >> 32) + ((u32)q >> 31), 16) * (--pcv)->scale; //результат - напряжение в V/VOLT_PNT в формате UQ12.20 *pr++ = j = j + (1u << 19) >> 20; if (n >= 4u) continue; if ((u32)(j - pcv->min) > pcv->range) e |= 1u << 13 << n; } while ((int)--n >= 0); return e; } При компиляции IAR_8.32.1 получаю тот же эффект - 7 условных инструкций после IT. Если интересно можете проверить на gcc. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amaora 25 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба GCC делает переход в этом месте. Второй блок ITT есть при Os и O2. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба 41 минуту назад, jcxz сказал: Если ещё интересно - я выхолостил функцию. Гляну, конечно, чуть позже. Для багрепорта это всё равно же надо было сделать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба 5 минут назад, amaora сказал: GCC делает переход в этом месте. Второй блок ITT есть при Os и O2. Т.е. - для первого условия не лепит в один единый блок условного выполнения? Ну так и правильно по идее. 3 минуты назад, VladislavS сказал: Гляну, конечно, чуть позже. Для багрепорта это всё равно же надо было сделать. Чуть позже отправлю им багрепорт пожалуй. Они обещали в начале июня новую версию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amaora 25 27 мая, 2019 Опубликовано 27 мая, 2019 · Жалоба 35 minutes ago, jcxz said: Т.е. - для первого условия не лепит в один единый блок условного выполнения? Ну так и правильно по идее. cmp r4, #4 beq .L5 ldrh r9, [r6, #2] ldrh r2, [r6, #4] sub r3, r3, r9 cmp r3, r2 itt hi lslhi r3, r8, r4 orrhi r0, r0, r3 subs r4, r4, #1 adds r2, r4, #1 mov r3, r4 beq .L8 .L3: add r3, r3, lr ldrb r3, [r3, #32] @ zero_extendqisi2 ldrh r9, [r6, #-6] b .L2 .L5: movs r3, #3 mov r4, r3 b .L3 Это -O2. cmp r2, #4 beq .L2 ldrh r9, [r4, #26] sub r3, r3, r9 ldrh r9, [r4, #28] cmp r3, r9 itt hi lslhi r3, r8, r2 orrhi r0, r0, r3 .L2: subs r2, r2, #1 adds r3, r2, #1 sub r4, r4, #6 bne .L4 А это -Os. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться