pic icon indicating copy to clipboard operation
pic copied to clipboard

Unnecessary instructions in LOOP forms

Open takagi opened this issue 9 years ago • 1 comments

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 and BTFSC 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

takagi avatar Feb 28 '15 07:02 takagi

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.

takagi avatar Mar 03 '15 09:03 takagi