sigmaN 0 9 мая, 2017 Опубликовано 9 мая, 2017 · Жалоба #pragma inline=forced static void inline f(uint8_t i) { while(--i) asm(""); } int main() { f(10); } В результате: 183 int main() 184 { \ main: \ 000000 52 01 SUB SP, #0x1 186 f(10); \ 000002 35 0A .... MOV S:?b0, #0xa \ 000006 20 00 JRA L:??main_0 \ ??main_1: \ ??main_0: \ 000008 B6 .. LD A, S:?b0 \ 00000A 4A DEC A \ 00000B B7 .. LD S:?b0, A \ 00000D 26 F9 JRNE L:??main_1 ЗАЧЕМ? Зачем он делает всё это???? Настройки компилятора по полной программе: Multi-file compilation, High, Speed +No size constraints P.S. Cosmic же на много толковее справился, хотя я конечно по прежнему не понимаю почему нельзя просто с регистром A работать.... Зачем в стек то? 60 .text: section .text,new 61 0000 _main: 63 0000 88 push a 64 00000001 OFST: set 1 67 ; 10 f(12); 70 0001 a60c ld a,#12 71 0003 6b01 ld (OFST+0,sp),a 74 0005 L72: 75 ; 5 _asm(""); 79 ; 4 while(--i) 81 0005 0a01 dec (OFST+0,sp) 83 0007 26fc jrne L72 /////////////////////////////////////////////// 84 0009 L73: 86 0009 20fe jra L73 99 xdef _main 118 end Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 235 9 мая, 2017 Опубликовано 9 мая, 2017 · Жалоба Cosmic же на много толковее справился, хотя я конечно по прежнему не понимаю почему нельзя просто с регистром A работать.... Зачем в стек то? Оба облажались - результат компиляции такого "кода" должен полностью отсутствовать. :laughing: Да и не виноват тут компилятор, это косяки скорее оптимизатора. Думаю: STM8 - не особо важное семейство, поэтому и не парились особо с оптимизатором/компилятором. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Посмотрите, что из вашего кода делает sdcc, и успокойтесь:) Вот: (я только заменил asm("") на asm("nop"), для однозначности). ld a, #0x0a 00101$: dec a tnz a jrne 00116$ ret 00116$: nop jra 00101$ ret Вот, если интересно, сравнение компиляторов для stm8. По нему видно, что IAR далеко не лидер в области размера кода. Зато он побеждает в тестах скорости. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Грустно, потому что я в другом окне смотрю, что из этого кода делает avr-gcc( вариант с asm("nop") ) 00000048 LDI R24,0x09 Load immediate 00000049 NOP No operation 0000004A SUBI R24,0x01 Subtract immediate 0000004B BRNE PC-0x02 Branch if not equal Алсо не очень понятно, как IAR может быть при всех этих лишних телодвижениях быстрее........ Очень жаль, что разработчики компиляторов считают СТМ8 не важной архитектурой :( У меня еще есть пример как IAR весело тупит на куске С++ кода, где на этапе компиляции рекурсивно обходится список типов и вызывается функция. Так вот там аналогичным образом IAR просто делает одно и то-же: кладет в стек, грузит в А, кладет в стек, грузит в А.... В то время как GCC просто взял и прошелся одним значением по всем вызовам(ибо они реально не меняются и это известно во время компиляции). В общем печаль полнейшая с этим IAR.... Обидно, что кроме него плюсы никто не поддерживает больше. Sdcc снапшот от 9 мая sdcc -mstm8 --std-c99 --opt-code-size main.c вариант с asm(nop) функциa объявлена как static inline dly(char i); 000000 81 _dly: 82; main.c: 3: while(--i) 000000 7B 03 [ 1] 83 ld a, (0x03, sp) 000002 84 00101$: 000002 4A [ 1] 85 dec a 000003 4D [ 1] 86 tnz a 000004 26 01 [ 1] 87 jrne 00115$ 000006 81 [ 4] 88 ret 000007 89 00115$: 90; main.c: 4: __asm__("nop"); 000007 9D [ 1] 91 nop 000008 20 F8 [ 2] 92 jra 00101$ 00000A 81 [ 4] 93 ret 94; main.c: 7: void main(void) 95; ----------------------------------------- 96; function main 97; ----------------------------------------- 00000B 98 _main: 99; main.c: 3: while(--i) 00000B A6 0A [ 1] 100 ld a, #0x0a 00000D 101 00101$: 00000D 4A [ 1] 102 dec a 00000E 4D [ 1] 103 tnz a 00000F 26 01 [ 1] 104 jrne 00116$ 000011 81 [ 4] 105 ret 000012 106 00116$: 107; main.c: 4: __asm__("nop"); 000012 9D [ 1] 108 nop 000013 20 F8 [ 2] 109 jra 00101$ 110; main.c: 9: dly(10); 000015 81 [ 4] 111 ret ЗАИНЛАЙНИЛ БЛИН..... :( :( :( :( :( :( IAR при инлайне хоть тело функции догадывается убрать.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 235 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Грустно, потому что я в другом окне смотрю, что из этого кода делает avr-gcc( вариант с asm("nop") ) ... В общем печаль полнейшая с этим IAR.... Всё ясно, цель была - развести очередной холивар по мерянью пиписьками мелкоконтроллерами... :laughing: Тогда посмотрите что делает IAR for ARM с таким кодом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Цели никакой нет и холливара тоже. Просто обидно что хорошие по переферии и цене процы стм8 так и не имеют сравнимого с авр-гцц компилятора. И даже иар, который всегда был самым крутым, слился:( Я прям искренне удивился! И даже не поленился перепроверить и сравнить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба А как, по-вашему, должен выглядеть предложенный вами кусок? Покажите, интересно. Я вот сделал пару проектов с использованием sdcc, всё поместилось, всё успелось. Посмотрел в дизассемблер, улыбнулся. Всё выглядит как gcc -O0. Неиспользуемые функции не выкидываются. Ну и ладно. Многие и с gcc так работают, и не жужжат :) Кстати, сейчас вроде бы появился вариант LLVM+SDCC. Теоретически, там всё может быть получше. C++ опять же... Попробуете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 235 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Просто обидно что хорошие по переферии и цене процы стм8 так и не имеют сравнимого с авр-гцц компилятора Ну и что? Кому он реально нужен на этом ядре? Реально, а не для того чтоб "проверить". Чтобы решать какую-то вычислительную задачу, требующую серьёзных вычислений на этом ядре??? Для этого следует выбирать другое ядро. Ниша STM8 - помахать ножками немножко, поуправлять не спеша простой периферией. В случае чего в редких случаях можно и асм использовать. Да и рынок пользователей STM8 очень ограничен, это далеко не экосистема ARM - вот там реально нужны хорошие оптимизаторы, и туда и следует прикладывать максимум усилий, и сообщество пользователей там несравнимо больше. И работы по оптимизатору там ещё - море. Нефиг ресурсы разработчиков понапрасну распылять. :) PS: А "реально нужен" следует ещё читать и как "кто готов за это заплатить деньги". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Выглядеть этот кусок может и должен в точности как сделал авр-гцц: кладем в А число итераций-1, тело цикла, dec А далее условный переход на начало тела цикла(jrne метка). Все данные для такого преобразования у компилятора имеются, что гцц и продемонстрировал. LLVM надо конечно попробовать, но учитывая присутствие в связке sdcc...надежды мало:) Я конечно не готов платить и использую триал версию IAR, но просто перенести мои наработки с авра на стм8 в полном объёме не получится и это печально. Придется опять на голый си и писать все "в одну функцию" ибо оно даже заинлайнить толково не может однократно вызываемую статик функцию.... я молчу уже про плюсы, где тоже есть явные недоработки оптимизатора:( опять же есть с чем сравнивать, хоть меня и обвинят в холливаре. Причины наверно понятны, я конечно не могу оценить объем работ объективно, но что-то прям так и подсказывает, что ИАР просто самую малость не допилили. Вот реально чууть-чуть осталось им и всё было бы круто! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Выглядеть этот кусок может и должен в точности как сделал авр-гцц: кладем в А число итераций-1, тело цикла, dec А далее условный переход на начало тела цикла(jrne метка). Дело в том, что любое непустое тело цикла почти гарантированно испортит аккумулятор. Вероятно поэтому IAR сразу располагает переменную цикла в ОЗУ. И вообще, судить об оптимизации по тому, как компилятор заоптмизировал пустой цикл - по меньшей мере странно. К тому же, надо ещё посчитать по тактам, какой вариант выгоднее. Вполне возможно, что IAR при большем числе команд выигрывает в скорости. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Тоже потом подумал про испорченный A. Однако же никто не отменял direct indexed sp based адресацию, с которой в один такт может работать dec и jrne тоже сработает. В любом случае то, что делает IAR - это самый ужас, ибо там лишние действия по загрузке/выгрузке A выполняются каждую итерацию! Да, этот пример с пустым циклом он простой и показательный, хотя не претендует на полную объективность. Привести примеры, где происходит просто куча лишних движений не сложно. Опять же: гцц в случае с коротким циклом ума хватает, что такой-то регистр не затирается и его можно испоьзовать. Сделать цикл по-больше и стратегия изменится. Он полезет в стек тоже, а куда денется. Но в этом случае заметно, что компилятор(и его разработчики) стараются ))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 235 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Придется опять на голый си и писать все "в одну функцию" ибо оно даже заинлайнить толково не может однократно вызываемую статик функцию.... Заинлайнить при каком уровне оптимизации? При уровнях оптимизации ниже High он как бы и не обязан (см. мануал). Да этот пример с пустым циклом он простой и показательный. Привести примеры где происходит просто куча лишних движений не сложно. Приведите лучше пример реализации БИХ-фильтра для разных компиляторов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Приведите лучше пример реализации БИХ-фильтра для разных компиляторов biggrin.gif Проверено на вполне боевой реализации void fir_mem16() из https://github.com/xiph/speex/blob/master/libspeex/filters.c из Speex Взято как средний случай обычного фильтра на Си, без особых оптимизаций там и всего прочего. Согласен, чистота эксперимента нарушена, т.к. это КИХ фильтр ))))) Но переделывать уже не охота ) Удивительно, но при раздутом размере IAR по тактам таки победил 19498 тактов у IAR 19929 Cosmic Оба последних версий, у обоих оптимизация на скорость включена по максимуму. Added: Мужики, ну я не удержался и скомпилил это на AVR-GCC 6.3.0 10708 тактов оптимизация -O3 Да-даа, я знаю что это разные архитектуры и сравнивать вот так в лоб нельзя, но я просто оставлю эти цифры здесь )))))) полный код теста: #include <stdint.h> typedef int16_t spx_int16_t; typedef uint16_t spx_uint16_t; typedef int32_t spx_int32_t; typedef uint32_t spx_uint32_t; #define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ #define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ #define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ #define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ #define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */ #define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */ #define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ typedef spx_int16_t spx_word16_t; typedef spx_int32_t spx_word32_t; typedef spx_word32_t spx_mem_t; typedef spx_word16_t spx_coef_t; typedef spx_word16_t spx_lsp_t; typedef spx_word32_t spx_sig_t; #define Q15ONE 32767 #define LPC_SCALING 8192 #define SIG_SCALING 16384 #define LSP_SCALING 8192. #define GAMMA_SCALING 32768. #define GAIN_SCALING 64 #define GAIN_SCALING_1 0.015625 #define LPC_SHIFT 13 #define LSP_SHIFT 13 #define SIG_SHIFT 14 #define GAIN_SHIFT 6 #define VERY_SMALL 0 #define VERY_LARGE32 ((spx_word32_t)2147483647) #define VERY_LARGE16 ((spx_word16_t)32767) #define Q15_ONE ((spx_word16_t)32767) #define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) #define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) #define NEG16(x) (-(x)) #define NEG32(x) (-(x)) #define EXTRACT16(x) ((spx_word16_t)(x)) #define EXTEND32(x) ((spx_word32_t)(x)) #define SHR16(a,shift) ((a) >> (shift)) #define SHL16(a,shift) ((a) << (shift)) #define SHR32(a,shift) ((a) >> (shift)) #define SHL32(a,shift) ((a) << (shift)) #define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) #define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) #define SHR(a,shift) ((a) >> (shift)) #define SHL(a,shift) ((spx_word32_t)(a) << (shift)) #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) #define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b))) #define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b)) #define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b)) #define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b)) /* result fits in 16 bits */ #define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) /* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ #define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) #define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) #define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12)) #define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13)) #define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14)) #define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)) #define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))) #define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15)) #define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)) #define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))) #define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11))) #define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13))) #define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13))) #define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11)) #define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13)) #define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14)) #define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15)) #define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13)) #define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14)) #define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15)) #define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15)) #define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))) #define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))) #define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b))) #define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))) ////////////////// #define NVALUE 32 #define ORD 2 spx_word16_t x[NVALUE]; spx_coef_t num[ORD]; spx_word16_t y[NVALUE]; spx_mem_t mem[ORD]; void fir_mem16(const spx_word16_t *x, const spx_coef_t *num, spx_word16_t *y, int N, int ord, spx_mem_t *mem, char *stack) { int i,j; spx_word16_t xi,yi; for (i=0;i<N;i++) { xi=x[i]; yi = EXTRACT16(SATURATE(ADD32(EXTEND32(x[i]),PSHR32(mem[0],LPC_SHIFT)),32767)); for (j=0;j<ord-1;j++) { mem[j] = MAC16_16(mem[j+1], num[j],xi); } mem[ord-1] = MULT16_16(num[ord-1],xi); y[i] = yi; } } void main() { asm("nop"); //for brakepoints fir_mem16(&x[0], &num[0], &y[0], NVALUE, ORD, &mem[0], 0x0000); asm("nop"); //for brakepoints } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 1 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Посмотрите, что из вашего кода делает sdcc, и успокойтесь:) Это да. Никакой оптимизации, к сожалению. Но, учитывая то, что больше свободных компиляторов под STM8 нет, приходится пользоваться им. Хоть что-то… Правда, мне больше нравятся STM32. Но и там не все так хорошо: "изкоробочная" сборка arm-none-eabi-gcc не работает с F0 (операции умножения и деления вызывают зависон), приходится брать готовую сборку. А еще надо от opencm3 полностью уйти на "голый CMSIS" для STM32F1. Под F0 я уже от библиотек ушел. Надо лишь с USB разобраться... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Cosmic для стм8 нынче абсолютно свободен и без ограничений на размеры и период использования. IDE там очень убогая, так что использовать удобнее в симбиозе с ST Visual Develop, который интегрируется с космиком прямо из коробки(правда, мне пришлось путь прописать). http://www.st.com/en/development-tools/stvd-stm8.html Космик брать тут: www.cosmic-software.com/download.php sdcc, к сожалению, еще совершенно не готов! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться