aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Corallo2021-01-01 11:09:00 +0100
committerAndrea Corallo2021-01-01 14:06:00 +0100
commit93ff838575d25eba76bb0b3d476a36a56bbfba30 (patch)
treed381a9fa1b24c74c79ab2de14324755ad1b2acad
parent6ba94f7c77b4013e15f8a5a9181fba9a2df20ab7 (diff)
downloademacs-93ff838575d25eba76bb0b3d476a36a56bbfba30.tar.gz
emacs-93ff838575d25eba76bb0b3d476a36a56bbfba30.zip
* Clean unreachable block using dominance tree to handle circularities
With this commit unreachable basic blocks are pruned automatically by comp-ssa relying on dominance analysis. This solves the issue of unreachable cluster of basic blocks referencing each other. * lisp/emacs-lisp/comp.el (comp-block-lap): New `no-ret' slot. (comp-compute-dominator-tree): Update. (comp-remove-unreachable-blocks): New functions. (comp-ssa): Update to call `comp-remove-unreachable-blocks'. (comp-clean-orphan-blocks): Delete. (comp-rewrite-non-locals): Update and simplify.
-rw-r--r--lisp/emacs-lisp/comp.el66
1 files changed, 31 insertions, 35 deletions
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 3ef9a6be739..227333f72c8 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -648,9 +648,12 @@ into it.")
648 (addr nil :type number 648 (addr nil :type number
649 :documentation "Start block LAP address.") 649 :documentation "Start block LAP address.")
650 (non-ret-insn nil :type list 650 (non-ret-insn nil :type list
651 :documentation "Non returning basic blocks. 651 :documentation "Insn known to perform a non local exit.
652`comp-fwprop' may identify and store here basic blocks performing 652`comp-fwprop' may identify and store here basic blocks performing
653non local exits.")) 653non local exits and mark it rewrite it later.")
654 (no-ret nil :type boolean
655 :documentation "t when the block is known to perform a
656non local exit (ends with an `unreachable' insn)."))
654 657
655(cl-defstruct (comp-latch (:copier nil) 658(cl-defstruct (comp-latch (:copier nil)
656 (:include comp-block)) 659 (:include comp-block))
@@ -2669,7 +2672,9 @@ blocks."
2669 when (comp-block-dom p) 2672 when (comp-block-dom p)
2670 do (setf new-idom (intersect p new-idom))) 2673 do (setf new-idom (intersect p new-idom)))
2671 unless (eq (comp-block-dom b) new-idom) 2674 unless (eq (comp-block-dom b) new-idom)
2672 do (setf (comp-block-dom b) new-idom 2675 do (setf (comp-block-dom b) (unless (and (comp-block-lap-p new-idom)
2676 (comp-block-lap-no-ret new-idom))
2677 new-idom)
2673 changed t)))))) 2678 changed t))))))
2674 2679
2675(defun comp-compute-dominator-frontiers () 2680(defun comp-compute-dominator-frontiers ()
@@ -2824,16 +2829,34 @@ PRE-LAMBDA and POST-LAMBDA are called in pre or post-order if non-nil."
2824 when (eq op 'phi) 2829 when (eq op 'phi)
2825 do (finalize-phi args b))))) 2830 do (finalize-phi args b)))))
2826 2831
2832(defun comp-remove-unreachable-blocks ()
2833 "Remove unreachable basic blocks.
2834Return t when one or more block was removed, nil otherwise."
2835 (cl-loop
2836 with ret
2837 for bb being each hash-value of (comp-func-blocks comp-func)
2838 for bb-name = (comp-block-name bb)
2839 when (and (not (eq 'entry bb-name))
2840 (null (comp-block-dom bb)))
2841 do
2842 (comp-log (format "Removing block: %s" bb-name) 1)
2843 (remhash bb-name (comp-func-blocks comp-func))
2844 (setf (comp-func-ssa-status comp-func) t
2845 ret t)
2846 finally return ret))
2847
2827(defun comp-ssa () 2848(defun comp-ssa ()
2828 "Port all functions into minimal SSA form." 2849 "Port all functions into minimal SSA form."
2829 (maphash (lambda (_ f) 2850 (maphash (lambda (_ f)
2830 (let* ((comp-func f) 2851 (let* ((comp-func f)
2831 (ssa-status (comp-func-ssa-status f))) 2852 (ssa-status (comp-func-ssa-status f)))
2832 (unless (eq ssa-status t) 2853 (unless (eq ssa-status t)
2833 (when (eq ssa-status 'dirty) 2854 (cl-loop
2834 (comp-clean-ssa f)) 2855 when (eq ssa-status 'dirty)
2835 (comp-compute-edges) 2856 do (comp-clean-ssa f)
2836 (comp-compute-dominator-tree) 2857 do (comp-compute-edges)
2858 (comp-compute-dominator-tree)
2859 until (null (comp-remove-unreachable-blocks)))
2837 (comp-compute-dominator-frontiers) 2860 (comp-compute-dominator-frontiers)
2838 (comp-log-block-info) 2861 (comp-log-block-info)
2839 (comp-place-phis) 2862 (comp-place-phis)
@@ -3023,25 +3046,6 @@ Return t if something was changed."
3023 do (setf modified t)) 3046 do (setf modified t))
3024 finally return modified)) 3047 finally return modified))
3025 3048
3026(defun comp-clean-orphan-blocks (block)
3027 "Iterativelly remove all non reachable blocks orphaned by BLOCK."
3028 (while
3029 (cl-loop
3030 with repeat = nil
3031 with blocks = (comp-func-blocks comp-func)
3032 for bb being each hash-value of blocks
3033 when (and (not (eq (comp-block-name bb) 'entry))
3034 (cl-notany (lambda (ed)
3035 (and (gethash (comp-block-name (comp-edge-src ed))
3036 blocks)
3037 (not (eq (comp-edge-src ed) block))))
3038 (comp-block-in-edges bb)))
3039 do
3040 (comp-log (format "Removing block: %s" (comp-block-name bb)) 1)
3041 (remhash (comp-block-name bb) blocks)
3042 (setf repeat t)
3043 finally return repeat)))
3044
3045(defun comp-rewrite-non-locals () 3049(defun comp-rewrite-non-locals ()
3046 "Make explicit in LIMPLE non-local exits if identified." 3050 "Make explicit in LIMPLE non-local exits if identified."
3047 (cl-loop 3051 (cl-loop
@@ -3050,18 +3054,10 @@ Return t if something was changed."
3050 (comp-block-lap-non-ret-insn bb)) 3054 (comp-block-lap-non-ret-insn bb))
3051 when non-local-insn 3055 when non-local-insn
3052 do 3056 do
3053 (cl-loop
3054 for ed in (comp-block-out-edges bb)
3055 for dst-bb = (comp-edge-dst ed)
3056 ;; Remove one or more block if necessary.
3057 when (length= (comp-block-in-edges dst-bb) 1)
3058 do
3059 (comp-log (format "Removing block: %s" (comp-block-name dst-bb)) 1)
3060 (remhash (comp-block-name dst-bb) (comp-func-blocks comp-func))
3061 (comp-clean-orphan-blocks bb))
3062 ;; Rework the current block. 3057 ;; Rework the current block.
3063 (let* ((insn-seq (memq non-local-insn (comp-block-insns bb)))) 3058 (let* ((insn-seq (memq non-local-insn (comp-block-insns bb))))
3064 (setf (comp-block-lap-non-ret-insn bb) () 3059 (setf (comp-block-lap-non-ret-insn bb) ()
3060 (comp-block-lap-no-ret bb) t
3065 (comp-block-out-edges bb) () 3061 (comp-block-out-edges bb) ()
3066 ;; Prune unnecessary insns! 3062 ;; Prune unnecessary insns!
3067 (cdr insn-seq) '((unreachable)) 3063 (cdr insn-seq) '((unreachable))