@@ -667,63 +667,82 @@ module Ssa {
667
667
)
668
668
}
669
669
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
+ )
673
682
}
674
683
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 , _)
680
687
}
681
688
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 , _) )
694
691
}
695
692
696
693
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 )
701
712
)
702
713
}
703
714
704
715
/**
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`.
707
719
*/
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
+ )
711
728
}
712
729
713
730
/**
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`.
716
734
*/
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 , _)
722
742
)
723
743
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 )
727
746
}
728
747
729
748
cached
@@ -736,23 +755,26 @@ module Ssa {
736
755
*/
737
756
cached
738
757
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 )
743
761
|
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 ( ) )
746
764
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
749
767
(
750
- // Read reaches end of enclosing callable
751
- not varBlockReaches ( v , bb , _ )
768
+ // Can reach exit directly
769
+ bb1 instanceof ControlFlow :: BasicBlocks :: ExitBlock
752
770
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 , _)
756
778
)
757
779
)
758
780
)
@@ -831,10 +853,9 @@ module Ssa {
831
853
*/
832
854
cached
833
855
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 )
838
859
)
839
860
}
840
861
@@ -845,10 +866,9 @@ module Ssa {
845
866
*/
846
867
cached
847
868
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 )
852
872
)
853
873
}
854
874
}
0 commit comments