Mesa (main): util/dag: Add dag_add_edge_max_data

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Nov 17 14:16:15 UTC 2021


Module: Mesa
Branch: main
Commit: b8fc7a08f9fac2822a58473b6806638709060e96
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=b8fc7a08f9fac2822a58473b6806638709060e96

Author: Connor Abbott <cwabbott0 at gmail.com>
Date:   Mon Nov  8 15:31:29 2021 +0100

util/dag: Add dag_add_edge_max_data

This will be useful for when the edge data represents a delay of some
sort, like it will with ir3.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13722>

---

 src/util/dag.c              | 45 +++++++++++++++++++++++++++++++-------
 src/util/dag.h              |  1 +
 src/util/tests/dag_test.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/src/util/dag.c b/src/util/dag.c
index 97fd7386a49..8625647f887 100644
--- a/src/util/dag.c
+++ b/src/util/dag.c
@@ -24,6 +24,21 @@
 #include "util/set.h"
 #include "util/dag.h"
 
+static void
+append_edge(struct dag_node *parent, struct dag_node *child, uintptr_t data)
+{
+   /* Remove the child as a DAG head. */
+   list_delinit(&child->link);
+
+   struct dag_edge edge = {
+      .child = child,
+      .data = data,
+   };
+
+   util_dynarray_append(&parent->edges, struct dag_edge, edge);
+   child->parent_count++;
+}
+
 /**
  * Adds a directed edge from the parent node to the child.
  *
@@ -37,16 +52,30 @@ dag_add_edge(struct dag_node *parent, struct dag_node *child, uintptr_t data)
       if (edge->child == child && edge->data == data)
          return;
    }
-   /* Remove the child as a DAG head. */
-   list_delinit(&child->link);
 
-   struct dag_edge edge = {
-      .child = child,
-      .data = data,
-   };
+   append_edge(parent, child, data);
+}
 
-   util_dynarray_append(&parent->edges, struct dag_edge, edge);
-   child->parent_count++;
+/**
+ * Adds a directed edge from the parent node to the child.
+ *
+ * Both nodes should have been initialized with dag_init_node(). If there is
+ * already an existing edge, the data is updated to the maximum of the
+ * previous data and the new data. This is useful if the data represents a
+ * delay.
+ */
+void
+dag_add_edge_max_data(struct dag_node *parent, struct dag_node *child,
+                      uintptr_t data)
+{
+   util_dynarray_foreach(&parent->edges, struct dag_edge, edge) {
+      if (edge->child == child) {
+         edge->data = MAX2(edge->data, data);
+         return;
+      }
+   }
+
+   append_edge(parent, child, data);
 }
 
 /* Removes a single edge from the graph, promoting the child to a DAG head.
diff --git a/src/util/dag.h b/src/util/dag.h
index fbc3ed93d48..3ede13d7548 100644
--- a/src/util/dag.h
+++ b/src/util/dag.h
@@ -53,6 +53,7 @@ struct dag {
 struct dag *dag_create(void *mem_ctx);
 void dag_init_node(struct dag *dag, struct dag_node *node);
 void dag_add_edge(struct dag_node *parent, struct dag_node *child, uintptr_t data);
+void dag_add_edge_max_data(struct dag_node *parent, struct dag_node *child, uintptr_t data);
 void dag_remove_edge(struct dag *dag, struct dag_edge *edge);
 void dag_traverse_bottom_up(struct dag *dag, void (*cb)(struct dag_node *node,
                                                         void *data), void *data);
diff --git a/src/util/tests/dag_test.cpp b/src/util/tests/dag_test.cpp
index d8c2ae9483c..6cace736972 100644
--- a/src/util/tests/dag_test.cpp
+++ b/src/util/tests/dag_test.cpp
@@ -56,6 +56,16 @@ struct node: public dag_node {
                    static_cast<struct dag_node *>(&child), 0);
       return child;
    }
+
+   void add_edge(struct node &child, uintptr_t data) {
+      dag_add_edge(static_cast<struct dag_node *>(this),
+                   static_cast<struct dag_node *>(&child), data);
+   }
+
+   void add_edge_max_data(struct node &child, uintptr_t data) {
+      dag_add_edge_max_data(static_cast<struct dag_node *>(this),
+                            static_cast<struct dag_node *>(&child), data);
+   }
 };
 
 static void output_cb(struct dag_node *dag_node, void *data)
@@ -151,6 +161,49 @@ TEST_F(dag_test, simple)
    TEST_CHECK();
 }
 
+TEST_F(dag_test, duplicate_edge)
+{
+   INIT_NODES(3);
+
+   node[0].add_edge(node[1], 0);
+   node[0].add_edge(node[1], 1);
+   node[0].add_edge(node[2], 0);
+
+   EXPECT_EQ(util_dynarray_num_elements(&node[0].edges, struct dag_edge), 3);
+
+   SET_EXPECTED(1, 2, 0);
+
+   dag_traverse_bottom_up(dag, output_cb, &actual);
+
+   TEST_CHECK();
+}
+
+TEST_F(dag_test, duplicate_edge_max_data)
+{
+   INIT_NODES(3);
+
+   node[0].add_edge_max_data(node[1], 0);
+   node[0].add_edge_max_data(node[1], 1);
+   node[0].add_edge_max_data(node[2], 0);
+
+   EXPECT_EQ(util_dynarray_num_elements(&node[0].edges, struct dag_edge), 2);
+
+   util_dynarray_foreach (&node[0].edges, struct dag_edge, edge) {
+      if (edge->child == &node[1]) {
+         EXPECT_EQ(edge->data, 1);
+      } else {
+         EXPECT_EQ(edge->child, &node[2]);
+         EXPECT_EQ(edge->data, 0);
+      }
+   }
+
+   SET_EXPECTED(1, 2, 0);
+
+   dag_traverse_bottom_up(dag, output_cb, &actual);
+
+   TEST_CHECK();
+}
+
 TEST_F(dag_test, simple_many_children)
 {
    INIT_NODES(6);



More information about the mesa-commit mailing list