@@ -17,18 +17,18 @@ private module Liveness {
1717 * (certain or uncertain) writes.
1818 */
1919 private newtype TRefKind =
20- Read ( ) or
21- Write ( boolean certain ) { certain = true or certain = false }
20+ Read ( boolean certain ) { certain in [ false , true ] } or
21+ Write ( boolean certain ) { certain in [ false , true ] }
2222
2323 private class RefKind extends TRefKind {
2424 string toString ( ) {
25- this = Read ( ) and result = "read"
25+ exists ( boolean certain | this = Read ( certain ) and result = "read (" + certain + ")" )
2626 or
2727 exists ( boolean certain | this = Write ( certain ) and result = "write (" + certain + ")" )
2828 }
2929
3030 int getOrder ( ) {
31- this = Read ( ) and
31+ this = Read ( _ ) and
3232 result = 0
3333 or
3434 this = Write ( _) and
@@ -40,7 +40,7 @@ private module Liveness {
4040 * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
4141 */
4242 private predicate ref ( BasicBlock bb , int i , SourceVariable v , RefKind k ) {
43- variableRead ( bb , i , v ) and k = Read ( )
43+ exists ( boolean certain | variableRead ( bb , i , v , certain ) | k = Read ( certain ) )
4444 or
4545 exists ( boolean certain | variableWrite ( bb , i , v , certain ) | k = Write ( certain ) )
4646 }
@@ -95,7 +95,7 @@ private module Liveness {
9595 */
9696 predicate liveAtEntry ( BasicBlock bb , SourceVariable v ) {
9797 // The first read or certain write to `v` inside `bb` is a read
98- refRank ( bb , _, v , Read ( ) ) = firstReadOrCertainWrite ( bb , v )
98+ refRank ( bb , _, v , Read ( _ ) ) = firstReadOrCertainWrite ( bb , v )
9999 or
100100 // There is no certain write to `v` inside `bb`, but `v` is live at entry
101101 // to a successor basic block of `bb`
@@ -120,7 +120,7 @@ private module Liveness {
120120 liveAtExit ( bb , v )
121121 or
122122 ref ( bb , i , v , kind ) and
123- kind = Read ( )
123+ kind = Read ( _ )
124124 or
125125 exists ( RefKind nextKind |
126126 liveAtRank ( bb , _, v , rnk + 1 ) and
@@ -237,7 +237,7 @@ private module SsaDefReaches {
237237 * Unlike `Liveness::ref`, this includes `phi` nodes.
238238 */
239239 predicate ssaRef ( BasicBlock bb , int i , SourceVariable v , SsaRefKind k ) {
240- variableRead ( bb , i , v ) and
240+ variableRead ( bb , i , v , _ ) and
241241 k = SsaRead ( )
242242 or
243243 exists ( Definition def | def .definesAt ( v , bb , i ) ) and
@@ -304,7 +304,7 @@ private module SsaDefReaches {
304304 exists ( int rnk |
305305 ssaDefReachesRank ( bb , def , rnk , v ) and
306306 rnk = ssaRefRank ( bb , i , v , SsaRead ( ) ) and
307- variableRead ( bb , i , v )
307+ variableRead ( bb , i , v , _ )
308308 )
309309 }
310310
@@ -368,7 +368,7 @@ private module SsaDefReaches {
368368 predicate defAdjacentRead ( Definition def , BasicBlock bb1 , BasicBlock bb2 , int i2 ) {
369369 varBlockReaches ( def , bb1 , bb2 ) and
370370 ssaRefRank ( bb2 , i2 , def .getSourceVariable ( ) , SsaRead ( ) ) = 1 and
371- variableRead ( bb2 , i2 , _)
371+ variableRead ( bb2 , i2 , _, _ )
372372 }
373373}
374374
@@ -394,6 +394,7 @@ private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, Sour
394394 * block `bb`, at which point it is still live, without crossing another
395395 * SSA definition of `v`.
396396 */
397+ pragma [ nomagic]
397398predicate ssaDefReachesEndOfBlock ( BasicBlock bb , Definition def , SourceVariable v ) {
398399 exists ( int last | last = maxSsaRefRank ( bb , v ) |
399400 ssaDefReachesRank ( bb , def , last , v ) and
@@ -412,10 +413,11 @@ predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable
412413 * basic block `bb`, without crossing another SSA definition of `v`. The read
413414 * is of kind `rk`.
414415 */
416+ pragma [ nomagic]
415417predicate ssaDefReachesRead ( SourceVariable v , Definition def , BasicBlock bb , int i ) {
416418 ssaDefReachesReadWithinBlock ( v , def , bb , i )
417419 or
418- variableRead ( bb , i , v ) and
420+ variableRead ( bb , i , v , _ ) and
419421 ssaDefReachesEndOfBlock ( getABasicBlockPredecessor ( bb ) , def , v ) and
420422 not ssaDefReachesReadWithinBlock ( v , _, bb , i )
421423}
@@ -427,25 +429,51 @@ predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int
427429 * or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
428430 * path between them without any read of `def`.
429431 */
432+ pragma [ nomagic]
430433predicate adjacentDefRead ( Definition def , BasicBlock bb1 , int i1 , BasicBlock bb2 , int i2 ) {
431434 exists ( int rnk |
432435 rnk = ssaDefRank ( def , _, bb1 , i1 , _) and
433436 rnk + 1 = ssaDefRank ( def , _, bb1 , i2 , SsaRead ( ) ) and
434- variableRead ( bb1 , i2 , _) and
437+ variableRead ( bb1 , i2 , _, _ ) and
435438 bb2 = bb1
436439 )
437440 or
438441 exists ( SourceVariable v | ssaDefRank ( def , v , bb1 , i1 , _) = maxSsaRefRank ( bb1 , v ) ) and
439442 defAdjacentRead ( def , bb1 , bb2 , i2 )
440443}
441444
445+ private predicate adjacentDefReachesRead (
446+ Definition def , BasicBlock bb1 , int i1 , BasicBlock bb2 , int i2
447+ ) {
448+ adjacentDefRead ( def , bb1 , i1 , bb2 , i2 ) and
449+ not variableRead ( bb1 , i1 , def .getSourceVariable ( ) , false )
450+ or
451+ exists ( BasicBlock bb3 , int i3 |
452+ adjacentDefReachesRead ( def , bb1 , i1 , bb3 , i3 ) and
453+ variableRead ( bb3 , i3 , _, false ) and
454+ adjacentDefRead ( def , bb3 , i3 , bb2 , i2 )
455+ )
456+ }
457+
458+ /**
459+ * NB: If this predicate is exposed, it should be cached.
460+ *
461+ * Same as `adjacentDefRead`, but ignores uncertain reads.
462+ */
463+ pragma [ nomagic]
464+ predicate adjacentDefNoUncertainReads ( Definition def , BasicBlock bb1 , int i1 , BasicBlock bb2 , int i2 ) {
465+ adjacentDefReachesRead ( def , bb1 , i1 , bb2 , i2 ) and
466+ variableRead ( bb2 , i2 , _, true )
467+ }
468+
442469/**
443470 * NB: If this predicate is exposed, it should be cached.
444471 *
445472 * Holds if the node at index `i` in `bb` is a last reference to SSA definition
446473 * `def`. The reference is last because it can reach another write `next`,
447474 * without passing through another read or write.
448475 */
476+ pragma [ nomagic]
449477predicate lastRefRedef ( Definition def , BasicBlock bb , int i , Definition next ) {
450478 exists ( int rnk , SourceVariable v , int j | rnk = ssaDefRank ( def , v , bb , i , _) |
451479 // Next reference to `v` inside `bb` is a write
@@ -462,6 +490,29 @@ predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
462490 )
463491}
464492
493+ private predicate adjacentDefReachesUncertainRead (
494+ Definition def , BasicBlock bb1 , int i1 , BasicBlock bb2 , int i2
495+ ) {
496+ adjacentDefReachesRead ( def , bb1 , i1 , bb2 , i2 ) and
497+ variableRead ( bb2 , i2 , _, false )
498+ }
499+
500+ /**
501+ * NB: If this predicate is exposed, it should be cached.
502+ *
503+ * Same as `lastRefRedef`, but ignores uncertain reads.
504+ */
505+ pragma [ nomagic]
506+ predicate lastRefRedefNoUncertainReads ( Definition def , BasicBlock bb , int i , Definition next ) {
507+ lastRefRedef ( def , bb , i , next ) and
508+ not variableRead ( bb , i , def .getSourceVariable ( ) , false )
509+ or
510+ exists ( BasicBlock bb0 , int i0 |
511+ lastRefRedef ( def , bb0 , i0 , next ) and
512+ adjacentDefReachesUncertainRead ( def , bb , i , bb0 , i0 )
513+ )
514+ }
515+
465516/**
466517 * NB: If this predicate is exposed, it should be cached.
467518 *
@@ -472,6 +523,7 @@ predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
472523 * SSA definition for the underlying source variable, without passing through
473524 * another read.
474525 */
526+ pragma [ nomagic]
475527predicate lastRef ( Definition def , BasicBlock bb , int i ) {
476528 lastRefRedef ( def , bb , i , _)
477529 or
@@ -487,6 +539,22 @@ predicate lastRef(Definition def, BasicBlock bb, int i) {
487539 )
488540}
489541
542+ /**
543+ * NB: If this predicate is exposed, it should be cached.
544+ *
545+ * Same as `lastRefRedef`, but ignores uncertain reads.
546+ */
547+ pragma [ nomagic]
548+ predicate lastRefNoUncertainReads ( Definition def , BasicBlock bb , int i ) {
549+ lastRef ( def , bb , i ) and
550+ not variableRead ( bb , i , def .getSourceVariable ( ) , false )
551+ or
552+ exists ( BasicBlock bb0 , int i0 |
553+ lastRef ( def , bb0 , i0 ) and
554+ adjacentDefReachesUncertainRead ( def , bb , i , bb0 , i0 )
555+ )
556+ }
557+
490558/** A static single assignment (SSA) definition. */
491559class Definition extends TDefinition {
492560 /** Gets the source variable underlying this SSA definition. */
0 commit comments