@@ -1405,14 +1405,80 @@ private class PhiCycle extends PhiCycleEquivalence::EquivalenceClass { |
1405 | 1405 | } |
1406 | 1406 | } |
1407 | 1407 |
|
1408 | | -/** An static single assignment (SSA) definition. */ |
1409 | | -class Definition extends SsaImpl::Definition { |
1410 | | - private Definition getAPhiInputOrPriorDefinition() { |
1411 | | - result = this.(PhiNode).getAnInput() |
1412 | | - or |
1413 | | - uncertainWriteDefinitionInput(this, result) |
| 1408 | +private Definition getAPhiInputOrPriorDefinition(Definition def) { |
| 1409 | + result = def.(PhiNode).getAnInput() |
| 1410 | + or |
| 1411 | + uncertainWriteDefinitionInput(def, result) |
| 1412 | +} |
| 1413 | + |
| 1414 | +module Public { |
| 1415 | + /** |
| 1416 | + * A module signature to define relevant ultimate definitions for an |
| 1417 | + * optimized version of `Definition.getAnUltimateDefinition`. |
| 1418 | + */ |
| 1419 | + signature module GetAnUltimateDefinitionSig { |
| 1420 | + /** |
| 1421 | + * Holds if `def` is a relevant definition. This defines the set |
| 1422 | + * of `Definition`s which may be returned by |
| 1423 | + * `GetAnUltimateDefinition::getAnUltimateDefinition`. |
| 1424 | + */ |
| 1425 | + predicate isRelevantUltimateDefinition(Definition def); |
| 1426 | + } |
| 1427 | + |
| 1428 | + /** |
| 1429 | + * A module which constructs an optimized version of |
| 1430 | + * ``` |
| 1431 | + * Definition.getAnUltimateDefinition |
| 1432 | + * ``` |
| 1433 | + * by restricting the set of possible ultimate definitions. |
| 1434 | + * |
| 1435 | + * Use this module by defining a module `M` which implements |
| 1436 | + * `GetAnUltimateDefinitionSig` and then call: |
| 1437 | + * ``` |
| 1438 | + * GetAnUltimateDefinition<M>::getAnUltimateDefinition |
| 1439 | + * ``` |
| 1440 | + */ |
| 1441 | + module GetAnUltimateDefinition<GetAnUltimateDefinitionSig Sig> { |
| 1442 | + private import Sig |
| 1443 | + |
| 1444 | + private predicate relevantUltimateDefinition(Definition def) { |
| 1445 | + isRelevantUltimateDefinition(def) and |
| 1446 | + not def instanceof PhiNode |
| 1447 | + } |
| 1448 | + |
| 1449 | + private predicate fwd(Definition def) { |
| 1450 | + relevantUltimateDefinition(def) |
| 1451 | + or |
| 1452 | + exists(Definition def0 | |
| 1453 | + fwd(def0) and |
| 1454 | + def0 = getAPhiInputOrPriorDefinition(def) |
| 1455 | + ) |
| 1456 | + } |
| 1457 | + |
| 1458 | + private predicate step(Definition def1, Definition def2) { |
| 1459 | + fwd(def1) and |
| 1460 | + fwd(def2) and |
| 1461 | + def1 = getAPhiInputOrPriorDefinition(def2) |
| 1462 | + } |
| 1463 | + |
| 1464 | + /** |
| 1465 | + * Gets a definition that ultimately defines this SSA definition and is |
| 1466 | + * not itself a phi node. |
| 1467 | + * |
| 1468 | + * This predicate is restricted to ultimate definitions which |
| 1469 | + * satisfy `isRelevantUltimateDefinition`. |
| 1470 | + */ |
| 1471 | + Definition getAnUltimateDefinition(Definition def) { |
| 1472 | + step*(result, def) and |
| 1473 | + relevantUltimateDefinition(result) |
| 1474 | + } |
1414 | 1475 | } |
| 1476 | +} |
1415 | 1477 |
|
| 1478 | +import Public |
| 1479 | + |
| 1480 | +/** An static single assignment (SSA) definition. */ |
| 1481 | +class Definition extends SsaImpl::Definition { |
1416 | 1482 | /** |
1417 | 1483 | * Holds if this SSA definition is live at the end of basic block `bb`. |
1418 | 1484 | * That is, this definition reaches the end of basic block `bb`, at which |
@@ -1424,9 +1490,13 @@ class Definition extends SsaImpl::Definition { |
1424 | 1490 | /** |
1425 | 1491 | * Gets a definition that ultimately defines this SSA definition and is |
1426 | 1492 | * not itself a phi node. |
| 1493 | + * |
| 1494 | + * Note: A more efficient implementation of this predicate exists. See the |
| 1495 | + * `GetAnUltimateDefinition` module for a description of how to access |
| 1496 | + * the more efficient implementation. |
1427 | 1497 | */ |
1428 | 1498 | final Definition getAnUltimateDefinition() { |
1429 | | - result = this.getAPhiInputOrPriorDefinition*() and |
| 1499 | + result = getAPhiInputOrPriorDefinition*(this) and |
1430 | 1500 | not result instanceof PhiNode |
1431 | 1501 | } |
1432 | 1502 |
|
|