38#include <gtest/gtest.h>
59 for (
int i = 0; i < n; ++i)
60 nodes(
static_cast<size_t>(i)) = g.insert_node(i);
69 for (
auto it =
idoms.get_it(); it.has_curr(); it.next_ne())
71 auto [node,
idom] = it.get_curr();
87 auto nodes = make_nodes(g, 1);
101 auto nodes = make_nodes(g, 5);
125 auto nodes = make_nodes(g, 4);
150 auto nodes = make_nodes(g, 5);
177 auto nodes = make_nodes(g, 5);
204 auto n = make_nodes(g, 13);
205 g.insert_arc(n[0], n[1]);
206 g.insert_arc(n[0], n[5]);
207 g.insert_arc(n[0], n[9]);
208 g.insert_arc(n[1], n[2]);
209 g.insert_arc(n[2], n[3]);
210 g.insert_arc(n[3], n[4]);
211 g.insert_arc(n[3], n[1]);
212 g.insert_arc(n[4], n[12]);
213 g.insert_arc(n[5], n[6]);
214 g.insert_arc(n[6], n[7]);
215 g.insert_arc(n[6], n[8]);
216 g.insert_arc(n[7], n[4]);
217 g.insert_arc(n[8], n[12]);
218 g.insert_arc(n[9], n[10]);
219 g.insert_arc(n[10], n[11]);
220 g.insert_arc(n[11], n[9]);
221 g.insert_arc(n[11], n[12]);
260 auto nodes = make_nodes(g, 4);
277 auto nodes = make_nodes(g, 2);
300 auto nodes = make_nodes(g, 2);
321 auto nodes = make_nodes(g, 5);
336 for (
auto it = tree.get_node_it(); it.has_curr(); it.next_ne())
338 auto tn = it.get_curr();
349 auto nodes = make_nodes(g, 4);
369 auto nodes = make_nodes(g, 3);
376 for (
int i = 0; i < 3; ++i)
383 auto nodes = make_nodes(g, 5);
391 for (
int i = 0; i < 5; ++i)
403 auto nodes = make_nodes(g, 4);
430 auto nodes = make_nodes(g, 4);
463 auto nodes = make_nodes(g, 3);
490 auto nodes = make_nodes(g, 4);
497 DG::Node * n0 =
nodes[0];
498 DG::Node * n1 =
nodes[1];
499 DG::Node * n2 =
nodes[2];
500 DG::Node * n3 =
nodes[3];
511 auto nodes = make_nodes(g, 2);
528 auto nodes = make_nodes(g,
N);
530 std::mt19937
rng(42);
533 for (
int i = 0; i <
N - 1; ++i)
536 int j = i + 1 +
static_cast<int>(
rng() % std::min(5,
N - i - 1));
541 for (
int k = 0;
k < 2; ++
k)
543 int t = i + 1 +
static_cast<int>(
rng() % (
N - i - 1));
556 for (
auto it =
m.
get_it(); it.has_curr(); it.next_ne())
558 const auto & [node_id,
idom_id] = it.get_curr();
573 const char *
run_perf = std::getenv(
"ALEPH_RUN_DOMINATORS_PERF");
575 GTEST_SKIP() <<
"Set ALEPH_RUN_DOMINATORS_PERF=1 to run dominators perf test";
577 constexpr int N = 5000;
585 auto nodes = make_nodes(g,
N);
586 std::mt19937
rng(0xD01A70u);
588 for (
int i = 0; i <
N - 1; ++i)
590 const int max_step = std::min(12,
N - i - 1);
591 const int j = i + 1 +
static_cast<int>(
rng() %
max_step);
594 for (
int k = 0;
k < 4; ++
k)
596 const int t = i + 1 +
static_cast<int>(
rng() % (
N - i - 1));
601 const auto t0 = std::chrono::steady_clock::now();
606 const auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
607 std::chrono::steady_clock::now() -
t0).count();
613 <<
"Dominators perf regression: N=" <<
N
614 <<
", elapsed_ms=" << elapsed_ms
626 auto nodes = make_nodes(g, 3);
648 auto nodes = make_nodes(g, 4);
678 auto entry = g.insert_node(
"entry");
679 auto body = g.insert_node(
"body");
682 g.insert_arc(entry,
body);
688 for (
auto it =
idoms.get_it(); it.has_curr(); it.next_ne())
690 auto [node,
idom] = it.get_curr();
691 m[node->get_info()] =
idom ?
idom->get_info() :
"none";
711 for (
auto it =
ipdoms.get_it(); it.has_curr(); it.next_ne())
713 auto [node,
ipdom] = it.get_curr();
714 m[node->get_info()] =
ipdom ?
ipdom->get_info() : -1;
723 auto nodes = make_nodes(g, 1);
737 auto nodes = make_nodes(g, 4);
759 auto nodes = make_nodes(g, 4);
785 auto nodes = make_nodes(g, 5);
816 auto nodes = make_nodes(g, 5);
836 auto nodes = make_nodes(g, 3);
842 for (
int i = 0; i < 3; ++i)
851 auto nodes = make_nodes(g, 4);
858 for (
int i = 0; i < 4; ++i)
880 auto nodes = make_nodes(g, 4);
910 auto nodes = make_nodes(g, 4);
923 for (
auto it = tree.get_node_it(); it.has_curr(); it.next_ne())
925 auto tn = it.get_curr();
935 auto nodes = make_nodes(g, 2);
Dominator and post-dominator tree computation via the Lengauer-Tarjan algorithm.
Generic directed graph (digraph) wrapper template.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
Dynamic singly linked list with functional programming support.
Generic key-value map implemented on top of a binary search tree.
Computes dominator tree and dominance frontiers of a digraph using the Lengauer-Tarjan algorithm.
void build_tree(GT &g, Node *root, GT &tree)
Build the dominator tree as a separate graph.
Computes post-dominator tree and post-dominance frontiers of a digraph using the Lengauer-Tarjan algo...
Key * search(const Key &key) const noexcept
searches the table for the key.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
constexpr size_t size() const noexcept
Returns the number of entries in the table.
Key * insert(const Key &key)
Inserts a key into the hash table (copy version).
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
DynArray< Graph::Node * > nodes
void build_post_dominator_tree(const GT &g, typename GT::Node *exit_node, GT &tree, SA sa=SA())
Build the post-dominator tree of a digraph.
void build_dominator_tree(GT &g, typename GT::Node *root, GT &tree, SA sa=SA())
Build the dominator tree of a digraph.
DynList< std::pair< typename GT::Node *, typename GT::Node * > > compute_dominators(GT &g, typename GT::Node *root, SA sa=SA())
Compute immediate dominators of a digraph from a root node.
DynList< std::pair< typename GT::Node *, typename GT::Node * > > compute_post_dominators(const GT &g, typename GT::Node *exit_node, SA sa=SA())
Compute immediate post-dominators of a digraph from an exit node.
DynMapTree< typename GT::Node *, DynSetTree< typename GT::Node * > > compute_post_dominance_frontiers(const GT &g, typename GT::Node *exit_node, SA sa=SA())
Compute post-dominance frontiers of a digraph.
DynMapTree< typename GT::Node *, DynSetTree< typename GT::Node * > > compute_dominance_frontiers(GT &g, typename GT::Node *root, SA sa=SA())
Compute dominance frontiers of a digraph.
Main namespace for Aleph-w library functions.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
static long & df(typename GT::Node *p)
Internal helper: DFS discovery time stored in NODE_COUNTER(p).
Arc of graph implemented with double-linked adjacency lists.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Lazy and scalable dynamic array implementation.
Dynamic key-value map based on balanced binary search trees.
Generic graph and digraph implementations.