Forth
http://fforum.winglion.ru/

Глазковая оптимизация в Форте
http://fforum.winglion.ru/viewtopic.php?f=58&t=3185
Страница 1 из 2

Автор:  Victor__v [ Вт июл 24, 2018 00:22 ]
Заголовок сообщения:  Глазковая оптимизация в Форте

Оптимизатор работает как библиотека.
На данный момент при подключении сего творения (~er\opt\optimaizer.f) в контексте появится врем. словарь, в котором и содержатся обработчики оптимизаций.

Что сейчас есть:
Замена арифметических и пр. операций на итоговое значение.
К примеру вместо последовательности 10 2 * 5 + в коде сразу будет 25
Как это ни странно, но оптимизатор Новы тут несколько предсказуемей СПФа (вбейте в последнем : TEST 200 10 / ; и посмотрите дизассемблером)

Замена операций со стеком возвратов, пользовательскими переменными...
Замена операций со стеком данных. Внезапно, их всего две, да и то сделаны под нужды самого оптимизатора.

Замена условий IF и WHILE
Оптимизировал только более-менее часто встречающиеся варианты в своём коде. Вариантов на самом деле уйма.

И немного мелочи.
Тестовая компиляция выявила уменьшение объёма откомпилированных библиотек где-то на 2 кб. (без оптимизатора 14 кб).

