@@ -174,15 +174,34 @@ private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
174
174
}
175
175
176
176
cached
177
- newtype TDefinition =
178
- TWriteDef ( SourceVariable v , BasicBlock bb , int i ) {
179
- variableWrite ( bb , i , v , _) and
180
- liveAfterWrite ( bb , i , v )
181
- } or
182
- TPhiNode ( SourceVariable v , BasicBlock bb ) {
183
- inDefDominanceFrontier ( bb , v ) and
184
- liveAtEntry ( bb , v )
177
+ private module Cached {
178
+ cached
179
+ newtype TDefinition =
180
+ TWriteDef ( SourceVariable v , BasicBlock bb , int i ) {
181
+ variableWrite ( bb , i , v , _) and
182
+ liveAfterWrite ( bb , i , v )
183
+ } or
184
+ TPhiNode ( SourceVariable v , BasicBlock bb ) {
185
+ inDefDominanceFrontier ( bb , v ) and
186
+ liveAtEntry ( bb , v )
187
+ }
188
+
189
+ cached
190
+ predicate uncertainWriteDefinitionInput ( UncertainWriteDefinition def , Definition inp ) {
191
+ lastRefRedef ( inp , _, _, def )
192
+ }
193
+
194
+ cached
195
+ predicate phiHasInputFromBlock ( PhiNode phi , Definition inp , BasicBlock bb ) {
196
+ exists ( SourceVariable v , BasicBlock bbDef |
197
+ phi .definesAt ( v , bbDef , _) and
198
+ getABasicBlockPredecessor ( bbDef ) = bb and
199
+ ssaDefReachesEndOfBlock ( bb , inp , v )
200
+ )
185
201
}
202
+ }
203
+
204
+ import Cached
186
205
187
206
private module SsaDefReaches {
188
207
newtype TSsaRefKind =
@@ -369,11 +388,12 @@ private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, Sour
369
388
}
370
389
371
390
/**
391
+ * NB: If this predicate is exposed, it should be cached.
392
+ *
372
393
* Holds if the SSA definition of `v` at `def` reaches the end of basic
373
394
* block `bb`, at which point it is still live, without crossing another
374
395
* SSA definition of `v`.
375
396
*/
376
- cached
377
397
predicate ssaDefReachesEndOfBlock ( BasicBlock bb , Definition def , SourceVariable v ) {
378
398
exists ( int last | last = maxSsaRefRank ( bb , v ) |
379
399
ssaDefReachesRank ( bb , def , last , v ) and
@@ -386,11 +406,12 @@ predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable
386
406
}
387
407
388
408
/**
409
+ * NB: If this predicate is exposed, it should be cached.
410
+ *
389
411
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
390
412
* basic block `bb`, without crossing another SSA definition of `v`. The read
391
413
* is of kind `rk`.
392
414
*/
393
- cached
394
415
predicate ssaDefReachesRead ( SourceVariable v , Definition def , BasicBlock bb , int i ) {
395
416
ssaDefReachesReadWithinBlock ( v , def , bb , i )
396
417
or
@@ -400,26 +421,12 @@ predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int
400
421
}
401
422
402
423
/**
403
- * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
404
- * `redef` without crossing another SSA definition of `v`.
405
- */
406
- cached
407
- predicate ssaDefReachesUncertainDef ( SourceVariable v , Definition def , UncertainWriteDefinition redef ) {
408
- ssaDefReachesUncertainDefWithinBlock ( v , def , redef )
409
- or
410
- exists ( BasicBlock bb |
411
- redef .definesAt ( v , bb , _) and
412
- ssaDefReachesEndOfBlock ( getABasicBlockPredecessor ( bb ) , def , v ) and
413
- not ssaDefReachesUncertainDefWithinBlock ( v , _, redef )
414
- )
415
- }
416
-
417
- /**
424
+ * NB: If this predicate is exposed, it should be cached.
425
+ *
418
426
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
419
427
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
420
428
* path between them without any read of `def`.
421
429
*/
422
- cached
423
430
predicate adjacentDefRead ( Definition def , BasicBlock bb1 , int i1 , BasicBlock bb2 , int i2 ) {
424
431
exists ( int rnk |
425
432
rnk = ssaDefRank ( def , _, bb1 , i1 , _) and
@@ -433,11 +440,12 @@ predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2
433
440
}
434
441
435
442
/**
443
+ * NB: If this predicate is exposed, it should be cached.
444
+ *
436
445
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
437
446
* `def`. The reference is last because it can reach another write `next`,
438
447
* without passing through another read or write.
439
448
*/
440
- cached
441
449
predicate lastRefRedef ( Definition def , BasicBlock bb , int i , Definition next ) {
442
450
exists ( int rnk , SourceVariable v , int j | rnk = ssaDefRank ( def , v , bb , i , _) |
443
451
// Next reference to `v` inside `bb` is a write
@@ -455,14 +463,15 @@ predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
455
463
}
456
464
457
465
/**
466
+ * NB: If this predicate is exposed, it should be cached.
467
+ *
458
468
* Holds if the node at index `i` in `bb` is a last reference to SSA
459
469
* definition `def`.
460
470
*
461
471
* That is, the node can reach the end of the enclosing callable, or another
462
472
* SSA definition for the underlying source variable, without passing through
463
473
* another read.
464
474
*/
465
- cached
466
475
predicate lastRef ( Definition def , BasicBlock bb , int i ) {
467
476
lastRefRedef ( def , bb , i , _)
468
477
or
@@ -483,14 +492,6 @@ class Definition extends TDefinition {
483
492
/** Gets the source variable underlying this SSA definition. */
484
493
SourceVariable getSourceVariable ( ) { this .definesAt ( result , _, _) }
485
494
486
- /**
487
- * Holds is this SSA definition is live at the end of basic block `bb`.
488
- * That is, this definition reaches the end of basic block `bb`, at which
489
- * point it is still live, without crossing another SSA definition of the
490
- * same source variable.
491
- */
492
- final predicate isLiveAtEndOfBlock ( BasicBlock bb ) { ssaDefReachesEndOfBlock ( bb , this , _) }
493
-
494
495
/**
495
496
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
496
497
* Phi nodes are considered to be at index `-1`, while normal variable writes
@@ -541,20 +542,10 @@ class WriteDefinition extends Definition, TWriteDef {
541
542
/** A phi node. */
542
543
class PhiNode extends Definition , TPhiNode {
543
544
/** Gets an input of this phi node. */
544
- Definition getAnInput ( ) {
545
- exists ( BasicBlock bb , BasicBlock pred , SourceVariable v |
546
- this .definesAt ( v , bb , _) and
547
- getABasicBlockPredecessor ( bb ) = pred and
548
- ssaDefReachesEndOfBlock ( pred , result , v )
549
- )
550
- }
545
+ Definition getAnInput ( ) { this .hasInputFromBlock ( result , _) }
551
546
552
547
/** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */
553
- predicate hasInputFromBlock ( Definition inp , BasicBlock bb ) {
554
- inp = this .getAnInput ( ) and
555
- getABasicBlockPredecessor ( this .getBasicBlock ( ) ) = bb and
556
- ssaDefReachesEndOfBlock ( bb , inp , _)
557
- }
548
+ predicate hasInputFromBlock ( Definition inp , BasicBlock bb ) { phiHasInputFromBlock ( this , inp , bb ) }
558
549
559
550
override string toString ( ) { result = "Phi" }
560
551
}
@@ -575,5 +566,5 @@ class UncertainWriteDefinition extends WriteDefinition {
575
566
* Gets the immediately preceding definition. Since this update is uncertain,
576
567
* the value from the preceding definition might still be valid.
577
568
*/
578
- Definition getPriorDefinition ( ) { ssaDefReachesUncertainDef ( _ , result , this ) }
569
+ Definition getPriorDefinition ( ) { uncertainWriteDefinitionInput ( this , result ) }
579
570
}
0 commit comments