From d25a084858438dd1188113efb76548916c2da9de Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Wed, 19 Jun 2024 09:25:47 -0300
Subject: [PATCH] JIT: Ensure entry block has no predecessors on RegisterUsage
 pass (#6951)

---
 src/ARMeilleure/Translation/ControlFlowGraph.cs | 11 ++++++++++-
 src/ARMeilleure/Translation/RegisterUsage.cs    | 13 ++++++++++++-
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/ARMeilleure/Translation/ControlFlowGraph.cs b/src/ARMeilleure/Translation/ControlFlowGraph.cs
index 3ead49c93..45b092ec5 100644
--- a/src/ARMeilleure/Translation/ControlFlowGraph.cs
+++ b/src/ARMeilleure/Translation/ControlFlowGraph.cs
@@ -11,7 +11,7 @@ namespace ARMeilleure.Translation
         private int[] _postOrderMap;
 
         public int LocalsCount { get; private set; }
-        public BasicBlock Entry { get; }
+        public BasicBlock Entry { get; private set; }
         public IntrusiveList<BasicBlock> Blocks { get; }
         public BasicBlock[] PostOrderBlocks => _postOrderBlocks;
         public int[] PostOrderMap => _postOrderMap;
@@ -34,6 +34,15 @@ namespace ARMeilleure.Translation
             return result;
         }
 
+        public void UpdateEntry(BasicBlock newEntry)
+        {
+            newEntry.AddSuccessor(Entry);
+
+            Entry = newEntry;
+            Blocks.AddFirst(newEntry);
+            Update();
+        }
+
         public void Update()
         {
             RemoveUnreachableBlocks(Blocks);
diff --git a/src/ARMeilleure/Translation/RegisterUsage.cs b/src/ARMeilleure/Translation/RegisterUsage.cs
index c8c250626..472b0f67b 100644
--- a/src/ARMeilleure/Translation/RegisterUsage.cs
+++ b/src/ARMeilleure/Translation/RegisterUsage.cs
@@ -89,6 +89,17 @@ namespace ARMeilleure.Translation
 
         public static void RunPass(ControlFlowGraph cfg, ExecutionMode mode)
         {
+            if (cfg.Entry.Predecessors.Count != 0)
+            {
+                // We expect the entry block to have no predecessors.
+                // This is required because we have a implicit context load at the start of the function,
+                // but if there is a jump to the start of the function, the context load would trash the modified values.
+                // Here we insert a new entry block that will jump to the existing entry block.
+                BasicBlock newEntry = new BasicBlock(cfg.Blocks.Count);
+
+                cfg.UpdateEntry(newEntry);
+            }
+
             // Compute local register inputs and outputs used inside blocks.
             RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
             RegisterMask[] localOutputs = new RegisterMask[cfg.Blocks.Count];
@@ -201,7 +212,7 @@ namespace ARMeilleure.Translation
 
                 // The only block without any predecessor should be the entry block.
                 // It always needs a context load as it is the first block to run.
-                if (block.Predecessors.Count == 0 || hasContextLoad)
+                if (block == cfg.Entry || hasContextLoad)
                 {
                     long vecMask = globalInputs[block.Index].VecMask;
                     long intMask = globalInputs[block.Index].IntMask;