6363
6464namespace xls {
6565
66- namespace {
67-
68- // TODO: replace with a single visibility analysis that computes a variety of
69- // conservative visibility expressions with different trade-offs and that
70- // can be queried to provide the simplest visibility expressions it knows which
71- // prove the mutual exclusivity of a set of nodes.
72- struct VisibilityAnalyses {
73- const VisibilityAnalysis& general;
74- const SingleSelectVisibilityAnalysis& single_select;
75- };
76-
77- struct MutuallyExclPair {
78- Node* one;
79- Node* other;
80- MutuallyExclPair (Node* a, Node* b)
81- : one(std::min(a, b, NodeIdLessThan)),
82- other (std::max(a, b, NodeIdLessThan)) {}
83- bool operator ==(const MutuallyExclPair& o) const {
84- return one == o.one && other == o.other ;
85- }
86- template <typename H>
87- friend H AbslHashValue (H h, const MutuallyExclPair& d) {
88- return H::combine (std::move (h), d.one , d.other );
89- }
90- };
91-
92- } // namespace
93-
9466class TimingAnalysis {
9567 public:
9668 TimingAnalysis (
@@ -250,7 +222,6 @@ bool CanMapOpInto(Node* node_to_map, Node* folding_destination) {
250222// Check if we are currently capable to potentially handle the node given as
251223// input for folding.
252224bool CanTarget (Node* n) {
253- // We handle multipliers and adders
254225 if (n->OpIn ({Op::kUMul , Op::kSMul , Op::kAdd , Op::kSub , Op::kShrl , Op::kShra ,
255226 Op::kShll , Op::kDynamicBitSlice })) {
256227 return true ;
@@ -298,19 +269,10 @@ bool CanTarget(Node* n, Node* selector,
298269 return !nda.IsDependent (n, selector);
299270}
300271
301- // This function computes the set of mutual exclusive pairs of instructions.
302- // Each pair of instruction is associated with the select (of any kind) that
303- // made them mutually exclusive.
304- // We later use this association to extract the conditions to decide which
305- // inputs to use at the folded remaining node.
306- //
307- // This analysis is conservative and as such it might generate false negatives.
308- // In other words, some mutually-exclusive pairs of instructions might not be
309- // detected by this analysis.
310- // Hence, this analysis can be improved in the future.
311- absl::StatusOr<absl::flat_hash_set<MutuallyExclPair>>
312- ComputeMutualExclusionAnalysis (FunctionBase* f, OptimizationContext& context,
313- const VisibilityAnalyses& visibility) {
272+ absl::StatusOr<absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>>
273+ ResourceSharingPass::ComputeMutualExclusionAnalysis (
274+ FunctionBase* f, OptimizationContext& context,
275+ const VisibilityAnalyses& visibility) {
314276 absl::flat_hash_set<MutuallyExclPair> mutual_exclusivity;
315277
316278 std::vector<Node*> relevant_nodes;
@@ -357,10 +319,8 @@ ComputeMutualExclusionAnalysis(FunctionBase* f, OptimizationContext& context,
357319 return mutual_exclusivity;
358320}
359321
360- // This function returns all possible folding actions that we can legally
361- // perform.
362322absl::StatusOr<std::vector<std::unique_ptr<BinaryFoldingAction>>>
363- ComputeFoldableActions (
323+ ResourceSharingPass:: ComputeFoldableActions (
364324 FunctionBase* f, absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
365325 const VisibilityAnalyses& visibility) {
366326 std::vector<std::unique_ptr<BinaryFoldingAction>> foldable_actions;
@@ -452,12 +412,8 @@ bool GreaterBitwidthComparator(BinaryFoldingAction* a0,
452412 return a0_bitwidth > a1_bitwidth;
453413}
454414
455- // MakeNaryFoldingActions creates a single n-ary folding action from as many of
456- // the provided binary foldings as possible, given our understanding of the
457- // visibility of these nodes. It is possible that one of the binary foldings is
458- // on a node whose conservative visibility expression is too complicated to
459- // analyze efficiently, in which case we must drop that binary folding.
460- absl::StatusOr<std::unique_ptr<NaryFoldingAction>> MakeNaryFoldingAction (
415+ absl::StatusOr<std::unique_ptr<NaryFoldingAction>>
416+ ResourceSharingPass::MakeNaryFoldingAction (
461417 std::vector<BinaryFoldingAction*>& subset_of_edges_to_n, double area_saved,
462418 const VisibilityAnalyses& visibility) {
463419 XLS_RET_CHECK_NE (subset_of_edges_to_n.size (), 0 );
@@ -520,8 +476,9 @@ absl::StatusOr<std::unique_ptr<NaryFoldingAction>> MakeNaryFoldingAction(
520476// For example, when only multiplications that have the same bit-widths are
521477// considered.
522478absl::StatusOr<std::vector<std::unique_ptr<NaryFoldingAction>>>
523- SelectFoldingActionsBasedOnCliques (FoldingGraph* folding_graph,
524- const VisibilityAnalyses& visibility) {
479+ SelectFoldingActionsBasedOnCliques (
480+ FoldingGraph* folding_graph,
481+ const ResourceSharingPass::VisibilityAnalyses& visibility) {
525482 std::vector<std::unique_ptr<NaryFoldingAction>> folding_actions_to_perform;
526483
527484 // Choose all of them matching the maximum cliques of the folding graph
@@ -558,8 +515,8 @@ SelectFoldingActionsBasedOnCliques(FoldingGraph* folding_graph,
558515
559516 // Create a single n-ary folding action for the whole clique
560517 std::unique_ptr<NaryFoldingAction> new_action;
561- XLS_ASSIGN_OR_RETURN (new_action,
562- MakeNaryFoldingAction ( folds, area_saved, visibility));
518+ XLS_ASSIGN_OR_RETURN (new_action, ResourceSharingPass::MakeNaryFoldingAction (
519+ folds, area_saved, visibility));
563520 folding_actions_to_perform.push_back (std::move (new_action));
564521 }
565522
@@ -625,14 +582,16 @@ absl::StatusOr<double> EstimateAreaForNegatingNode(Node* n,
625582// into a single n-ary folding on the same destination. Note that binary
626583// foldings are sorted by benefit (e.g maximizing area savings) in descending
627584// order, meaning 'previous' is more important than 'next'.
628- bool CanFoldTogether (absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
585+ bool CanFoldTogether (absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
586+ mutual_exclusivity,
629587 BinaryFoldingAction* next, BinaryFoldingAction* previous) {
630588 if (previous->GetTo () != next->GetTo ()) {
631589 return false ;
632590 }
633591 Node* prev_node = previous->GetFrom ();
634592 Node* next_node = next->GetFrom ();
635- if (mutual_exclusivity.contains (MutuallyExclPair (prev_node, next_node))) {
593+ if (mutual_exclusivity.contains (
594+ ResourceSharingPass::MutuallyExclPair (prev_node, next_node))) {
636595 return true ;
637596 }
638597 VLOG (4 ) << " Excluding the following source because it is not "
@@ -769,8 +728,10 @@ absl::StatusOr<NaryFoldEstimate> SelectSubsetOfFolds(
769728absl::StatusOr<std::vector<std::unique_ptr<NaryFoldingAction>>>
770729ListOfAllFoldingActionsWithDestination (
771730 Node* n, FoldingGraph* folding_graph,
772- absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
773- const VisibilityAnalyses& visibility, const AreaEstimator& area_estimator,
731+ absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
732+ mutual_exclusivity,
733+ const ResourceSharingPass::VisibilityAnalyses& visibility,
734+ const AreaEstimator& area_estimator,
774735 const CriticalPathDelayAnalysis& critical_path_delay,
775736 VisibilityEstimator* visibility_estimator) {
776737 std::vector<std::unique_ptr<NaryFoldingAction>>
@@ -844,9 +805,9 @@ ListOfAllFoldingActionsWithDestination(
844805 // Create the hyper-edge by merging all these edges
845806 // Notice this is possible because all edges in @edges_to_n are guaranteed
846807 // to have @n as destination.
847- XLS_ASSIGN_OR_RETURN (
848- std::unique_ptr<NaryFoldingAction> new_action,
849- MakeNaryFoldingAction ( estimate.folds , estimate.area_saved , visibility));
808+ XLS_ASSIGN_OR_RETURN (std::unique_ptr<NaryFoldingAction> new_action,
809+ ResourceSharingPass::MakeNaryFoldingAction (
810+ estimate.folds , estimate.area_saved , visibility));
850811 potential_folding_actions_to_perform.push_back (std::move (new_action));
851812
852813 return potential_folding_actions_to_perform;
@@ -857,8 +818,10 @@ ListOfAllFoldingActionsWithDestination(
857818absl::StatusOr<std::vector<std::unique_ptr<NaryFoldingAction>>>
858819ListOfFoldingActionsWithDestination (
859820 Node* n, FoldingGraph* folding_graph,
860- absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
861- const VisibilityAnalyses& visibility, const AreaEstimator& area_estimator,
821+ absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
822+ mutual_exclusivity,
823+ const ResourceSharingPass::VisibilityAnalyses& visibility,
824+ const AreaEstimator& area_estimator,
862825 const CriticalPathDelayAnalysis& critical_path_delay,
863826 VisibilityEstimator* visibility_estimator) {
864827 std::vector<std::unique_ptr<NaryFoldingAction>>
@@ -954,25 +917,20 @@ ListOfFoldingActionsWithDestination(
954917 // Create the hyper-edge by merging all these edges
955918 // Notice this is possible because all edges in @edges_to_n are guaranteed
956919 // to have @n as destination.
957- XLS_ASSIGN_OR_RETURN (
958- std::unique_ptr<NaryFoldingAction> new_action,
959- MakeNaryFoldingAction ( estimate.folds , estimate.area_saved , visibility));
920+ XLS_ASSIGN_OR_RETURN (std::unique_ptr<NaryFoldingAction> new_action,
921+ ResourceSharingPass::MakeNaryFoldingAction (
922+ estimate.folds , estimate.area_saved , visibility));
960923 potential_folding_actions_to_perform.push_back (std::move (new_action));
961924 }
962925 return potential_folding_actions_to_perform;
963926}
964927
965- // Legalizes a sequence of folding actions by removing or modifying actions
966- // that conflict.
967- //
968- // Returns a pair where the first element is the legalized sequence of
969- // actions and the second element is a boolean that is true if the input
970- // sequence was modified.
971928absl::StatusOr<std::pair<std::vector<std::unique_ptr<NaryFoldingAction>>, bool >>
972- LegalizeSequenceOfFolding (
929+ ResourceSharingPass:: LegalizeSequenceOfFolding (
973930 absl::Span<const std::unique_ptr<NaryFoldingAction>>
974931 potential_folding_actions_to_perform,
975- absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
932+ absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
933+ mutual_exclusivity,
976934 std::optional<const AreaEstimator*> area_estimator) {
977935 std::vector<std::unique_ptr<NaryFoldingAction>> folding_actions_to_perform;
978936 bool modified = false ;
@@ -1286,8 +1244,10 @@ void SortNodesInDescendingOrderOfTheirInDegree(std::vector<Node*>& nodes,
12861244absl::StatusOr<std::vector<std::unique_ptr<NaryFoldingAction>>>
12871245SelectFoldingActionsBasedOnInDegree (
12881246 OptimizationContext& context, FoldingGraph* folding_graph,
1289- absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
1290- const VisibilityAnalyses& visibility, const AreaEstimator& area_estimator,
1247+ absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
1248+ mutual_exclusivity,
1249+ const ResourceSharingPass::VisibilityAnalyses& visibility,
1250+ const AreaEstimator& area_estimator,
12911251 const CriticalPathDelayAnalysis& critical_path_delay,
12921252 VisibilityEstimator* visibility_estimator) {
12931253 // Get the nodes of the folding graph
@@ -1379,7 +1339,7 @@ SelectFoldingActionsBasedOnInDegree(
13791339 std::vector<std::unique_ptr<NaryFoldingAction>> folding_actions_to_perform;
13801340 XLS_ASSIGN_OR_RETURN (
13811341 std::tie (folding_actions_to_perform, std::ignore),
1382- LegalizeSequenceOfFolding (
1342+ ResourceSharingPass:: LegalizeSequenceOfFolding (
13831343 std::move (
13841344 potential_folding_actions_to_perform_without_timing_problems),
13851345 mutual_exclusivity, &area_estimator));
@@ -1401,8 +1361,10 @@ SelectFoldingActionsBasedOnInDegree(
14011361absl::StatusOr<std::vector<std::unique_ptr<NaryFoldingAction>>>
14021362SelectAllFoldingActions (
14031363 OptimizationContext& context, FoldingGraph* folding_graph,
1404- absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
1405- const VisibilityAnalyses& visibility, const AreaEstimator& area_estimator,
1364+ absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
1365+ mutual_exclusivity,
1366+ const ResourceSharingPass::VisibilityAnalyses& visibility,
1367+ const AreaEstimator& area_estimator,
14061368 const CriticalPathDelayAnalysis& critical_path_delay,
14071369 VisibilityEstimator* visibility_estimator) {
14081370 // Get the nodes of the folding graph
@@ -1466,10 +1428,10 @@ SelectAllFoldingActions(
14661428 // However, a given n-ary folding action might be illegal if another one run
14671429 // before.
14681430 std::vector<std::unique_ptr<NaryFoldingAction>> folding_actions_to_perform;
1469- XLS_ASSIGN_OR_RETURN (
1470- std::tie (folding_actions_to_perform, std::ignore),
1471- LegalizeSequenceOfFolding ( std::move (potential_folding_actions_to_perform),
1472- mutual_exclusivity, &area_estimator));
1431+ XLS_ASSIGN_OR_RETURN (std::tie (folding_actions_to_perform, std::ignore),
1432+ ResourceSharingPass::LegalizeSequenceOfFolding (
1433+ std::move (potential_folding_actions_to_perform),
1434+ mutual_exclusivity, &area_estimator));
14731435
14741436 return folding_actions_to_perform;
14751437}
@@ -1480,8 +1442,9 @@ SelectAllFoldingActions(
14801442absl::StatusOr<std::vector<std::unique_ptr<NaryFoldingAction>>>
14811443SelectRandomlyFoldingActions (
14821444 FoldingGraph* folding_graph,
1483- absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
1484- const VisibilityAnalyses& visibility) {
1445+ absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
1446+ mutual_exclusivity,
1447+ const ResourceSharingPass::VisibilityAnalyses& visibility) {
14851448 std::vector<std::unique_ptr<NaryFoldingAction>> folding_actions_to_perform;
14861449
14871450 // Get all edges of the folding graph
@@ -1529,8 +1492,8 @@ SelectRandomlyFoldingActions(
15291492
15301493 // Create a single n-ary folding action
15311494 std::unique_ptr<NaryFoldingAction> new_action;
1532- XLS_ASSIGN_OR_RETURN (new_action,
1533- MakeNaryFoldingAction ( folds, area_saved, visibility));
1495+ XLS_ASSIGN_OR_RETURN (new_action, ResourceSharingPass::MakeNaryFoldingAction (
1496+ folds, area_saved, visibility));
15341497
15351498 // Add the new n-ary folding action to the list of actions to perform
15361499 folding_actions_to_perform.push_back (std::move (new_action));
@@ -1545,8 +1508,9 @@ SelectRandomlyFoldingActions(
15451508absl::StatusOr<std::vector<std::unique_ptr<NaryFoldingAction>>>
15461509SelectFoldingActions (OptimizationContext& context, FoldingGraph* folding_graph,
15471510 ResourceSharingPass::ProfitabilityGuard heuristics,
1548- absl::flat_hash_set<MutuallyExclPair>& mutual_exclusivity,
1549- const VisibilityAnalyses& visibility,
1511+ absl::flat_hash_set<ResourceSharingPass::MutuallyExclPair>&
1512+ mutual_exclusivity,
1513+ const ResourceSharingPass::VisibilityAnalyses& visibility,
15501514 const AreaEstimator& area_estimator,
15511515 const CriticalPathDelayAnalysis& critical_path_delay,
15521516 VisibilityEstimator* visibility_estimator) {
@@ -1625,11 +1589,7 @@ SelectFoldingActions(OptimizationContext& context, FoldingGraph* folding_graph,
16251589 return folding_actions_to_perform;
16261590}
16271591
1628- // This function performs the folding actions specified in its input following
1629- // the order specified.
1630- // @next_node_id is used to determine what nodes were generated by this pass
1631- // and is only used for logging purposes; see ToMathNotation.
1632- absl::StatusOr<bool > PerformFoldingActions (
1592+ absl::StatusOr<bool > ResourceSharingPass::PerformFoldingActions (
16331593 FunctionBase* f, int64_t next_node_id,
16341594 VisibilityBuilder* visibility_builder,
16351595 const std::vector<std::unique_ptr<NaryFoldingAction>>&
0 commit comments