pic
pic copied to clipboard
Unnecessary instructions in LOOP forms
Situation
The language's loop
form, currently implemented as a PIC macro, is compiled into instructions including SUBWF
, BTFSC
and a recursive function call.
For example, the following expression:
(loop 10
0) ; nop
is expanded into:
(let ((_loop (i)
(if (= i 0)
0
(progn
0
(_loop (- i 1))))))
(_loop 10)
then, is compiled into:
MOVLW 00Ah
MOVLW I0
GOTO __LOOP1014
__LOOP1014
MOVF I0,W
MOVWF L0
MOVLW 000h
SUBWF L0,W
BTFSC STATUS,Z
GOTO _ELSE10
RETLW 000h
_ELSE10
MOVLW 001h
SUBWF L0,W
MOVWF L1
MOVF L1,W
MOVWF I0
GOTO __LOOP1014
Problem
There are unnecessary instructions in the compiled assembly compared with the case using DECFSZ
instruction.
- get from and put into an input pseudo-register
- the first
GOTO
instruction - a conditional branch with
SUBWF
andBTFSC
instructions -
SUBWF
instruction for decrement
Goal
Make loop
forms compiled into instructions using DECFSZ
instruction.
MOVLW 00Ah
MOVWF L0
__LOOP
DECFSZ L0,F
GOTO __LOOP
RETLW 000h
Approach The following approaches are considerable:
- introducing
loop
syntax, not as a PIC macro - identifying loop structure to be optimized (chains of recurrences?)
Notes There are some notes.
- updating
mdelay1
function's magic number
For now, LOOP syntax is introduced in 1d6f5a92a7208ebe31547bb5f50ff335e2a3fd2f.
LOOP syntax
LOOP times body
Repeatedly executes body
form for times
times.
LOOP instruction
LOOP var body
Repeatedly executes body
form for var
times.
Register assignment
When a let bound variable is used as a function call's parameter in a LOOP syntax, it is assigned to a local pseudo-register, not to an input pseudo-register.
For example:
(let ((x (foo)))
(loop 10
(bar x)))
the let bound variable x
is assigned to L0
, not to I0
.
Alive register
A register used as a loop counter in LOOP syntax keeps alive in the LOOP's body part.
For example,
(let ((x 10))
(loop x
(do-something)))
the local pseudo-register L0
, assigned for x
as a loop counter, keep alive in the loop and can not be assigned again.
NULL destination
For LOOP bodies, newly provided is NULL destination (:non-tail :null)
which does not move and discards results of LOOP bodies.