22using System . Collections . Generic ;
33using System . Diagnostics ;
44using System . Diagnostics . Contracts ;
5+ using System . Linq ;
56using Microsoft . Boogie ;
67using Microsoft . Boogie . GraphUtil ;
78using VC ;
@@ -73,25 +74,26 @@ public void ConvertCfg2Dag(ImplementationRun run, Dictionary<Block, List<Block>>
7374
7475 #endregion
7576 }
76- private void SubstituteBlocks ( Block b , Dictionary < Block , Block > subst )
77+ private static void SubstituteBranchTargets ( Block b , Dictionary < Block , Block > subst )
7778 {
7879 TransferCmd transferCmd = b . TransferCmd ;
7980 if ( transferCmd is not GotoCmd )
8081 {
8182 return ;
8283 }
83- foreach ( var ( oldBlock , newBlock ) in subst )
84+
85+ GotoCmd gotoCmd = ( GotoCmd ) transferCmd ;
86+ foreach ( Block currentBlock in gotoCmd . LabelTargets . ToList ( ) )
8487 {
85- GotoCmd gotoCmd = ( GotoCmd ) transferCmd ;
86- if ( gotoCmd . LabelTargets . Contains ( oldBlock ) )
88+ if ( subst . TryGetValue ( currentBlock , out Block dupBlock ) )
8789 {
88- gotoCmd . RemoveTarget ( oldBlock ) ;
89- gotoCmd . AddTarget ( newBlock ) ;
90- }
90+ gotoCmd . RemoveTarget ( currentBlock ) ;
91+ gotoCmd . AddTarget ( dupBlock ) ;
92+ }
9193 }
9294 }
9395
94- private Block duplicateBlock ( Block b )
96+ private static Block DuplicateBlock ( Block b , Dictionary < Block , int > nextLabels )
9597 {
9698 List < Cmd > dupCmds = new List < Cmd > ( ) ;
9799 b . Cmds . ForEach ( dupCmds . Add ) ;
@@ -112,63 +114,36 @@ private Block duplicateBlock(Block b)
112114 dupTransferCmd = new GotoCmd ( Token . NoToken , dupLabelNames , dupLabelTargets ) ;
113115 }
114116
115- Block dupBlock = new Block ( Token . NoToken , b . Label + "_dup_" + b . UpdateDuplicates ( ) , dupCmds , dupTransferCmd ) ;
117+ Block dupBlock = new Block ( Token . NoToken , b . Label + "_dup_" + nextLabels [ b ] , dupCmds , dupTransferCmd ) ;
118+ nextLabels [ b ] ++ ;
119+ nextLabels . Add ( dupBlock , 0 ) ;
116120 return dupBlock ;
117121 }
118122 private Graph < Block > ConvertToReducible ( Implementation impl )
119123 {
124+ Dictionary < Block , int > nextLabels = impl . Blocks . ToDictionary ( b => b , _ => 0 ) ;
120125 Graph < Block > g = Program . GraphFromImpl ( impl ) ;
121126 impl . ComputePredecessorsForBlocks ( ) ;
122127 g . ComputeLoops ( ) ; // this is the call that does all of the processing
123128 while ( ! g . Reducible )
124129 {
125- // throw new VCGenException("Irreducible flow graphs are unsupported.");
126-
127130 // We will be looking for a block that can be split, and for a looply connected block that has an invariant
128-
129- Block splitBlock = null ;
130- foreach ( Block b in g . SplitCandidates )
131- {
132- if ( b . Predecessors . Count > 1 && ! b . HasInvariant ( ) )
133- {
134- splitBlock = b ;
135- break ;
136- }
137- }
138-
139- if ( splitBlock == null )
140- {
141- // If all of the loop blocks have invariants, then choose any of them
142- foreach ( Block b in g . SplitCandidates )
143- {
144- if ( b . Predecessors . Count > 1 )
145- {
146- splitBlock = b ;
147- break ;
148- }
149- }
150- }
131+ Block splitBlock = g . SplitCandidates
132+ . FirstOrDefault ( b => b . Predecessors . Count > 1 && ! b . HasInvariant ( ) )
133+ ?? g . SplitCandidates . FirstOrDefault ( b => b . Predecessors . Count > 1 ) ;
151134
152135 // splitBlock should be a perfectly good split candidate now.
153136 // We have to find the nodes that are dominated by it, to duplicate them too
154- List < Block > region = new List < Block > ( ) ;
155- foreach ( Block b in impl . Blocks )
137+ List < Block > region = [ .. impl . Blocks . Where ( b => g . DominatorMap . DominatedBy ( b , splitBlock ) ) ] ;
138+ foreach ( Block pred in splitBlock . Predecessors )
156139 {
157- if ( g . DominatorMap . DominatedBy ( b , splitBlock ) )
158- {
159- region . Add ( b ) ;
160- }
161- }
162- for ( int idx = 0 ; idx < splitBlock . Predecessors . Count ; idx ++ )
163- {
164- Block pred = splitBlock . Predecessors [ idx ] ;
165140 if ( g . DominatorMap . DominatedBy ( pred , splitBlock ) )
166141 {
167142 continue ;
168143 }
169144
170145 // duplicate the splitBlock
171- Block dupBlock = duplicateBlock ( splitBlock ) ;
146+ Block dupBlock = DuplicateBlock ( splitBlock , nextLabels ) ;
172147
173148 // Remove edge of the previous block
174149 GotoCmd predGoto = ( GotoCmd ) pred . TransferCmd ;
@@ -181,29 +156,23 @@ private Graph<Block> ConvertToReducible(Implementation impl)
181156 impl . Blocks . Add ( dupBlock ) ;
182157
183158 // duplicate the whole region
184- Dictionary < Block , Block > duplicatesDict = new Dictionary < Block , Block > ( ) ;
185- List < Block > duplicates = new List < Block >
159+ Dictionary < Block , Block > duplicatesDict = new Dictionary < Block , Block >
186160 {
187- dupBlock
161+ { splitBlock , dupBlock }
188162 } ;
189- duplicatesDict . Add ( splitBlock , dupBlock ) ;
190163
191- // Replace the blocks in the region with their duplicates
192164 foreach ( Block currentBlock in region )
193165 {
194166 if ( currentBlock != splitBlock )
195167 {
196- Block newBlock = duplicateBlock ( currentBlock ) ;
168+ Block newBlock = DuplicateBlock ( currentBlock , nextLabels ) ;
197169 impl . Blocks . Add ( newBlock ) ;
198170 duplicatesDict [ currentBlock ] = newBlock ;
199- duplicates . Add ( newBlock ) ;
200171 }
201172 }
202173
203- foreach ( Block currentBlock in duplicates )
204- {
205- SubstituteBlocks ( currentBlock , duplicatesDict ) ;
206- }
174+ // Replace the blocks in the region with their duplicates
175+ duplicatesDict . Values . ForEach ( b => SubstituteBranchTargets ( b , duplicatesDict ) ) ;
207176 }
208177
209178 impl . PruneUnreachableBlocks ( generator . Options ) ;
0 commit comments