File 1140-AArch64-Add-a-helper-for-flushing-three-registers.patch of Package erlang

From 59c5ac5065de383601823fe3dce7e5600075cd25 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Fri, 29 Sep 2023 06:35:22 +0200
Subject: [PATCH 20/25] AArch64: Add a helper for flushing three registers

---
 erts/emulator/beam/jit/arm/beam_asm.hpp | 51 +++++++++++++++++++------
 1 file changed, 40 insertions(+), 11 deletions(-)

diff --git a/erts/emulator/beam/jit/arm/beam_asm.hpp b/erts/emulator/beam/jit/arm/beam_asm.hpp
index 5d4ee1364c..9503f0bb4b 100644
--- a/erts/emulator/beam/jit/arm/beam_asm.hpp
+++ b/erts/emulator/beam/jit/arm/beam_asm.hpp
@@ -1511,25 +1511,54 @@ protected:
         }
     }
 
-    void flush_vars(const Variable<arm::Gp> &to1,
-                    const Variable<arm::Gp> &to2) {
-        const arm::Mem &mem1 = to1.mem;
-        const arm::Mem &mem2 = to2.mem;
+    enum Relation { none, consecutive, reverse_consecutive };
 
+    static Relation memory_relation(const arm::Mem &mem1,
+                                    const arm::Mem &mem2) {
         if (mem1.hasBaseReg() && mem2.hasBaseReg() &&
             mem1.baseId() == mem2.baseId()) {
             if (mem1.offset() + 8 == mem2.offset()) {
-                stp_cache(to1.reg, to2.reg, mem1);
-                return;
+                return consecutive;
             } else if (mem1.offset() == mem2.offset() + 8) {
-                stp_cache(to2.reg, to1.reg, mem2);
-                return;
+                return reverse_consecutive;
             }
         }
+        return none;
+    }
+
+    void flush_vars(const Variable<arm::Gp> &to1,
+                    const Variable<arm::Gp> &to2) {
+        const arm::Mem &mem1 = to1.mem;
+        const arm::Mem &mem2 = to2.mem;
+
+        switch (memory_relation(to1.mem, to2.mem)) {
+        case Relation::consecutive:
+            stp_cache(to1.reg, to2.reg, mem1);
+            break;
+        case Relation::reverse_consecutive:
+            stp_cache(to2.reg, to1.reg, mem2);
+            break;
+        case Relation::none:
+            /* Not possible to optimize with stp. */
+            flush_var(to1);
+            flush_var(to2);
+            break;
+        }
+    }
 
-        /* Not possible to optimize with stp. */
-        flush_var(to1);
-        flush_var(to2);
+    void flush_vars(const Variable<arm::Gp> &to1,
+                    const Variable<arm::Gp> &to2,
+                    const Variable<arm::Gp> &to3) {
+        if (memory_relation(to2.mem, to3.mem) != Relation::none) {
+            flush_vars(to2, to3);
+            flush_var(to1);
+        } else if (memory_relation(to1.mem, to3.mem) != Relation::none) {
+            flush_vars(to1, to3);
+            flush_var(to2);
+        } else {
+            flush_vars(to1, to2);
+            flush_var(to3);
+        }
     }
 
     void mov_arg(const ArgVal &To, const ArgVal &From) {
-- 
2.35.3

openSUSE Build Service is sponsored by