Skip to content

Commit e0d65ad

Browse files
authored
WI #2014 Add basic dominator algorithms (#2015)
* WI #2014 Add basic dominator algorithms * WI #2014 Simply result format * WI #2014 Change Review * WI #2014 make DumpDominators static
1 parent 2ca4582 commit e0d65ad

File tree

8 files changed

+250
-1
lines changed

8 files changed

+250
-1
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Dominators[Block0]={0}
2+
Dominators[Block1]={0, 1}
3+
Dominators[Block2]={0, 1, 2}
4+
Dominators[Block3]={0, 1, 2, 3, 25, 26, 29}
5+
Dominators[Block4]={0, 1, 2, 3, 4, 25, 26, 29}
6+
Dominators[Block5]={0, 1, 2, 3, 4, 5, 25, 26, 29}
7+
Dominators[Block6]={0, 1, 2, 3, 4, 5, 6, 25, 26, 29}
8+
Dominators[Block25]={0, 1, 2, 25}
9+
Dominators[Block26]={0, 1, 2, 25, 26}
10+
Dominators[Block27]={0, 1, 2, 25, 26, 27}
11+
Dominators[Block29]={0, 1, 2, 25, 26, 29}
12+
Dominators[Block30]={0, 1, 2, 3, 4, 25, 26, 29, 30}
13+
Dominators[Block31]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31}
14+
Dominators[Block32]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32}
15+
Dominators[Block33]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32, 33}
16+
Dominators[Block34]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32, 33, 34, 43}
17+
Dominators[Block35]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 35}
18+
Dominators[Block36]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 36}
19+
Dominators[Block37]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37}
20+
Dominators[Block38]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37, 38}
21+
Dominators[Block39]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37, 38, 39, 44}
22+
Dominators[Block40]={0, 1, 2, 3, 4, 25, 26, 29, 30, 40}
23+
Dominators[Block43]={0, 1, 2, 3, 4, 25, 26, 29, 30, 31, 32, 33, 43}
24+
Dominators[Block44]={0, 1, 2, 3, 4, 25, 26, 29, 30, 37, 38, 44}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Dominators[Block0]={}
2+
Dominators[Block1]={0}
3+
Dominators[Block2]={1}
4+
Dominators[Block3]={29}
5+
Dominators[Block4]={3}
6+
Dominators[Block5]={4}
7+
Dominators[Block6]={5}
8+
Dominators[Block25]={2}
9+
Dominators[Block26]={25}
10+
Dominators[Block27]={26}
11+
Dominators[Block29]={26}
12+
Dominators[Block30]={4}
13+
Dominators[Block31]={30}
14+
Dominators[Block32]={31}
15+
Dominators[Block33]={32}
16+
Dominators[Block34]={43}
17+
Dominators[Block35]={31}
18+
Dominators[Block36]={31}
19+
Dominators[Block37]={30}
20+
Dominators[Block38]={37}
21+
Dominators[Block39]={44}
22+
Dominators[Block40]={30}
23+
Dominators[Block43]={33}
24+
Dominators[Block44]={38}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using System.IO;
3+
using TypeCobol.Analysis.Graph;
4+
using TypeCobol.Test;
5+
using static TypeCobol.Analysis.Test.CfgTestUtils;
6+
using CFG = TypeCobol.Analysis.Graph.ControlFlowGraph<TypeCobol.Compiler.Nodes.Node,
7+
TypeCobol.Analysis.Dfa.DfaBasicBlockInfo<TypeCobol.Compiler.Symbols.VariableSymbol>>;
8+
9+
namespace TypeCobol.Analysis.Test
10+
{
11+
[TestClass]
12+
public class CfgDfaDominatorTests
13+
{
14+
[TestMethod]
15+
[TestCategory("Dominator")]
16+
public void HanoiPrgCfgExtendedDominator()
17+
{
18+
string path = Path.Combine(BasicCfgPrograms, "HanoiPrg.cbl");
19+
var dfaResults = ParseCompareDiagnosticsWithDfa(path);
20+
Assert.IsTrue(dfaResults.Graphs.Count == 1);
21+
var blocks_dominators = dfaResults.Graphs[0].ComputeDominators();
22+
23+
string expectedDomsFile = Path.Combine(BasicCfgPrograms, "HanoiPrg.doms");
24+
StringWriter writer = new StringWriter();
25+
CFG.DumpDominators(blocks_dominators.Item2, writer);
26+
// compare with expected result
27+
string result = writer.ToString();
28+
string expected = File.ReadAllText(expectedDomsFile);
29+
TestUtils.compareLines(path, result, expected, expectedDomsFile);
30+
}
31+
32+
private static void HanoiPrgCfgExtendedImmediateDominator(bool duplicate)
33+
{
34+
string path = Path.Combine(BasicCfgPrograms, "HanoiPrg.cbl");
35+
var dfaResults = ParseCompareDiagnosticsWithDfa(path);
36+
Assert.IsTrue(dfaResults.Graphs.Count == 1);
37+
var blocks_dominators = dfaResults.Graphs[0].ComputeDominators();
38+
var idoms = dfaResults.Graphs[0].ComputeImmediateDominators(blocks_dominators.Item1, blocks_dominators.Item2, duplicate);
39+
40+
string expectedDomsFile = Path.Combine(BasicCfgPrograms, "HanoiPrg.idoms");
41+
StringWriter writer = new StringWriter();
42+
CFG.DumpDominators(idoms, writer);
43+
// compare with expected result
44+
string result = writer.ToString();
45+
string expected = File.ReadAllText(expectedDomsFile);
46+
TestUtils.compareLines(path, result, expected, expectedDomsFile);
47+
}
48+
49+
[TestMethod]
50+
[TestCategory("ImmediateDominator")]
51+
public void HanoiPrgCfgExtendedImmediateDominatorDup()
52+
{
53+
HanoiPrgCfgExtendedImmediateDominator(true);
54+
}
55+
56+
[TestMethod]
57+
[TestCategory("ImmediateDominator")]
58+
public void HanoiPrgCfgExtendedImmediateDominatorNoDup()
59+
{
60+
HanoiPrgCfgExtendedImmediateDominator(false);
61+
}
62+
}
63+
}

