|
|
@@ -8,47 +8,48 @@ namespace ARMeilleure.Translation
|
|
|
class ControlFlowGraph
|
|
|
{
|
|
|
public BasicBlock Entry { get; }
|
|
|
-
|
|
|
public IntrusiveList<BasicBlock> Blocks { get; }
|
|
|
-
|
|
|
public BasicBlock[] PostOrderBlocks { get; }
|
|
|
-
|
|
|
public int[] PostOrderMap { get; }
|
|
|
|
|
|
public ControlFlowGraph(BasicBlock entry, IntrusiveList<BasicBlock> blocks)
|
|
|
{
|
|
|
- Entry = entry;
|
|
|
+ Entry = entry;
|
|
|
Blocks = blocks;
|
|
|
|
|
|
RemoveUnreachableBlocks(blocks);
|
|
|
|
|
|
- HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
|
|
|
-
|
|
|
- Stack<BasicBlock> blockStack = new Stack<BasicBlock>();
|
|
|
+ var visited = new HashSet<BasicBlock>();
|
|
|
+ var blockStack = new Stack<BasicBlock>();
|
|
|
|
|
|
PostOrderBlocks = new BasicBlock[blocks.Count];
|
|
|
-
|
|
|
PostOrderMap = new int[blocks.Count];
|
|
|
|
|
|
visited.Add(entry);
|
|
|
-
|
|
|
blockStack.Push(entry);
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
|
while (blockStack.TryPop(out BasicBlock block))
|
|
|
{
|
|
|
- if (block.Next != null && visited.Add(block.Next))
|
|
|
- {
|
|
|
- blockStack.Push(block);
|
|
|
- blockStack.Push(block.Next);
|
|
|
- }
|
|
|
- else if (block.Branch != null && visited.Add(block.Branch))
|
|
|
+ bool visitedNew = false;
|
|
|
+
|
|
|
+ for (int i = 0; i < block.SuccessorCount; i++)
|
|
|
{
|
|
|
- blockStack.Push(block);
|
|
|
- blockStack.Push(block.Branch);
|
|
|
+ BasicBlock succ = block.GetSuccessor(i);
|
|
|
+
|
|
|
+ if (visited.Add(succ))
|
|
|
+ {
|
|
|
+ blockStack.Push(block);
|
|
|
+ blockStack.Push(succ);
|
|
|
+
|
|
|
+ visitedNew = true;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ if (!visitedNew)
|
|
|
{
|
|
|
PostOrderMap[block.Index] = index;
|
|
|
|
|
|
@@ -59,26 +60,24 @@ namespace ARMeilleure.Translation
|
|
|
|
|
|
private void RemoveUnreachableBlocks(IntrusiveList<BasicBlock> blocks)
|
|
|
{
|
|
|
- HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
|
|
|
-
|
|
|
- Queue<BasicBlock> workQueue = new Queue<BasicBlock>();
|
|
|
+ var visited = new HashSet<BasicBlock>();
|
|
|
+ var workQueue = new Queue<BasicBlock>();
|
|
|
|
|
|
visited.Add(Entry);
|
|
|
-
|
|
|
workQueue.Enqueue(Entry);
|
|
|
|
|
|
while (workQueue.TryDequeue(out BasicBlock block))
|
|
|
{
|
|
|
Debug.Assert(block.Index != -1, "Invalid block index.");
|
|
|
|
|
|
- if (block.Next != null && visited.Add(block.Next))
|
|
|
+ for (int i = 0; i < block.SuccessorCount; i++)
|
|
|
{
|
|
|
- workQueue.Enqueue(block.Next);
|
|
|
- }
|
|
|
+ BasicBlock succ = block.GetSuccessor(i);
|
|
|
|
|
|
- if (block.Branch != null && visited.Add(block.Branch))
|
|
|
- {
|
|
|
- workQueue.Enqueue(block.Branch);
|
|
|
+ if (visited.Add(succ))
|
|
|
+ {
|
|
|
+ workQueue.Enqueue(succ);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -93,8 +92,10 @@ namespace ARMeilleure.Translation
|
|
|
|
|
|
if (!visited.Contains(block))
|
|
|
{
|
|
|
- block.Next = null;
|
|
|
- block.Branch = null;
|
|
|
+ while (block.SuccessorCount > 0)
|
|
|
+ {
|
|
|
+ block.RemoveSuccessor(index: block.SuccessorCount - 1);
|
|
|
+ }
|
|
|
|
|
|
blocks.Remove(block);
|
|
|
}
|
|
|
@@ -112,14 +113,12 @@ namespace ARMeilleure.Translation
|
|
|
{
|
|
|
BasicBlock splitBlock = new BasicBlock(Blocks.Count);
|
|
|
|
|
|
- if (predecessor.Next == successor)
|
|
|
+ for (int i = 0; i < predecessor.SuccessorCount; i++)
|
|
|
{
|
|
|
- predecessor.Next = splitBlock;
|
|
|
- }
|
|
|
-
|
|
|
- if (predecessor.Branch == successor)
|
|
|
- {
|
|
|
- predecessor.Branch = splitBlock;
|
|
|
+ if (predecessor.GetSuccessor(i) == successor)
|
|
|
+ {
|
|
|
+ predecessor.SetSuccessor(i, splitBlock);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (splitBlock.Predecessors.Count == 0)
|
|
|
@@ -127,26 +126,7 @@ namespace ARMeilleure.Translation
|
|
|
throw new ArgumentException("Predecessor and successor are not connected.");
|
|
|
}
|
|
|
|
|
|
- // Insert the new block on the list of blocks.
|
|
|
- BasicBlock succPrev = successor.ListPrevious;
|
|
|
-
|
|
|
- if (succPrev != null && succPrev != predecessor && succPrev.Next == successor)
|
|
|
- {
|
|
|
- // Can't insert after the predecessor or before the successor.
|
|
|
- // Here, we insert it before the successor by also spliting another
|
|
|
- // edge (the one between the block before "successor" and "successor").
|
|
|
- BasicBlock splitBlock2 = new BasicBlock(splitBlock.Index + 1);
|
|
|
-
|
|
|
- succPrev.Next = splitBlock2;
|
|
|
-
|
|
|
- splitBlock2.Branch = successor;
|
|
|
-
|
|
|
- splitBlock2.Operations.AddLast(OperationHelper.Operation(Instruction.Branch, null));
|
|
|
-
|
|
|
- Blocks.AddBefore(successor, splitBlock2);
|
|
|
- }
|
|
|
-
|
|
|
- splitBlock.Next = successor;
|
|
|
+ splitBlock.AddSuccessor(successor);
|
|
|
|
|
|
Blocks.AddBefore(successor, splitBlock);
|
|
|
|