[committed] contrib: add mdcompact
Checks
Commit Message
Hello all,
this patch checks in mdcompact, the tool written in elisp that I used
to mass convert all the multi choice pattern in the aarch64 back-end to
the new compact syntax.
I tested it on Emacs 29 (might run on older versions as well not
sure), also I verified it runs cleanly on a few other back-ends (arm,
loongarch).
The tool can be used to convert a single pattern, an open buffer or
all md files in a directory.
The tool might need further adjustment to run on some specific
back-end, in case very happy to help.
This patch was pre-approved here [1].
Best Regards
Andrea Corallo
[1] <https://gcc.gnu.org/pipermail/gcc-patches/2023-October/631830.html>
contrib/ChangeLog
* mdcompact/mdcompact-testsuite.el: New file.
* mdcompact/mdcompact.el: Likewise.
* mdcompact/tests/1.md: Likewise.
* mdcompact/tests/1.md.out: Likewise.
* mdcompact/tests/2.md: Likewise.
* mdcompact/tests/2.md.out: Likewise.
* mdcompact/tests/3.md: Likewise.
* mdcompact/tests/3.md.out: Likewise.
* mdcompact/tests/4.md: Likewise.
* mdcompact/tests/4.md.out: Likewise.
* mdcompact/tests/5.md: Likewise.
* mdcompact/tests/5.md.out: Likewise.
* mdcompact/tests/6.md: Likewise.
* mdcompact/tests/6.md.out: Likewise.
* mdcompact/tests/7.md: Likewise.
* mdcompact/tests/7.md.out: Likewise.
---
contrib/mdcompact/mdcompact-testsuite.el | 56 +++++
contrib/mdcompact/mdcompact.el | 296 +++++++++++++++++++++++
contrib/mdcompact/tests/1.md | 36 +++
contrib/mdcompact/tests/1.md.out | 32 +++
contrib/mdcompact/tests/2.md | 25 ++
contrib/mdcompact/tests/2.md.out | 21 ++
contrib/mdcompact/tests/3.md | 16 ++
contrib/mdcompact/tests/3.md.out | 17 ++
contrib/mdcompact/tests/4.md | 17 ++
contrib/mdcompact/tests/4.md.out | 17 ++
contrib/mdcompact/tests/5.md | 12 +
contrib/mdcompact/tests/5.md.out | 11 +
contrib/mdcompact/tests/6.md | 11 +
contrib/mdcompact/tests/6.md.out | 11 +
contrib/mdcompact/tests/7.md | 11 +
contrib/mdcompact/tests/7.md.out | 11 +
16 files changed, 600 insertions(+)
create mode 100644 contrib/mdcompact/mdcompact-testsuite.el
create mode 100644 contrib/mdcompact/mdcompact.el
create mode 100644 contrib/mdcompact/tests/1.md
create mode 100644 contrib/mdcompact/tests/1.md.out
create mode 100644 contrib/mdcompact/tests/2.md
create mode 100644 contrib/mdcompact/tests/2.md.out
create mode 100644 contrib/mdcompact/tests/3.md
create mode 100644 contrib/mdcompact/tests/3.md.out
create mode 100644 contrib/mdcompact/tests/4.md
create mode 100644 contrib/mdcompact/tests/4.md.out
create mode 100644 contrib/mdcompact/tests/5.md
create mode 100644 contrib/mdcompact/tests/5.md.out
create mode 100644 contrib/mdcompact/tests/6.md
create mode 100644 contrib/mdcompact/tests/6.md.out
create mode 100644 contrib/mdcompact/tests/7.md
create mode 100644 contrib/mdcompact/tests/7.md.out
Comments
On Thu, Oct 5, 2023 at 5:49 PM Andrea Corallo <andrea.corallo@arm.com> wrote:
>
> Hello all,
>
> this patch checks in mdcompact, the tool written in elisp that I used
> to mass convert all the multi choice pattern in the aarch64 back-end to
> the new compact syntax.
>
> I tested it on Emacs 29 (might run on older versions as well not
> sure), also I verified it runs cleanly on a few other back-ends (arm,
> loongarch).
>
> The tool can be used to convert a single pattern, an open buffer or
> all md files in a directory.
>
> The tool might need further adjustment to run on some specific
> back-end, in case very happy to help.
>
> This patch was pre-approved here [1].
Does the result generate identical insn-*.cc files?
> Best Regards
>
> Andrea Corallo
>
> [1] <https://gcc.gnu.org/pipermail/gcc-patches/2023-October/631830.html>
>
> contrib/ChangeLog
>
> * mdcompact/mdcompact-testsuite.el: New file.
> * mdcompact/mdcompact.el: Likewise.
> * mdcompact/tests/1.md: Likewise.
> * mdcompact/tests/1.md.out: Likewise.
> * mdcompact/tests/2.md: Likewise.
> * mdcompact/tests/2.md.out: Likewise.
> * mdcompact/tests/3.md: Likewise.
> * mdcompact/tests/3.md.out: Likewise.
> * mdcompact/tests/4.md: Likewise.
> * mdcompact/tests/4.md.out: Likewise.
> * mdcompact/tests/5.md: Likewise.
> * mdcompact/tests/5.md.out: Likewise.
> * mdcompact/tests/6.md: Likewise.
> * mdcompact/tests/6.md.out: Likewise.
> * mdcompact/tests/7.md: Likewise.
> * mdcompact/tests/7.md.out: Likewise.
> ---
> contrib/mdcompact/mdcompact-testsuite.el | 56 +++++
> contrib/mdcompact/mdcompact.el | 296 +++++++++++++++++++++++
> contrib/mdcompact/tests/1.md | 36 +++
> contrib/mdcompact/tests/1.md.out | 32 +++
> contrib/mdcompact/tests/2.md | 25 ++
> contrib/mdcompact/tests/2.md.out | 21 ++
> contrib/mdcompact/tests/3.md | 16 ++
> contrib/mdcompact/tests/3.md.out | 17 ++
> contrib/mdcompact/tests/4.md | 17 ++
> contrib/mdcompact/tests/4.md.out | 17 ++
> contrib/mdcompact/tests/5.md | 12 +
> contrib/mdcompact/tests/5.md.out | 11 +
> contrib/mdcompact/tests/6.md | 11 +
> contrib/mdcompact/tests/6.md.out | 11 +
> contrib/mdcompact/tests/7.md | 11 +
> contrib/mdcompact/tests/7.md.out | 11 +
> 16 files changed, 600 insertions(+)
> create mode 100644 contrib/mdcompact/mdcompact-testsuite.el
> create mode 100644 contrib/mdcompact/mdcompact.el
> create mode 100644 contrib/mdcompact/tests/1.md
> create mode 100644 contrib/mdcompact/tests/1.md.out
> create mode 100644 contrib/mdcompact/tests/2.md
> create mode 100644 contrib/mdcompact/tests/2.md.out
> create mode 100644 contrib/mdcompact/tests/3.md
> create mode 100644 contrib/mdcompact/tests/3.md.out
> create mode 100644 contrib/mdcompact/tests/4.md
> create mode 100644 contrib/mdcompact/tests/4.md.out
> create mode 100644 contrib/mdcompact/tests/5.md
> create mode 100644 contrib/mdcompact/tests/5.md.out
> create mode 100644 contrib/mdcompact/tests/6.md
> create mode 100644 contrib/mdcompact/tests/6.md.out
> create mode 100644 contrib/mdcompact/tests/7.md
> create mode 100644 contrib/mdcompact/tests/7.md.out
>
> diff --git a/contrib/mdcompact/mdcompact-testsuite.el b/contrib/mdcompact/mdcompact-testsuite.el
> new file mode 100644
> index 00000000000..494c0b5cd68
> --- /dev/null
> +++ b/contrib/mdcompact/mdcompact-testsuite.el
> @@ -0,0 +1,56 @@
> +;;; -*- lexical-binding: t; -*-
> +
> +;; This file is part of GCC.
> +
> +;; GCC is free software: you can redistribute it and/or modify it
> +;; under the terms of the GNU General Public License as published by
> +;; the Free Software Foundation, either version 3 of the License, or
> +;; (at your option) any later version.
> +
> +;; GCC is distributed in the hope that it will be useful, but WITHOUT
> +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> +;; License for more details.
> +
> +;; You should have received a copy of the GNU General Public License
> +;; along with GCC. If not, see <https://www.gnu.org/licenses/>.
> +
> +;;; Commentary:
> +
> +;;; Usage:
> +;; $ emacs -batch -l mdcompact.el -l mdcompact-testsuite.el -f ert-run-tests-batch-and-exit
> +
> +;;; Code:
> +
> +(require 'mdcompact)
> +(require 'ert)
> +
> +(defconst mdcompat-test-directory (concat (file-name-directory
> + (or load-file-name
> + buffer-file-name))
> + "tests/"))
> +
> +(defun mdcompat-test-run (f)
> + (with-temp-buffer
> + (insert-file-contents f)
> + (mdcomp-run-at-point)
> + (let ((a (buffer-string))
> + (b (with-temp-buffer
> + (insert-file-contents (concat f ".out"))
> + (buffer-string))))
> + (should (string= a b)))))
> +
> +(defmacro mdcompat-gen-tests ()
> + `(progn
> + ,@(cl-loop
> + for f in (directory-files mdcompat-test-directory t "md$")
> + collect
> + `(ert-deftest ,(intern (concat "mdcompat-test-"
> + (file-name-sans-extension
> + (file-name-nondirectory f))))
> + ()
> + (mdcompat-test-run ,f)))))
> +
> +(mdcompat-gen-tests)
> +
> +;;; mdcompact-testsuite.el ends here
> diff --git a/contrib/mdcompact/mdcompact.el b/contrib/mdcompact/mdcompact.el
> new file mode 100644
> index 00000000000..9b639f53188
> --- /dev/null
> +++ b/contrib/mdcompact/mdcompact.el
> @@ -0,0 +1,296 @@
> +;;; -*- lexical-binding: t; -*-
> +
> +;; Author: Andrea Corallo <andrea.corallo@arm.com>
> +;; Package: mdcompact
> +;; Keywords: languages, extensions
> +;; Package-Requires: ((emacs "29"))
> +
> +;; This file is part of GCC.
> +
> +;; GCC is free software: you can redistribute it and/or modify it
> +;; under the terms of the GNU General Public License as published by
> +;; the Free Software Foundation, either version 3 of the License, or
> +;; (at your option) any later version.
> +
> +;; GCC is distributed in the hope that it will be useful, but WITHOUT
> +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> +;; License for more details.
> +
> +;; You should have received a copy of the GNU General Public License
> +;; along with GCC. If not, see <https://www.gnu.org/licenses/>.
> +
> +;;; Commentary:
> +
> +;; Convert multi choice GCC machine description patterns to compact
> +;; syntax.
> +
> +;;; Usage:
> +
> +;; With the point on a pattern run 'M-x mdcomp-run-at-point' to
> +;; convert that pattern.
> +
> +;; Run 'M-x mdcomp-run-buffer' to convert all convertible patterns in
> +;; the current buffer.
> +
> +;; Run 'M-x mdcomp-run-directory' to convert all convertible patterns
> +;; in a directory.
> +
> +;; One can invoke the tool from shell as well, ex for running it on
> +;; the arm backend from the GCC checkout directory:
> +;; emacs -batch -l ./contrib/mdcompact/mdcompact.el -f mdcomp-run-directory ./gcc/config/arm/
> +
> +;;; Code:
> +
> +(require 'cl-lib)
> +(require 'rx)
> +
> +(defconst
> + mdcomp-constr-rx
> + (rx "(match_operand" (? ":" (1+ (or punct alnum)))
> + (1+ space) (group-n 1 num) (1+ space) "\""
> + (1+ (or alnum "_" "<" ">")) "\""
> + (group-n 2 (1+ space) "\"" (group-n 3 (0+ (not "\""))) "\"")
> + ")"))
> +
> +(cl-defstruct mdcomp-operand
> + num
> + cstr)
> +
> +(cl-defstruct mdcomp-attr
> + name
> + vals)
> +
> +;; A reasonable name
> +(rx-define mdcomp-name (1+ (or alnum "_")))
> +
> +(defconst mdcomp-attr-rx
> + (rx "(set_attr" (1+ space) "\""
> + (group-n 1 mdcomp-name)
> + "\"" (1+ space) "\""
> + (group-n 2 (1+ (not ")")))
> + "\"" (0+ space) ")"))
> +
> +(defun mdcomp-parse-delete-attr ()
> + (save-match-data
> + (when (re-search-forward mdcomp-attr-rx nil t)
> + (let ((res (save-match-data
> + (make-mdcomp-attr
> + :name (match-string-no-properties 1)
> + :vals (cl-delete-if #'string-empty-p
> + (split-string
> + (replace-regexp-in-string
> + (rx "\\") ""
> + (match-string-no-properties 2))
> + (rx (1+ (or space ",")))))))))
> + (if (length= (mdcomp-attr-vals res) 1)
> + 'short
> + (delete-region (match-beginning 0) (match-end 0))
> + res)))))
> +
> +(defun mdcomp-parse-attrs ()
> + (save-excursion
> + (let* ((res (cl-loop for x = (mdcomp-parse-delete-attr)
> + while x
> + collect x))
> + (beg (re-search-backward (rx bol (1+ space) "["))))
> + (unless (memq 'short res)
> + (when res
> + (delete-region beg (re-search-forward (rx "]")))))
> + (cl-delete 'short res))))
> +
> +(defun mdcomp-remove-quoting (beg)
> + (save-excursion
> + (save-match-data
> + (replace-regexp-in-region (regexp-quote "\\\\") "\\\\" beg (point-max))
> + (replace-regexp-in-region (regexp-quote "\\\"") "\"" beg (point-max)))))
> +
> +(defun mdcomp-remove-escaped-newlines (beg)
> + (save-excursion
> + (save-match-data
> + (replace-regexp-in-region (rx "\\" eol (0+ space)) " " beg (point-max)))))
> +
> +(defun mdcomp-parse-delete-cstr ()
> + (cl-loop while (re-search-forward mdcomp-constr-rx nil t)
> + unless (string= "" (match-string-no-properties 3))
> + collect (save-match-data
> + (make-mdcomp-operand
> + :num (string-to-number (match-string-no-properties 1))
> + :cstr (cl-delete-if #'string-empty-p
> + (split-string
> + (replace-regexp-in-string " " ""
> + (match-string-no-properties 3))
> + (rx (1+ ","))))))
> + do (delete-region (match-beginning 2) (match-end 2))))
> +
> +(defun mdcomp-run* ()
> + (let* ((ops (mdcomp-parse-delete-cstr))
> + (attrs (mdcomp-parse-attrs))
> + (beg (re-search-forward "\"@")))
> + (cl-sort ops (lambda (x y)
> + (< (mdcomp-operand-num x) (mdcomp-operand-num y))))
> + (mdcomp-remove-escaped-newlines beg)
> + (save-match-data
> + (save-excursion
> + (left-char 2)
> + (forward-sexp)
> + (left-char 1)
> + (delete-char 1)
> + (insert "\n }")))
> + (mdcomp-remove-quoting beg)
> + (replace-match "{@")
> + (re-search-forward (rx (or "\"" ")")))
> + (re-search-backward "@")
> + (right-char 1)
> + (insert "[ cons: ")
> + (cl-loop
> + for op in ops
> + when (string-match "=" (cl-first (mdcomp-operand-cstr op)))
> + do (insert "=")
> + do (insert (number-to-string (mdcomp-operand-num op)) ", ")
> + finally
> + (progn
> + ;; In case add attributes names
> + (when attrs
> + (delete-char -2)
> + (insert "; attrs: ")
> + (cl-loop for attr in attrs
> + do (insert (mdcomp-attr-name attr) ", ")))
> + (delete-char -2)
> + (insert "]")))
> + (cl-loop
> + while (re-search-forward (rx bol (0+ space) (or (group-n 1 "* return")
> + (group-n 2 "}")
> + "#" alpha "<"))
> + nil t)
> + for i from 0
> + when (match-string 2)
> + do (cl-return)
> + when (match-string 1)
> + do (progn
> + (delete-region (match-beginning 1) (+ (match-beginning 1) (length "* return")))
> + (insert "<<")
> + (left-char 1))
> + do
> + (progn
> + (left-char 1)
> + (cl-loop
> + initially (insert " [ ")
> + for op in ops
> + for c = (nth i (mdcomp-operand-cstr op))
> + unless c
> + do (cl-return)
> + do (insert (if (string-match "=" c)
> + (substring c 1 nil)
> + c)
> + ", ")
> + finally (progn
> + (when attrs
> + (delete-char -2)
> + (insert "; ")
> + (cl-loop for attr in attrs
> + for str = (nth i (mdcomp-attr-vals attr))
> + when str
> + do (insert str)
> + do (insert ", ")))
> + (delete-char -2)
> + (insert " ] ")
> + (move-end-of-line 1)))))
> + ;; remove everything after ] align what needs to be aligned
> + ;; and re-add the asm template
> + (re-search-backward (regexp-quote "@[ cons:"))
> + (let* ((n (length (mdcomp-operand-cstr (car ops))))
> + (asms (cl-loop
> + initially (re-search-forward "]")
> + repeat n
> + collect (let* ((beg (re-search-forward "]"))
> + (end (re-search-forward (rx eol)))
> + (str (buffer-substring-no-properties beg end)))
> + (delete-region beg end)
> + str)))
> + (beg (re-search-backward (regexp-quote "@[ cons:")))
> + (indent-tabs-mode nil))
> + (re-search-forward "}")
> + (align-regexp beg (point) (rx (group-n 1 "") "["))
> + (align-regexp beg (point) (rx (group-n 1 "") (or "," ";")) nil nil t)
> + (align-regexp beg (point) (rx (group-n 1 "") "]"))
> + (goto-char beg)
> + (cl-loop
> + initially (re-search-forward "]")
> + for i below n
> + do (progn
> + (re-search-forward "]")
> + (insert (nth i asms))))
> + (when (re-search-forward (rx (1+ (or space eol)) ")") nil t)
> + (replace-match "\n)" nil t)))))
> +
> +(defun mdcomp-narrow-to-md-pattern ()
> + (condition-case nil
> + (let ((beg (re-search-forward "\n("))
> + (end (re-search-forward (rx bol (1+ ")")))))
> + (narrow-to-region beg end))
> + (error
> + (narrow-to-defun))))
> +
> +(defun mdcomp-run-at-point ()
> + "Convert the multi choice top-level form around point to compact syntax."
> + (interactive)
> + (save-restriction
> + (save-mark-and-excursion
> + (mdcomp-narrow-to-md-pattern)
> + (goto-char (point-min))
> + (let ((pattern-name (save-excursion
> + (re-search-forward (rx "\"" (group-n 1 (1+ (not "\""))) "\""))
> + (match-string-no-properties 1)))
> + (orig-text (buffer-substring-no-properties (point-min) (point-max))))
> + (condition-case nil
> + (progn
> + (mdcomp-run*)
> + (message "Converted: %s" pattern-name))
> + (error
> + (message "Skipping convertion for: %s" pattern-name)
> + (delete-region (point-min) (point-max))
> + (insert orig-text)
> + 'fail))))))
> +
> +(defun mdcomp-run-buffer ()
> + "Convert the multi choice top-level forms in the buffer to compact syntax."
> + (interactive)
> + (save-excursion
> + (message "Conversion for buffer %s started" (buffer-file-name))
> + (goto-char (point-min))
> + (while (re-search-forward
> + (rx "match_operand" (1+ any) letter (0+ space) "," (0+ space) letter) nil t)
> + (when (eq (mdcomp-run-at-point) 'fail)
> + (condition-case nil
> + (forward-sexp)
> + (error
> + ;; If forward-sexp fails falls back.
> + (re-search-forward (rx ")" eol eol))))))
> + (message "Conversion done")))
> +
> +(defconst mdcomp-file-rx (rx bol alpha (0+ not-newline) ".md" eol))
> +
> +(defun mdcomp-run-directory (folder &optional recursive)
> + "Run el mdcompact on a FOLDER possibly in a RECURSIVE fashion."
> + (interactive "D")
> + (let ((before-save-hook nil)
> + (init-time (current-time)))
> + (mapc (lambda (f)
> + (with-temp-file f
> + (message "Working on %s" f)
> + (insert-file-contents f)
> + (mdcomp-run-buffer)
> + (message "Done with %s" f)))
> + (if recursive
> + (directory-files-recursively folder mdcomp-file-rx)
> + (directory-files folder t mdcomp-file-rx)))
> + (message "Converted in %f sec" (float-time (time-since init-time)))))
> +
> +(defun mdcomp-batch-run-directory ()
> + "Same as `mdcomp-run-directory' but use cmd line args."
> + (mdcomp-run-directory (nth 0 argv) (nth 1 argv)))
> +
> +(provide 'mdcompact)
> +
> +;;; mdcompact.el ends here
> diff --git a/contrib/mdcompact/tests/1.md b/contrib/mdcompact/tests/1.md
> new file mode 100644
> index 00000000000..8f57ab487a5
> --- /dev/null
> +++ b/contrib/mdcompact/tests/1.md
> @@ -0,0 +1,36 @@
> +(define_insn_and_split "*movsi_aarch64"
> + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, r, w,r,w, w")
> + (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usw,Usa,Ush,rZ,w,w,Ds"))]
> + "(register_operand (operands[0], SImode)
> + || aarch64_reg_or_zero (operands[1], SImode))"
> + "@
> + mov\\t%w0, %w1
> + mov\\t%w0, %w1
> + mov\\t%w0, %w1
> + mov\\t%w0, %1
> + #
> + * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
> + ldr\\t%w0, %1
> + ldr\\t%s0, %1
> + str\\t%w1, %0
> + str\\t%s1, %0
> + adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1]
> + adr\\t%x0, %c1
> + adrp\\t%x0, %A1
> + fmov\\t%s0, %w1
> + fmov\\t%w0, %s1
> + fmov\\t%s0, %s1
> + * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
> + "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
> + && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
> + [(const_int 0)]
> + "{
> + aarch64_expand_mov_immediate (operands[0], operands[1]);
> + DONE;
> + }"
> + [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
> + load_4,store_4,store_4,load_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
> + (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,*,fp,fp,fp,simd")
> + (set_attr "length" "4,4,4,4,*, 4,4, 4,4, 4,8,4,4, 4, 4, 4, 4")
> +]
> +)
> diff --git a/contrib/mdcompact/tests/1.md.out b/contrib/mdcompact/tests/1.md.out
> new file mode 100644
> index 00000000000..24f280dd29e
> --- /dev/null
> +++ b/contrib/mdcompact/tests/1.md.out
> @@ -0,0 +1,32 @@
> +(define_insn_and_split "*movsi_aarch64"
> + [(set (match_operand:SI 0 "nonimmediate_operand")
> + (match_operand:SI 1 "aarch64_mov_operand"))]
> + "(register_operand (operands[0], SImode)
> + || aarch64_reg_or_zero (operands[1], SImode))"
> + {@ [ cons: =0 , 1 ; attrs: type , arch , length ]
> + [ r , r ; mov_reg , * , 4 ] mov\t%w0, %w1
> + [ k , r ; mov_reg , * , 4 ] mov\t%w0, %w1
> + [ r , k ; mov_reg , * , 4 ] mov\t%w0, %w1
> + [ r , M ; mov_imm , * , 4 ] mov\t%w0, %1
> + [ r , n ; mov_imm , * , * ] #
> + [ r , Usv ; mov_imm , sve , 4 ] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
> + [ r , m ; load_4 , * , 4 ] ldr\t%w0, %1
> + [ w , m ; load_4 , fp , 4 ] ldr\t%s0, %1
> + [ m , rZ ; store_4 , * , 4 ] str\t%w1, %0
> + [ m , w ; store_4 , fp , 4 ] str\t%s1, %0
> + [ r , Usw ; load_4 , * , 8 ] adrp\t%x0, %A1\;ldr\t%w0, [%x0, %L1]
> + [ r , Usa ; adr , * , 4 ] adr\t%x0, %c1
> + [ r , Ush ; adr , * , 4 ] adrp\t%x0, %A1
> + [ w , rZ ; f_mcr , fp , 4 ] fmov\t%s0, %w1
> + [ r , w ; f_mrc , fp , 4 ] fmov\t%w0, %s1
> + [ w , w ; fmov , fp , 4 ] fmov\t%s0, %s1
> + [ w , Ds ; neon_move , simd , 4 ] << aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
> + }
> + "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
> + && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
> + [(const_int 0)]
> + "{
> + aarch64_expand_mov_immediate (operands[0], operands[1]);
> + DONE;
> + }"
> +)
> diff --git a/contrib/mdcompact/tests/2.md b/contrib/mdcompact/tests/2.md
> new file mode 100644
> index 00000000000..61fba28af95
> --- /dev/null
> +++ b/contrib/mdcompact/tests/2.md
> @@ -0,0 +1,25 @@
> +(define_insn "*movti_aarch64"
> + [(set (match_operand:TI 0
> + "nonimmediate_operand" "= r,w,w,w, r,w,r,m,m,w,m")
> + (match_operand:TI 1
> + "aarch64_movti_operand" " rUti,Z,Z,r, w,w,m,r,Z,m,w"))]
> + "(register_operand (operands[0], TImode)
> + || aarch64_reg_or_zero (operands[1], TImode))"
> + "@
> + #
> + movi\\t%0.2d, #0
> + fmov\t%d0, xzr
> + #
> + #
> + mov\\t%0.16b, %1.16b
> + ldp\\t%0, %H0, %1
> + stp\\t%1, %H1, %0
> + stp\\txzr, xzr, %0
> + ldr\\t%q0, %1
> + str\\t%q1, %0"
> + [(set_attr "type" "multiple,neon_move,f_mcr,f_mcr,f_mrc,neon_logic_q, \
> + load_16,store_16,store_16,\
> + load_16,store_16")
> + (set_attr "length" "8,4,4,8,8,4,4,4,4,4,4")
> + (set_attr "arch" "*,simd,*,*,*,simd,*,*,*,fp,fp")]
> +)
> diff --git a/contrib/mdcompact/tests/2.md.out b/contrib/mdcompact/tests/2.md.out
> new file mode 100644
> index 00000000000..b3d5402df78
> --- /dev/null
> +++ b/contrib/mdcompact/tests/2.md.out
> @@ -0,0 +1,21 @@
> +(define_insn "*movti_aarch64"
> + [(set (match_operand:TI 0
> + "nonimmediate_operand")
> + (match_operand:TI 1
> + "aarch64_movti_operand"))]
> + "(register_operand (operands[0], TImode)
> + || aarch64_reg_or_zero (operands[1], TImode))"
> + {@ [ cons: =0 , 1 ; attrs: type , length , arch ]
> + [ r , rUti ; multiple , 8 , * ] #
> + [ w , Z ; neon_move , 4 , simd ] movi\t%0.2d, #0
> + [ w , Z ; f_mcr , 4 , * ] fmov\t%d0, xzr
> + [ w , r ; f_mcr , 8 , * ] #
> + [ r , w ; f_mrc , 8 , * ] #
> + [ w , w ; neon_logic_q , 4 , simd ] mov\t%0.16b, %1.16b
> + [ r , m ; load_16 , 4 , * ] ldp\t%0, %H0, %1
> + [ m , r ; store_16 , 4 , * ] stp\t%1, %H1, %0
> + [ m , Z ; store_16 , 4 , * ] stp\txzr, xzr, %0
> + [ w , m ; load_16 , 4 , fp ] ldr\t%q0, %1
> + [ m , w ; store_16 , 4 , fp ] str\t%q1, %0
> + }
> +)
> diff --git a/contrib/mdcompact/tests/3.md b/contrib/mdcompact/tests/3.md
> new file mode 100644
> index 00000000000..79f3a1a88f8
> --- /dev/null
> +++ b/contrib/mdcompact/tests/3.md
> @@ -0,0 +1,16 @@
> +(define_insn "*add<mode>3_compareV_cconly_imm"
> + [(set (reg:CC_V CC_REGNUM)
> + (compare:CC_V
> + (plus:<DWI>
> + (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
> + (match_operand:<DWI> 1 "const_scalar_int_operand" ""))
> + (sign_extend:<DWI>
> + (plus:GPI
> + (match_dup 0)
> + (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))]
> + "INTVAL (operands[1]) == INTVAL (operands[2])"
> + "@
> + cmn\\t%<w>0, %<w>1
> + cmp\\t%<w>0, #%n1"
> + [(set_attr "type" "alus_imm")]
> +)
> diff --git a/contrib/mdcompact/tests/3.md.out b/contrib/mdcompact/tests/3.md.out
> new file mode 100644
> index 00000000000..1ea25ee44f0
> --- /dev/null
> +++ b/contrib/mdcompact/tests/3.md.out
> @@ -0,0 +1,17 @@
> +(define_insn "*add<mode>3_compareV_cconly_imm"
> + [(set (reg:CC_V CC_REGNUM)
> + (compare:CC_V
> + (plus:<DWI>
> + (sign_extend:<DWI> (match_operand:GPI 0 "register_operand"))
> + (match_operand:<DWI> 1 "const_scalar_int_operand"))
> + (sign_extend:<DWI>
> + (plus:GPI
> + (match_dup 0)
> + (match_operand:GPI 2 "aarch64_plus_immediate")))))]
> + "INTVAL (operands[1]) == INTVAL (operands[2])"
> + {@ [ cons: 0 , 2 ]
> + [ r , I ] cmn\t%<w>0, %<w>1
> + [ r , J ] cmp\t%<w>0, #%n1
> + }
> + [(set_attr "type" "alus_imm")]
> +)
> diff --git a/contrib/mdcompact/tests/4.md b/contrib/mdcompact/tests/4.md
> new file mode 100644
> index 00000000000..360f63b42e1
> --- /dev/null
> +++ b/contrib/mdcompact/tests/4.md
> @@ -0,0 +1,17 @@
> +(define_insn "*sibcall_insn"
> + [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
> + (match_operand 1 ""))
> + (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
> + (return)]
> + "SIBLING_CALL_P (insn)"
> + {
> + if (which_alternative == 0)
> + {
> + output_asm_insn ("br\\t%0", operands);
> + return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
> + }
> + return "b\\t%c0";
> + }
> + [(set_attr "type" "branch, branch")
> + (set_attr "sls_length" "retbr,none")]
> +)
> \ No newline at end of file
> diff --git a/contrib/mdcompact/tests/4.md.out b/contrib/mdcompact/tests/4.md.out
> new file mode 100644
> index 00000000000..360f63b42e1
> --- /dev/null
> +++ b/contrib/mdcompact/tests/4.md.out
> @@ -0,0 +1,17 @@
> +(define_insn "*sibcall_insn"
> + [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
> + (match_operand 1 ""))
> + (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
> + (return)]
> + "SIBLING_CALL_P (insn)"
> + {
> + if (which_alternative == 0)
> + {
> + output_asm_insn ("br\\t%0", operands);
> + return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
> + }
> + return "b\\t%c0";
> + }
> + [(set_attr "type" "branch, branch")
> + (set_attr "sls_length" "retbr,none")]
> +)
> \ No newline at end of file
> diff --git a/contrib/mdcompact/tests/5.md b/contrib/mdcompact/tests/5.md
> new file mode 100644
> index 00000000000..100dffbc8b1
> --- /dev/null
> +++ b/contrib/mdcompact/tests/5.md
> @@ -0,0 +1,12 @@
> +(define_insn "<optab><mode>3"
> + [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
> + (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
> + (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
> + ""
> + "@
> + <logical>\\t%<w>0, %<w>1, %<w>2
> + <logical>\\t%<w>0, %<w>1, %2
> + <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
> + [(set_attr "type" "logic_reg,logic_imm,neon_logic")
> + (set_attr "arch" "*,*,simd")]
> +)
> diff --git a/contrib/mdcompact/tests/5.md.out b/contrib/mdcompact/tests/5.md.out
> new file mode 100644
> index 00000000000..ed460ee1530
> --- /dev/null
> +++ b/contrib/mdcompact/tests/5.md.out
> @@ -0,0 +1,11 @@
> +(define_insn "<optab><mode>3"
> + [(set (match_operand:GPI 0 "register_operand")
> + (LOGICAL:GPI (match_operand:GPI 1 "register_operand")
> + (match_operand:GPI 2 "aarch64_logical_operand")))]
> + ""
> + {@ [ cons: =0 , 1 , 2 ; attrs: type , arch ]
> + [ r , %r , r ; logic_reg , * ] <logical>\t%<w>0, %<w>1, %<w>2
> + [ rk , r , <lconst> ; logic_imm , * ] <logical>\t%<w>0, %<w>1, %2
> + [ w , w , w ; neon_logic , simd ] <logical>\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>
> + }
> +)
> diff --git a/contrib/mdcompact/tests/6.md b/contrib/mdcompact/tests/6.md
> new file mode 100644
> index 00000000000..a9f609503e2
> --- /dev/null
> +++ b/contrib/mdcompact/tests/6.md
> @@ -0,0 +1,11 @@
> +(define_insn "aarch64_wrffr"
> + [(set (reg:VNx16BI FFR_REGNUM)
> + (match_operand:VNx16BI 0 "aarch64_simd_reg_or_minus_one"))
> + (set (reg:VNx16BI FFRT_REGNUM)
> + (unspec:VNx16BI [(match_dup 0)] UNSPEC_WRFFR))]
> + "TARGET_SVE"
> + {@ [ cons: 0 ]
> + [ Dm ] setffr
> + [ Upa ] wrffr\t%0.b
> + }
> +)
> diff --git a/contrib/mdcompact/tests/6.md.out b/contrib/mdcompact/tests/6.md.out
> new file mode 100644
> index 00000000000..a9f609503e2
> --- /dev/null
> +++ b/contrib/mdcompact/tests/6.md.out
> @@ -0,0 +1,11 @@
> +(define_insn "aarch64_wrffr"
> + [(set (reg:VNx16BI FFR_REGNUM)
> + (match_operand:VNx16BI 0 "aarch64_simd_reg_or_minus_one"))
> + (set (reg:VNx16BI FFRT_REGNUM)
> + (unspec:VNx16BI [(match_dup 0)] UNSPEC_WRFFR))]
> + "TARGET_SVE"
> + {@ [ cons: 0 ]
> + [ Dm ] setffr
> + [ Upa ] wrffr\t%0.b
> + }
> +)
> diff --git a/contrib/mdcompact/tests/7.md b/contrib/mdcompact/tests/7.md
> new file mode 100644
> index 00000000000..6616deaa8db
> --- /dev/null
> +++ b/contrib/mdcompact/tests/7.md
> @@ -0,0 +1,11 @@
> +(define_insn "and<mode>3<vczle><vczbe>"
> + [(set (match_operand:VDQ_I 0 "register_operand" "=w,w")
> + (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
> + (match_operand:VDQ_I 2 "aarch64_reg_or_bic_imm" "w,Db")))]
> + "TARGET_SIMD"
> + "@
> + and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>
> + * return aarch64_output_simd_mov_immediate (operands[2], <bitsize>,\
> + AARCH64_CHECK_BIC);"
> + [(set_attr "type" "neon_logic<q>")]
> +)
> diff --git a/contrib/mdcompact/tests/7.md.out b/contrib/mdcompact/tests/7.md.out
> new file mode 100644
> index 00000000000..199b37a810f
> --- /dev/null
> +++ b/contrib/mdcompact/tests/7.md.out
> @@ -0,0 +1,11 @@
> +(define_insn "and<mode>3<vczle><vczbe>"
> + [(set (match_operand:VDQ_I 0 "register_operand")
> + (and:VDQ_I (match_operand:VDQ_I 1 "register_operand")
> + (match_operand:VDQ_I 2 "aarch64_reg_or_bic_imm")))]
> + "TARGET_SIMD"
> + {@ [ cons: =0 , 1 , 2 ]
> + [ w , w , w ] and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>
> + [ w , 0 , Db ] << aarch64_output_simd_mov_immediate (operands[2], <bitsize>, AARCH64_CHECK_BIC);
> + }
> + [(set_attr "type" "neon_logic<q>")]
> +)
> --
> 2.25.1
>
Richard Biener <richard.guenther@gmail.com> writes:
> On Thu, Oct 5, 2023 at 5:49 PM Andrea Corallo <andrea.corallo@arm.com> wrote:
>>
>> Hello all,
>>
>> this patch checks in mdcompact, the tool written in elisp that I used
>> to mass convert all the multi choice pattern in the aarch64 back-end to
>> the new compact syntax.
>>
>> I tested it on Emacs 29 (might run on older versions as well not
>> sure), also I verified it runs cleanly on a few other back-ends (arm,
>> loongarch).
>>
>> The tool can be used to convert a single pattern, an open buffer or
>> all md files in a directory.
>>
>> The tool might need further adjustment to run on some specific
>> back-end, in case very happy to help.
>>
>> This patch was pre-approved here [1].
>
> Does the result generate identical insn-*.cc files?
No, there can be indentation/aesthetic differences.
BR
Andrea
new file mode 100644
@@ -0,0 +1,56 @@
+;;; -*- lexical-binding: t; -*-
+
+;; This file is part of GCC.
+
+;; GCC is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Usage:
+;; $ emacs -batch -l mdcompact.el -l mdcompact-testsuite.el -f ert-run-tests-batch-and-exit
+
+;;; Code:
+
+(require 'mdcompact)
+(require 'ert)
+
+(defconst mdcompat-test-directory (concat (file-name-directory
+ (or load-file-name
+ buffer-file-name))
+ "tests/"))
+
+(defun mdcompat-test-run (f)
+ (with-temp-buffer
+ (insert-file-contents f)
+ (mdcomp-run-at-point)
+ (let ((a (buffer-string))
+ (b (with-temp-buffer
+ (insert-file-contents (concat f ".out"))
+ (buffer-string))))
+ (should (string= a b)))))
+
+(defmacro mdcompat-gen-tests ()
+ `(progn
+ ,@(cl-loop
+ for f in (directory-files mdcompat-test-directory t "md$")
+ collect
+ `(ert-deftest ,(intern (concat "mdcompat-test-"
+ (file-name-sans-extension
+ (file-name-nondirectory f))))
+ ()
+ (mdcompat-test-run ,f)))))
+
+(mdcompat-gen-tests)
+
+;;; mdcompact-testsuite.el ends here
new file mode 100644
@@ -0,0 +1,296 @@
+;;; -*- lexical-binding: t; -*-
+
+;; Author: Andrea Corallo <andrea.corallo@arm.com>
+;; Package: mdcompact
+;; Keywords: languages, extensions
+;; Package-Requires: ((emacs "29"))
+
+;; This file is part of GCC.
+
+;; GCC is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Convert multi choice GCC machine description patterns to compact
+;; syntax.
+
+;;; Usage:
+
+;; With the point on a pattern run 'M-x mdcomp-run-at-point' to
+;; convert that pattern.
+
+;; Run 'M-x mdcomp-run-buffer' to convert all convertible patterns in
+;; the current buffer.
+
+;; Run 'M-x mdcomp-run-directory' to convert all convertible patterns
+;; in a directory.
+
+;; One can invoke the tool from shell as well, ex for running it on
+;; the arm backend from the GCC checkout directory:
+;; emacs -batch -l ./contrib/mdcompact/mdcompact.el -f mdcomp-run-directory ./gcc/config/arm/
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'rx)
+
+(defconst
+ mdcomp-constr-rx
+ (rx "(match_operand" (? ":" (1+ (or punct alnum)))
+ (1+ space) (group-n 1 num) (1+ space) "\""
+ (1+ (or alnum "_" "<" ">")) "\""
+ (group-n 2 (1+ space) "\"" (group-n 3 (0+ (not "\""))) "\"")
+ ")"))
+
+(cl-defstruct mdcomp-operand
+ num
+ cstr)
+
+(cl-defstruct mdcomp-attr
+ name
+ vals)
+
+;; A reasonable name
+(rx-define mdcomp-name (1+ (or alnum "_")))
+
+(defconst mdcomp-attr-rx
+ (rx "(set_attr" (1+ space) "\""
+ (group-n 1 mdcomp-name)
+ "\"" (1+ space) "\""
+ (group-n 2 (1+ (not ")")))
+ "\"" (0+ space) ")"))
+
+(defun mdcomp-parse-delete-attr ()
+ (save-match-data
+ (when (re-search-forward mdcomp-attr-rx nil t)
+ (let ((res (save-match-data
+ (make-mdcomp-attr
+ :name (match-string-no-properties 1)
+ :vals (cl-delete-if #'string-empty-p
+ (split-string
+ (replace-regexp-in-string
+ (rx "\\") ""
+ (match-string-no-properties 2))
+ (rx (1+ (or space ",")))))))))
+ (if (length= (mdcomp-attr-vals res) 1)
+ 'short
+ (delete-region (match-beginning 0) (match-end 0))
+ res)))))
+
+(defun mdcomp-parse-attrs ()
+ (save-excursion
+ (let* ((res (cl-loop for x = (mdcomp-parse-delete-attr)
+ while x
+ collect x))
+ (beg (re-search-backward (rx bol (1+ space) "["))))
+ (unless (memq 'short res)
+ (when res
+ (delete-region beg (re-search-forward (rx "]")))))
+ (cl-delete 'short res))))
+
+(defun mdcomp-remove-quoting (beg)
+ (save-excursion
+ (save-match-data
+ (replace-regexp-in-region (regexp-quote "\\\\") "\\\\" beg (point-max))
+ (replace-regexp-in-region (regexp-quote "\\\"") "\"" beg (point-max)))))
+
+(defun mdcomp-remove-escaped-newlines (beg)
+ (save-excursion
+ (save-match-data
+ (replace-regexp-in-region (rx "\\" eol (0+ space)) " " beg (point-max)))))
+
+(defun mdcomp-parse-delete-cstr ()
+ (cl-loop while (re-search-forward mdcomp-constr-rx nil t)
+ unless (string= "" (match-string-no-properties 3))
+ collect (save-match-data
+ (make-mdcomp-operand
+ :num (string-to-number (match-string-no-properties 1))
+ :cstr (cl-delete-if #'string-empty-p
+ (split-string
+ (replace-regexp-in-string " " ""
+ (match-string-no-properties 3))
+ (rx (1+ ","))))))
+ do (delete-region (match-beginning 2) (match-end 2))))
+
+(defun mdcomp-run* ()
+ (let* ((ops (mdcomp-parse-delete-cstr))
+ (attrs (mdcomp-parse-attrs))
+ (beg (re-search-forward "\"@")))
+ (cl-sort ops (lambda (x y)
+ (< (mdcomp-operand-num x) (mdcomp-operand-num y))))
+ (mdcomp-remove-escaped-newlines beg)
+ (save-match-data
+ (save-excursion
+ (left-char 2)
+ (forward-sexp)
+ (left-char 1)
+ (delete-char 1)
+ (insert "\n }")))
+ (mdcomp-remove-quoting beg)
+ (replace-match "{@")
+ (re-search-forward (rx (or "\"" ")")))
+ (re-search-backward "@")
+ (right-char 1)
+ (insert "[ cons: ")
+ (cl-loop
+ for op in ops
+ when (string-match "=" (cl-first (mdcomp-operand-cstr op)))
+ do (insert "=")
+ do (insert (number-to-string (mdcomp-operand-num op)) ", ")
+ finally
+ (progn
+ ;; In case add attributes names
+ (when attrs
+ (delete-char -2)
+ (insert "; attrs: ")
+ (cl-loop for attr in attrs
+ do (insert (mdcomp-attr-name attr) ", ")))
+ (delete-char -2)
+ (insert "]")))
+ (cl-loop
+ while (re-search-forward (rx bol (0+ space) (or (group-n 1 "* return")
+ (group-n 2 "}")
+ "#" alpha "<"))
+ nil t)
+ for i from 0
+ when (match-string 2)
+ do (cl-return)
+ when (match-string 1)
+ do (progn
+ (delete-region (match-beginning 1) (+ (match-beginning 1) (length "* return")))
+ (insert "<<")
+ (left-char 1))
+ do
+ (progn
+ (left-char 1)
+ (cl-loop
+ initially (insert " [ ")
+ for op in ops
+ for c = (nth i (mdcomp-operand-cstr op))
+ unless c
+ do (cl-return)
+ do (insert (if (string-match "=" c)
+ (substring c 1 nil)
+ c)
+ ", ")
+ finally (progn
+ (when attrs
+ (delete-char -2)
+ (insert "; ")
+ (cl-loop for attr in attrs
+ for str = (nth i (mdcomp-attr-vals attr))
+ when str
+ do (insert str)
+ do (insert ", ")))
+ (delete-char -2)
+ (insert " ] ")
+ (move-end-of-line 1)))))
+ ;; remove everything after ] align what needs to be aligned
+ ;; and re-add the asm template
+ (re-search-backward (regexp-quote "@[ cons:"))
+ (let* ((n (length (mdcomp-operand-cstr (car ops))))
+ (asms (cl-loop
+ initially (re-search-forward "]")
+ repeat n
+ collect (let* ((beg (re-search-forward "]"))
+ (end (re-search-forward (rx eol)))
+ (str (buffer-substring-no-properties beg end)))
+ (delete-region beg end)
+ str)))
+ (beg (re-search-backward (regexp-quote "@[ cons:")))
+ (indent-tabs-mode nil))
+ (re-search-forward "}")
+ (align-regexp beg (point) (rx (group-n 1 "") "["))
+ (align-regexp beg (point) (rx (group-n 1 "") (or "," ";")) nil nil t)
+ (align-regexp beg (point) (rx (group-n 1 "") "]"))
+ (goto-char beg)
+ (cl-loop
+ initially (re-search-forward "]")
+ for i below n
+ do (progn
+ (re-search-forward "]")
+ (insert (nth i asms))))
+ (when (re-search-forward (rx (1+ (or space eol)) ")") nil t)
+ (replace-match "\n)" nil t)))))
+
+(defun mdcomp-narrow-to-md-pattern ()
+ (condition-case nil
+ (let ((beg (re-search-forward "\n("))
+ (end (re-search-forward (rx bol (1+ ")")))))
+ (narrow-to-region beg end))
+ (error
+ (narrow-to-defun))))
+
+(defun mdcomp-run-at-point ()
+ "Convert the multi choice top-level form around point to compact syntax."
+ (interactive)
+ (save-restriction
+ (save-mark-and-excursion
+ (mdcomp-narrow-to-md-pattern)
+ (goto-char (point-min))
+ (let ((pattern-name (save-excursion
+ (re-search-forward (rx "\"" (group-n 1 (1+ (not "\""))) "\""))
+ (match-string-no-properties 1)))
+ (orig-text (buffer-substring-no-properties (point-min) (point-max))))
+ (condition-case nil
+ (progn
+ (mdcomp-run*)
+ (message "Converted: %s" pattern-name))
+ (error
+ (message "Skipping convertion for: %s" pattern-name)
+ (delete-region (point-min) (point-max))
+ (insert orig-text)
+ 'fail))))))
+
+(defun mdcomp-run-buffer ()
+ "Convert the multi choice top-level forms in the buffer to compact syntax."
+ (interactive)
+ (save-excursion
+ (message "Conversion for buffer %s started" (buffer-file-name))
+ (goto-char (point-min))
+ (while (re-search-forward
+ (rx "match_operand" (1+ any) letter (0+ space) "," (0+ space) letter) nil t)
+ (when (eq (mdcomp-run-at-point) 'fail)
+ (condition-case nil
+ (forward-sexp)
+ (error
+ ;; If forward-sexp fails falls back.
+ (re-search-forward (rx ")" eol eol))))))
+ (message "Conversion done")))
+
+(defconst mdcomp-file-rx (rx bol alpha (0+ not-newline) ".md" eol))
+
+(defun mdcomp-run-directory (folder &optional recursive)
+ "Run el mdcompact on a FOLDER possibly in a RECURSIVE fashion."
+ (interactive "D")
+ (let ((before-save-hook nil)
+ (init-time (current-time)))
+ (mapc (lambda (f)
+ (with-temp-file f
+ (message "Working on %s" f)
+ (insert-file-contents f)
+ (mdcomp-run-buffer)
+ (message "Done with %s" f)))
+ (if recursive
+ (directory-files-recursively folder mdcomp-file-rx)
+ (directory-files folder t mdcomp-file-rx)))
+ (message "Converted in %f sec" (float-time (time-since init-time)))))
+
+(defun mdcomp-batch-run-directory ()
+ "Same as `mdcomp-run-directory' but use cmd line args."
+ (mdcomp-run-directory (nth 0 argv) (nth 1 argv)))
+
+(provide 'mdcompact)
+
+;;; mdcompact.el ends here
new file mode 100644
@@ -0,0 +1,36 @@
+(define_insn_and_split "*movsi_aarch64"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, r, w,r,w, w")
+ (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usw,Usa,Ush,rZ,w,w,Ds"))]
+ "(register_operand (operands[0], SImode)
+ || aarch64_reg_or_zero (operands[1], SImode))"
+ "@
+ mov\\t%w0, %w1
+ mov\\t%w0, %w1
+ mov\\t%w0, %w1
+ mov\\t%w0, %1
+ #
+ * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
+ ldr\\t%w0, %1
+ ldr\\t%s0, %1
+ str\\t%w1, %0
+ str\\t%s1, %0
+ adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1]
+ adr\\t%x0, %c1
+ adrp\\t%x0, %A1
+ fmov\\t%s0, %w1
+ fmov\\t%w0, %s1
+ fmov\\t%s0, %s1
+ * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
+ "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
+ && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "{
+ aarch64_expand_mov_immediate (operands[0], operands[1]);
+ DONE;
+ }"
+ [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
+ load_4,store_4,store_4,load_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
+ (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,*,fp,fp,fp,simd")
+ (set_attr "length" "4,4,4,4,*, 4,4, 4,4, 4,8,4,4, 4, 4, 4, 4")
+]
+)
new file mode 100644
@@ -0,0 +1,32 @@
+(define_insn_and_split "*movsi_aarch64"
+ [(set (match_operand:SI 0 "nonimmediate_operand")
+ (match_operand:SI 1 "aarch64_mov_operand"))]
+ "(register_operand (operands[0], SImode)
+ || aarch64_reg_or_zero (operands[1], SImode))"
+ {@ [ cons: =0 , 1 ; attrs: type , arch , length ]
+ [ r , r ; mov_reg , * , 4 ] mov\t%w0, %w1
+ [ k , r ; mov_reg , * , 4 ] mov\t%w0, %w1
+ [ r , k ; mov_reg , * , 4 ] mov\t%w0, %w1
+ [ r , M ; mov_imm , * , 4 ] mov\t%w0, %1
+ [ r , n ; mov_imm , * , * ] #
+ [ r , Usv ; mov_imm , sve , 4 ] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
+ [ r , m ; load_4 , * , 4 ] ldr\t%w0, %1
+ [ w , m ; load_4 , fp , 4 ] ldr\t%s0, %1
+ [ m , rZ ; store_4 , * , 4 ] str\t%w1, %0
+ [ m , w ; store_4 , fp , 4 ] str\t%s1, %0
+ [ r , Usw ; load_4 , * , 8 ] adrp\t%x0, %A1\;ldr\t%w0, [%x0, %L1]
+ [ r , Usa ; adr , * , 4 ] adr\t%x0, %c1
+ [ r , Ush ; adr , * , 4 ] adrp\t%x0, %A1
+ [ w , rZ ; f_mcr , fp , 4 ] fmov\t%s0, %w1
+ [ r , w ; f_mrc , fp , 4 ] fmov\t%w0, %s1
+ [ w , w ; fmov , fp , 4 ] fmov\t%s0, %s1
+ [ w , Ds ; neon_move , simd , 4 ] << aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
+ }
+ "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
+ && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "{
+ aarch64_expand_mov_immediate (operands[0], operands[1]);
+ DONE;
+ }"
+)
new file mode 100644
@@ -0,0 +1,25 @@
+(define_insn "*movti_aarch64"
+ [(set (match_operand:TI 0
+ "nonimmediate_operand" "= r,w,w,w, r,w,r,m,m,w,m")
+ (match_operand:TI 1
+ "aarch64_movti_operand" " rUti,Z,Z,r, w,w,m,r,Z,m,w"))]
+ "(register_operand (operands[0], TImode)
+ || aarch64_reg_or_zero (operands[1], TImode))"
+ "@
+ #
+ movi\\t%0.2d, #0
+ fmov\t%d0, xzr
+ #
+ #
+ mov\\t%0.16b, %1.16b
+ ldp\\t%0, %H0, %1
+ stp\\t%1, %H1, %0
+ stp\\txzr, xzr, %0
+ ldr\\t%q0, %1
+ str\\t%q1, %0"
+ [(set_attr "type" "multiple,neon_move,f_mcr,f_mcr,f_mrc,neon_logic_q, \
+ load_16,store_16,store_16,\
+ load_16,store_16")
+ (set_attr "length" "8,4,4,8,8,4,4,4,4,4,4")
+ (set_attr "arch" "*,simd,*,*,*,simd,*,*,*,fp,fp")]
+)
new file mode 100644
@@ -0,0 +1,21 @@
+(define_insn "*movti_aarch64"
+ [(set (match_operand:TI 0
+ "nonimmediate_operand")
+ (match_operand:TI 1
+ "aarch64_movti_operand"))]
+ "(register_operand (operands[0], TImode)
+ || aarch64_reg_or_zero (operands[1], TImode))"
+ {@ [ cons: =0 , 1 ; attrs: type , length , arch ]
+ [ r , rUti ; multiple , 8 , * ] #
+ [ w , Z ; neon_move , 4 , simd ] movi\t%0.2d, #0
+ [ w , Z ; f_mcr , 4 , * ] fmov\t%d0, xzr
+ [ w , r ; f_mcr , 8 , * ] #
+ [ r , w ; f_mrc , 8 , * ] #
+ [ w , w ; neon_logic_q , 4 , simd ] mov\t%0.16b, %1.16b
+ [ r , m ; load_16 , 4 , * ] ldp\t%0, %H0, %1
+ [ m , r ; store_16 , 4 , * ] stp\t%1, %H1, %0
+ [ m , Z ; store_16 , 4 , * ] stp\txzr, xzr, %0
+ [ w , m ; load_16 , 4 , fp ] ldr\t%q0, %1
+ [ m , w ; store_16 , 4 , fp ] str\t%q1, %0
+ }
+)
new file mode 100644
@@ -0,0 +1,16 @@
+(define_insn "*add<mode>3_compareV_cconly_imm"
+ [(set (reg:CC_V CC_REGNUM)
+ (compare:CC_V
+ (plus:<DWI>
+ (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
+ (match_operand:<DWI> 1 "const_scalar_int_operand" ""))
+ (sign_extend:<DWI>
+ (plus:GPI
+ (match_dup 0)
+ (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))]
+ "INTVAL (operands[1]) == INTVAL (operands[2])"
+ "@
+ cmn\\t%<w>0, %<w>1
+ cmp\\t%<w>0, #%n1"
+ [(set_attr "type" "alus_imm")]
+)
new file mode 100644
@@ -0,0 +1,17 @@
+(define_insn "*add<mode>3_compareV_cconly_imm"
+ [(set (reg:CC_V CC_REGNUM)
+ (compare:CC_V
+ (plus:<DWI>
+ (sign_extend:<DWI> (match_operand:GPI 0 "register_operand"))
+ (match_operand:<DWI> 1 "const_scalar_int_operand"))
+ (sign_extend:<DWI>
+ (plus:GPI
+ (match_dup 0)
+ (match_operand:GPI 2 "aarch64_plus_immediate")))))]
+ "INTVAL (operands[1]) == INTVAL (operands[2])"
+ {@ [ cons: 0 , 2 ]
+ [ r , I ] cmn\t%<w>0, %<w>1
+ [ r , J ] cmp\t%<w>0, #%n1
+ }
+ [(set_attr "type" "alus_imm")]
+)
new file mode 100644
@@ -0,0 +1,17 @@
+(define_insn "*sibcall_insn"
+ [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
+ (match_operand 1 ""))
+ (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
+ (return)]
+ "SIBLING_CALL_P (insn)"
+ {
+ if (which_alternative == 0)
+ {
+ output_asm_insn ("br\\t%0", operands);
+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
+ }
+ return "b\\t%c0";
+ }
+ [(set_attr "type" "branch, branch")
+ (set_attr "sls_length" "retbr,none")]
+)
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,17 @@
+(define_insn "*sibcall_insn"
+ [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
+ (match_operand 1 ""))
+ (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
+ (return)]
+ "SIBLING_CALL_P (insn)"
+ {
+ if (which_alternative == 0)
+ {
+ output_asm_insn ("br\\t%0", operands);
+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
+ }
+ return "b\\t%c0";
+ }
+ [(set_attr "type" "branch, branch")
+ (set_attr "sls_length" "retbr,none")]
+)
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,12 @@
+(define_insn "<optab><mode>3"
+ [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
+ (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
+ (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
+ ""
+ "@
+ <logical>\\t%<w>0, %<w>1, %<w>2
+ <logical>\\t%<w>0, %<w>1, %2
+ <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
+ [(set_attr "type" "logic_reg,logic_imm,neon_logic")
+ (set_attr "arch" "*,*,simd")]
+)
new file mode 100644
@@ -0,0 +1,11 @@
+(define_insn "<optab><mode>3"
+ [(set (match_operand:GPI 0 "register_operand")
+ (LOGICAL:GPI (match_operand:GPI 1 "register_operand")
+ (match_operand:GPI 2 "aarch64_logical_operand")))]
+ ""
+ {@ [ cons: =0 , 1 , 2 ; attrs: type , arch ]
+ [ r , %r , r ; logic_reg , * ] <logical>\t%<w>0, %<w>1, %<w>2
+ [ rk , r , <lconst> ; logic_imm , * ] <logical>\t%<w>0, %<w>1, %2
+ [ w , w , w ; neon_logic , simd ] <logical>\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>
+ }
+)
new file mode 100644
@@ -0,0 +1,11 @@
+(define_insn "aarch64_wrffr"
+ [(set (reg:VNx16BI FFR_REGNUM)
+ (match_operand:VNx16BI 0 "aarch64_simd_reg_or_minus_one"))
+ (set (reg:VNx16BI FFRT_REGNUM)
+ (unspec:VNx16BI [(match_dup 0)] UNSPEC_WRFFR))]
+ "TARGET_SVE"
+ {@ [ cons: 0 ]
+ [ Dm ] setffr
+ [ Upa ] wrffr\t%0.b
+ }
+)
new file mode 100644
@@ -0,0 +1,11 @@
+(define_insn "aarch64_wrffr"
+ [(set (reg:VNx16BI FFR_REGNUM)
+ (match_operand:VNx16BI 0 "aarch64_simd_reg_or_minus_one"))
+ (set (reg:VNx16BI FFRT_REGNUM)
+ (unspec:VNx16BI [(match_dup 0)] UNSPEC_WRFFR))]
+ "TARGET_SVE"
+ {@ [ cons: 0 ]
+ [ Dm ] setffr
+ [ Upa ] wrffr\t%0.b
+ }
+)
new file mode 100644
@@ -0,0 +1,11 @@
+(define_insn "and<mode>3<vczle><vczbe>"
+ [(set (match_operand:VDQ_I 0 "register_operand" "=w,w")
+ (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
+ (match_operand:VDQ_I 2 "aarch64_reg_or_bic_imm" "w,Db")))]
+ "TARGET_SIMD"
+ "@
+ and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>
+ * return aarch64_output_simd_mov_immediate (operands[2], <bitsize>,\
+ AARCH64_CHECK_BIC);"
+ [(set_attr "type" "neon_logic<q>")]
+)
new file mode 100644
@@ -0,0 +1,11 @@
+(define_insn "and<mode>3<vczle><vczbe>"
+ [(set (match_operand:VDQ_I 0 "register_operand")
+ (and:VDQ_I (match_operand:VDQ_I 1 "register_operand")
+ (match_operand:VDQ_I 2 "aarch64_reg_or_bic_imm")))]
+ "TARGET_SIMD"
+ {@ [ cons: =0 , 1 , 2 ]
+ [ w , w , w ] and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>
+ [ w , 0 , Db ] << aarch64_output_simd_mov_immediate (operands[2], <bitsize>, AARCH64_CHECK_BIC);
+ }
+ [(set_attr "type" "neon_logic<q>")]
+)