Skip to content

Commit 1b71498

Browse files
Add support for irreducible CFG (#1032)
This PR addresses Issue #921. **Added:** Conversion of irreducible flow graphs by _Node Splitting_ (see Dragon book section 9.7.6). For every irreducible loop found, we duplicate one of the nodes (we first try to duplicate one that does not have invariants, if that exists) and all of the nodes that it dominates. **Tests:** The former _Irreducible.bpl_ test from _test0_ has been dropped and a new dedicated directory has been created: _irreduciblecfg_. 6 other test-cases have been added: - _Canonical.bpl_: similar to the previous Irreducible.bpl - _BackEdgeCounter.bpl_: A test case provided by @gauravpartha on the corresponding issue to justify why _Back Edge Elimination_ shouldn't be done directly on irreducible CFGs. - _CanonicalConditions.bpl_: A simple canonical irreducible CFG with some conditions - _Tangled.bpl_: A larger irreducible CFG that has to maintain an invariant - _Unsound.bpl_: A while + goto example provided by @petemud on the corresponding issue. It previously gave a false positive with the /extractLoops option. With the current approach, the failing trace is successfully identified. - _Await.bpl_: A simplified and slightly modified version of the example that we initially wanted to verify when we opened the issue. --------- Co-authored-by: Shaz Qadeer <[email protected]>
1 parent ea8e456 commit 1b71498

File tree

19 files changed

+448
-156
lines changed

19 files changed

+448
-156
lines changed

Source/Core/AST/GotoBoogie/Block.cs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Microsoft.Boogie;
77

88
public sealed class Block : Absy
99
{
10-
10+
1111
public string Label { get; set; } // Note, Label is mostly readonly, but it can change to the name of a nearby block during block coalescing and empty-block removal
1212

1313
[Rep]
@@ -49,7 +49,6 @@ public enum VisitState
4949
public int SuccCount;
5050

5151
private HashSet<Variable> liveVarsBefore;
52-
5352
public IEnumerable<Variable> LiveVarsBefore
5453
{
5554
get
@@ -97,10 +96,11 @@ public bool IsLive(Variable v)
9796
return LiveVarsBefore.Contains(v);
9897
}
9998

100-
public static Block ShallowClone(Block block) {
99+
public static Block ShallowClone(Block block)
100+
{
101101
return new Block(block.tok, block.Label, block.Cmds, block.TransferCmd);
102102
}
103-
103+
104104
public Block(IToken tok, TransferCmd cmd)
105105
: this(tok, "", new List<Cmd>(), new ReturnCmd(tok))
106106
{
@@ -196,4 +196,55 @@ public override Absy StdDispatch(StandardVisitor visitor)
196196
Contract.Ensures(Contract.Result<Absy>() != null);
197197
return visitor.VisitBlock(this);
198198
}
199+
200+
public bool HasInvariant()
201+
{
202+
return Cmds.Count >= 1 && Cmds[0] is AssertCmd;
203+
}
204+
205+
public void SubstituteBranchTargets(Dictionary<Block, Block> subst)
206+
{
207+
TransferCmd transferCmd = this.TransferCmd;
208+
if (transferCmd is not GotoCmd)
209+
{
210+
return;
211+
}
212+
213+
GotoCmd gotoCmd = (GotoCmd)transferCmd;
214+
foreach (Block currentBlock in gotoCmd.LabelTargets.ToList())
215+
{
216+
if (subst.TryGetValue(currentBlock, out Block dupBlock))
217+
{
218+
gotoCmd.RemoveTarget(currentBlock);
219+
gotoCmd.AddTarget(dupBlock);
220+
}
221+
}
222+
}
223+
224+
public Block DuplicateBlock(Dictionary<Block, int> nextLabels)
225+
{
226+
List<Cmd> dupCmds = new List<Cmd>();
227+
this.Cmds.ForEach(dupCmds.Add);
228+
229+
TransferCmd splitTransferCmd = this.TransferCmd;
230+
TransferCmd dupTransferCmd;
231+
232+
if (splitTransferCmd is not GotoCmd)
233+
{
234+
dupTransferCmd = new ReturnCmd(Token.NoToken);
235+
}
236+
else
237+
{
238+
List<string> dupLabelNames = [.. ((GotoCmd)splitTransferCmd).LabelNames];
239+
List<Block> dupLabelTargets = new List<Block>();
240+
((GotoCmd)splitTransferCmd).LabelTargets.ForEach(dupLabelTargets.Add);
241+
242+
dupTransferCmd = new GotoCmd(Token.NoToken, dupLabelNames, dupLabelTargets);
243+
}
244+
245+
Block dupBlock = new Block(Token.NoToken, this.Label + "_dup_" + nextLabels[this], dupCmds, dupTransferCmd);
246+
nextLabels[this]++;
247+
nextLabels.Add(dupBlock, 0);
248+
return dupBlock;
249+
}
199250
}

0 commit comments

Comments
 (0)