Снял слепки с Avoset, sdcc, z88dk. В ближайшее время попробую проанализировать и их код. У кого еще какие компилеры завалялись?
Вид для печати
Снял слепки с Avoset, sdcc, z88dk. В ближайшее время попробую проанализировать и их код. У кого еще какие компилеры завалялись?
Что заметно дешевле KEIL. Так что как сказать...Цитата:
Сообщение от jdigreze
Hitech могу дать.Цитата:
Сообщение от caro
Итак, препарируемый- Avocet. Этот компилятор не понял старого синтаксиса теста (см. заголовки функций), поэтому пришлось слегка его подработать напильником.
Вот что он нагенерил (лишние директивы вырезаны).
0.Пролог
1.Размножение констант и копийКод:;не суть важно, все равно один раз делается...
push ix
push de
push hl
ld ix,-?TSC0
add ix,sp
push af
2.Свертка константКод:ld hl,2
ld (_j4),hl
;лишняя операция
ld de,(_j4)
ld hl,(_i2)
and a
;использование нативных операций- плюс в копилку
sbc hl,de
;хитровымудренная система переходов- жирный минус
jp p,$+8
jp pe,?BOL0
jr +3
jp po,?BOL0
?ACC0: .equal $
ld de,(_j4)
ld hl,(_i4)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL0
jr +3
jp po,?BOL0
?PLC0: .equal $
ld hl,2
ld (_i2),hl
?BOL0: .equal $
;короче, никаких размножений констант не применяется
;и этот кусок- практически полная копия предыдущего
ld hl,(_k5)
ld (_j4),hl
ld e,l
ld d,h
ld hl,(_i2)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL1
jr +3
jp po,?BOL1
?ACC1: .equal $
ld de,(_j4)
ld hl,(_i4)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL1
jr +3
jp po,?BOL1
?PLC1: .equal $
ld hl,3
ld (_i5),hl
?BOL1: .equal $
3.Лишнее присваиваниеКод:;благополучно свернул целочисленные константы
ld hl,3
ld (_i3),hl
.const_data
?CGL0: .double 8.69999999999999930000
.program
;также свернул дробную
ld de,?CGL0
ld hl,_flt_1
call __store_double
;просто константа
ld hl,5
ld (_i2),hl
;а это убожество...
ld de,0
ld hl,(_i)
add hl,de
ld (_j2),hl
;здесь не сообразил что на 1 делить не надо...
ld de,1
ld hl,(_i)
call __div_int
ld (_k2),hl
;да и умножать тоже...
ld de,1
ld hl,(_i)
call __mult_int
ld (_i4),hl
;а это вообще хохма
ld de,0
ld hl,(_i)
call __mult_int
ld (_i5),hl
;и на 0 мы делить тоже умеем! :)
;как целочисленно...
ld de,0
ld hl,(_i)
call __div_int
ld (_i2),hl
.const_data
?CGL1: .double 0.0
.program
;...так и с плавающей запятой
ld de,?CGL1
ld hl,_flt_1
call __div_double
ex de,hl
ld hl,_flt_2
call __store_double
.const_data
?CGL2: .double 2.39999999999999990000
.program
;вот деление константы на константу он свернул
ld de,?CGL2
ld hl,_flt_3
call __store_double
.const_data
?CGL3: .double 1.00000010000000010000
.program
;сложение тоже
ld de,?CGL3
ld hl,_flt_4
call __store_double
.const_data
?CGL4: .double 0.0
.program
;но вот умножение на 0 не догадался облагородить
ld de,?CGL4
ld hl,_flt_6
call __mult_double
ex de,hl
ld hl,_flt_5
call __store_double
;ничего интересного
ld de,_flt_3
ld hl,_flt_2
call __mult_double
ex de,hl
ld hl,_flt_6
call __store_double
4.Снижение мощностиКод:;за такое надо руки отрывать...
ld hl,1
ld (_k3),hl
ld hl,1
ld (_k3),hl
5.Простой циклКод:;никакой фантазии...
ld de,(_j5)
ld hl,4
call __mult_int
ld (_k2),hl
ld hl,0
ld (_i),hl
?FLC2: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
;опять сложная система переходов
jr z,+11
jp p,$+8
jp pe,?BOL2
jr +3
jp po,?BOL2
jp ?FLB2
?FLA2: .equal $
;регистровые переменные не поддерживаются,
;по крайней мере здесь
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC2
?FLB2: .equal $
;это просто мрак...
ld de,2
ld hl,(_i)
call __mult_int
ld (ix+0),l
ld (ix+0+1),h
ld hl,(_i)
add hl,hl
ld bc,_ivector4
add hl,bc
ld e,l
ld d,h
;люди, не смотрите на это :)
ld l,(ix+0)
ld h,(ix+0+1)
push de
pop iy
ld (iy+0),l
ld (iy+1),h
jp ?FLA2
?BOL2: .equal $
6.Управление переменной индукции циклаКод:ld hl,0
ld (_j5),hl
ld hl,10000
ld (_k5),hl
?TOL3: .equal $
;просто ни ума, ни фантазии...
ld de,1
ld hl,(_k5)
and a
sbc hl,de
ld (_k5),hl
ld de,1
ld hl,(_j5)
add hl,de
ld (_j5),hl
ld de,3
ld hl,(_k5)
call __mult_int
ld (ix+0),l
ld (ix+0+1),h
ld de,5
ld hl,(_j5)
call __mult_int
ld e,l
ld d,h
ld l,(ix+0)
ld h,(ix+0+1)
call __div_int
ld (_i5),hl
?DCL3: .equal $
;просто верх кодерского разума- сравнение на 0...
ld de,0
ld hl,(_k5)
and a
sbc hl,de
jp z,?BOL3
jp p,$+8
jp po,?BOL3
jr +3
jp pe,?BOL3
?PLC2: .equal $
jp ?TOL3
?BOL3: .equal $
7. Глубокие подвыраженияКод:;достаточно приличный заголовок цикла
ld hl,0
ld (_i),hl
?FLC4: .equal $
ld de,100
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL4
jr +3
jp po,?BOL4
jp ?FLB4
?FLA4: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC4
?FLB4: .equal $
;а здесь начинаются страшные вычисления без каких
;бы то ни было следов оптимизации
ld de,2
ld hl,(_i)
call __mult_int
ld e,l
ld d,h
ld hl,3
add hl,de
add hl,hl
ld bc,_ivector5
add hl,bc
ld e,l
ld d,h
ld hl,5
push de
pop iy
ld (iy+0),l
ld (iy+1),h
jp ?FLA4
?BOL4: .equal $
8.Генерация адреса переменной с константным индексом, размножение копий и регистровКод:;без слов. все и так видно...
ld de,10
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL5
jr +3
jp po,?BOL5
?PLC3: .equal $
ld de,(_i2)
ld hl,(_i5)
add hl,de
ld (_j5),hl
jp ?EOI5
?BOL5: .equal $
ld de,(_i2)
ld hl,(_i5)
add hl,de
ld (_k5),hl
?EOI5: .equal $
9.Удаление общих подвыраженийКод:ld hl,_ivector+0
ld e,l
ld d,h
ld hl,1
;ребята наверное не знают про команду ld (hl),..
push de
pop iy
ld (iy+0),l
ld (iy+1),h
ld hl,(_i2)
add hl,hl
ld bc,_ivector
add hl,bc
ld e,l
ld d,h
ld hl,2
push de
pop iy
ld (iy+0),l
ld (iy+1),h
ld hl,(_i2)
add hl,hl
ld bc,_ivector
add hl,bc
ld e,l
ld d,h
ld hl,2
push de
pop iy
ld (iy+0),l
ld (iy+1),h
ld hl,_ivector+4
ld e,l
ld d,h
ld hl,3
push de
pop iy
ld (iy+0),l
ld (iy+1),h
10.Вынесение инвариантного кодаКод:ld de,(_k3)
ld hl,(_h3)
add hl,de
ld de,0
and a
sbc hl,de
jp p,$+8
jp po,?PLC4
jr +3
jp pe,?PLC4
?OCC2: .equal $
ld de,(_k3)
ld hl,(_h3)
add hl,de
ld de,5
and a
sbc hl,de
jp z,?BOL6
jp p,$+8
jp po,?BOL6
jr +3
jp pe,?BOL6
?PLC4: .equal $
.const_data
?PLC5: .byte "Common subexpression elimination",0ah,0
.program
ld hl,?PLC5
call _printf
jp ?EOI6
?BOL6: .equal $
;иными словами, никаких выделений не производится
ld de,(_k3)
ld hl,(_h3)
add hl,de
ld de,(_i3)
call __div_int
ld (_m3),hl
ld de,(_k3)
ld hl,(_h3)
add hl,de
ld e,l
ld d,h
ld hl,(_i3)
add hl,de
ld (_g3),hl
?EOI6: .equal $
Код:;приемлимое начало цикла
ld hl,0
ld (_i4),hl
?FLC7: .equal $
ld de,2
ld hl,(_i4)
and a
sbc hl,de
jr z,+11
;но его структура в коде просто ужасна!
jp p,$+8
jp pe,?BOL7
jr +3
jp po,?BOL7
jp ?FLB7
?FLA7: .equal $
ld hl,(_i4)
inc hl
ld (_i4),hl
jp ?FLC7
?FLB7: .equal $
;никакого вынесения нет- вычисления на каждой итерации
ld de,(_k)
ld hl,(_j)
call __mult_int
ld (ix+0),l
ld (ix+0+1),h
ld hl,(_i4)
ld bc,_ivector2
add hl,bc
ld e,l
ld d,h
ld l,(ix+0)
ld h,(ix+0+1)
ld a,l
ld (de),a
jp ?FLA7
11.Вызов функции с аргументами. Определение недостижимого кода
Код:.const_data
?PLC6: .byte "This line should not be printed",0
.program
;хоть тут никаких изысков, параметры в регистрах
ld de,?PLC6
ld hl,1
call _dead_code
12.Вызов функции без аргументов. Исключение цикловКод:_dead_code: .equal $
;страшный пролог!
push ix
push de
push hl
ld ix,-?TSC1
add ix,sp
push af
ld l,(ix+0+?TSC1)
ld h,(ix+0+?TSC1+1)
ld (ix-2),l
ld (ix-2+1),h
;страх и ужас!
ld a,0
cp a,0
jp z,?BOL8
?PLC7: .equal $
.const_data
?PLC8: .byte "%s",0ah,0
.program
ld e,(ix+2+?TSC1)
ld d,(ix+2+?TSC1+1)
ld hl,?PLC8
call _printf
?BOL8: .equal $
?BOF1: .equal $
;и не менее страшный эпилог
pop bc
pop bc
pop bc
pop ix
ret
Код:;как обычно, ничего никуда не передаем
call _unnecessary_loop
13. Слияние заголовков цикловКод:_unnecessary_loop: .equal $
push ix
ld ix,-?TSC2
add ix,sp
push af
;все тот же кошмарный пролог...
ld hl,0
ld (ix-2),l
ld (ix-2+1),h
ld hl,0
ld (_i),hl
?FLC9: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL9
jr +3
jp po,?BOL9
jp ?FLB9
?FLA9: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC9
?FLB9: .equal $
;постоянные вычисления, тут даже пресловутое
;примечание опускает руки :)
ld de,(_j5)
ld l,(ix-2)
ld h,(ix-2+1)
add hl,de
ld (_k5),hl
jp ?FLA9
?BOL9: .equal $
?BOF2: .equal $
pop bc
pop ix
ret
14.Разворачивание цикловКод:_loop_jamming: .equal $
push ix
push hl
ld ix,-?TSC3
add ix,sp
ld hl,0
ld (_i),hl
?FLC10: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL10
jr +3
jp po,?BOL10
jp ?FLB10
?FLA10: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC10
?FLB10: .equal $
ld de,(_i)
ld hl,(_j5)
call __mult_int
ld e,l
ld d,h
ld l,(ix+0+?TSC3)
ld h,(ix+0+?TSC3+1)
add hl,de
ld (_k5),hl
jp ?FLA10
?BOL10: .equal $
;никакого слияния плюс страшные вычисления
ld hl,0
ld (_i),hl
?FLC11: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL11
jr +3
jp po,?BOL11
jp ?FLB11
?FLA11: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC11
?FLB11: .equal $
ld de,(_k5)
ld l,(ix+0+?TSC3)
ld h,(ix+0+?TSC3+1)
call __mult_int
ld e,l
ld d,h
ld hl,(_i)
call __mult_int
ld (_i5),hl
jp ?FLA11
?BOL11: .equal $
?BOF3: .equal $
pop bc
pop ix
ret
15.Сжатие цепочки переходовКод:_loop_unrolling: .equal $
push ix
push hl
ld ix,-?TSC4
add ix,sp
ld hl,0
ld (_i),hl
?FLC12: .equal $
;разворота нет
ld de,6
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL12
jr +3
jp po,?BOL12
jp ?FLB12
?FLA12: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC12
?FLB12: .equal $
;да еще и вычисления страшные
ld hl,(_i)
;хоть не догадался умножать на 2 процедурой...
add hl,hl
ld bc,_ivector4
add hl,bc
ld e,l
ld d,h
ld hl,0
push de
pop iy
ld (iy+0),l
ld (iy+1),h
jp ?FLA12
?BOL12: .equal $
?BOF4: .equal $
pop bc
pop ix
ret
Итоговая оценка- 4/10. Поставил бы 3/10, да понравился достаточно легкий заголовок цикла.Код:_jump_compression: .equal $
push ix
push de
push hl
ld ix,-?TSC5
add ix,sp
.c_start 0ba1h,260
?beg_1: .equal $
ld e,(ix+2+?TSC5)
ld d,(ix+2+?TSC5+1)
ld l,(ix+0+?TSC5)
ld h,(ix+0+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL13
jr +3
jp po,?BOL13
?PLC9: .equal $
ld e,(ix+8+?TSC5)
ld d,(ix+8+?TSC5+1)
ld l,(ix+2+?TSC5)
ld h,(ix+2+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL14
jr +3
jp po,?BOL14
?PLC10: .equal $
ld e,(ix+10+?TSC5)
ld d,(ix+10+?TSC5+1)
ld l,(ix+8+?TSC5)
ld h,(ix+8+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL15
jr +3
jp po,?BOL15
?PLC11: .equal $
ld e,(ix+12+?TSC5)
ld d,(ix+12+?TSC5+1)
ld l,(ix+10+?TSC5)
ld h,(ix+10+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL16
jr +3
jp po,?BOL16
?PLC12: .equal $
ld e,(ix+12+?TSC5)
ld d,(ix+12+?TSC5+1)
ld l,(ix+10+?TSC5)
ld h,(ix+10+?TSC5+1)
add hl,de
ld (ix+10+?TSC5),l
ld (ix+10+?TSC5+1),h
jp ?EOI16
?BOL16: .equal $
;нет оптимизации
jp ?end_1
?EOI16: .equal $
jp ?EOI15
?BOL15: .equal $
ld e,(ix+10+?TSC5)
ld d,(ix+10+?TSC5+1)
ld l,(ix+8+?TSC5)
ld h,(ix+8+?TSC5+1)
add hl,de
ld (ix+8+?TSC5),l
ld (ix+8+?TSC5+1),h
?EOI15: .equal $
jp ?EOI14
?BOL14: .equal $
ld e,(ix+8+?TSC5)
ld d,(ix+8+?TSC5+1)
ld l,(ix+2+?TSC5)
ld h,(ix+2+?TSC5+1)
add hl,de
ld (ix+2+?TSC5),l
ld (ix+2+?TSC5+1),h
?end_1: .equal $
jp ?beg_1
?EOI14: .equal $
jp ?EOI13
?BOL13: .equal $
ld e,(ix+2+?T
;а дальше текст почемуто потерян...
Плюс данный компилятор распространяетя со средой разработки и отладки под винду. Опций настройки я не нашел- они задавались в настройках проекта, но в хелпе я нашел не все указанные опции. Про оптимизацию там не было сказано ни слова. Итого- это просто транслятор с примитивной сверткой констант (и только!). Выходной ассемблерный файл без указания строк исходного файла, весьма неудобно по нему лазить.
Короче, использовать не рекомендуется :)
Следующий кандидат- Small Device C Compiler
Испытания проводились с оптимизацией по размеру и по скорости- результат одинаковый.
0. Пролог.
1. Тест на размножение констант и копий.Код:;классика жанра для переменных в стеке
_main:
push ix
ld ix,#0
add ix,sp
2.Свертка константКод:;жирный-жирный минус- использование тяжелой
;артиллерии в виде индексных регистров
;test.c:59: j4 = 2;
ld iy,#_j4
ld 0(iy),#0x02
ld 1(iy),#0x00
;test.c:60: if( i2 < j4 && i4 < j4 )
;вот оно- распространение констант в действии!!!
ld iy,#_i2
;вместо вычитания j4 используется вычитание константы
ld a,0(iy)
sub a,#0x02
ld a,1(iy)
sbc a,#0x00
jp p,00102$
;аналогично вторая половина
ld iy,#_i4
ld a,0(iy)
sub a,#0x02
ld a,1(iy)
sbc a,#0x00
jp p,00102$
;test.c:61: i2 = 2;
;опять IY...
ld iy,#_i2
ld 0(iy),#0x02
ld 1(iy),#0x00
00102$:
;test.c:63: j4 = k5;
;ну почему загрузка сделана нормально, но сохранение
;так лажово?
ld hl,(_k5)
ld iy,#_j4
ld 0(iy),l
ld 1(iy),h
;test.c:64: if( i2 < j4 && i4 < j4 )
;просто страшная перезагрузка!!! нет использования
;предыдущего операнда в hl!!!
ld iy,#_i2
ld a,0(iy)
ld iy,#_j4
sub a,0(iy)
ld iy,#_i2
ld a,1(iy)
ld iy,#_j4
sbc a,1(iy)
jp p,00105$
;то же самое...
ld iy,#_i4
ld a,0(iy)
ld iy,#_j4
sub a,0(iy)
ld iy,#_i4
ld a,1(iy)
ld iy,#_j4
sbc a,1(iy)
jp p,00105$
;test.c:65: i5 = 3;
ld iy,#_i5
ld 0(iy),#0x03
ld 1(iy),#0x00
00105$:
3.Лишнее присваиваниеКод:;test.c:72: i3 = 1 + 2;
;свернул
ld iy,#_i3
ld 0(iy),#0x03
ld 1(iy),#0x00
;test.c:73: flt_1 = 2.4 + 6.3;
;вот здесь использование индексных регистров можно
;оправдать, да и то с натяжкой...
ld iy,#_flt_1
ld 0(iy),#0x33
ld 1(iy),#0x33
ld 2(iy),#0x0B
ld 3(iy),#0x41
;test.c:74: i2 = 5;
ld iy,#_i2
ld 0(iy),#0x05
ld 1(iy),#0x00
;test.c:75: j2 = i + 0;
;0 не стал добавлять, просто копирование
ld hl,(_i)
ld iy,#_j2
ld 0(iy),l
ld 1(iy),h
;test.c:76: k2 = i / 1;
;и на 1 делить не стал
ld hl,(_i)
ld iy,#_k2
ld 0(iy),l
ld 1(iy),h
;test.c:77: i4 = i * 1;
;да и умножать тоже
ld hl,(_i)
ld iy,#_i4
ld 0(iy),l
ld 1(iy),h
;test.c:78: i5 = i * 0;
;сообразительный малый :)
ld iy,#_i5
ld 0(iy),#0x00
ld 1(iy),#0x00
;test.c:88: printf( "This compiler handles divide-by-zero as
;деление на 0 не словил на этапе комппиляции, пытается
;печатать
;передача параметров через стек- не очень хорошо...
ld hl,#__str_0
push hl
call _printf
;и очистка вызывающей функцией- классическая
;парадигма _cdecl
pop af
;test.c:91: flt_3 = 2.4 / 1.0;
;с плавающей запятой константы тоже сворачивает
ld iy,#_flt_3
ld 0(iy),#0x9A
ld 1(iy),#0x99
ld 2(iy),#0x19
ld 3(iy),#0x40
;test.c:92: flt_4 = 1.0 + 0.0000001;
ld iy,#_flt_4
ld 0(iy),#0x01
ld 1(iy),#0x00
ld 2(iy),#0x80
ld 3(iy),#0x3F
;test.c:93: flt_5 = flt_6 * 0.0;
;молодец :)
ld iy,#_flt_5
ld 0(iy),#0x00
ld 1(iy),#0x00
ld 2(iy),#0x00
ld 3(iy),#0x00
;test.c:94: flt_6 = flt_2 * flt_3;
;распространение константы flt_3 = 2.4
ld hl,#0x4019
push hl
ld hl,#0x999A
push hl
ld hl,(_flt_2 + 2)
push hl
ld hl,(_flt_2)
push hl
call ___fsmul
;заволновался по поводу hl...
ld b,h
ld c,l
;освобождение стека- 8 байт
pop af
pop af
pop af
pop af
ld iy,#_flt_6
ld 0(iy),c
ld 1(iy),b
ld 2(iy),e
ld 3(iy),d
4.Снижение мощностиКод:;test.c:101: k3 = 1;
;было благополучно удалено!
ld iy,#_k3
ld 0(iy),#0x01
ld 1(iy),#0x00
5.Простой циклКод:;test.c:107: k2 = 4 * j5;
;это просто "шедевр"! это надо видеть!!!
ld iy,#_j5
ld a,0(iy)
ld iy,#_k2
ld 0(iy),a
ld iy,#_j5
ld a,1(iy)
ld iy,#_k2
ld 1(iy),a
;впервые на манеже ТАКИЕ извращения при попытке
;заменить умножение сдвигами :)
ld a,#0x02+1
jp 00146$
00145$:
ld iy,#_k2
sla 0(iy)
rl 1(iy)
00146$:
dec a
jp nz,00145$
;test.c:108: for( i = 0; i <= 5; i++ )
;переменная цикла тоже в индексном... грустно...
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00117$:
ld a,#0x05
ld iy,#_i
sub a,0(iy)
ld a,#0x00
sbc a,1(iy)
jp m,00120$
;test.c:109: ivector4[ i ] = i * 2;
;мрачно...
ld c,0(iy)
ld b,1(iy)
sla c
rl b
ld hl,#_ivector4
add hl,bc
;так и не понял, для чего эти две команды...
ld e,l
ld d,h
ld (hl),c
inc hl
ld (hl),b
;test.c:108: for( i = 0; i <= 5; i++ )
;а вот это небольшой финт- полупересчетка
ld iy,#_i
inc 0(iy)
jp nz,00149$
inc 1(iy)
00149$:
jp 00117$
00120$:
6.Управление переменной индукции циклаКод:;test.c:115: j5 = 0;
ld iy,#_j5
ld 0(iy),#0x00
ld 1(iy),#0x00
;test.c:116: k5 = 10000;
ld iy,#_k5
ld 0(iy),#0x10
ld 1(iy),#0x27
;test.c:117: do {
00107$:
;test.c:118: k5 = k5 - 1;
;ну достаточно логичная конструкция- почему в остальных
;местах IY????
ld hl,(_k5)
dec hl
ld (_k5),hl
;test.c:119: j5 = j5 + 1;
;например, здесь????
ld iy,#_j5
inc 0(iy)
jp nz,00150$
inc 1(iy)
00150$:
;test.c:120: i5 = (k5 * 3) / (j5 * constant5);
;ну просто конфетка! :)
ld de,(_k5)
ld l,e
ld h,d
add hl,hl
add hl,de
ld c,l
ld b,h
;он даже константу развернул!!!
ld de,(_j5)
ld l,e
ld h,d
add hl,hl
add hl,hl
add hl,de
ld e,l
ld d,h
;параметры через стек
push de
push bc
call __divsint_rrx_s
;непонятного назначения конструкция...
ld b,h
ld c,l
pop af
pop af
ld iy,#_i5
ld 0(iy),c
ld 1(iy),b
;test.c:121: } while ( k5 > 0 );
;страшная конструкция...
ld a,#0x00
ld iy,#_k5
sub a,0(iy)
ld a,#0x00
sbc a,1(iy)
jp m,00107$
7.Глубокие подвыраженияКод:;test.c:126: for( i = 0; i < 100; i++ )
;стандартный заголовок цикла
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00121$:
ld iy,#_i
ld a,0(iy)
sub a,#0x64
ld a,1(iy)
sbc a,#0x00
jp p,00124$
;test.c:127: ivector5[ i * 2 + 3 ] = 5;
;выделение индукции нет, но интересно- сообразил, что
; переменная цикла помещается в один байт
ld c,0(iy)
ld a,c
add a,a
ld c,a
;эх, не догадался базу массива сместить :)
inc c
inc c
inc c
;не забываем про размер
ld a,c
add a,a
ld c,a
;вот это интересно- использование полуслов адреса
ld a,#<_ivector5
add a,c
ld c,a
ld a,#>_ivector5
adc a,#0x00
ld b,a
;бережет он HL непонятно с какими целями...
ld l,c
ld h,b
ld (hl),#0x05
inc hl
ld (hl),#0x00
;test.c:126: for( i = 0; i < 100; i++ )
;стандарный инкремент
inc 0(iy)
jp nz,00151$
inc 1(iy)
00151$:
jp 00121$
00124$:
8.Генерация адреса переменной с константным индексом, размножение копий и регистровКод:;test.c:133: if( i < 10 )
ld iy,#_i
ld a,0(iy)
sub a,#0x0A
ld a,1(iy)
sbc a,#0x00
jp p,00111$
;test.c:134: j5 = i5 + i2;
;страхолюдная конструкция...
ld hl,#_i2
push de
ld iy,#_j5
push iy
pop de
ld iy,#_i5
ld a,0(iy)
add a,(hl)
ld (de),a
ld a,1(iy)
inc hl
adc a,(hl)
inc de
ld (de),a
pop de
jp 00112$
00111$:
;test.c:136: k5 = i5 + i2;
;иными словами- никакого выделения общего подвыражения нет
ld hl,#_i2
push de
ld iy,#_k5
push iy
pop de
ld iy,#_i5
ld a,0(iy)
add a,(hl)
ld (de),a
ld a,1(iy)
inc hl
adc a,(hl)
inc de
ld (de),a
pop de
00112$:
9.Удаление общих подвыраженийКод:;test.c:144: ivector[ 0 ] = 1;
;ну почему в обычном варианте этого нет???
ld hl,#_ivector
ld (hl),#0x01
inc hl
ld (hl),#0x00
;test.c:145: ivector[ i2 ] = 2;
;страсти-то какие...
ld iy,#_i2
ld c,0(iy)
ld b,1(iy)
sla c
rl b
dec hl
add hl,bc
ld c,l
ld b,h
ld (hl),#0x02
inc hl
ld (hl),#0x00
;test.c:146: ivector[ i2 ] = 2;
;эти две команды лишние, но в целом используется
;результат предыдущих вычислений
ld l,c
ld h,b
ld (hl),#0x02
inc hl
ld (hl),#0x00
;test.c:147: ivector[ 2 ] = 3;
;почему так странно?
ld bc,#_ivector + 4
ld l,c
ld h,b
ld (hl),#0x03
inc hl
ld (hl),#0x00
10.Вынесение инвариантного кодаКод:;test.c:154: if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 )
;советую присмотреться внимательно- компилятор
;запомнил, что k3 не менялся и равен 1- размножение
;константы плюс сокращенные вычисления плюс сразу
;два сравнения
;ЗЫ. закрывайте глаза на реализацию идеи :)
ld iy,#_h3
ld c,0(iy)
ld b,1(iy)
;вот это мы добавляем к3
inc bc
;проверка на <0 - проще простого
ld a,b
bit 7,a
jp nz,00113$
;а также на >5
ld a,#0x05
sub a,c
ld a,#0x00
sbc a,b
jp p,00114$
00113$:
;test.c:155: printf("Common subexpression elimination\n");
;параметры через стек
ld hl,#__str_1
push hl
call _printf
pop af
jp 00115$
00114$:
;test.c:157: m3 = ( h3 + k3 ) / i3;
;выделение общих подвыражений действует!- выражение
;в скобках не вычисляется повторно, а хранится в bc
push bc
ld hl,(_i3)
push hl
push bc
call __divsint_rrx_s
ld d,h
ld e,l
pop af
pop af
pop bc
ld iy,#_m3
ld 0(iy),e
ld 1(iy),d
;test.c:158: g3 = i3 + (h3 + k3);
;аналогично и здесь
ld hl,#_g3
ld iy,#_i3
ld a,0(iy)
add a,c
ld (hl),a
ld a,1(iy)
adc a,b
inc hl
ld (hl),a
00115$:
Код:;test.c:166: for( i4 = 0; i4 <= max_vector; i4++)
ld iy,#_i4
ld 0(iy),#0x00
ld 1(iy),#0x00
00125$:
ld a,#0x02
ld iy,#_i4
sub a,0(iy)
ld a,#0x00
sbc a,1(iy)
jp m,00128$
;test.c:167: ivector2[ i4 ] = j * k;
;весьма оригинальное разыменование указателя
ld hl,#_i4
ld a,#<_ivector2
add a,(hl)
ld c,a
ld a,#>_ivector2
inc hl
adc a,(hl)
ld b,a
;но вынесения инвариантной части нет- каждый цикл
;выполняются вычисления
ld iy,#_j
ld e,0(iy)
ld iy,#_k
ld d,0(iy)
push bc
push de
inc sp
ld a,e
push af
inc sp
call __mulschar_rrx_s
ld e,l
pop af
pop bc
ld a,e
ld (bc),a
;test.c:166: for( i4 = 0; i4 <= max_vector; i4++)
ld iy,#_i4
inc 0(iy)
jp nz,00154$
inc 1(iy)
00154$:
jp 00125$
00128$:
11.Вызов функции с аргументами. Определение недостижимого кода
Код:;test.c:173: dead_code( 1, "This line should not be printed" );
;обычная передача параметров через стек и очистка
ld hl,#__str_2
push hl
ld hl,#0x0001
push hl
call _dead_code
pop af
pop af
12.Вызов функции без аргументов. Исключение цикловКод:_dead_code:
;лишнее выделение стекового места, но полная оптимизация
;внутренностей функции
push ix
ld ix,#0
add ix,sp
;test.c:196: printf( "%s\n", b );
00103$:
pop ix
ret
Код:;test.c:179: unnecessary_loop();
call _unnecessary_loop
00129$:
13. Слияние заголовков цикловКод:_unnecessary_loop:
;test.c:212: for( i = 0; i < 5; i++ )
ld iy,#_i
;обратите внимание- компилятор перевернул цикл!
ld 0(iy),#0x05
ld 1(iy),#0x00
00103$:
;test.c:214: k5 = x + j5;
;размножение константы х = 0
;но повторная загрузка имеется, простительно
ld hl,(_j5)
ld iy,#_k5
ld 0(iy),l
ld 1(iy),h
ld hl,(_i)
dec hl
ld (_i),hl
;test.c:212: for( i = 0; i < 5; i++ )
;оригинальная концовка!
ld iy,#_i
ld a,0(iy)
or a,1(iy)
jp nz,00103$
;а этот код потому что i является глобально переменной
ld 0(iy),#0x05
ld 1(iy),#0x00
00104$:
ret
14.Разворачивание цикловКод:_loop_jamming:
push ix
ld ix,#0
add ix,sp
;test.c:226: for( i = 0; i < 5; i++ )
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00101$:
ld iy,#_i
ld a,0(iy)
sub a,#0x05
ld a,1(iy)
sbc a,#0x00
jp p,00104$
;test.c:227: k5 = x + j5 * i;
ld hl,(_i)
push hl
ld hl,(_j5)
push hl
call __mulint_rrx_s
ld b,h
ld c,l
pop af
pop af
;переменная x хранится в стеке
ld hl,#_k5
ld a,4(ix)
add a,c
ld (hl),a
ld a,5(ix)
adc a,b
inc hl
ld (hl),a
;test.c:226: for( i = 0; i < 5; i++ )
ld iy,#_i
inc 0(iy)
jp nz,00115$
inc 1(iy)
00115$:
jp 00101$
00104$:
;test.c:228: for( i = 0; i < 5; i++ )
;слияния заголовков нет
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00105$:
ld iy,#_i
ld a,0(iy)
sub a,#0x05
ld a,1(iy)
sbc a,#0x00
jp p,00109$
;test.c:229: i5 = x * k5 * i;
ld hl,(_k5)
push hl
ld l,4(ix)
ld h,5(ix)
push hl
call __mulint_rrx_s
ld b,h
ld c,l
pop af
pop af
ld hl,(_i)
push hl
push bc
call __mulint_rrx_s
ld b,h
ld c,l
pop af
pop af
ld iy,#_i5
ld 0(iy),c
ld 1(iy),b
;test.c:228: for( i = 0; i < 5; i++ )
ld iy,#_i
inc 0(iy)
jp nz,00116$
inc 1(iy)
00116$:
jp 00105$
00109$:
pop ix
ret
15.Сжатие цепочки переходовКод:_loop_unrolling:
push ix
ld ix,#0
add ix,sp
;test.c:243: for( i = 0; i < 6; i++ )
;разворота нет
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00101$:
ld iy,#_i
ld a,0(iy)
sub a,#0x06
ld a,1(iy)
sbc a,#0x00
jp p,00105$
;test.c:244: ivector4[ i ] = 0;
;экзотическая загрузка :)
ld c,0(iy)
ld b,1(iy)
sla c
rl b
ld hl,#_ivector4
add hl,bc
ld c,l
ld b,h
ld (hl),#0x00
inc hl
ld (hl),#0x00
;test.c:243: for( i = 0; i < 6; i++ )
ld iy,#_i
inc 0(iy)
jp nz,00111$
inc 1(iy)
00111$:
jp 00101$
00105$:
pop ix
ret
Итоговая оценка- 7/10. Умное распространение констант, сжатие переходов, приемлимый заголовок цикла, различная оптимизация, но повсеместное использование индексного регистра для хранения глобальных переменных все портит. Надо будет проверить как он себя ведет на статических переменных и возможно ли убрать работу с индексными регистрами. Если получится, то данный компилятор можно рекомендовать к применению! :)Код:_jump_compression:
push ix
ld ix,#0
add ix,sp
;test.c:256: beg_1:
ld a,8(ix)
sub a,10(ix)
ld a,9(ix)
sbc a,11(ix)
;интересный финт- в С результат сравнения k и l
rlca
and a,#0x01
ld c,a
ld a,10(ix)
sub a,12(ix)
ld a,11(ix)
sbc a,13(ix)
;а в А результат сравнения l и m
rlca
and a,#0x01
;только он почему-то не используется, а теряется...
00101$:
;test.c:257: if( i < j )
ld a,4(ix)
sub a,6(ix)
ld a,5(ix)
sbc a,7(ix)
jp p,00113$
;test.c:259: if( j < k )
ld a,6(ix)
sub a,8(ix)
ld a,7(ix)
sbc a,9(ix)
jp p,00110$
;test.c:261: if( k < l )
;использование предыдущего результата
xor a,a
or a,c
jp z,00106$
;test.c:263: if( l < m )
;очень странный код... не понимаю как работает....
or a,a
;есть свертка перехода!
jp z,00101$
;test.c:264: l += m;
ld a,10(ix)
add a,12(ix)
ld 10(ix),a
ld a,11(ix)
adc a,13(ix)
ld 11(ix),a
jp 00114$
;test.c:266: goto end_1;
; genLabel
00106$:
;test.c:269: k += l;
ld a,8(ix)
add a,10(ix)
ld 8(ix),a
ld a,9(ix)
adc a,11(ix)
ld 9(ix),a
jp 00114$
00110$:
;test.c:273: j += k;
ld a,6(ix)
add a,8(ix)
ld 6(ix),a
ld a,7(ix)
adc a,9(ix)
ld 7(ix),a
;test.c:275: goto beg_1;
jp 00101$
00113$:
;test.c:279: i += j;
ld a,4(ix)
add a,6(ix)
ld 4(ix),a
ld a,5(ix)
adc a,7(ix)
ld 5(ix),a
00114$:
;test.c:280: return( i + j + k + l + m );
ld a,4(ix)
add a,6(ix)
ld c,a
ld a,5(ix)
adc a,7(ix)
ld b,a
ld a,c
add a,8(ix)
ld c,a
ld a,b
adc a,9(ix)
ld b,a
ld a,c
add a,10(ix)
ld c,a
ld a,b
adc a,11(ix)
ld b,a
ld l,12(ix)
ld h,13(ix)
add hl,bc
00115$:
pop ix
ret
Последний из имеющихся пациент- z88dk. Порядком помучался пока заставил его генерить исходник ассемблера. Если попросить, вставляет в исходный текст строки на С, но честно предупреждает, что в таком случае некоторая оптимизация не получится. Я буду уточнять, в каких местах возникла разница.
Использовался уровень оптимизации 2
0.Пролог
Его просто нет. Сразу идет код main.
1. Тест на размножение констант и копий.
2.Свертка константКод:;j4 = 2;
ld hl,2 ;const
ld (_j4),hl
;if( i2 < j4 && i4 < j4 )
;нет размножения констант плюс функции для сравнения
ld de,(_i2)
ld hl,(_j4)
call l_lt
jp nc,i_4
ld de,(_i4)
ld hl,(_j4)
call l_lt
;обратите внимание- использование коротких команд
;перехода
;но в то же время систему переходов можно (и нужно)
;было бы оптимизировать
jr c,i_5_i_4
.i_4
jp i_3
.i_5_i_4
;i2 = 2;
ld hl,2 ;const
ld (_i2),hl
;j4 = k5;
.i_3
;та же картина
ld hl,(_k5)
ld (_j4),hl
;if( i2 < j4 && i4 < j4 )
ld de,(_i2)
ld hl,(_j4)
call l_lt
jp nc,i_7
ld de,(_i4)
ld hl,(_j4)
call l_lt
jr c,i_8_i_7
.i_7
jp i_6
.i_8_i_7
;i5 = 3;
ld hl,3 ;const
ld (_i5),hl
.i_6
3.Лишнее присваиваниеКод:;i3 = 1 + 2;
;свернул
ld hl,3 ;const
ld (_i3),hl
;flt_1 = 2.4 + 6.3;
;оп-па! не свернул!
ld hl,i_2+0
call dldpsh
ld hl,i_2+6
call dload
call dadd
ld hl,_flt_1
call dstore
;i2 = 5;
;загрузка константы
ld hl,5 ;const
ld (_i2),hl
;j2 = i + 0;
;0 не стал прибавлять
ld hl,(_i)
ld (_j2),hl
;k2 = i / 1;
;а вот на 1 поделить не побрезговал....
ld hl,(_i)
ld de,1 ;const
ex de,hl
call l_div
ld (_k2),hl
;i4 = i * 1;
;и умножить тоже
ld hl,(_i)
ld de,1
call l_mult
ld (_i4),hl
;i5 = i * 0;
;и на ноль тоже...
ld hl,(_i)
ld de,0
call l_mult
ld (_i5),hl
;printf( "This compiler handles divide-by-zero as an error\n");
;да, он прохавал деление на нулевую константу
;параметры через стек
ld hl,i_1+0
push hl
call _printf
pop bc
;flt_3 = 2.4 / 1.0;
;мрак... на 1 тоже делит, да еще и в реальном времени...
ld hl,i_2+0
call dldpsh
ld hl,i_2+12
call dload
call ddiv
ld hl,_flt_3
call dstore
;flt_4 = 1.0 + 0.0000001;
;без слов...
ld hl,i_2+12
call dldpsh
ld hl,i_2+18
call dload
call dadd
ld hl,_flt_4
call dstore
;flt_5 = flt_6 * 0.0;
;...одни эмоции
ld hl,_flt_6
call dldpsh
ld hl,i_2+24
call dload
call dmul
ld hl,_flt_5
call dstore
;flt_6 = flt_2 * flt_3;
;ну тут по другому никак
ld hl,_flt_2
call dldpsh
ld hl,_flt_3
call dload
call dmul
ld hl,_flt_6
call dstore
4.Снижение мощностиКод:;k3 = 1;
ld hl,1 ;const
ld (_k3),hl
;k3 = 1;
;в худших традициях...
ld hl,1 ;const
ld (_k3),hl
5.Простой циклКод:;k2 = 4 * j5;
;не заметил возможности умножения "малой кровью"
ld hl,(_j5)
ld de,4
call l_mult
ld (_k2),hl
;for( i = 0; i <= 5; i++ )
;реализация цикла for в лучших традициях!
ld hl,0 ;const
ld (_i),hl
jp i_11
.i_9
;ivector4[ i ] = i * 2;
;хорошо что хоть догадался сдвигами умножать на размер
;типа, а не функциями, но лишние операции со стеком
ld hl,_ivector4
push hl
ld hl,(_i)
add hl,hl
pop de
add hl,de
push hl
ld hl,(_i)
add hl,hl
pop de
call l_pint
;классика!
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_11
;мрак...
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_le
jp c,i_9
.i_10
6.Управление переменной индукции циклаКод:;j5 = 0;
ld hl,0 ;const
ld (_j5),hl
;k5 = 10000;
ld hl,10000 ;const
ld (_k5),hl
;do {
.i_14
;k5 = k5 - 1;
;распознал вычитание единицы!
ld hl,(_k5)
dec hl
ld (_k5),hl
;j5 = j5 + 1;
;и ее прибавление
ld hl,(_j5)
inc hl
ld (_j5),hl
;i5 = (k5 * 3) / (j5 * 5);
;ну ведь можешь же умножать когда хочешь!
ld hl,(_k5)
ld b,h
ld c,l
add hl,bc
add hl,bc
push hl
ld hl,(_j5)
ld b,h
ld c,l
add hl,hl
add hl,hl
add hl,bc
pop de
call l_div
ld (_i5),hl
;} while ( k5 > 0 );
.i_12
;оригинальная проверка на конец цикла
ld hl,(_k5)
xor a
or h
jp m,i_13
or l
jp nz,i_14
.i_13
7.Глубокие подвыраженияКод:;for( i = 0; i < 100; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_17
.i_15
;ivector5[ i * 2 + 3 ] = 5;
;специфично, но в целом терпимо
ld hl,_ivector5
push hl
ld hl,(_i)
add hl,hl
inc hl
inc hl
inc hl
add hl,hl
pop de
add hl,de
ld (hl),#(5 % 256)
inc hl
ld (hl),#(5 / 256)
ld hl,(_i)
inc hl
ld (_i),hl
;а это зачем???
dec hl
.i_17
;оптимизацию for не доделали...
ld hl,(_i)
ld de,100 ;const
ex de,hl
call l_lt
jp c,i_15
.i_16
8.Генерация адреса переменной с константным индексом, размножение копий и регистровКод:;if( i < 10 )
;хреново сравнивает!
ld hl,(_i)
ld de,10 ;const
ex de,hl
call l_lt
jp nc,i_18
;j5 = i5 + i2;
;зато хоть складывает нормально
ld de,(_i5)
ld hl,(_i2)
add hl,de
ld (_j5),hl
;else
jp i_19
.i_18
;k5 = i5 + i2;
;выделения подвыражений нет
ld de,(_i5)
ld hl,(_i2)
add hl,de
ld (_k5),hl
.i_19
9.Удаление общих подвыраженийКод:;ivector[ 0 ] = 1;
;правильно
ld hl,1 ;const
ld (_ivector),hl
;ivector[ i2 ] = 2;
;лишние операции со стеком, простая перестановка дала
;бы прирост эффективности
ld hl,_ivector
push hl
ld hl,(_i2)
add hl,hl
pop de
add hl,de
ld de,2 ;const
ex de,hl
;да что за мрак!
call l_pint
;ivector[ i2 ] = 2;
;не воспользовался результатом предыдущей операции
ld hl,_ivector
push hl
ld hl,(_i2)
add hl,hl
pop de
add hl,de
ld de,2 ;const
ex de,hl
call l_pint
;ivector[ 2 ] = 3;
;тут все правильно
ld hl,3 ;const
ld (_ivector+4),hl
10.Вынесение инвариантного кодаКод:;if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 )
;хорошее начало, но дальше не очень
ld de,(_h3)
ld hl,(_k3)
add hl,de
ld de,0 ;const
ex de,hl
call l_lt
jp c,i_21
;не используются результаты...
ld de,(_h3)
ld hl,(_k3)
add hl,de
ld de,5 ;const
ex de,hl
call l_gt
jp nc,i_20
.i_21
;printf("Common subexpression elimination\n");
;параметры через стек
ld hl,i_1+63
push hl
call _printf
pop bc
;else {
jp i_23
.i_20
;m3 = ( h3 + k3 ) / i3;
;совсем не используются...
ld de,(_h3)
ld hl,(_k3)
add hl,de
ex de,hl
ld hl,(_i3)
call l_div
ld (_m3),hl
;g3 = i3 + (h3 + k3);
ld hl,(_i3)
push hl
ld de,(_h3)
ld hl,(_k3)
add hl,de
pop de
add hl,de
ld (_g3),hl
;}
.i_23
Код:;for( i4 = 0; i4 <= 2; i4++)
ld hl,0 ;const
ld (_i4),hl
jp i_26
.i_24
;ivector2[ i4 ] = j * k;
;обычная обработка индекса массива
ld de,_ivector2
ld hl,(_i4)
add hl,de
push hl
;но вынесения кода нет
ld de,(_j)
ld hl,(_k)
call l_mult
pop de
ld a,l
ld (de),a
ld hl,(_i4)
inc hl
ld (_i4),hl
dec hl
.i_26
ld hl,(_i4)
ld de,2 ;const
ex de,hl
call l_le
jp c,i_24
.i_25
11.Вызов функции с аргументами. Определение недостижимого кода
Код:;dead_code( 1, "This line should not be printed" );
;параметры через стек, слева направо (хотя должно быть наоборот...)
ld hl,1 ;const
push hl
ld hl,i_1+97
push hl
call _dead_code
pop bc
pop bc
12.Вызов функции без аргументов. Исключение цикловКод:;void dead_code( a, b )
;int a;
;char *b;
._dead_code
;{
;int idead_store;
;idead_store = a;
ld hl,6-2 ;const
add hl,sp
call l_gint ;
push hl
;if( 0 )
;переход выполняет
jp i_27
;printf( "%s\n", b );
;но код для пустышки генерит!
ld hl,i_1+129
push hl
ld hl,6 ;const
add hl,sp
call l_gint ;
push hl
call _printf
pop bc
pop bc
;}
.i_27
pop bc
ret
Код:call _unnecessary_loop
13. Слияние заголовков цикловКод:;void unnecessary_loop()
;{
._unnecessary_loop
;int x;
;x = 0;
;регистровая переменная- хорошо
ld hl,0 ;const
;но в стеке- плохо
push hl
;for( i = 0; i < 5; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_30
.i_28
;k5 = x + j5;
;прикольно :)
pop de
push de
ld hl,(_j5)
add hl,de
ld (_k5),hl
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_30
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_lt
jp c,i_28
.i_29
;}
pop bc
ret
14.Разворачивание цикловКод:;void loop_jamming( x )
;int x;
._loop_jamming
;{
;for( i = 0; i < 5; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_33
.i_31
;k5 = x + j5 * i;
;наверное ошибка- на стеке на один параметр меньше
pop bc
pop hl
push hl
push bc
push hl
ld de,(_j5)
ld hl,(_i)
call l_mult
pop de
add hl,de
ld (_k5),hl
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_33
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_lt
jp c,i_31
.i_32
;for( i = 0; i < 5; i++ )
;второй цикл точная копия первого
ld hl,0 ;const
ld (_i),hl
jp i_36
.i_34
;i5 = x * k5 * i;
pop bc
pop hl
push hl
push bc
ex de,hl
ld hl,(_k5)
call l_mult
ex de,hl
ld hl,(_i)
call l_mult
ld (_i5),hl
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_36
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_lt
jp c,i_34
.i_35
;}
ret
15.Сжатие цепочки переходовКод:;void loop_unrolling( x )
;int x;
._loop_unrolling
;{
;for( i = 0; i < 6; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_39
.i_37
;ivector4[ i ] = 0;
;нет разворота, да и загрузка достаточно тяжела
ld hl,_ivector4
push hl
ld hl,(_i)
add hl,hl
pop de
add hl,de
ld (hl),#(0 % 256)
inc hl
ld (hl),#(0 / 256)
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_39
ld hl,(_i)
ld de,6 ;const
ex de,hl
call l_lt
jp c,i_37
.i_38
;}
ret
Итоговая оценка- 5/10. Туповатый компилятор, на который изредка находит озарение и он генерит неплохой код. К применению не рекомендуется...Код:;int jump_compression( i, j, k, l, m )
;int i, j, k, l, m;
._jump_compression
;{
;beg_1:
.i_40
;if( i < j )
;вот тут бы не помешали индексные регистры, да не
;используются совсем...
ld hl,10 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,10 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_41
;{
;if( j < k )
ld hl,8 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,8 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_42
;{
;if( k < l )
ld hl,6 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,6 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_43
;{
;if( l < m )
ld hl,4 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,4 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_44
;l += m;
ld hl,4 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,6 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
;else
jp i_45
.i_44
;goto end_1;
;нет оптимизации переходов
jp i_46
.i_45
;}
;else
jp i_47
.i_43
;k += l;
ld hl,6 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,8 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
.i_47
;}
;else
jp i_48
.i_42
;{
;j += k;
ld hl,8 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,10 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
;end_1:
.i_46
.i_49
;goto beg_1;
jp i_40
;}
.i_48
;}
;else
jp i_50
.i_41
;i += j;
ld hl,10 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,12 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
.i_50
;return( i + j + k + l + m );
ld hl,10 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,10 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
ex de,hl
ld hl,8-2 ;const
add hl,sp
call l_gint ;
add hl,de
ex de,hl
ld hl,6-2 ;const
add hl,sp
call l_gint ;
add hl,de
ex de,hl
ld hl,4-2 ;const
add hl,sp
call l_gint ;
add hl,de
ret
;}
Спасибо, интересное исследование. Значит sdcc... Но вот меня смущает, что на sdcc.sf.net постоянно упоминается "freeware", несмотря на его GPL'ность.
А по поводу переменных, наверное в реальных проектах будет много глобальных статических, чтобы компилятор их просто клал в память, не извращаясь со стеком или IX/IY.