Автор:  chess [ Вт авг 21, 2018 22:47 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Рассмотрим варианты реализации в коде конкатенации строк для SPF и VFX,
в которых как раз используется глазковая оптимизация.
Код:
\ SPF
: s+(spf) ( a1 u1 a2 u2 -- a u )
  >R OVER R@ + ALLOCATE THROW
  DUP >R -ROT >R DUP >R MOVE
  R> R> R> ROT 2DUP + -ROT R@
  -ROT >R >R MOVE R> R> R> +
;
: s+(spfl) { a1 u1 a2 u2 \ a -- a u }
u1 u2 + ALLOCATE THROW TO a
a1 a u1 MOVE a2 a u1 + u2 MOVE a u1 u2 +
;

SEE s+(spf)
SEE s+(spfl)

CODE s+(spf)
5DA2A3 50               PUSH    EAX
5DA2A4 8B4504           MOV     EAX , 4 [EBP]
5DA2A7 030424           ADD     EAX , [ESP]
5DA2AA E8EDACF7FF       CALL    554F9C  ( ALLOCATE )
5DA2AF E800AEF7FF       CALL    5550B4  ( THROW )
5DA2B4 50               PUSH    EAX
5DA2B5 8B5504           MOV     EDX , 4 [EBP]
5DA2B8 894504           MOV     4 [EBP] , EAX
5DA2BB 8B4500           MOV     EAX , 0 [EBP]
5DA2BE 895500           MOV     0 [EBP] , EDX
5DA2C1 50               PUSH    EAX
5DA2C2 8B4500           MOV     EAX , 0 [EBP]
5DA2C5 50               PUSH    EAX
5DA2C6 8D6D04           LEA     EBP , 4 [EBP]
5DA2C9 E8B69AF7FF       CALL    553D84  ( MOVE )
5DA2CE 8945FC           MOV     FC [EBP] , EAX
5DA2D1 58               POP     EAX
5DA2D2 59               POP     ECX
5DA2D3 8BD1             MOV     EDX , ECX
5DA2D5 59               POP     ECX
5DA2D6 894DF4           MOV     F4 [EBP] , ECX
5DA2D9 8955F8           MOV     F8 [EBP] , EDX
5DA2DC 8BD1             MOV     EDX , ECX
5DA2DE 8945F0           MOV     F0 [EBP] , EAX
5DA2E1 8D0402           LEA     EAX , [EDX] [EAX]
5DA2E4 8B55F4           MOV     EDX , F4 [EBP]
5DA2E7 8945F4           MOV     F4 [EBP] , EAX
5DA2EA 8B45F0           MOV     EAX , F0 [EBP]
5DA2ED 8955F0           MOV     F0 [EBP] , EDX
5DA2F0 8B0C24           MOV     ECX , [ESP]
5DA2F3 8B55F0           MOV     EDX , F0 [EBP]
5DA2F6 894DF0           MOV     F0 [EBP] , ECX
5DA2F9 8955EC           MOV     EC [EBP] , EDX
5DA2FC 50               PUSH    EAX
5DA2FD 8B45EC           MOV     EAX , EC [EBP]
5DA300 50               PUSH    EAX
5DA301 8B45F0           MOV     EAX , F0 [EBP]
5DA304 8D6DF4           LEA     EBP , F4 [EBP]
5DA307 E8789AF7FF       CALL    553D84  ( MOVE )
5DA30C 8945FC           MOV     FC [EBP] , EAX
5DA30F 58               POP     EAX
5DA310 8945F8           MOV     F8 [EBP] , EAX
5DA313 58               POP     EAX
5DA314 59               POP     ECX
5DA315 8D0408           LEA     EAX , [EAX] [ECX]
5DA318 8D6DF8           LEA     EBP , F8 [EBP]
5DA31B C3               RET     NEAR
END-CODE
( 121 bytes, 47 instructions )

CODE s+(spfl)
5DA333 8945FC           MOV     FC [EBP] , EAX
5DA336 B810000000       MOV     EAX , # 10
5DA33B 8D6DFC           LEA     EBP , FC [EBP]
5DA33E E8A58DF7FF       CALL    5530E8  ( DRMOVE )
5DA343 8945FC           MOV     FC [EBP] , EAX
5DA346 B801000000       MOV     EAX , # 1
5DA34B 8D6DFC           LEA     EBP , FC [EBP]
5DA34E E8D18EF7FF       CALL    553224  ( (RALLOT) )
5DA353 6814000000       PUSH    , # 14
5DA358 686C325500       PUSH    , # 55326C
5DA35D 8945FC           MOV     FC [EBP] , EAX
5DA360 8B442414         MOV     EAX , 14 [ESP]
5DA364 0344240C         ADD     EAX , C [ESP]
5DA368 8D6DFC           LEA     EBP , FC [EBP]
5DA36B E82CACF7FF       CALL    554F9C  ( ALLOCATE )
5DA370 E83FADF7FF       CALL    5550B4  ( THROW )
5DA375 89442408         MOV     8 [ESP] , EAX
5DA379 8B442418         MOV     EAX , 18 [ESP]
5DA37D 8945FC           MOV     FC [EBP] , EAX
5DA380 8B442408         MOV     EAX , 8 [ESP]
5DA384 8945F8           MOV     F8 [EBP] , EAX
5DA387 8B442414         MOV     EAX , 14 [ESP]
5DA38B 8D6DF8           LEA     EBP , F8 [EBP]
5DA38E E8F199F7FF       CALL    553D84  ( MOVE )
5DA393 8945FC           MOV     FC [EBP] , EAX
5DA396 8B442410         MOV     EAX , 10 [ESP]
5DA39A 8945F8           MOV     F8 [EBP] , EAX
5DA39D 8B442408         MOV     EAX , 8 [ESP]
5DA3A1 03442414         ADD     EAX , 14 [ESP]
5DA3A5 8945F4           MOV     F4 [EBP] , EAX
5DA3A8 8B44240C         MOV     EAX , C [ESP]
5DA3AC 8D6DF4           LEA     EBP , F4 [EBP]
5DA3AF E8D099F7FF       CALL    553D84  ( MOVE )
5DA3B4 8945FC           MOV     FC [EBP] , EAX
5DA3B7 8B442408         MOV     EAX , 8 [ESP]
5DA3BB 8945F8           MOV     F8 [EBP] , EAX
5DA3BE 8B442414         MOV     EAX , 14 [ESP]
5DA3C2 0344240C         ADD     EAX , C [ESP]
5DA3C6 8D6DF8           LEA     EBP , F8 [EBP]
5DA3C9 C3               RET     NEAR
END-CODE
( 151 bytes, 40 instructions )


\ VFX
: s+(vfx) ( a1 u1 a2 u2 -- a u )
  >R OVER R@ + ALLOCATE THROW
  DUP >R -ROT >R DUP >R MOVE
  R> R> R> ROT 2DUP + -ROT R@
  -ROT >R >R MOVE R> R> R> +
;
: s+(vfxl) {: a1 u1 a2 u2 | a  -- a u :}
u1 u2 + ALLOCATE THROW TO a
a1 a u1 MOVE a2 a u1 + u2 MOVE a u1 u2 +

SEE s+(vfx)
SEE s+(vfxl)

s+(vfx)
( 004D45D0    53 )                    PUSH      EBX
( 004D45D1    8B1C24 )                MOV       EBX, [ESP]
( 004D45D4    035D04 )                ADD       EBX, [EBP+04]
( 004D45D7    FF1591604100 )          CALL      [00416091]      ALLOCATE
( 004D45DD    E82AECF3FF )            CALL      0041320C        THROW
( 004D45E2    53 )                    PUSH      EBX
( 004D45E3    FF7500 )                PUSH      [EBP]
( 004D45E6    8B5504 )                MOV       EDX, [EBP+04]
( 004D45E9    52 )                    PUSH      EDX
( 004D45EA    895D04 )                MOV       [EBP+04], EBX
( 004D45ED    8BDA )                  MOV       EBX, EDX
( 004D45EF    8D6D04 )                LEA       EBP, [EBP+04]
( 004D45F2    E88902F3FF )            CALL      00404880        MOVE
( 004D45F7    5A )                    POP       EDX
( 004D45F8    59 )                    POP       ECX
( 004D45F9    58 )                    POP       EAX
( 004D45FA    8D6DEC )                LEA       EBP, [EBP+-14]
( 004D45FD    894500 )                MOV       [EBP], EAX
( 004D4600    895504 )                MOV       [EBP+04], EDX
( 004D4603    894508 )                MOV       [EBP+08], EAX
( 004D4606    894D0C )                MOV       [EBP+0C], ECX
( 004D4609    895D10 )                MOV       [EBP+10], EBX
( 004D460C    8BDA )                  MOV       EBX, EDX
( 004D460E    035D00 )                ADD       EBX, [EBP]
( 004D4611    8B1424 )                MOV       EDX, [ESP]
( 004D4614    FF7504 )                PUSH      [EBP+04]
( 004D4617    FF7508 )                PUSH      [EBP+08]
( 004D461A    895D08 )                MOV       [EBP+08], EBX
( 004D461D    8BDA )                  MOV       EBX, EDX
( 004D461F    8D6D08 )                LEA       EBP, [EBP+08]
( 004D4622    E85902F3FF )            CALL      00404880        MOVE
( 004D4627    5A )                    POP       EDX
( 004D4628    59 )                    POP       ECX
( 004D4629    58 )                    POP       EAX
( 004D462A    03C1 )                  ADD       EAX, ECX
( 004D462C    8D6DF8 )                LEA       EBP, [EBP+-08]
( 004D462F    895500 )                MOV       [EBP], EDX
( 004D4632    895D04 )                MOV       [EBP+04], EBX
( 004D4635    8BD8 )                  MOV       EBX, EAX
( 004D4637    C3 )                    NEXT,
( 104 bytes, 40 instructions )

SEE s+(vfxl)
s+(vfxl)
( 004D46A0    8BD4 )                  MOV       EDX, ESP
( 004D46A2    FF7508 )                PUSH      [EBP+08]
( 004D46A5    FF7504 )                PUSH      [EBP+04]
( 004D46A8    FF7500 )                PUSH      [EBP]
( 004D46AB    53 )                    PUSH      EBX
( 004D46AC    52 )                    PUSH      EDX
( 004D46AD    57 )                    PUSH      EDI
( 004D46AE    8BFC )                  MOV       EDI, ESP
( 004D46B0    81EC04000000 )          SUB       ESP, 00000004
( 004D46B6    8B5D0C )                MOV       EBX, [EBP+0C]
( 004D46B9    8D6D10 )                LEA       EBP, [EBP+10]
( 004D46BC    8B5708 )                MOV       EDX, [EDI+08]
( 004D46BF    035710 )                ADD       EDX, [EDI+10]
( 004D46C2    8D6DFC )                LEA       EBP, [EBP+-04]
( 004D46C5    895D00 )                MOV       [EBP], EBX
( 004D46C8    8BDA )                  MOV       EBX, EDX
( 004D46CA    FF1591604100 )          CALL      [00416091]      ALLOCATE
( 004D46D0    E837EBF3FF )            CALL      0041320C        THROW
( 004D46D5    895FFC )                MOV       [EDI+-04], EBX
( 004D46D8    8D6DF8 )                LEA       EBP, [EBP+-08]
( 004D46DB    8B5F10 )                MOV       EBX, [EDI+10]
( 004D46DE    8B57FC )                MOV       EDX, [EDI+-04]
( 004D46E1    895500 )                MOV       [EBP], EDX
( 004D46E4    8B5714 )                MOV       EDX, [EDI+14]
( 004D46E7    895504 )                MOV       [EBP+04], EDX
( 004D46EA    E89101F3FF )            CALL      00404880        MOVE
( 004D46EF    8B5710 )                MOV       EDX, [EDI+10]
( 004D46F2    0357FC )                ADD       EDX, [EDI+-04]
( 004D46F5    8D6DF4 )                LEA       EBP, [EBP+-0C]
( 004D46F8    895500 )                MOV       [EBP], EDX
( 004D46FB    8B570C )                MOV       EDX, [EDI+0C]
( 004D46FE    895504 )                MOV       [EBP+04], EDX
( 004D4701    895D08 )                MOV       [EBP+08], EBX
( 004D4704    8B5F08 )                MOV       EBX, [EDI+08]
( 004D4707    E87401F3FF )            CALL      00404880        MOVE
( 004D470C    8B5708 )                MOV       EDX, [EDI+08]
( 004D470F    035710 )                ADD       EDX, [EDI+10]
( 004D4712    8D6DF8 )                LEA       EBP, [EBP+-08]
( 004D4715    8B4FFC )                MOV       ECX, [EDI+-04]
( 004D4718    894D00 )                MOV       [EBP], ECX
( 004D471B    895D04 )                MOV       [EBP+04], EBX
( 004D471E    8BDA )                  MOV       EBX, EDX
( 004D4720    8B6704 )                MOV       ESP, [EDI+04]
( 004D4723    8B3F )                  MOV       EDI, 0 [EDI]
( 004D4725    C3 )                    NEXT,
( 134 bytes, 45 instructions )
ok

Теперь напишем это по другому ( в SPF )
Код:
: s+(spfsa) \ a1 u1 a2 u2 -- a u
DUP $ 8 A+@P ALLOCATE THROW
5$54354152 $ 0x14 @P+A $ 0xC @P+A MOVE MOVE
;

SEE s+(spfsa)
CODE s+(spfsa)
5DA3E3 8945FC           MOV     FC [EBP] , EAX
5DA3E6 8D6DFC           LEA     EBP , FC [EBP]
5DA3E9 034508           ADD     EAX , 8 [EBP]
5DA3EC E8ABABF7FF       CALL    554F9C  ( ALLOCATE )
5DA3F1 E8BEACF7FF       CALL    5550B4  ( THROW )
5DA3F6 8B5D0C           MOV     EBX , C [EBP]
5DA3F9 8B7500           MOV     ESI , 0 [EBP]
5DA3FC 89450C           MOV     C [EBP] , EAX
5DA3FF 894500           MOV     0 [EBP] , EAX
5DA402 8945F4           MOV     F4 [EBP] , EAX
5DA405 8B4508           MOV     EAX , 8 [EBP]
5DA408 897508           MOV     8 [EBP] , ESI
5DA40B 8975FC           MOV     FC [EBP] , ESI
5DA40E 895DF8           MOV     F8 [EBP] , EBX
5DA411 8D6DF4           LEA     EBP , F4 [EBP]
5DA414 014500           ADD     0 [EBP] , EAX
5DA417 014500           ADD     0 [EBP] , EAX
5DA41A E86599F7FF       CALL    553D84  ( MOVE )
5DA41F E86099F7FF       CALL    553D84  ( MOVE )
5DA424 C3               RET     NEAR
END-CODE
( 66 bytes, 20 instructions )

ПС.
Результат значительно лучше.
Просматривается другой более эффективный подход к оптимизации:
в стек забрасывается сразу необходимое(пусть и большое) количество параметров,
затем идут операции между параметрами как правило не фортовские,
с сохранением результатов не на вершине стека, а внутри стека
(стек при этом по глубине не меняется), в конечном итоге в стеке
лежит набор параметров, необходимый для последовательной работы слов,
выполняющим основной объем работы( в данном случае это MOVE MOVE ).
Такой подход похоже будет попроще в реализации и эффективнее по результату, чем глазковая оптимизация.

Автор:  KPG [ Ср авг 22, 2018 03:44 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Ещё вариант работы со стеком. (возможно ещё где то можно ужаться) :)
Код:
: s+  \ a1 u1 a2 u2  -- a u
DUP 3 PICK +  DUP >R  ALLOCATE THROW  DUP >R
3 PICK + SWAP MOVE   R@ SWAP MOVE   R>  R>
;

SEE s+ (spf4)
Код:
5729DF 8945FC           MOV     FC [EBP] , EAX
5729E2 034504           ADD     EAX , 4 [EBP]
5729E5 50               PUSH    EAX
5729E6 8D6DFC           LEA     EBP , FC [EBP]
5729E9 E8AE25FEFF       CALL    554F9C  ( ALLOCATE )
5729EE E8C126FEFF       CALL    5550B4  ( THROW )
5729F3 50               PUSH    EAX
5729F4 034508           ADD     EAX , 8 [EBP]
5729F7 8B5500           MOV     EDX , 0 [EBP]
5729FA 894500           MOV     0 [EBP] , EAX
5729FD 8BC2             MOV     EAX , EDX
5729FF E88013FEFF       CALL    553D84  ( MOVE )
572A04 8BD0             MOV     EDX , EAX
572A06 8B0424           MOV     EAX , [ESP]
572A09 8945FC           MOV     FC [EBP] , EAX
572A0C 8BC2             MOV     EAX , EDX
572A0E 8D6DFC           LEA     EBP , FC [EBP]
572A11 E86E13FEFF       CALL    553D84  ( MOVE )
572A16 8945FC           MOV     FC [EBP] , EAX
572A19 58               POP     EAX
572A1A 8945F8           MOV     F8 [EBP] , EAX
572A1D 58               POP     EAX
572A1E 8D6DF8           LEA     EBP , F8 [EBP]
572A21 C3               RET     NEAR
END-CODE 
( 68 bytes, 24 instructions )

see s+ (vfx)
Код:
( 004D4620    8BD3 )                  MOV       EDX, EBX
( 004D4622    035D04 )                ADD       EBX, [EBP+04]
( 004D4625    53 )                    PUSH      EBX
( 004D4626    8D6DFC )                LEA       EBP, [EBP+-04]
( 004D4629    895500 )                MOV       [EBP], EDX
( 004D462C    FF1591604100 )          CALL      [00416091]      ALLOCATE
( 004D4632    E8D5EBF3FF )            CALL      0041320C        THROW
( 004D4637    53 )                    PUSH      EBX
( 004D4638    035D08 )                ADD       EBX, [EBP+08]
( 004D463B    8BD3 )                  MOV       EDX, EBX
( 004D463D    8B5D00 )                MOV       EBX, [EBP]
( 004D4640    895500 )                MOV       [EBP], EDX
( 004D4643    E83802F3FF )            CALL      00404880        MOVE
( 004D4648    8B1424 )                MOV       EDX, [ESP]
( 004D464B    8D6DFC )                LEA       EBP, [EBP+-04]
( 004D464E    895500 )                MOV       [EBP], EDX
( 004D4651    E82A02F3FF )            CALL      00404880        MOVE
( 004D4656    5A )                    POP       EDX
( 004D4657    59 )                    POP       ECX
( 004D4658    8D6DF8 )                LEA       EBP, [EBP+-08]
( 004D465B    895500 )                MOV       [EBP], EDX
( 004D465E    895D04 )                MOV       [EBP+04], EBX
( 004D4661    8BD9 )                  MOV       EBX, ECX
( 004D4663    C3 )                    NEXT,
( 68 bytes, 24 instructions )


P.S. Но, больше интересен замер скорости разных этих вариантов.

Автор:  Victor__v [ Ср авг 22, 2018 09:39 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Ну Нова так не смогёт :)
Девочка ещё не научилась.
К тому же в ваших примерах достаточно стекомаханий.
Максимум, что Нова сможет оптимизировать, так это связку DUP >R , да и то не уверен прописывал ли такой сценарий.

Мой вариант кода:
Код:
: S+
4 N>R
1 RPICK 3 RPICK + DUP CELL+ ALLOCATE THROW      \ CELL+ для нуля в конце
4 RPICK OVER 3 RPICK MOVE
2 RPICK OVER 3 RPICK + 1 RPICK MOVE
SWAP
5 CELLS RP@ + RP!               \ оптимизируется в одну инструкцию
;


Мне кажется слова такого рода не самый лучший пример для работы оптимизатора
В любом случае вызовы ALLOCATE MOVE THROW никто не отменял. А жрут-то они, особенно первый представитель ряда

Автор:  chess [ Ср авг 22, 2018 21:35 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

KPG писал(а):
Ещё вариант работы со стеком. (возможно ещё где то можно ужаться)

Эквилибр на стеке? Как-то не хочется на это тратить время.
Я, первое, что приходило в голову, то и писал на plain форте для реализации s+.
А насчет оптимизации, то то, что я предложил можно использовать и в "ручном" режиме:

Определение групп слов типа 'M+N', 'M-N', 'MorN', 'MandN', 'MxorN', M=N,
где M и N номера ячеек стека (Mmax = 9, Nmax = 9)
0 - это вершина(в регистре EAX), 1 - это ячейка под вершиной и тд
результат операции помещается в ячейку с номером M (всего около 600 вариантов от 0+0 до 9=9)

Код:
: eax+eax  0xC003 W,    ;
: eax+@ebp 0x4503 W, C, ;
: @ebp+eax 0x4501 W, C, ;
: ebx=@ebp 0x5D8B W, C, ;
: @ebp+ebx 0x5D01 W, C, ;
: eax-@ebp 0x452B W, C, ;
: @ebp-eax 0x4529 W, C, ;
: @ebp-ebx 0x5D29 W, C, ;
: eax|@ebp 0x450B W, C, ;
: @ebp|eax 0x4509 W, C, ;
: @ebp|ebx 0x5D09 W, C, ;
: eax&@ebp 0x4523 W, C, ;
: @ebp&eax 0x4521 W, C, ;
: @ebp&ebx 0x5D21 W, C, ;
: eax^eax  0xC033 W,    ;
: eax^@ebp 0x4533 W, C, ;
: @ebp^eax 0x4531 W, C, ;
: @ebp^ebx 0x5D31 W, C, ;
: eax=@ebp 0x458B W, C, ;
: @ebp=eax 0x4589 W, C, ;
: @ebp=ebx 0x5D89 W, C, ;

: NOTFOUND { a u \ p1 p2 op -- }
  a C@ TO p1 a 1+ C@ TO op a 2+ C@ TO p2
  u 3 <> p1 '0' ':' WITHIN p2 '0' ':' WITHIN OR 0= OR
  op '+' = op '-' = OR op '|' = OR op '&' = OR op '^' = OR op '=' = OR 0=  OR
  IF a u NOTFOUND EXIT THEN
  p1 '0' - 1- 4 * TO p1 p2 '0' - 1- 4 * TO p2
  p1 0< p2 0< AND op '+' = AND    IF eax+eax     EXIT THEN
  p1 0< p2 0< 0= AND op '+' = AND IF p2 eax+@ebp EXIT THEN
  p1 0< 0= p2 0< AND op '+' = AND IF p1 @ebp+eax EXIT THEN
  p1 0< 0= p2 0< 0= AND op '+' = AND IF p2 ebx=@ebp p1 @ebp+ebx EXIT THEN
  p1 0< p2 0< 0= AND op '-' = AND IF p2 eax-@ebp EXIT THEN
  p1 0< 0= p2 0< AND op '-' = AND IF p1 @ebp-eax EXIT THEN
  p1 0< 0= p2 0< 0= AND op '-' = AND IF p2 ebx=@ebp p1 @ebp-ebx EXIT THEN
  p1 0< p2 0< 0= AND op '|' = AND IF p2 eax|@ebp EXIT THEN
  p1 0< 0= p2 0< AND op '|' = AND IF p1 @ebp|eax EXIT THEN
  p1 0< 0= p2 0< 0= AND op '|' = AND IF p2 ebx=@ebp p1 @ebp|ebx EXIT THEN
  p1 0< p2 0< 0= AND op '&' = AND IF p2 eax&@ebp EXIT THEN
  p1 0< 0= p2 0< AND op '&' = AND IF p1 @ebp&eax EXIT THEN
  p1 0< 0= p2 0< 0= AND op '&' = AND IF p2 ebx=@ebp p1 @ebp&ebx EXIT THEN
  p1 0< p2 0< AND op '^' = AND    IF eax^eax     EXIT THEN
  p1 0< p2 0< 0= AND op '^' = AND IF p2 eax^@ebp EXIT THEN
  p1 0< 0= p2 0< AND op '^' = AND IF p1 @ebp^eax EXIT THEN
  p1 0< 0= p2 0< 0= AND op '^' = AND IF p2 ebx=@ebp p1 @ebp^ebx EXIT THEN
  p1 0< p2 0< 0= AND op '=' = AND IF p2 eax=@ebp EXIT THEN
  p1 0< 0= p2 0< AND op '=' = AND IF p1 @ebp=eax EXIT THEN
  p1 0< 0= p2 0< 0= AND op '=' = AND IF p2 ebx=@ebp p1 @ebp=ebx EXIT THEN
;
\ и тогда для s+
            \ 3  2  1  0
: s+(spfsa) \ a1 u1 a2 u2 -- a u
DUP  0+3 ALLOCATE THROW
\ 76543210 - номера ячеек
5$54354152 6+0 4+0 MOVE MOVE
;

пс.
DUP-ами растягиваем стек, формируем набор параметров из уже существующих на стеке и тд...
Можно, если нужно, легко дополнить и другими операциями( *, /, MOD и тп и тд ).
Получается что-то типа стекового ассемблера. Непереносимо, но Форт-программы и так практически не переносятся, несмотря на наличие всяких стандартов.

Автор:  KPG [ Ср авг 22, 2018 23:56 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

chess писал(а):
Эквилибр на стеке? Как-то не хочется на это тратить время.

Отнюдь. :) Правильное понимание механики возможностей стека.
И да, четыре входных параметров слова на стеке - это не типичный случай.
В этом варианте строки могут быть и со счётчиком.

Автор:  Victor__v [ Чт авг 23, 2018 15:46 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

chess писал(а):
KPG писал(а):
Ещё вариант работы со стеком. (возможно ещё где то можно ужаться)

Эквилибр на стеке?
Получается что-то типа стекового ассемблера. Непереносимо, но Форт-программы и так практически не переносятся, несмотря на наличие всяких стандартов.


Хм, у меня есть похожий.
Только вместо безконечной череды IF THEN
Поиск ведётся в словаре.

И в чём проблема переносимости?
К примеру для новой архитектуры, моему варианту придётся всего лишь подключить другой форт-ассемблер и переписать алиасы

Если уж говорить о работе такого слова, как s+
то быстрее всего будет реализовать на асме, если уж очень критично

Автор:  chess [ Чт авг 30, 2018 09:52 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Уменьшил объем писанины путем использования макросов, расширил количество групп слов
пересылками из ячейки в ячейку и обменом между ячейками, а также ввел группу по увеличению
глубины стека
Код:
\ инструкции
: a+a  0xC003 W,    ;
: a+@p 0x4503 W, C, ;
: @p+a 0x4501 W, C, ;
: b=@p 0x5D8B W, C, ;
: @p+b 0x5D01 W, C, ;
: a-@p 0x452B W, C, ;
: @p-a 0x4529 W, C, ;
: @p-b 0x5D29 W, C, ;
: a|@p 0x450B W, C, ;
: @p|a 0x4509 W, C, ;
: @p|b 0x5D09 W, C, ;
: a&@p 0x4523 W, C, ;
: @p&a 0x4521 W, C, ;
: @p&b 0x5D21 W, C, ;
: a^a  0xC033 W,    ;
: a^@p 0x4533 W, C, ;
: @p^a 0x4531 W, C, ;
: @p^b 0x5D31 W, C, ;
: a=@p 0x458B W, C, ;
: @p=a 0x4589 W, C, ;
: @p=b 0x5D89 W, C, ;
: b=a  0xD88B W,    ;
: a=b  0xC38B W,    ;
: d=@p 0x558B W, C, ;
: @p=d 0x5589 W, C, ;
: p+   0x6D8D W, C, ;

\ макросы
M: b00 op = p1 0< p2 0< AND AND IF ;
M: bp0 op = p1 0< 0= p2 0< AND AND IF ;
M: b0p op = p1 0< p2 0< 0= AND AND IF ;
M: bpp op = p1 0< 0= p2 0< 0= AND AND IF ;
M: end EXIT THEN ;

\ определение групп слов типа 'M+N', 'M-N', 'M|N', 'M&N', 'M^N',
\ M=N(пересылка из N в M), M~N(swap M N), M_0(увеличение глубины стека)
\ где M и N номера ячеек стека (Mmax = 9, Nmax = 9)
\ 0 - это вершина(в регистре EAX), 1 - это ячейка под вершиной и тд
\ результат операции помещается в ячейку с номером M (всего около 700 вариантов от 0+0 до 9~9)
: NOTFOUND { a u \ p1 p2 op -- }
  a C@ TO p1 a 1+ C@ TO op a 2+ C@ TO p2
  u 3 <> p1 '0' ':' WITHIN p2 '0' ':' WITHIN OR 0= OR
  op '_' = op '+' = OR op '-' = OR op '|' = OR op '&' = OR op '^' = OR op '=' = OR op '~' = OR 0=  OR
  IF a u NOTFOUND EXIT THEN
  p1 '0' - 1- 4 * TO p1 p2 '0' - 1- 4 * TO p2
  '+' b00 a+a end  '+' b0p p2 a+@p end  '+' bp0 p1 @p+a end  '+' bpp p2 b=@p p1 @p+b end
                   '-' b0p p2 a-@p end  '-' bp0 p1 @p-a end  '-' bpp p2 b=@p p1 @p-b end
                   '|' b0p p2 a|@p end  '|' bp0 p1 @p|a end  '|' bpp p2 b=@p p1 @p|b end
                   '&' b0p p2 a&@p end  '&' bp0 p1 @p&a end  '&' bpp p2 b=@p p1 @p&b end
  '^' b00 a^a end  '^' b0p p2 a^@p end  '^' bp0 p1 @p^a end  '^' bpp p2 b=@p p1 @p^b end
                   '=' b0p p2 a=@p end  '=' bp0 p1 @p=a end  '=' bpp p2 b=@p p1 @p=b end
  '~' b0p b=a p2 a=@p p2 @p=b end  '~' bp0 p1 b=@p p1 @p=a a=b end  '~' bpp p2 b=@p p1 d=@p p1 @p=b p2 @p=d end
  '_' bp0 p1 CELL+ NEGATE p+ end
;

PS.
Получил "побочный" результат на лексеме 1_0(увеличение глубины стека на 1 ячейку).
Код:
: tst 1_0 ; SEE tst
CODE tst
5DB217 8D6DFC           LEA     EBP , FC [EBP]
5DB21A C3               RET     NEAR
END-CODE
( 4 bytes, 2 instructions )

Ok
1 tst
Ok ( 1 1 )

1_0 работает как DUP, т.е. DUP
можно определить проще, а именно:
Код:
: DUP $ -4 Pa ;
или
Код:
CODE DUP
LEA     EBP , FC [EBP]
RET     NEAR
END-CODE

Автор:  Victor__v [ Чт авг 30, 2018 16:37 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

DUP
Копирует верхний элемент стека, а не выделяет на нём память :) :P

Корректней
Код:
LEA EBP, [EBP-CELL]
MOV [EBP], EAX
RET


Или в моём варианте:
Код:
0/00

Автор:  chess [ Чт авг 30, 2018 21:14 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Victor__v писал(а):
DUP
Копирует верхний элемент стека, а не выделяет на нём память

Точнее увеличивает глубину стека на одну ячейку памяти, которая становится новой верхней ячейкой стека.
В эту новую верхнюю ячейку копирует данные из предыдущей верхней ячейки стека(это когда стек весь в памяти).
В SPF верхняя ячейка стека находится в регистре EAX, поэтому его содержимое копируется в новую добавленную ячейку стека.
Если просто добавить ячейку в стек, передвинув указатель на эту добавленную ячейку без копирования в нее содержимого
EAX, то в этой ячейке стека должно быть неопределенное значение, а на практике это не так. Мне это непонятно. :(

Автор:  Victor__v [ Пт авг 31, 2018 04:06 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Скомпилируй пару таких инструкций подряд в слове и вызови его.
И просветление не за горами :)

Автор:  chess [ Пт авг 31, 2018 08:50 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Victor__v писал(а):
Скомпилируй пару таких инструкций подряд в слове и вызови его.
И просветление не за горами

Меня интересует вариант не только с компиляцией, но и с интерпретацией, хотя и с компиляцией
непонятки остаются(по вашему предложению только одна ячейка остается в неопределенном состоянии, а должно
быть две). Подозреваю, что это связано с работой встроенного оптимизатора, но лобовой вариант его отключения
(типа DIS-OPT и 0 TO MM_SIZE) ничего не дает. А при интерпретации что DUP что dup дают один результат:

Код:
: dup $ -4 Pa ;  SEE dup


CODE dup
5DA29F 8D6DFC LEA EBP , FC [EBP]
5DA2A2 C3 RET NEAR
END-CODE
( 4 bytes, 2 instructions )

Код:
1 dup dup

Ok ( 1 1 1 )

Автор:  Victor__v [ Пт авг 31, 2018 17:47 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Думаю, нет смысла обсуждать эту скрытую фичу.
Лучше уж обсудить как лучше делать разбор кода постфактум (для форта это наиболее надёжно).
Хотя это уже не глазковая оптимизация, так как можно к коду применять параметры (скорость, размер и их комбинации)

Автор:  Victor__v [ Вс фев 24, 2019 21:53 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Оптимизация в Nova-forth
Зачем она нужна?
Повышение ТТХ Новы и приложений написанных на ней (размер, скорость и пр.).

Как сейчас обстоят дела?
При целевой компиляции размер Новы ужимается примерно на 2 кб. Эта работа делается препроцессором написанным на форте. Простота заданий подстановок делает препроцессор идеальным вариантом для сборки стабильного форт-кода (т. е. без полиморфизма).

Но для оптимизации кода для приложений он может не подойти из-за того же полиморфизма.

Поэтому в Нове по умолчанию (прописано в INI-файле) используется простейший оптимизатор нативного форт-кода.
Что примечательно, ассемблер в этом случае не участвует вообще никак. Всё достигается самими средствами форта. Что повышает пригодность оптимизатора к разным разрядностям и архитектурам. По крайней мере, портировать будет достаточно просто.

Однако ограничения "использовать только форт" и "не использовать ассемблер" сказываются на списке правил оптимизации - их мало.
По этой причине использование такого оптимизатора даёт результат минимум эффекта при минимуме усилий.
Также в 6-м обновлении этот оптимизатор был несколько "усилен". Так в нём появились правила, которые "проверяют на вшивость" следующее слово. Но поскольку оптимизатор применяется на месте (где указан соответствующий контекст и состояние глоб. переменных), то такой закос под препроцессор не играет роли.

Моя скромная мечта написать нормальный оптимизатор с ассемблером в своё время наткнулась на необходимость дизассемблера, чтобы после компактификации кода по правилам убрать последние "косяки", программные "криворукости" и то, что в падлу вычленять фортом. Однако на данным момент "нормальный" оптимизатор заброшен. И работоспособность кода на выходе давно (полтора месяца, минимум) не тестировалась.

Автор:  Hishnik [ Вс фев 24, 2019 23:02 ]
Заголовок сообщения:  Re: Глазковая оптимизация в Форте

Victor__v писал(а):
Повышение ТТХ Новы и приложений написанных на ней (размер, скорость и пр.).

А, в свою очередь, зачем нужно вот это?

Страница 1 из 2 Часовой пояс: UTC + 3 часа [ Летнее время ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/