From 0f0ba054bee97eafec3c380078d44f7959504c9e Mon Sep 17 00:00:00 2001 From: John Lorentzson Date: Wed, 9 Jul 2025 15:15:57 +0200 Subject: [PATCH] Add pre-assembly.lisp, which handles transformations needed for asm --- .../backend/pre-assembly.lisp | 64 +++++++++++++++++++ .../backend/value-allocator.lisp | 33 ---------- .../user-side-compiler/user-side-compiler.asd | 3 +- 3 files changed, 66 insertions(+), 34 deletions(-) create mode 100644 wip-duuqnd/user-side-compiler/backend/pre-assembly.lisp diff --git a/wip-duuqnd/user-side-compiler/backend/pre-assembly.lisp b/wip-duuqnd/user-side-compiler/backend/pre-assembly.lisp new file mode 100644 index 0000000..c0a4a53 --- /dev/null +++ b/wip-duuqnd/user-side-compiler/backend/pre-assembly.lisp @@ -0,0 +1,64 @@ +(in-package #:user-side-compiler) + +(defun optim-reuse-temporary-slots (start-iblock allocations) + (let ((free '())) + (do-iblocks (iblock start-iblock) + (do-instructions (inst iblock) + (let ((ending (find inst allocations + :key (alexandria:compose #'last-use + #'data))) + (beginning (find (output inst) allocations :key #'data))) + (cond ((and ending + (eql (strategy ending) :temporary-variable) + (not (null (varvec-index ending)))) + (pushnew (varvec-index ending) free)) + ((and beginning + (eql (strategy beginning) :temporary-variable) + (not (null (varvec-index beginning))) + (not (null free))) + (setf (varvec-index beginning) (pop free))))))))) + +(defun optim-prepare-direct-instructions (iblock) + (do-instructions (inst iblock) + (when (typep inst 'ir-operation) + (assert (= (length (inputs inst)) 2)) + (destructuring-bind (accumulator operand) + (inputs inst) + (when (typep (definition accumulator) '(or ir-fetchvar ir-getconst)) + (move-instruction-above (definition accumulator) inst)) + (when (typep (definition operand) '(or ir-fetchvar ir-getconst)) + (when (typep (definition operand) 'ir-fetchvar) + (setf (inputs inst) + (substitute (input (definition operand)) operand + (inputs inst)))) + (delete-instruction (definition operand))))))) + +(defparameter *operation-routines* + '((ir-mult . "mult") + (ir-div . "div"))) + +(defun pre-assembly-software-operations (start-iblock) + (do-iblocks (ib start-iblock) + (do-instructions (inst ib) + (when (member (type-of inst) *operation-routines* :key #'car) + (let ((inputs (inputs inst)) + (output (output inst)) + (implementation (get-asm-function + (cdr (assoc (type-of inst) + *operation-routines*))))) + (setf (inputs inst) '() + (output inst) nil) + (let ((new (make-instance 'ir-call + :callee implementation + :inputs inputs :output output))) + (insert-instruction-above new inst) + (delete-instruction inst) + ;; To ensure that the code walking continues correctly + (setf inst new))))))) + +(defun pre-assembly (iblock) + (pre-assembly-software-operations iblock) + (optim-prepare-direct-instructions iblock) + (let ((allocs (allocate-values iblock))) + (optim-reuse-temporary-slots iblock allocs) + allocs)) diff --git a/wip-duuqnd/user-side-compiler/backend/value-allocator.lisp b/wip-duuqnd/user-side-compiler/backend/value-allocator.lisp index 607e1e7..d643a6f 100644 --- a/wip-duuqnd/user-side-compiler/backend/value-allocator.lisp +++ b/wip-duuqnd/user-side-compiler/backend/value-allocator.lisp @@ -27,21 +27,6 @@ (%strategy :accessor strategy :initform :temporary-variable) (%varvec-index :accessor varvec-index :initform nil))) -(defun optim-prepare-direct-instructions (iblock) - (do-instructions (inst iblock) - (when (typep inst 'ir-operation) - (assert (= (length (inputs inst)) 2)) - (destructuring-bind (accumulator operand) - (inputs inst) - (when (typep (definition accumulator) '(or ir-fetchvar ir-getconst)) - (move-instruction-above (definition accumulator) inst)) - (when (typep (definition operand) '(or ir-fetchvar ir-getconst)) - (when (typep (definition operand) 'ir-fetchvar) - (setf (inputs inst) - (substitute (input (definition operand)) operand - (inputs inst)))) - (delete-instruction (definition operand))))))) - (defmethod choose-allocation-strategy ((alc value-allocation)) (setf (strategy alc) @@ -91,21 +76,3 @@ (loop :for allocation :in (append named temporary) :do (setf (varvec-index allocation) (incf counter)))) allocations)) - -(defun optim-reuse-temporary-slots (start-iblock allocations) - (let ((free '())) - (do-iblocks (iblock start-iblock) - (do-instructions (inst iblock) - (let ((ending (find inst allocations - :key (alexandria:compose #'last-use - #'data))) - (beginning (find (output inst) allocations :key #'data))) - (cond ((and ending - (eql (strategy ending) :temporary-variable) - (not (null (varvec-index ending)))) - (pushnew (varvec-index ending) free)) - ((and beginning - (eql (strategy beginning) :temporary-variable) - (not (null (varvec-index beginning))) - (not (null free))) - (setf (varvec-index beginning) (pop free))))))))) diff --git a/wip-duuqnd/user-side-compiler/user-side-compiler.asd b/wip-duuqnd/user-side-compiler/user-side-compiler.asd index 12121db..0abb93d 100644 --- a/wip-duuqnd/user-side-compiler/user-side-compiler.asd +++ b/wip-duuqnd/user-side-compiler/user-side-compiler.asd @@ -2,7 +2,7 @@ (defsystem #:user-side-compiler :serial t - :depends-on (#:closer-mop #:alexandria) + :depends-on (#:closer-mop #:alexandria #:trivial-backtrace) :components ((:file "package") (:file "error-handling") @@ -35,4 +35,5 @@ :depends-on ("middle") :serial t :components ((:file "value-allocator") + (:file "pre-assembly") (:file "code-generator")))))