Re: [PATCH] x86-64: Add load-after-store elimination peephole optimization

Anthony Green <[email protected]>
Newsgroups gmane.lisp.steel-bank.devel
Message-ID <CACxje59+_GUXrcJJtRm+Aow8=hCyjKQp7bdcck4=JcXWX77tzQ@mail.gmail.com>
No, I don't think so.

AG


On Fri, Nov 7, 2025 at 8:45 PM Charles Zhang <[email protected]>
wrote:

> Would it be possible to do this as part of the cost model in register
> allocation? There is a backend-independent move coalescing pass already.
>
> On Friday, November 7, 2025, 11:23 PM, Anthony Green <[email protected]>
> wrote:
>
> When code stores a register to memory and immediately loads from the
> same memory location, eliminate the redundant memory load by copying
> from the source register instead.
>
> This optimization transforms:
>   MOV [memory], REG1
>   MOV REG2, [memory]
>
> Into:
>   MOV [memory], REG1
>   MOV REG2, REG1      ; faster and one byte shorter
>
> The pattern commonly appears in structure slot updates and list
> manipulation code. During a full SBCL build, this optimization fires
> approximately 19 times in src/code/seq.lisp alone.
>
> While modern CPUs have store-to-load forwarding, register-to-register
> moves can be eliminated entirely via register renaming.
>
> Anthony
>
> ---
>  src/compiler/x86-64/insts.lisp   | 16 ++++++++++++++++
>  tests/x86-64-codegen.impure.lisp | 22 ++++++++++++++++++++++
>  2 files changed, 38 insertions(+)
>
> diff --git a/src/compiler/x86-64/insts.lisp
> b/src/compiler/x86-64/insts.lisp
> index d7dcfd624..8c69b2922 100644
> --- a/src/compiler/x86-64/insts.lisp
> +++ b/src/compiler/x86-64/insts.lisp
> @@ -3579,3 +3579,19 @@
>        (add-stmt-labels stmt (stmt-labels next))
>        (delete-stmt next)
>        stmt)))
> +
> +;;; Load after store elimination - Transform store-then-load from same
> memory
> +;;; location into a register-to-register move, eliminating the load.
> +(defpattern "load after store elim" ((mov) (mov)) (stmt next)
> +  (binding* (((size1 dst1 src1) (parse-2-operands stmt))
> +             ((size2 dst2 src2) (parse-2-operands next)))
> +    (when (and (eq size1 :qword)
> +               (eq size2 :qword)
> +               (gpr-tn-p src1)  ; First MOV stores from register
> +               (gpr-tn-p dst2)  ; Second MOV loads into register
> +               (ea-p dst1)      ; First MOV stores to memory
> +               (ea-p src2)      ; Second MOV loads from memory
> +               (ea= dst1 src2)) ; Same effective address
> +      ;; Transform the load to copy from the register instead
> +      (setf (stmt-operands next) `(,(encode-size-prefix size2) ,dst2
> ,src1))
> +      next)))
> diff --git a/tests/x86-64-codegen.impure.lisp
> b/tests/x86-64-codegen.impure.lisp
> index dbc2df515..73f78730c 100644
> --- a/tests/x86-64-codegen.impure.lisp
> +++ b/tests/x86-64-codegen.impure.lisp
> @@ -1383,3 +1383,25 @@
>
>  (with-test (:name :signed-vops) (test-signed))
>  (with-test (:name :unsigned-vops) (test-unsigned))
> +
> +(with-test (:name :load-after-store-elim)
> +  ;; Test that store-then-load from same memory location is optimized
> +  ;; to store-then-register-move, eliminating the redundant memory load.
> +  (let* ((f (checked-compile
> +             '(lambda (cons-cell new-car)
> +               (declare (optimize (speed 3) (safety 0)))
> +               (setf (car cons-cell) new-car)
> +               (car cons-cell))))
> +         (lines (disassembly-lines f)))
> +    ;; Without optimization: MOV [mem], reg  ; MOV reg, [mem]
> +    ;; With optimization:    MOV [mem], reg  ; MOV reg, reg
> +    ;; Check that after the store, we don't load from memory
> +    (let ((store-pos (position-if (lambda (line)
> +                                    (and (search "MOV [" line)
> +                                         (search "], " line)))
> +                                  lines)))
> +      (when store-pos
> +        (assert (notany (lambda (line)
> +                          (and (search "MOV " line)
> +                               (search ", [" line)))
> +                        (nthcdr (1+ store-pos) lines)))))))
> --
>
> _______________________________________________
> Sbcl-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/sbcl-devel
>
>

_______________________________________________
Sbcl-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.