https://hal.archives-ouvertes.fr/hal-03445821
dag.h
/*
Copyright Universite de Versailles Saint-Quentin en Yvelines 2009
AUTHORS: Sebastien Briais, Sid Touati
This file is part of GDD.
GDD is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
GDD is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with GDD. If not, see
<http://www.gnu.org/licenses/>.
*/
#ifndef __GDD_DAG_H
#define __GDD_DAG_H
/** \file dag.h
\brief Data Dependency Acyclic Graphs */
#include "opcode.h"
#include "ddg.h"
#include <SCEDA/list.h>
#include <SCEDA/graph.h>
#include <SCEDA/hashmap.h>
/** Type of DAGs (acyclic DDGs) */
typedef struct {
SCEDA_Graph *g;
SCEDA_Graph *gf;
SCEDA_HashMap *g_to_gf;
} GDD_DAG;
/** Create a new GDD_DAG.
@param[in] g = underlying DDG (must be acyclic)
@return a GDD_DAG or NULL if g is not acyclic */
GDD_DAG *GDD_dag_create(SCEDA_Graph *g);
/** Delete a GDD_DAG.
@param[in] dag = GDD_DAG to delete
The underlying graph is not deleted. */
void GDD_dag_delete(GDD_DAG *dag);
/** Updates the precomputed values. This should be called if the underlying DDG
structure change.
@param[in] dag = GDD_DAG to update */
void GDD_dag_update(GDD_DAG *dag);
/** Get the graph of a GDD_DAG.
@param[in] dag = GDD_DAG
@return the associated DAG
\hideinitializer */
#define GDD_dag_get_ddg(dag) ((dag)->g)
/** Test whether there is a path from v1 to v2, where v1 and v2 are
two vertices of the underlying DAG.
@param[in] dag = GDD_DAG
@param[in] v1 = first vertex
@param[in] v2 = second vertex
@return TRUE iff there is a path from v1 to v2 */
int GDD_dag_lt(GDD_DAG *dag, SCEDA_Vertex *v1, SCEDA_Vertex *v2);
/** Test whether the two given vertices (of the underlying DAG) are
parallel.
@param[in] dag = GDD_DAG
@param[in] v1 = first vertex
@param[in] v2 = second vertex
@return TRUE iff the two vertices are parallel */
int GDD_dag_parallel(GDD_DAG *dag, SCEDA_Vertex *v1, SCEDA_Vertex *v2);
/* Set GDD_DAG_PRECALC to FALSE to disable usage of precomputed data
(slower but cheaper regarding memory usage) */
#define GDD_DAG_PRECALC 1
#if(GDD_DAG_PRECALC)
/** Iterator over the UpSet of a vertex (of the underlying DAG).
The upset is the set of vertices reachable from the given vertex. */
typedef SCEDA_VertexSuccIterator GDD_DAG_UpsetIterator;
/** Initialise an upset iterator.
@param[in] dag = GDD_DAG
@param[in] v = vertex
@param[in] iter = iterator */
void GDD_dag_upset_iterator_init(GDD_DAG *dag, SCEDA_Vertex *v, GDD_DAG_UpsetIterator *iter);
/** Is there a next vertex in the iterator?
\hideinitializer */
#define GDD_dag_upset_iterator_has_next SCEDA_vertex_succ_iterator_has_next
/** Get the next vertex in the iterator.
@param[in] iter = iterator
@return the next (reachable) vertex */
#define GDD_dag_upset_iterator_next(iter$) (SCEDA_vertex_get_data(SCEDA_Vertex *, SCEDA_vertex_succ_iterator_next(iter$)))
/** Clean up an (upset) iterator.
\hideinitializer */
#define GDD_dag_upset_iterator_cleanup SCEDA_vertex_succ_iterator_cleanup
#else
#include <SCEDA/graph_traversal.h>
typedef SCEDA_BFSIterator GDD_DAG_UpsetIterator;
#define GDD_dag_upset_iterator_init(ddg$, v$, iter$) \
({ \
SCEDA_bfs_iterator_init(v$, iter$); \
SCEDA_bfs_iterator_next(iter$); })
#define GDD_dag_upset_iterator_has_next SCEDA_bfs_iterator_has_next
#define GDD_dag_upset_iterator_next SCEDA_bfs_iterator_next
#define GDD_dag_upset_iterator_cleanup SCEDA_bfs_iterator_cleanup
#endif
#endif
/** \page dag Data Dependency Acyclic Graphs
\section dag_intro Introduction
Acyclic DDG are of particular interest: GDD_DAG structure offer new
functions that operate on an acyclic DDG.
A GDD_DAG is based on a DDG.
If \f$v, w\f$ are two vertices of an acyclic DDG, we write \f$v <
w\f$ if there exists a path from \f$v\f$ to \f$w\f$ in the DDG (ie
there exists a path \f$v_0 v_1 \ldots v_n\f$ with \f$v = v_0\f$
and \f$w = v_n\f$ in the DDG). If neither \f$v < w\f$ nor \f$w <
v\f$, we write \f$v \parallel w\f$ and say that \f$v\f$ and
\f$w\f$ are parallel.
The upset of a vertex \f$v\f$ is the set \f$\mathop{U}(v) = \{ w
\mid v < w \wedge v \neq w \}\f$: it is the set of vertices
reachable from v in the underlying DDG.
\section dag_api API
\code
GDD_DAG *GDD_dag_create(SCEDA_Graph *g);
\endcode
Create a GDD_DAG, corresponding the given graph. It fails if g is not
acyclic.
\code
void GDD_dag_delete(GDD_DAG *dag);
\endcode
Delete a GDD_DAG (but not its associated graph).
\code
void GDD_dag_update(GDD_DAG *dag);
\endcode
Update internal structure of a GDD_DAG, reflecting changes to the DDG
upon which it is based.
\code
SCEDA_Graph *GDD_dag_get_ddg(GDD_DAG *dag);
\endcode
Return the underlying DDG.
\code
int GDD_dag_lt(SCEDA_Vertex *v1, SCEDA_Vertex *v2);
\endcode
Test whether there is a path from GDD vertex v1 to GDD vertex v2
in the underlying GDD, ie perform the test \f$v_1 < v_2\f$.
\code
int GDD_dag_parallel(SCEDA_Vertex *v1, SCEDA_Vertex *v2);
\endcode
Return TRUE iff there is no path from v1 to v2 and no path from v2
to v1 in the underlying GDD, ie perform the test \f$v_1 \parallel
v_2\f$.
\code
void GDD_dag_upset_iterator_init(GDD_DAG *dag, SCEDA_Vertex *v, GDD_DAG_UpsetIterator *iter);
int GDD_dag_upset_iterator_has_next(GDD_DAG_UpsetIterator *iter);
SCEDA_Vertex *GDD_dag_upset_iterator_next(GDD_DAG_UpsetIterator *iter);
void GDD_dag_upset_iterator_cleanup(GDD_DAG_UpsetIterator *iter);
\endcode
Iterator over the upset of a vertex, ie the set \f$\mathop{U}(v)\f$.
\section dag_example Example
\include "dag/main.c"
*/