diff options
| author | Andrea Corallo | 2021-01-01 11:09:00 +0100 |
|---|---|---|
| committer | Andrea Corallo | 2021-01-01 14:06:00 +0100 |
| commit | 93ff838575d25eba76bb0b3d476a36a56bbfba30 (patch) | |
| tree | d381a9fa1b24c74c79ab2de14324755ad1b2acad | |
| parent | 6ba94f7c77b4013e15f8a5a9181fba9a2df20ab7 (diff) | |
| download | emacs-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.el | 66 |
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 |
| 653 | non local exits.")) | 653 | non 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 | ||
| 656 | non 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. | ||
| 2834 | Return 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)) |