@@ -1405,14 +1405,80 @@ private class PhiCycle extends PhiCycleEquivalence::EquivalenceClass {
14051405 }
14061406}
14071407
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+ }
14141475 }
1476+ }
14151477
1478+ import Public
1479+
1480+ /** An static single assignment (SSA) definition. */
1481+ class Definition extends SsaImpl:: Definition {
14161482 /**
14171483 * Holds if this SSA definition is live at the end of basic block `bb`.
14181484 * That is, this definition reaches the end of basic block `bb`, at which
@@ -1424,9 +1490,13 @@ class Definition extends SsaImpl::Definition {
14241490 /**
14251491 * Gets a definition that ultimately defines this SSA definition and is
14261492 * 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.
14271497 */
14281498 final Definition getAnUltimateDefinition ( ) {
1429- result = this . getAPhiInputOrPriorDefinition * ( ) and
1499+ result = getAPhiInputOrPriorDefinition * ( this ) and
14301500 not result instanceof PhiNode
14311501 }
14321502
0 commit comments