find-natural-loops
authorDavid Vázquez <davazp@gmail.com>
Fri, 24 May 2013 20:16:36 +0000 (21:16 +0100)
committerDavid Vázquez <davazp@gmail.com>
Fri, 24 May 2013 20:16:36 +0000 (21:16 +0100)
experimental/compiler.lisp

index 448683e..f8ef505 100644 (file)
              (:constructor make-block)
              (:predicate block-p)
              (:print-object generic-printer))
-  (id (generate-id 'basic-block))
   ;; List of successors and predecessors of this basic block. They are
   ;; null only for deleted blocks and component's entry and exit.
   succ pred
   component
   ;; The order in the reverse post ordering of the blocks.
   order
+  ;; The innermost loop this block belongs to.
+  loop
   ;; A bit-vector representing the set of dominators. See the function
   ;; `compute-dominators' to know how to use it properly.
   dominators%
   (let ((order (block-order block1)))
     (= 1 (aref (block-dominators% block2) order))))
 
-;;; Check if BLOCK is a loop header. It is to say if it dominates one
-;;; of its predecessors.
+
+
+;;;; Natural Loops
+
+(defstruct natural-loop
+  parent
+  header
+  body)
+
+(defun find-natural-loops (&optional (component *component*))
+  (let ((size (length (component-blocks component))))
+    ;; We look for loop headers in reverse post order, so we will find
+    ;; outermost loop first. It makes sure we can fill the LOOP slot
+    ;; of the blocks and it will not be rewritten by an outer loop.
+    (do-blocks-forward (header component)
+      (dolist (block (block-pred header))
+        (when (dominate-p header block) ; Back edge
+          (let* ((loop
+                    ;; If header is already the header of a loop, then
+                    ;; just merge the natural loop for this back edge
+                    ;; into the same loop.
+                    (if (loop-header-p header)
+                        (block-loop header)
+                        (make-natural-loop
+                         :parent (block-loop header)
+                         :header header
+                         :body (make-array size :element-type 'bit :initial-element 0))))
+                 ;; The set of nodes which belongs to this loop.
+                 (body (natural-loop-body loop)))
+            ;; The header belongs to the loop
+            (format t "~S ~S~%" (block-order header) loop)
+            (setf (aref body (block-order header)) 1
+                  (block-loop header) loop)
+            ;; Add to the loop all the blocks which can reach the tail
+            ;; without going throught the header.
+            (labels ((explore-backward (block)
+                       (unless (= 1 (aref body (block-order block)))
+                         (setf (aref body (block-order block)) 1
+                               (block-loop block) loop)
+                         (dolist (pred (block-pred block))
+                           (explore-backward pred)))))
+              (explore-backward block))))))))
+
+;;; Check if BLOCK is a loop header.
 (defun loop-header-p (block)
-  (some (lambda (pred) (dominate-p block pred))
-        (block-pred block)))
+  (let ((loop (block-loop block)))
+    (and loop (eq (natural-loop-header loop) block))))
+
+
+
 
 ;;; Save the edges of the flow graph of the current component. Then,
 ;;; execute BODY as an implicit progn and restore the edges even if
                  (let ((newblocks '()))
                    (dolist (pred (cdr predecessors) newblocks)
                      (let ((newblock (copy-basic-block block)))
-                       (setf (block-id newblock) (generate-id 'basic-block))
                        (setf (block-pred newblock) (list pred))
                        (setf (block-succ pred) (substitute newblock block (block-succ pred)))
                        (push newblock newblocks))))))))
     ((component-exit-p block)
      (format nil "EXIT-~a" (component-id (block-component block))))
     (t
-     (format nil "BLOCK ~a" (block-id block)))))
+     (format nil "BLOCK ~a" (block-order block)))))
 
 
 (defun print-node (node)
       (reduce-component)
       (compute-reverse-post-order)
       (compute-dominators)
+      (find-natural-loops)
       (/print *component*)
       *component*)))