Ну что, прогнал HitechC по тесту, осталось весьма приятное впечатление. Некоторые вещи, конечно, хотелось бы улучшить, но все же.
Итак, что он, собственно накрутил. Испытания проводились с учетом максимального уровня оптимизации
0. Пролог. Весьма короткий:
Код:
_main:
push ix
ld ix,0
add ix,sp
дальше идет непосредственно код
1. Тест на размножение констант и копий.
Код:
;TEST.C: 62: j4 = 2;
ld hl,02h
ld (_j4),hl
;TEST.C: 63: if( i2 < j4 && i4 < j4 )
;лишняя загрузка из j4 - следствие того, что для
;сравнения используется функция с фиксированными
;позициями для параметра, но все равно- мог бы
;использовать de для инициализации или сделать
;ld d,h:ld e,l
ld de,(_j4)
ld hl,(_i2)
call wrelop
;также использование jp не есть хорошо. сокращенные
;вычисления используются в соответствии со стандартом
jp p,l4
ld de,(_j4)
ld hl,(_i4)
call wrelop
jp p,l4
;TEST.C: 64: i2 = 2;
ld hl,02h
ld (_i2),hl
l4:
;TEST.C: 66: j4 = k5;
ld hl,(_k5)
ld (_j4),hl
;TEST.C: 67: if( i2 < j4 && i4 < j4 )
;картина полностью аналогичная
ld de,(_j4)
ld hl,(_i2)
call wrelop
jp p,l5
ld de,(_j4)
ld hl,(_i4)
call wrelop
;TEST.C: 68: i5 = 3;
ld hl,03h
jp p,L2
ld (_i5),hl
l5:
2.Свертка констант
Код:
;TEST.C: 75: i3 = 1 + 2;
;успешно
ld hl,03h
L2:
ld (_i3),hl
;TEST.C: 76: flt_1 = 2.4 + 6.3;
;аналогично
ld de,(e1)
ld hl,(e1+02h)
ld (_flt_1),de
ld (_flt_1+02h),hl
;TEST.C: 77: i2 = 5;
ld hl,05h
ld (_i2),hl
;TEST.C: 78: j2 = i + 0;
;ничего прибавлять не стал, молодец :)
ld hl,(_i)
ld (_j2),hl
;TEST.C: 79: k2 = i / 1;
;равно как не стал и делить, плюс не стал лишний раз
;делать загрузку!
ld (_k2),hl
;TEST.C: 80: i4 = i * 1;
;аналогично
ld (_i4),hl
;TEST.C: 81: i5 = i * 0;
;ну и умножение на ноль тоже распознал
ld hl,0
ld (_i5),hl
Код:
;TEST.C: 94: flt_3 = 2.4 / 1.0;
;свернул деление
ld de,(e2)
ld hl,(e2+02h)
ld (_flt_3),de
ld (_flt_3+02h),hl
;TEST.C: 95: flt_4 = 1.0 + 0.0000001;
;свернул сложение
ld de,(e3)
ld hl,(e3+02h)
ld (_flt_4),de
ld (_flt_4+02h),hl
;TEST.C: 96: flt_5 = flt_6 * 0.0;
;а вот здесь прокосячил- наверное нет проверки на 0
;для констант с плавающей запятой
ld hl,(e4+02h)
push hl
ld hl,(e4)
push hl
ld de,(_flt_6)
ld hl,(_flt_6+02h)
call flmul
ld (_flt_5),de
ld (_flt_5+02h),hl
;TEST.C: 97: flt_6 = flt_2 * flt_3;
;ничего интересного
ld hl,(_flt_3+02h)
push hl
ld hl,(_flt_3)
push hl
ld de,(_flt_2)
ld hl,(_flt_2+02h)
call flmul
ld (_flt_6),de
ld (_flt_6+02h),hl
2.1.Ошибка деления на ноль была успешно распознана и компилятор ничего не собирал до тех пор, пока не определил NO_ZERO_DIVIDE
3.Лишнее присваивание
Код:
;TEST.C: 103: k3 = 1;
ld hl,01h
ld (_k3),hl
;TEST.C: 104: k3 = 1;
;сэкономил загрузку, но выполнил лишнее присваивание
;в силу того, что компилятор для встроенных систем на
;базе микроконтроллеров, повторное присваивание (а
;также чтение) имеют свой смысл. Так что это не ошибка
ld (_k3),hl
4.Снижение мощности
Код:
;TEST.C: 110: k2 = 4 * j5;
;вполне логично свернул умножение на 4
ld hl,(_j5)
add hl,hl
add hl,hl
ld (_k2),hl
;TEST.C: 111: for( i = 0; i <= 5; i++ )
;но просто отвратительно сделал цикл с изначально
;известными условиями- по шаблону
ld hl,0
ld (_i),hl
ld de,06h
ld hl,(_i)
call wrelop
jp p,l7
l6:
;TEST.C: 112: ivector4[ i ] = i * 2;
;чуда не произошло- снижения мощности нет
;в принципе, для такого шаблона без регистровых
;переменных это и логично...
ld de,_ivector4
ld hl,(_i)
add hl,hl
add hl,de
ex de,hl
ld hl,(_i)
add hl,hl
ld a,l
ld (de),a
inc de
ld a,h
ld (de),a
ld hl,(_i)
inc hl
ld (_i),hl
ld de,06h
call wrelop
jp m,l6
l7:
5.Простой цикл
Код:
;TEST.C: 118: j5 = 0;
ld hl,0
ld (_j5),hl
;TEST.C: 119: k5 = 10000;
ld hl,02710h
ld (_k5),hl
l11:
;TEST.C: 120: do {
;TEST.C: 121: k5 = k5 - 1;
;недостатки отсутствия регистровых переменных во
;всей красе...
ld hl,(_k5)
dec hl
ld (_k5),hl
;TEST.C: 122: j5 = j5 + 1;
ld hl,(_j5)
inc hl
ld (_j5),hl
;TEST.C: 123: i5 = (k5 * 3) / (j5 * 5);
;хотя тут их отсутствие вполне закономерно- иначе
;пришлось бы мучаться со стеком
;достойная свертка констант умножения
ld b,h
ld c,l
add hl,hl
add hl,hl
add hl,bc
ex de,hl
ld hl,(_k5)
ld b,h
ld c,l
add hl,hl
add hl,bc
call adiv
ld (_i5),hl
;TEST.C: 124: } while ( k5 > 0 );
;глупое сравнение на >=1...
ld de,01h
ld hl,(_k5)
call wrelop
jp p,l11
6.Управление переменной индукции цикла
Код:
;TEST.C: 129: for( i = 0; i < 100; i++ )
;та же лажа с циклом
ld hl,0
ld (_i),hl
ld de,064h
call wrelop
jp p,l13
l12:
;TEST.C: 130: ivector5[ i * 2 + 3 ] = 5;
;переменной индукции нет (не регистровая)
;но смещение индекса преобразовано в смещение базы
;массива
ld hl,(_i)
add hl,hl
add hl,hl
ld de,_ivector5+06h
add hl,de
ld (hl),05h
inc hl
ld (hl),0
ld hl,(_i)
inc hl
ld (_i),hl
ld de,064h
call wrelop
jp m,l12
l13:
7.Глубокие подвыражения
Код:
;TEST.C: 136: if( i < 10 )
ld de,0Ah
ld hl,(_i)
call wrelop
;TEST.C: 137: j5 = i5 + i2;
;весьма хитро- загрузку параметров вынесли перед
;переходом, а сложение после, чтобы не портить флаг
ld hl,(_i5)
ld de,(_i2)
jp p,L1
add hl,de
ld (_j5),hl
;TEST.C: 138: else
jp l16
;TEST.C: 139: k5 = i5 + i2;
L1:
add hl,de
ld (_k5),hl
l16:
8.Генерация адреса переменной с константным индексом, размножение копий и регистров
Код:
;TEST.C: 147: ivector[ 0 ] = 1;
;логично
ld hl,01h
ld (_ivector),hl
;TEST.C: 148: ivector[ i2 ] = 2;
ld hl,(_i2)
add hl,hl
ld de,_ivector
add hl,de
ld (hl),02h
inc hl
ld (hl),0
;TEST.C: 149: ivector[ i2 ] = 2;
;повтор вычислений, но запоминание смещения-
;недостаток модели распределения регистров
ld hl,(_i2)
add hl,hl
add hl,de
ld (hl),02h
inc hl
ld (hl),0
;TEST.C: 150: ivector[ 2 ] = 3;
;тоже логично :)
ld hl,03h
ld (_ivector+04h),hl
9.Удаление общих подвыражений
Код:
;TEST.C: 157: if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 )
ld hl,(_h3)
ld de,(_k3)
add hl,de
;наконец-то вспомнили о битовых операциях...
bit 07h,h
jp nz,u90
;а тут косяк- нахрена подобные вычисления?
;переменные ведь не volatile...
ld de,06h
ld hl,(_h3)
ld bc,(_k3)
add hl,bc
call wrelop
jp m,u91
u90:
;TEST.C: 158: printf("Common subexpression elimination\n");
ld hl,u29
push hl
call _printf
pop bc
;TEST.C: 159: else {
jp l18
u91:
;TEST.C: 160: m3 = ( h3 + k3 ) / i3;
;опять вычисления с нуля
ld de,(_i3)
ld hl,(_h3)
ld bc,(_k3)
add hl,bc
call adiv
ld (_m3),hl
;TEST.C: 161: g3 = i3 + (h3 + k3);
;фиаско! никаких промежуточных сохранений результатов
ld hl,(_i3)
ld de,(_h3)
add hl,de
ld de,(_k3)
add hl,de
ld (_g3),hl
l18:
;TEST.C: 162: }
10.Вынесение инвариантного кода
Код:
;TEST.C: 168: for( i4 = 0; i4 <= 2; i4++)
;все тот же бешеный цикл...
ld hl,0
ld (_i4),hl
ld de,03h
ld hl,(_i4)
call wrelop
jp p,l20
l19:
;TEST.C: 169: ivector2[ i4 ] = j * k;
;полная Ж... вычисление j * k в каждой итерации цикла
ld a,(_k)
ld e,a
ld d,0
ld a,(_j)
ld l,a
ld h,d
call lmul
ld a,l
ld hl,(_i4)
ld de,_ivector2
add hl,de
ld (hl),a
ld hl,(_i4)
inc hl
ld (_i4),hl
ld de,03h
call wrelop
jp m,l19
l20: