-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize blocks #919
Merged
keyboardDrummer
merged 51 commits into
boogie-org:master
from
keyboardDrummer:optimizeBlocks
Aug 15, 2024
Merged
Optimize blocks #919
Changes from 49 commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
be35cf1
Extracted classes into separate files
keyboardDrummer 52d696b
Print splits and various small fixes
keyboardDrummer 5e2d548
Update tests
keyboardDrummer c4a0342
Update tests
keyboardDrummer b89dde0
Add back /print
keyboardDrummer 70ec2a0
Optimize blocks
keyboardDrummer 51d1322
Update expect file
keyboardDrummer 8393fce
Update expect file
keyboardDrummer 1a161c8
Update split expect files
keyboardDrummer 149c07e
Merge branch 'printSplit' into optimizeBlocks
keyboardDrummer 8bed7e5
Fix bug and update test
keyboardDrummer e98b27e
Move deadVarElim.cs classes into separate files
keyboardDrummer 07ad293
Clean up code in BlockCoalescer and remove duplicate feature in Block…
keyboardDrummer e08091b
Fix test
keyboardDrummer 83ae368
Refactoring
keyboardDrummer 9e868e4
Remove unused import
keyboardDrummer 2b64f97
Merge commit 'c7878aa7ac1' into optimizeBlocks
keyboardDrummer e522dbf
Fixes
keyboardDrummer 9cd2a55
Fix
keyboardDrummer 6aa492c
Fix tests
keyboardDrummer 78a851d
Merge remote-tracking branch 'origin/master' into optimizeBlocks
keyboardDrummer 61f5902
Merge branch 'master' into optimizeBlocks
keyboardDrummer 5eed5f6
Configure a VC timeout for all tests
keyboardDrummer c79011b
Fix concurrency issue in QuantifierInstantiationEngine
keyboardDrummer 2870fb0
Add a process limit timeout
keyboardDrummer 735fee4
Make trace output culture invariant
keyboardDrummer 830ac55
Fix Rlimitouts0.bpl
keyboardDrummer 9d5ef3d
Fix tests
keyboardDrummer bb5a3a6
Merge remote-tracking branch 'origin/master' into setTimeout
keyboardDrummer 43ca15e
Fix indentation
keyboardDrummer f98fe32
Fix comp error
keyboardDrummer b57c1ed
Increase timeout of KeyboardClass test
keyboardDrummer 2b662ef
Add more cancellation
keyboardDrummer 1e9f7ce
Interrupt threads when disposing custom stack scheduler
keyboardDrummer 972c9be
Add blame-hang-timeout to unit test
keyboardDrummer 3d84ae9
Fix
keyboardDrummer 3e9470b
Refactoring
keyboardDrummer 2e8ca55
Fix warning
keyboardDrummer 02b3561
Removed output that causes tests to fail
keyboardDrummer dabf0ef
Delete accident
keyboardDrummer 00ef399
Add process time limit
keyboardDrummer 8d49878
Merge branch 'setTimeout' into optimizeBlocks
keyboardDrummer df7861b
Increase timeout for treiber
keyboardDrummer 3fe0fc5
Infinite timeout for treiber-stack
keyboardDrummer d6711d3
Merge commit 'a3cc4bae85db' into optimizeBlocks
keyboardDrummer 4c2cfee
Reduce changes
keyboardDrummer 24d5acc
Undo changes
keyboardDrummer 7f3d836
Reduce changes
keyboardDrummer c258866
Merge remote-tracking branch 'origin/master' into optimizeBlocks
keyboardDrummer 100ee6c
Cleanup
keyboardDrummer b4d6abc
Merge branch 'master' into optimizeBlocks
keyboardDrummer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,165 +1,161 @@ | ||
#nullable enable | ||
|
||
using System.Collections.Generic; | ||
using System.Diagnostics.Contracts; | ||
using System.Linq; | ||
|
||
namespace Microsoft.Boogie; | ||
|
||
public class BlockCoalescer : ReadOnlyVisitor | ||
{ | ||
public static void CoalesceBlocks(Program program) | ||
{ | ||
Contract.Requires(program != null); | ||
BlockCoalescer blockCoalescer = new BlockCoalescer(); | ||
var blockCoalescer = new BlockCoalescer(); | ||
blockCoalescer.Visit(program); | ||
} | ||
|
||
private static HashSet<Block /*!*/> /*!*/ ComputeMultiPredecessorBlocks(Implementation /*!*/ impl) | ||
private static HashSet<Block> ComputeMultiPredecessorBlocks(Block rootBlock) | ||
{ | ||
Contract.Requires(impl != null); | ||
Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Block>>())); | ||
HashSet<Block /*!*/> visitedBlocks = new HashSet<Block /*!*/>(); | ||
HashSet<Block /*!*/> multiPredBlocks = new HashSet<Block /*!*/>(); | ||
Stack<Block /*!*/> dfsStack = new Stack<Block /*!*/>(); | ||
dfsStack.Push(impl.Blocks[0]); | ||
var visitedBlocks = new HashSet<Block /*!*/>(); | ||
var result = new HashSet<Block>(); | ||
var dfsStack = new Stack<Block>(); | ||
dfsStack.Push(rootBlock); | ||
while (dfsStack.Count > 0) | ||
{ | ||
Block /*!*/ | ||
b = dfsStack.Pop(); | ||
Contract.Assert(b != null); | ||
if (visitedBlocks.Contains(b)) | ||
var /*!*/ block = dfsStack.Pop(); | ||
Contract.Assert(block != null); | ||
if (!visitedBlocks.Add(block)) | ||
{ | ||
multiPredBlocks.Add(b); | ||
result.Add(block); | ||
continue; | ||
} | ||
|
||
visitedBlocks.Add(b); | ||
if (b.TransferCmd == null) | ||
if (block.TransferCmd == null) | ||
{ | ||
continue; | ||
} | ||
|
||
if (b.TransferCmd is ReturnCmd) | ||
if (block.TransferCmd is ReturnCmd) | ||
{ | ||
continue; | ||
} | ||
|
||
Contract.Assert(b.TransferCmd is GotoCmd); | ||
GotoCmd gotoCmd = (GotoCmd) b.TransferCmd; | ||
Contract.Assert(block.TransferCmd is GotoCmd); | ||
var gotoCmd = (GotoCmd) block.TransferCmd; | ||
if (gotoCmd.labelTargets == null) | ||
{ | ||
continue; | ||
} | ||
|
||
foreach (Block /*!*/ succ in gotoCmd.labelTargets) | ||
foreach (var /*!*/ succ in gotoCmd.labelTargets) | ||
{ | ||
Contract.Assert(succ != null); | ||
dfsStack.Push(succ); | ||
} | ||
} | ||
|
||
return multiPredBlocks; | ||
return result; | ||
} | ||
|
||
public override Implementation VisitImplementation(Implementation impl) | ||
{ | ||
//Contract.Requires(impl != null); | ||
Contract.Ensures(Contract.Result<Implementation>() != null); | ||
//Console.WriteLine("Procedure {0}", impl.Name); | ||
//Console.WriteLine("Initial number of blocks = {0}", impl.Blocks.Count); | ||
|
||
HashSet<Block /*!*/> multiPredBlocks = ComputeMultiPredecessorBlocks(impl); | ||
Contract.Assert(cce.NonNullElements(multiPredBlocks)); | ||
HashSet<Block /*!*/> visitedBlocks = new HashSet<Block /*!*/>(); | ||
HashSet<Block /*!*/> removedBlocks = new HashSet<Block /*!*/>(); | ||
Stack<Block /*!*/> dfsStack = new Stack<Block /*!*/>(); | ||
dfsStack.Push(impl.Blocks[0]); | ||
while (dfsStack.Count > 0) | ||
var newBlocks = CoalesceFromRootBlock(impl.Blocks); | ||
impl.Blocks = newBlocks; | ||
foreach (var block in impl.Blocks) | ||
{ | ||
Block /*!*/ | ||
b = dfsStack.Pop(); | ||
Contract.Assert(b != null); | ||
if (visitedBlocks.Contains(b)) | ||
if (block.TransferCmd is ReturnCmd) | ||
{ | ||
continue; | ||
} | ||
|
||
visitedBlocks.Add(b); | ||
if (b.TransferCmd == null) | ||
var gotoCmd = (GotoCmd)block.TransferCmd; | ||
gotoCmd.labelNames = new List<string>(); | ||
foreach (var successor in gotoCmd.labelTargets) | ||
{ | ||
gotoCmd.labelNames.Add(successor.Label); | ||
} | ||
} | ||
return impl; | ||
} | ||
|
||
public static List<Block> CoalesceFromRootBlock(List<Block> blocks) | ||
{ | ||
if (!blocks.Any()) | ||
{ | ||
return blocks; | ||
} | ||
var multiPredecessorBlocks = ComputeMultiPredecessorBlocks(blocks[0]); | ||
Contract.Assert(cce.NonNullElements(multiPredecessorBlocks)); | ||
var visitedBlocks = new HashSet<Block>(); | ||
var removedBlocks = new HashSet<Block>(); | ||
var toVisit = new Stack<Block>(); | ||
toVisit.Push(blocks[0]); | ||
while (toVisit.Count > 0) | ||
{ | ||
var block = toVisit.Pop(); | ||
Contract.Assert(block != null); | ||
if (!visitedBlocks.Add(block)) | ||
{ | ||
continue; | ||
} | ||
|
||
if (b.TransferCmd is ReturnCmd) | ||
if (block.TransferCmd == null) | ||
{ | ||
continue; | ||
} | ||
|
||
Contract.Assert(b.TransferCmd is GotoCmd); | ||
GotoCmd gotoCmd = (GotoCmd) b.TransferCmd; | ||
if (block.TransferCmd is ReturnCmd) | ||
{ | ||
continue; | ||
} | ||
|
||
Contract.Assert(block.TransferCmd is GotoCmd); | ||
var gotoCmd = (GotoCmd) block.TransferCmd; | ||
if (gotoCmd.labelTargets == null) | ||
{ | ||
continue; | ||
} | ||
|
||
if (gotoCmd.labelTargets.Count == 1) | ||
if (gotoCmd.labelTargets.Count != 1) | ||
{ | ||
Block /*!*/ | ||
succ = cce.NonNull(gotoCmd.labelTargets[0]); | ||
if (!multiPredBlocks.Contains(succ)) | ||
foreach (var aSuccessor in gotoCmd.labelTargets) | ||
{ | ||
foreach (Cmd /*!*/ cmd in succ.Cmds) | ||
{ | ||
Contract.Assert(cmd != null); | ||
b.Cmds.Add(cmd); | ||
} | ||
|
||
b.TransferCmd = succ.TransferCmd; | ||
if (!b.tok.IsValid && succ.tok.IsValid) | ||
{ | ||
b.tok = succ.tok; | ||
b.Label = succ.Label; | ||
} | ||
|
||
removedBlocks.Add(succ); | ||
dfsStack.Push(b); | ||
visitedBlocks.Remove(b); | ||
continue; | ||
Contract.Assert(aSuccessor != null); | ||
toVisit.Push(aSuccessor); | ||
} | ||
continue; | ||
} | ||
|
||
foreach (Block /*!*/ succ in gotoCmd.labelTargets) | ||
var successor = cce.NonNull(gotoCmd.labelTargets[0]); | ||
if (multiPredecessorBlocks.Contains(successor)) | ||
{ | ||
Contract.Assert(succ != null); | ||
dfsStack.Push(succ); | ||
toVisit.Push(successor); | ||
continue; | ||
} | ||
} | ||
|
||
List<Block /*!*/> newBlocks = new List<Block /*!*/>(); | ||
foreach (Block /*!*/ b in impl.Blocks) | ||
{ | ||
Contract.Assert(b != null); | ||
if (visitedBlocks.Contains(b) && !removedBlocks.Contains(b)) | ||
block.Cmds.AddRange(successor.Cmds); | ||
block.TransferCmd = successor.TransferCmd; | ||
if (!block.tok.IsValid && successor.tok.IsValid) | ||
{ | ||
newBlocks.Add(b); | ||
block.tok = successor.tok; | ||
block.Label = successor.Label; | ||
} | ||
|
||
removedBlocks.Add(successor); | ||
toVisit.Push(block); | ||
visitedBlocks.Remove(block); | ||
} | ||
|
||
impl.Blocks = newBlocks; | ||
foreach (Block b in impl.Blocks) | ||
var newBlocks = new List<Block>(); | ||
foreach (var block in blocks) | ||
{ | ||
if (b.TransferCmd is ReturnCmd) | ||
{ | ||
continue; | ||
} | ||
|
||
GotoCmd gotoCmd = b.TransferCmd as GotoCmd; | ||
gotoCmd.labelNames = new List<string>(); | ||
foreach (Block succ in gotoCmd.labelTargets) | ||
Contract.Assert(block != null); | ||
if (visitedBlocks.Contains(block) && !removedBlocks.Contains(block)) | ||
{ | ||
gotoCmd.labelNames.Add(succ.Label); | ||
newBlocks.Add(block); | ||
} | ||
} | ||
|
||
// Console.WriteLine("Final number of blocks = {0}", impl.Blocks.Count); | ||
return impl; | ||
return newBlocks; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
using System.Collections.Generic; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.Contracts; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this change? A change in line ending? |
||
|
||
namespace Microsoft.Boogie; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've added some trailing whitespace here. I find that Rider is very eager to do this!