Archived
1
0
Fork 0
forked from Mirror/Ryujinx

JIT: Ensure entry block has no predecessors on RegisterUsage pass (#6951)

This commit is contained in:
gdkchan 2024-06-19 09:25:47 -03:00 committed by GitHub
parent 311ca3c3f1
commit d25a084858
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 2 deletions

View file

@ -11,7 +11,7 @@ namespace ARMeilleure.Translation
private int[] _postOrderMap; private int[] _postOrderMap;
public int LocalsCount { get; private set; } public int LocalsCount { get; private set; }
public BasicBlock Entry { get; } public BasicBlock Entry { get; private set; }
public IntrusiveList<BasicBlock> Blocks { get; } public IntrusiveList<BasicBlock> Blocks { get; }
public BasicBlock[] PostOrderBlocks => _postOrderBlocks; public BasicBlock[] PostOrderBlocks => _postOrderBlocks;
public int[] PostOrderMap => _postOrderMap; public int[] PostOrderMap => _postOrderMap;
@ -34,6 +34,15 @@ namespace ARMeilleure.Translation
return result; return result;
} }
public void UpdateEntry(BasicBlock newEntry)
{
newEntry.AddSuccessor(Entry);
Entry = newEntry;
Blocks.AddFirst(newEntry);
Update();
}
public void Update() public void Update()
{ {
RemoveUnreachableBlocks(Blocks); RemoveUnreachableBlocks(Blocks);

View file

@ -89,6 +89,17 @@ namespace ARMeilleure.Translation
public static void RunPass(ControlFlowGraph cfg, ExecutionMode mode) 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. // Compute local register inputs and outputs used inside blocks.
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count]; RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
RegisterMask[] localOutputs = 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. // 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. // 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 vecMask = globalInputs[block.Index].VecMask;
long intMask = globalInputs[block.Index].IntMask; long intMask = globalInputs[block.Index].IntMask;