@@ -436,6 +436,37 @@ module Make<LocationSig Location, InputSig<Location> Input> {
436436 rnk = ssaRefRank ( bb , _, v , SsaActualRead ( ) )
437437 }
438438
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+
439470 /**
440471 * Holds if the SSA definition of `v` at `def` reaches index `i` in the same
441472 * basic block `bb`, without crossing another SSA definition of `v`.
@@ -446,6 +477,21 @@ module Make<LocationSig Location, InputSig<Location> Input> {
446477 rnk = ssaRefRank ( bb , i , v , SsaActualRead ( ) )
447478 )
448479 }
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+ }
449495 }
450496
451497 private module SsaDefReaches {
0 commit comments