TypeCobol.Analysis.Test/TypeCobol.Analysis.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<Compile Include="BasicControlFlowInstructionTest.cs" />
3737
<Compile Include="BitSetTest.cs" />
3838
<Compile Include="CfgDfaBuildingTests.cs" />
39+
<Compile Include="CfgDfaDominatorTests.cs" />
3940
<Compile Include="CfgTestUtils.cs" />
4041
<Compile Include="CfgTestResults.cs" />
4142
<Compile Include="DfaBuildUseAndDefListTest.cs" />
@@ -62,6 +63,8 @@
6263
</ProjectReference>
6364
</ItemGroup>
6465
<ItemGroup>
66+
<None Include="BasicCfgPrograms\HanoiPrg.doms" />
67+
<None Include="BasicCfgPrograms\HanoiPrg.idoms" />
6568
<None Include="packages.config" />
6669
</ItemGroup>
6770
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using TypeCobol.Analysis.Util;
4+
5+
namespace TypeCobol.Analysis.Graph
6+
{
7+
/// <summary>
8+
/// Dominator algorithm implementation
9+
/// </summary>
10+
/// <typeparam name="N"></typeparam>
11+
/// <typeparam name="D"></typeparam>
12+
public partial class ControlFlowGraph<N, D>
13+
{
14+
/// <summary>
15+
/// Compute a Dominator set on this CFG Graph
16+
/// </summary>
17+
/// <returns>A Tuple of a List of reachable nodes and an array of BitSet indexed by BasicBlock Indices</returns>
18+
public Tuple<List<int>,BitSet[]> ComputeDominators()
19+
{
20+
BitSet[] dominators = new BitSet[this.AllBlocks.Count];
21+
//Compute reachable blocks
22+
List<int> blocks = new List<int>();
23+
this.DFS((block, incomingEdge, predecessorBlock, cfg) =>
24+
{
25+
blocks.Add(block.Index);
26+
dominators[block.Index] = new BitSet(dominators.Length);
27+
if (block.Index != this.RootBlock.Index)
28+
dominators[block.Index].Full();
29+
return true;
30+
});
31+
//Setup prececessors
32+
this.SetupPredecessorEdgesFromRoot();
33+
34+
//Reflexivity on root block
35+
dominators[this.RootBlock.Index].Set(this.RootBlock.Index);
36+
37+
bool change = false;
38+
BitSet workSet = new BitSet(dominators.Length); //workingSet
39+
do
40+
{
41+
change = false;
42+
foreach (int n in blocks)
43+
{
44+
if (n == this.RootBlock.Index)
45+
continue;
46+
BasicBlock<N, D> b = this.AllBlocks[n];
47+
System.Diagnostics.Debug.Assert(b.PredecessorEdges != null);
48+
workSet.Full();
49+
foreach (int r in b.PredecessorEdges)
50+
{
51+
BasicBlock<N, D> p = PredecessorEdges[r];
52+
workSet.And(dominators[p.Index]);
53+
}
54+
workSet.Set(n);//reflexivity
55+
if (!workSet.Equals(dominators[n]))
56+
{
57+
dominators[n].Copy(workSet);
58+
change = true;
59+
}
60+
}
61+
} while (change);
62+
63+
return new Tuple<List<int>, BitSet[]>(blocks, dominators);
64+
}
65+
66+
/// <summary>
67+
/// Compute the immediate dominance relation.
68+
/// </summary>
69+
/// <param name="blocks">The blocks of the graph on which to work.</param>
70+
/// <param name="dominators">The dominator sets</param>
71+
/// <param name="duplicate">true to create new sets, rather then pruning dominators set</param>
72+
/// <returns>The immediate dominance sets</returns>
73+
public BitSet[] ComputeImmediateDominators(List<int> blocks, BitSet[] dominators, bool duplicate = true)
74+
{
75+
BitSet[] idoms = duplicate ? new BitSet[dominators.Length] : dominators;
76+
foreach (var b in blocks)
77+
{
78+
if (duplicate)
79+
{
80+
idoms[b] = new BitSet(dominators.Length);
81+
idoms[b].Copy(dominators[b]);
82+
}
83+
idoms[b].Clear(b); //Remove reflexivity
84+
}
85+
BitSet tmp = new BitSet();
86+
foreach (var r in blocks)
87+
{
88+
if (r == this.RootBlock.Index) continue;
89+
tmp.Copy(idoms[r]);
90+
foreach (var s in blocks)
91+
{
92+
if (tmp.Get(s))
93+
{
94+
foreach (var t in blocks)
95+
{
96+
if (t == s) continue;
97+
if (tmp.Get(t) && idoms[s].Get(t))
98+
{
99+
idoms[r].Clear(t);
100+
}
101+
}
102+
}
103+
}
104+
}
105+
return idoms;
106+
}
107+
108+
/// <summary>
109+
/// Dump a set of Dominators
110+
/// </summary>
111+
/// <param name="dominators">The set of Dominators</param>
112+
/// <param name="writer"></param>
113+
public static void DumpDominators(BitSet[] dominators, System.IO.TextWriter writer)
114+
{
115+
for (int i = 0; i < dominators.Length; i++)
116+
{
117+
BitSet doms = dominators[i];
118+
if (doms != null)
119+
{
120+
writer.WriteLine($"Dominators[Block{i}]={doms.ToString()}");
121+
}
122+
}
123+
}
124+
}
125+
}

