@@ -180,6 +180,15 @@ export function structureFunction(
180180
181181 while ( currentBlockId !== null && currentBlockId !== regionEnd ) {
182182 if ( processed . has ( currentBlockId ) ) {
183+ // If the block was already consumed by a nested call, skip to the
184+ // post-dominator so we can continue structuring downstream blocks
185+ // that haven't been processed yet.
186+ const skipTarget = dominance . postImmediateDominator . get ( currentBlockId ) ;
187+ if ( skipTarget !== undefined && skipTarget !== currentBlockId
188+ && skipTarget !== regionEnd && ! processed . has ( skipTarget ) ) {
189+ currentBlockId = skipTarget ;
190+ continue ;
191+ }
183192 break ;
184193 }
185194
@@ -277,6 +286,46 @@ export function structureFunction(
277286 return { kind : 'sequence' , children } ;
278287 }
279288
289+ function structureAfterWhileLoop (
290+ whileNode : StructuredNode ,
291+ loop : NaturalLoop ,
292+ primaryExitId : number ,
293+ regionEnd : number | null ,
294+ ) : StructuredNode {
295+ const afterChildren : StructuredNode [ ] = [ whileNode ] ;
296+
297+ // Find convergence point where all loop exits meet
298+ const postDom = dominance . postImmediateDominator . get ( loop . headerId ) ;
299+ const convergenceId = ( postDom !== undefined && ! loop . bodyIds . has ( postDom ) ) ? postDom : null ;
300+
301+ // Structure the primary exit path (the while condition's false branch)
302+ if ( primaryExitId !== regionEnd && ! processed . has ( primaryExitId ) ) {
303+ if ( primaryExitId !== convergenceId ) {
304+ const primaryPath = structureRegion ( primaryExitId , convergenceId ?? regionEnd ) ;
305+ afterChildren . push ( primaryPath ) ;
306+ }
307+ }
308+
309+ // Structure any other unprocessed exit paths reached via break statements
310+ for ( const exitId of loop . exitIds ) {
311+ if ( exitId === primaryExitId || exitId === regionEnd || processed . has ( exitId ) ) { continue ; }
312+ if ( exitId === convergenceId ) { continue ; }
313+ const exitPath = structureRegion ( exitId , convergenceId ?? regionEnd ) ;
314+ afterChildren . push ( exitPath ) ;
315+ }
316+
317+ // Structure from convergence point onward
318+ if ( convergenceId !== null && convergenceId !== regionEnd && ! processed . has ( convergenceId ) ) {
319+ const afterConvergence = structureRegion ( convergenceId , regionEnd ) ;
320+ afterChildren . push ( afterConvergence ) ;
321+ }
322+
323+ if ( afterChildren . length === 1 ) {
324+ return whileNode ;
325+ }
326+ return { kind : 'sequence' , children : afterChildren } ;
327+ }
328+
280329 function structureLoop (
281330 headerId : number ,
282331 loop : NaturalLoop ,
@@ -301,12 +350,7 @@ export function structureFunction(
301350 condition : terminator . condition ,
302351 body : prependNode ( preBody , bodyNode ) ,
303352 } ;
304- const exitId = falseTarget ;
305- if ( exitId !== regionEnd && ! processed . has ( exitId ) ) {
306- const afterLoop = structureRegion ( exitId , regionEnd ) ;
307- return { kind : 'sequence' , children : [ whileNode , afterLoop ] } ;
308- }
309- return whileNode ;
353+ return structureAfterWhileLoop ( whileNode , loop , falseTarget , regionEnd ) ;
310354 }
311355
312356 if ( ! trueInLoop && falseInLoop ) {
@@ -318,12 +362,7 @@ export function structureFunction(
318362 condition : negatedCondition ,
319363 body : prependNode ( preBody , bodyNode ) ,
320364 } ;
321- const exitId = trueTarget ;
322- if ( exitId !== regionEnd && ! processed . has ( exitId ) ) {
323- const afterLoop = structureRegion ( exitId , regionEnd ) ;
324- return { kind : 'sequence' , children : [ whileNode , afterLoop ] } ;
325- }
326- return whileNode ;
365+ return structureAfterWhileLoop ( whileNode , loop , trueTarget , regionEnd ) ;
327366 }
328367 }
329368
@@ -707,6 +746,21 @@ export function structureFunction(
707746 return { node : prependNode ( preBody , ifNode ) , mergeBlockId : nextId } ;
708747 }
709748
749+ // Merge point equals one of the targets — structure the other branch, use target as merge
750+ if ( mergePoint === falseTarget && ! processed . has ( trueTarget ) ) {
751+ const thenBody = structureRegion ( trueTarget , falseTarget ) ;
752+ const ifNode : StructuredNode = { kind : 'if' , condition : terminator . condition , thenBody, elseBody : null } ;
753+ const mergeId = falseTarget !== regionEnd && ! processed . has ( falseTarget ) ? falseTarget : null ;
754+ return { node : prependNode ( preBody , ifNode ) , mergeBlockId : mergeId } ;
755+ }
756+ if ( mergePoint === trueTarget && ! processed . has ( falseTarget ) ) {
757+ const elseBody = structureRegion ( falseTarget , trueTarget ) ;
758+ const negated = negateCondition ( terminator . condition ) ;
759+ const ifNode : StructuredNode = { kind : 'if' , condition : negated , thenBody : elseBody , elseBody : null } ;
760+ const mergeId = trueTarget !== regionEnd && ! processed . has ( trueTarget ) ? trueTarget : null ;
761+ return { node : prependNode ( preBody , ifNode ) , mergeBlockId : mergeId } ;
762+ }
763+
710764 // Last resort — emit block instructions and continue
711765 const labeledBody = blockToNode ( block ) ;
712766 return { node : labeledBody , mergeBlockId : null } ;
0 commit comments