@@ -667,63 +667,82 @@ module Ssa {
667667 )
668668 }
669669
670- /** Holds if `v` is defined or read in basic block `bb`. */
671- private predicate varOccursInBlock ( TrackedVar v , BasicBlock bb ) {
672- exists ( ssaRefRank ( bb , _, v , _) )
670+ /**
671+ * Same as `ssaRefRank()`, but restricted to actual reads of `def`, or
672+ * `def` itself.
673+ */
674+ private int ssaDefRank ( TrackedDefinition def , TrackedVar v , BasicBlock bb , int i ) {
675+ v = def .getSourceVariable ( ) and
676+ result = ssaRefRank ( bb , i , v , _) and
677+ (
678+ ssaDefReachesRead ( _, def , bb .getNode ( i ) , ActualRead ( ) )
679+ or
680+ definesAt ( def , bb , i , _)
681+ )
673682 }
674683
675- /** Holds if `v` occurs in `bb` or one of `bb`'s transitive successors. */
676- private predicate blockPrecedesVar ( TrackedVar v , BasicBlock bb ) {
677- varOccursInBlock ( v , bb )
678- or
679- blockPrecedesVar ( v , bb .getASuccessor ( ) )
684+ private int maxSsaDefRefRank ( BasicBlock bb , TrackedVar v ) {
685+ result = ssaDefRank ( _, v , bb , _) and
686+ not result + 1 = ssaDefRank ( _, v , bb , _)
680687 }
681688
682- /**
683- * Holds if `bb2` is a transitive successor of `bb1` and `v` occurs in `bb1` and
684- * in `bb2` or one of its transitive successors but not in any block on the path
685- * between `bb1` and `bb2`.
686- */
687- private predicate varBlockReaches ( TrackedVar v , BasicBlock bb1 , BasicBlock bb2 ) {
688- varOccursInBlock ( v , bb1 ) and
689- bb2 = bb1 .getASuccessor ( ) and
690- blockPrecedesVar ( v , bb2 )
691- or
692- varBlockReachesRec ( v , bb1 , bb2 ) and
693- blockPrecedesVar ( v , bb2 )
689+ private predicate varOccursInBlock ( TrackedDefinition def , BasicBlock bb , TrackedVar v ) {
690+ exists ( ssaDefRank ( def , v , bb , _) )
694691 }
695692
696693 pragma [ noinline]
697- private predicate varBlockReachesRec ( TrackedVar v , BasicBlock bb1 , BasicBlock bb2 ) {
698- exists ( BasicBlock mid | varBlockReaches ( v , bb1 , mid ) |
699- bb2 = mid .getASuccessor ( ) and
700- not varOccursInBlock ( v , mid )
694+ private BasicBlock getAMaybeLiveSuccessor ( Definition def , BasicBlock bb ) {
695+ result = bb .getASuccessor ( ) and
696+ not varOccursInBlock ( _, bb , def .getSourceVariable ( ) ) and
697+ ssaDefReachesEndOfBlock ( bb , def , _)
698+ }
699+
700+ /**
701+ * Holds if `def` is accessed in basic block `bb1` (either a read or a write),
702+ * `bb2` is a transitive successor of `bb1`, and `def` is *maybe* read in `bb2`
703+ * or one of its transitive successors, but not in any block on the path between
704+ * `bb1` and `bb2`.
705+ */
706+ private predicate varBlockReaches ( TrackedDefinition def , BasicBlock bb1 , BasicBlock bb2 ) {
707+ varOccursInBlock ( def , bb1 , _) and
708+ bb2 = bb1 .getASuccessor ( )
709+ or
710+ exists ( BasicBlock mid | varBlockReaches ( def , bb1 , mid ) |
711+ bb2 = getAMaybeLiveSuccessor ( def , mid )
701712 )
702713 }
703714
704715 /**
705- * Holds if `bb2` is a transitive successor of `bb1` and `v` occurs in `bb1` and
706- * `bb2` but not in any block on the path between `bb1` and `bb2`.
716+ * Holds if `def` is accessed in basic block `bb1` (either a read or a write),
717+ * `def` is read at `cfn`, `cfn` is in a transitive successor block of `bb1`,
718+ * and `def` is not read in any block on the path between `bb1` and `cfn`.
707719 */
708- private predicate varBlockStep ( TrackedVar v , BasicBlock bb1 , BasicBlock bb2 ) {
709- varBlockReaches ( v , bb1 , bb2 ) and
710- varOccursInBlock ( v , bb2 )
720+ private predicate varBlockReachesRead (
721+ TrackedDefinition def , BasicBlock bb1 , ControlFlow:: Node cfn
722+ ) {
723+ exists ( BasicBlock bb2 , int i2 |
724+ varBlockReaches ( def , bb1 , bb2 ) and
725+ ssaRefRank ( bb2 , i2 , def .getSourceVariable ( ) , SsaRead ( ) ) = 1 and
726+ variableRead ( bb2 , i2 , _, cfn , _)
727+ )
711728 }
712729
713730 /**
714- * Holds if `v` is accessed at index `i1` in basic block `bb1` and at index `i2` in
715- * basic block `bb2` and there is a path between them without any access to `v`.
731+ * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
732+ * or a write), `def` is read at `cfn`, and there is a path between them without
733+ * any read of `def`.
716734 */
717- private predicate adjacentVarRefs ( TrackedVar v , BasicBlock bb1 , int i1 , BasicBlock bb2 , int i2 ) {
718- exists ( int rankix |
719- bb1 = bb2 and
720- rankix = ssaRefRank ( bb1 , i1 , v , _) and
721- rankix + 1 = ssaRefRank ( bb2 , i2 , v , _)
735+ private predicate adjacentVarRead (
736+ TrackedDefinition def , BasicBlock bb1 , int i1 , ControlFlow:: Node cfn
737+ ) {
738+ exists ( int rankix , int i2 |
739+ rankix = ssaDefRank ( def , _, bb1 , i1 ) and
740+ rankix + 1 = ssaDefRank ( def , _, bb1 , i2 ) and
741+ variableRead ( bb1 , i2 , _, cfn , _)
722742 )
723743 or
724- ssaRefRank ( bb1 , i1 , v , _) = maxSsaRefRank ( bb1 , v ) and
725- varBlockStep ( v , bb1 , bb2 ) and
726- ssaRefRank ( bb2 , i2 , v , _) = 1
744+ exists ( SourceVariable v | ssaDefRank ( def , v , bb1 , i1 ) = maxSsaDefRefRank ( bb1 , v ) ) and
745+ varBlockReachesRead ( def , bb1 , cfn )
727746 }
728747
729748 cached
@@ -736,23 +755,26 @@ module Ssa {
736755 */
737756 cached
738757 predicate lastRead ( TrackedDefinition def , ControlFlow:: Node cfn ) {
739- exists ( TrackedVar v , BasicBlock bb , int i , int rnk |
740- exists ( def .getAReadAtNode ( cfn ) ) and
741- variableRead ( bb , i , v , cfn , _) and
742- rnk = ssaRefRank ( bb , i , v , SsaRead ( ) )
758+ exists ( BasicBlock bb1 , int i1 , int rnk , TrackedVar v |
759+ variableRead ( bb1 , i1 , v , cfn , _) and
760+ rnk = ssaDefRank ( def , v , bb1 , i1 )
743761 |
744- // Next reference to `v` inside `bb ` is a write
745- rnk + 1 = ssaRefRank ( bb , _, v , SsaDef ( ) )
762+ // Next reference to `v` inside `bb1 ` is a write
763+ rnk + 1 = ssaRefRank ( bb1 , _, v , SsaDef ( ) )
746764 or
747- // No next reference to `v` inside `bb `
748- rnk = maxSsaRefRank ( bb , v ) and
765+ // No more references to `v` inside `bb1 `
766+ rnk = maxSsaDefRefRank ( bb1 , def . getSourceVariable ( ) ) and
749767 (
750- // Read reaches end of enclosing callable
751- not varBlockReaches ( v , bb , _ )
768+ // Can reach exit directly
769+ bb1 instanceof ControlFlow :: BasicBlocks :: ExitBlock
752770 or
753- // Read reaches an SSA definition in a successor block
754- exists ( BasicBlock bb2 | varBlockReaches ( v , bb , bb2 ) |
755- 1 = ssaRefRank ( bb2 , _, v , SsaDef ( ) )
771+ exists ( BasicBlock bb2 | varBlockReaches ( def , bb1 , bb2 ) |
772+ // Can reach a write using one or more steps
773+ 1 = ssaRefRank ( bb2 , _, def .getSourceVariable ( ) , SsaDef ( ) )
774+ or
775+ // Can reach a block using one or more steps, where `def` is no longer live
776+ not varOccursInBlock ( def , bb2 , _) and
777+ not ssaDefReachesEndOfBlock ( bb2 , def , _)
756778 )
757779 )
758780 )
@@ -831,10 +853,9 @@ module Ssa {
831853 */
832854 cached
833855 predicate firstReadSameVar ( TrackedDefinition def , ControlFlow:: Node cfn ) {
834- exists ( TrackedVar v , BasicBlock b1 , int i1 , BasicBlock b2 , int i2 |
835- adjacentVarRefs ( v , b1 , i1 , b2 , i2 ) and
836- definesAt ( def , b1 , i1 , v ) and
837- variableRead ( b2 , i2 , v , cfn , _)
856+ exists ( BasicBlock bb1 , int i1 |
857+ definesAt ( def , bb1 , i1 , _) and
858+ adjacentVarRead ( def , bb1 , i1 , cfn )
838859 )
839860 }
840861
@@ -845,10 +866,9 @@ module Ssa {
845866 */
846867 cached
847868 predicate adjacentReadPairSameVar ( ControlFlow:: Node cfn1 , ControlFlow:: Node cfn2 ) {
848- exists ( TrackedVar v , BasicBlock bb1 , int i1 , BasicBlock bb2 , int i2 |
849- adjacentVarRefs ( v , bb1 , i1 , bb2 , i2 ) and
850- variableRead ( bb1 , i1 , v , cfn1 , _) and
851- variableRead ( bb2 , i2 , v , cfn2 , _)
869+ exists ( TrackedDefinition def , BasicBlock bb1 , int i1 |
870+ variableRead ( bb1 , i1 , _, cfn1 , _) and
871+ adjacentVarRead ( def , bb1 , i1 , cfn2 )
852872 )
853873 }
854874 }
0 commit comments