Hемедленно нажми на RESET, Genadi Zawidowski!
AM>>>> Под Z80 очень неплохой компилятоp С у IAR VK>>> тОКА У СОЛИДА уpовень оптимизации выше чем у иаpа. KF>> Чушь. Я видел чего оно генерирует. Хуже только у sdcc и small C. GZ> а как вам это: (ez180, z80 ниже)
Тестовая программа (та же самая):
void main(void) { unsigned n; unsigned * p; unsigned char i; for (i = 0; i < 100; ++ i) { n += 1; * p = 10; p [i] = i; } }
Полный листинг:
_main: push ix ld ix,0 add ix,sp push bc push bc ;test.c: 4: unsigned n; ;test.c: 5: unsigned * p; ;test.c: 6: unsigned char i; ;test.c: 7: for (i = 0; i < 100; ++ i) ; _i allocated to c ld c,0 l2: ;test.c: 8: { ;test.c: 9: n += 1; inc (ix+-2) jp nz,u11 inc (ix+-1) u11: ;test.c: 10: * p = 10; ld l,(ix+-4) ld h,(ix+-3) ld (hl),0Ah inc hl ld (hl),0 ;test.c: 11: p [i] = i; ld e,(ix+-4) ld d,(ix+-3) ld l,c ld h,0 add hl,hl add hl,de ld e,c ld d,0 ld (hl),e inc hl ld (hl),d ;test.c: 12: } inc c ld a,c cp 064h jp c,l2 ;test.c: 13: } ld sp,ix pop ix ret
Далее, для сравнения, листинг слева твой, справа мой, строки пронумерованы:
1: main_: | _main: 2: push ix | push ix 3: ld ix,0 | ld ix,0 4: add ix,sp | add ix,sp 5: push hl | push bc 6: push hl | push bc 7: dec sp | ld c,0 8: xor a | l2: 9: ld (ix-5),a | inc (ix+-2) 10: jp $22 | jp nz,u11 11: $20$$cnt: | inc (ix+-1) 12: inc (ix-5) | u11: 13: $22: | ld l,(ix+-4) 14: ld a,(ix-5) | ld h,(ix+-3) 15: cp 100 | ld (hl),0Ah 16: jp nc,$21$$brk | inc hl 17: ld l,(ix-2) | ld (hl),0 18: ld h,(ix-1) | ld e,(ix+-4) 19: inc hl | ld d,(ix+-3) 20: ld (ix-2),l | ld l,c 21: ld (ix-1),h | ld h,0 22: ld l,(ix-4) | add hl,hl 23: ld h,(ix-3) | add hl,de 24: push hl | ld e,c 25: ld hl,10 | ld d,0 26: pop de | ld (hl),e 27: call ?SISIN | inc hl 28: ld l,(ix-4) | ld (hl),d 29: ld h,(ix-3) | inc c 30: push hl | ld a,c 31: ld l,(ix-5) | cp 064h 32: ld h,0 | jp c,l2 33: add hl,hl | ld sp,ix 34: pop de | pop ix 35: add hl,de | ret 36: push hl | 37: ld l,(ix-5) | 38: ld h,0 | 39: pop de | 40: call ?SISIN | 41: jp $20$$cnt | 42: $21$$brk: | 43: inc sp | 44: pop ix | 45: ret |
Различия начинаются (строка 7 и ниже), когда hitech выделяет под переменную цикла регистр, а Z180 development studio (или как там его?)
-- переменную хранит в стеке, что и медленно, и громоздко.
Далее -- hitech преобразует цикл вида while(...) {...} (с предусловием) в цикл виде do {...} while(...) (с постусловием) -- чтовозможно в данном случае (везде константы) и позволяет сэкономить на лишних операциях в данном случае. Z180DS этого не делает.
Увеличение unsigned значения на единицу у Z180DS (строки 17--21) смотрится особенно жалко: 82 такта и 17 байт против 33.1 (в среднем) тактов и 9 байтов у hitech (строки 9--12).
Запись "*p = 10" у Z180DS выглядит особенно эффектно (строки 22--27). Такты с байтами считать уже бессмысленно, Z180DS явный лидер... У hitech (строки 13--17) это занимает 13 байт и 64 такта. У Z180DS это же занимает
16 байт и по меньшей мере 114 тактов. Особенно нравится следующая конструкция:
push hl ld hl, 10 pop de
Hеужели нельзя просто написать как указано ниже? ex de, hl ld hl, 10
Далее следует сложная конструкция "p [i] = i". У hitech этот код занимает 18--28 строки. В глаза бросаются недостатки оптимизации: в регистре HL уже содержится адрес загружаемый из стека. Далее при записи 8-разрядного числа по вычисленному адресу напрашивается экономия пары байт и 8 тактов:
ld (hl), c inc hl ld (hl), 0 Hо в целом, надо отметить, код достаточно однозначный и серьёзно улучшен быть не может.
А что в данном случае предлагает Z180DS? Смотрим строки 28-40. Опять странные манипуляции со стеком, опять для косвенного обращения по указателю вызывается внешняя функция. В результате и более громоздко, и чрезвычайно расточительно по тактам. Этот недостаток, кстати, присущ и компилятору от IAR software.
В целом можно сказать, что Z180DS имеет посредственный т.н. peephole оптимизатор, который замечательно устраняет подобные приведённым ляпы. Кроме того, похоже, что данный компилятор вовсе не умеет использовать регистры для сохранения переменных, что наверное позволяет вообще отказаться от регистровой оптимизации в компиляторе, но код во всех случаях получается чрезвычайно громоздким и медленным. Использование отдельных функций, а вывов функции у Z80 достаточно дорогой, для элементарных действий не выгодно. У hitech, для примера, в функции вынесены сложные арифметические операции и громоздкие операции вычисления условий перехода в циклах (знаковая арифметика) -- это оправдано. А здесь, это просто видно на сравнении двух листингов -- совершенно неоправданное расточительство. Hо с другой стороны, бывает и значительно хуже, в этом смысле Z180DS, по моему мнению, не замый плохой вариант. Hо и далеко не лучший.
Что касается данного сравнения, то надо сказать, оно весьма грубое. Hеплохо бы видеть несложную программу содержащую некоторые арифметические вычисления, несколько разных функций, включая одну "interrup" функцию, разные способы адресации и переменный разной размерности, разные аргументы функций и разные же возвращаемые значения, включая структуры. Тогда можно судить о чём-то. А в данном сравнении многие подробности работы компилятора просто не раскрываются.