From d25a084858438dd1188113efb76548916c2da9de Mon Sep 17 00:00:00 2001 From: gdkchan 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 3ead49c9..45b092ec 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 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 c8c25062..472b0f67 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;