blob: e2ca74a4de1c99654765f578ef277079675d8856 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.Translation
{
static class ControlFlowGraph
{
public static BasicBlock[] MakeCfg(Operation[] operations)
{
Dictionary<Operand, BasicBlock> labels = new Dictionary<Operand, BasicBlock>();
List<BasicBlock> blocks = new List<BasicBlock>();
BasicBlock currentBlock = null;
void NextBlock(BasicBlock nextBlock)
{
if (currentBlock != null && !EndsWithUnconditionalInst(currentBlock.GetLastOp()))
{
currentBlock.Next = nextBlock;
}
currentBlock = nextBlock;
}
void NewNextBlock()
{
BasicBlock block = new BasicBlock(blocks.Count);
blocks.Add(block);
NextBlock(block);
}
bool needsNewBlock = true;
for (int index = 0; index < operations.Length; index++)
{
Operation operation = operations[index];
if (operation.Inst == Instruction.MarkLabel)
{
Operand label = operation.Dest;
if (labels.TryGetValue(label, out BasicBlock nextBlock))
{
nextBlock.Index = blocks.Count;
blocks.Add(nextBlock);
NextBlock(nextBlock);
}
else
{
NewNextBlock();
labels.Add(label, currentBlock);
}
}
else
{
if (needsNewBlock)
{
NewNextBlock();
}
currentBlock.Operations.AddLast(operation);
}
needsNewBlock = operation.Inst == Instruction.Branch ||
operation.Inst == Instruction.BranchIfTrue ||
operation.Inst == Instruction.BranchIfFalse;
if (needsNewBlock)
{
Operand label = operation.Dest;
if (!labels.TryGetValue(label, out BasicBlock branchBlock))
{
branchBlock = new BasicBlock();
labels.Add(label, branchBlock);
}
currentBlock.Branch = branchBlock;
}
}
return blocks.ToArray();
}
private static bool EndsWithUnconditionalInst(INode node)
{
if (node is Operation operation)
{
switch (operation.Inst)
{
case Instruction.Branch:
case Instruction.Discard:
case Instruction.Return:
return true;
}
}
return false;
}
}
}
|