@@ -436,6 +436,37 @@ module Make<LocationSig Location, InputSig<Location> Input> {
436
436
rnk = ssaRefRank ( bb , _, v , SsaActualRead ( ) )
437
437
}
438
438
439
+ pragma [ nomagic]
440
+ predicate liveThroughExt ( BasicBlock bb , SourceVariable v ) {
441
+ liveAtExit ( bb , v ) and
442
+ not ssaRef ( bb , _, v , ssaDefExt ( ) )
443
+ }
444
+
445
+ /**
446
+ * NB: If this predicate is exposed, it should be cached.
447
+ *
448
+ * Holds if the SSA definition of `v` at `def` reaches the end of basic
449
+ * block `bb`, at which point it is still live, without crossing another
450
+ * SSA definition of `v`.
451
+ */
452
+ pragma [ nomagic]
453
+ predicate ssaDefReachesEndOfBlockExt ( BasicBlock bb , DefinitionExt def , SourceVariable v ) {
454
+ exists ( int last |
455
+ last = maxSsaRefRank ( pragma [ only_bind_into ] ( bb ) , pragma [ only_bind_into ] ( v ) ) and
456
+ ssaDefReachesRank ( bb , def , last , v ) and
457
+ liveAtExit ( bb , v )
458
+ )
459
+ or
460
+ // The construction of SSA form ensures that each read of a variable is
461
+ // dominated by its definition. An SSA definition therefore reaches a
462
+ // control flow node if it is the _closest_ SSA definition that dominates
463
+ // the node. If two definitions dominate a node then one must dominate the
464
+ // other, so therefore the definition of _closest_ is given by the dominator
465
+ // tree. Thus, reaching definitions can be calculated in terms of dominance.
466
+ ssaDefReachesEndOfBlockExt ( getImmediateBasicBlockDominator ( bb ) , def , pragma [ only_bind_into ] ( v ) ) and
467
+ liveThroughExt ( bb , pragma [ only_bind_into ] ( v ) )
468
+ }
469
+
439
470
/**
440
471
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
441
472
* basic block `bb`, without crossing another SSA definition of `v`.
@@ -446,6 +477,21 @@ module Make<LocationSig Location, InputSig<Location> Input> {
446
477
rnk = ssaRefRank ( bb , i , v , SsaActualRead ( ) )
447
478
)
448
479
}
480
+
481
+ /**
482
+ * NB: If this predicate is exposed, it should be cached.
483
+ *
484
+ * Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
485
+ * basic block `bb`, without crossing another SSA definition of `v`.
486
+ */
487
+ pragma [ nomagic]
488
+ predicate ssaDefReachesReadExt ( SourceVariable v , DefinitionExt def , BasicBlock bb , int i ) {
489
+ ssaDefReachesReadWithinBlock ( v , def , bb , i )
490
+ or
491
+ ssaRef ( bb , i , v , SsaActualRead ( ) ) and
492
+ ssaDefReachesEndOfBlockExt ( getABasicBlockPredecessor ( bb ) , def , v ) and
493
+ not ssaDefReachesReadWithinBlock ( v , _, bb , i )
494
+ }
449
495
}
450
496
451
497
private module SsaDefReaches {
0 commit comments