@@ -2516,8 +2516,12 @@ module ControlFlow {
25162516 result = strictcount ( getAnElement ( ) )
25172517 }
25182518
2519+ predicate immediatelyDominates ( PreBasicBlock bb ) {
2520+ bbIDominates ( this , bb )
2521+ }
2522+
25192523 predicate strictlyDominates ( PreBasicBlock bb ) {
2520- bbIDominates + ( this , bb )
2524+ this . immediatelyDominates + ( bb )
25212525 }
25222526
25232527 predicate dominates ( PreBasicBlock bb ) {
@@ -2584,8 +2588,6 @@ module ControlFlow {
25842588 }
25852589 }
25862590
2587- private newtype SsaRefKind = SsaRead ( ) or SsaDef ( )
2588-
25892591 class Definition extends TPreSsaDef {
25902592 string toString ( ) {
25912593 exists ( AssignableDefinition def |
@@ -2626,12 +2628,25 @@ module ControlFlow {
26262628 )
26272629 }
26282630
2631+ PreBasicBlock getBasicBlock ( ) {
2632+ this = TExplicitPreSsaDef ( result , _, _, _) or
2633+ this = TPhiPreSsaDef ( result , _)
2634+ }
2635+
26292636 AssignableDefinition getDefinition ( ) {
26302637 this = TExplicitPreSsaDef ( _, _, result , _)
26312638 }
2639+
2640+ Definition getAPhiInput ( ) {
2641+ exists ( PreBasicBlock bb , PreBasicBlock phiPred , SimpleLocalScopeVariable v |
2642+ this = TPhiPreSsaDef ( bb , v ) |
2643+ bb .getAPredecessor ( ) = phiPred and
2644+ ssaDefReachesEndOfBlock ( phiPred , result , v )
2645+ )
2646+ }
26322647 }
26332648
2634- predicate assignableDefAt ( PreBasicBlocks:: PreBasicBlock bb , int i , AssignableDefinition def , SimpleLocalScopeVariable v ) {
2649+ private predicate assignableDefAt ( PreBasicBlocks:: PreBasicBlock bb , int i , AssignableDefinition def , SimpleLocalScopeVariable v ) {
26352650 bb .getElement ( i ) = def .getExpr ( ) and
26362651 v = def .getTarget ( ) and
26372652 // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
@@ -2650,16 +2665,82 @@ module ControlFlow {
26502665 )
26512666 }
26522667
2668+ private predicate readAt ( PreBasicBlock bb , int i , LocalScopeVariableRead read , SimpleLocalScopeVariable v ) {
2669+ read = bb .getElement ( i ) and
2670+ read .getTarget ( ) = v
2671+ }
2672+
2673+ pragma [ noinline]
2674+ private predicate exitBlock ( PreBasicBlock bb , Callable c ) {
2675+ exists ( succExit ( bb .getLastElement ( ) , _) ) and
2676+ c = bb .getEnclosingCallable ( )
2677+ }
2678+
2679+ private predicate outRefExitRead ( PreBasicBlock bb , int i , SimpleLocalScopeVariable v ) {
2680+ exitBlock ( bb , v .getCallable ( ) ) and
2681+ i = bb .length ( ) + 1 and
2682+ ( v .isRef ( ) or v .( Parameter ) .isOut ( ) )
2683+ }
2684+
2685+ private newtype RefKind =
2686+ Read ( )
2687+ or
2688+ Write ( boolean certain ) { certain = true or certain = false }
2689+
2690+ private predicate ref ( PreBasicBlock bb , int i , SimpleLocalScopeVariable v , RefKind k ) {
2691+ ( readAt ( bb , i , _, v ) or outRefExitRead ( bb , i , v ) ) and
2692+ k = Read ( )
2693+ or
2694+ exists ( AssignableDefinition def , boolean certain |
2695+ assignableDefAt ( bb , i , def , v ) |
2696+ if def .getTargetAccess ( ) .isRefArgument ( ) then certain = false else certain = true and
2697+ k = Write ( certain )
2698+ )
2699+ }
2700+
2701+ private int refRank ( PreBasicBlock bb , int i , SimpleLocalScopeVariable v , RefKind k ) {
2702+ i = rank [ result ] ( int j | ref ( bb , j , v , _) ) and
2703+ ref ( bb , i , v , k )
2704+ }
2705+
2706+ private int firstReadOrCertainWrite ( PreBasicBlock bb , SimpleLocalScopeVariable v ) {
2707+ result = min ( int r , RefKind k |
2708+ r = refRank ( bb , _, v , k ) and
2709+ k != Write ( false )
2710+ |
2711+ r
2712+ )
2713+ }
2714+
2715+ predicate liveAtEntry ( PreBasicBlock bb , SimpleLocalScopeVariable v ) {
2716+ refRank ( bb , _, v , Read ( ) ) = firstReadOrCertainWrite ( bb , v )
2717+ or
2718+ not exists ( firstReadOrCertainWrite ( bb , v ) ) and
2719+ liveAtExit ( bb , v )
2720+ }
2721+
2722+ private predicate liveAtExit ( PreBasicBlock bb , SimpleLocalScopeVariable v ) {
2723+ liveAtEntry ( bb .getASuccessor ( ) , v )
2724+ }
2725+
2726+ predicate assignableDefAtLive ( PreBasicBlocks:: PreBasicBlock bb , int i , AssignableDefinition def , SimpleLocalScopeVariable v ) {
2727+ assignableDefAt ( bb , i , def , v ) and
2728+ exists ( int rnk |
2729+ rnk = refRank ( bb , i , v , Write ( _) ) |
2730+ rnk + 1 = refRank ( bb , _, v , Read ( ) )
2731+ or
2732+ rnk = max ( refRank ( bb , _, v , _) ) and
2733+ liveAtExit ( bb , v )
2734+ )
2735+ }
2736+
26532737 predicate defAt ( PreBasicBlock bb , int i , Definition def , SimpleLocalScopeVariable v ) {
26542738 def = TExplicitPreSsaDef ( bb , i , _, v )
26552739 or
26562740 def = TPhiPreSsaDef ( bb , v ) and i = - 1
26572741 }
26582742
2659- private predicate readAt ( PreBasicBlock bb , int i , LocalScopeVariableRead read , SimpleLocalScopeVariable v ) {
2660- read = bb .getElement ( i ) and
2661- read .getTarget ( ) = v
2662- }
2743+ private newtype SsaRefKind = SsaRead ( ) or SsaDef ( )
26632744
26642745 private predicate ssaRef ( PreBasicBlock bb , int i , SimpleLocalScopeVariable v , SsaRefKind k ) {
26652746 readAt ( bb , i , _, v ) and
@@ -2756,6 +2837,22 @@ module ControlFlow {
27562837 readAt ( bb2 , i2 , read2 , v )
27572838 )
27582839 }
2840+
2841+ predicate ssaDefReachesEndOfBlock ( PreBasicBlock bb , Definition def , SimpleLocalScopeVariable v ) {
2842+ liveAtExit ( bb , v ) and
2843+ (
2844+ exists ( int last |
2845+ last = max ( ssaRefRank ( bb , _, v , _) ) |
2846+ defReachesRank ( bb , def , v , last )
2847+ )
2848+ or
2849+ exists ( PreBasicBlock idom |
2850+ idom .immediatelyDominates ( bb ) |
2851+ ssaDefReachesEndOfBlock ( idom , def , v ) and
2852+ not exists ( ssaRefRank ( bb , _, v , SsaDef ( ) ) )
2853+ )
2854+ )
2855+ }
27592856 }
27602857
27612858 /**
@@ -3847,10 +3944,11 @@ module ControlFlow {
38473944 newtype TPreSsaDef =
38483945 TExplicitPreSsaDef ( PreBasicBlocks:: PreBasicBlock bb , int i , AssignableDefinition def , LocalScopeVariable v ) {
38493946 Guards:: Internal:: CachedWithCFG:: forceCachingInSameStage ( ) and
3850- PreSsa:: assignableDefAt ( bb , i , def , v )
3947+ PreSsa:: assignableDefAtLive ( bb , i , def , v )
38513948 }
38523949 or
38533950 TPhiPreSsaDef ( PreBasicBlocks:: PreBasicBlock bb , LocalScopeVariable v ) {
3951+ PreSsa:: liveAtEntry ( bb , v ) and
38543952 exists ( PreBasicBlocks:: PreBasicBlock def |
38553953 def .inDominanceFrontier ( bb ) |
38563954 PreSsa:: defAt ( def , _, _, v )
0 commit comments