TypeCobol.Analysis/Graph/ControlFlowGraph.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace TypeCobol.Analysis.Graph
1010
/// </summary>
1111
/// <typeparam name="N"></typeparam>
1212
/// <typeparam name="D"></typeparam>
13-
public class ControlFlowGraph<N, D>
13+
public partial class ControlFlowGraph<N, D>
1414
{
1515
/// <summary>
1616
/// BasicBlock callback type.

TypeCobol.Analysis/TypeCobol.Analysis.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<Compile Include="Graph\BasicBlock.cs" />
4949
<Compile Include="Graph\CfgDotFileForNodeGenerator.cs" />
5050
<Compile Include="Graph\ControlFlowGraph.cs" />
51+
<Compile Include="Graph\ControlFlowGraph.Dominator.cs" />
5152
<Compile Include="Graph\ICfgFileGenerator.cs" />
5253
<Compile Include="Graph\ICfgTransform.cs" />
5354
<Compile Include="Properties\AssemblyInfo.cs" />

TypeCobol.Analysis/Util/BitSet.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ public void Clear()
150150
_data[i] = 0;
151151
}
152152

153+
/// <summary>
154+
/// Set all bit to 1
155+
/// </summary>
156+
public void Full()
157+
{
158+
for (int i = 0; i < _data.Length; i++)
159+
_data[i] = ulong.MaxValue;
160+
}
161+
153162
public void Copy(BitSet from)
154163
{
155164
if (_data.Length != from._data.Length)

0 commit comments

Comments
 (0)