Skip to content

Commit

Permalink
Flip dependency graph edges to have non-weakly-connected correctly vi…
Browse files Browse the repository at this point in the history
…sited
  • Loading branch information
mscuttari committed Nov 26, 2024
1 parent 737e523 commit 827ec8e
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 454 deletions.
10 changes: 7 additions & 3 deletions include/public/marco/Modeling/ArrayEquationsDependencyGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include <type_traits>

namespace marco::modeling {
/// Graph storing the dependencies between array equations.
/// An edge from equation A to equation B is created if the computations inside
/// A depends on B, meaning that B needs to be computed first. The order of
/// computations is therefore given by a post-order visit of the graph.
template <typename VariableProperty, typename EquationProperty,
typename Graph =
internal::dependency::SingleEntryWeaklyConnectedDigraph<
Expand Down Expand Up @@ -208,8 +212,8 @@ class ArrayEquationsDependencyGraph {

/// Explore the read accesses in order to determine the dependencies among the
/// equations. An equation e1 depends on another equation e2 if e1 reads (a
/// part) of a variable that is written by e2. In this case, an arc from e2
/// to e1 is inserted (meaning that e2 must be computed before e1).
/// part) of a variable that is written by e2. In this case, an arc from e1
/// to e2 is inserted (meaning that e1 needs the result of e2).
template <typename EquationsIt>
void addEdges(EquationsIt equationsBeginIt, EquationsIt equationsEndIt) {
std::mutex graphMutex;
Expand All @@ -234,7 +238,7 @@ class ArrayEquationsDependencyGraph {

if (writtenIndices.overlaps(readIndices)) {
std::lock_guard<std::mutex> edgeLockGuard(graphMutex);
graph->addEdge(writeInfo.getEquation(), equationDescriptor);
graph->addEdge(equationDescriptor, writeInfo.getEquation());
}
}
}
Expand Down
249 changes: 109 additions & 140 deletions include/public/marco/Modeling/SCC.h
Original file line number Diff line number Diff line change
@@ -1,153 +1,122 @@
#ifndef MARCO_MODELING_SCC_H
#define MARCO_MODELING_SCC_H

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>

namespace marco::modeling
{
namespace dependency
{
template<typename SCC>
struct SCCTraits
{
// Elements to provide:
//
// typedef ElementRef : the type of the elements composing the SCC, which should be cheap to copy.
//
// static std::vector<ElementRef> getElements(const SCC* scc);
// return the elements composing the SCC.
//
// static std::vector<ElementRef> getDependencies(const SCC* scc, ElementRef element);
// return the elements (which may belong to other SCCs) on which a given one depends on.

using Error = typename SCC::UnknownSCCTypeError;
};
namespace marco::modeling {
namespace dependency {
template <typename SCC>
struct SCCTraits {
// Elements to provide:
//
// typedef ElementRef : the type of the elements composing the SCC, which
// should be cheap to copy.
//
// static std::vector<ElementRef> getElements(const SCC* scc);
// return the elements composing the SCC.
//
// static std::vector<ElementRef> getDependencies(const SCC* scc, ElementRef
// element);
// return the elements (which may belong to other SCCs) on which a given
// one depends on.

using Error = typename SCC::UnknownSCCTypeError;
};
} // namespace dependency

namespace internal::dependency {
/// List of the equations composing an SCC.
/// All the equations belong to a given graph.
template <typename Graph>
class SCC {
public:
using ElementDescriptor = typename Graph::VertexDescriptor;

private:
using Property = typename Graph::VertexProperty;
using Container = llvm::SmallVector<ElementDescriptor>;

public:
using iterator = typename Container::iterator;
using const_iterator = typename Container::const_iterator;

private:
const Graph *graph;
Container equations;

public:
template <typename It>
SCC(const Graph &graph, It equationsBegin, It equationsEnd)
: graph(&graph), equations(equationsBegin, equationsEnd) {}

const Graph &getGraph() const {
assert(graph != nullptr);
return *graph;
}

/// Get the number of equations composing the SCC.
[[nodiscard]] size_t size() const { return equations.size(); }

const Property &operator[](size_t index) const {
assert(index < equations.size());
return (*this)[equations[index]];
}

namespace internal::dependency
{
/// List of the equations composing an SCC.
/// All the equations belong to a given graph.
template<typename Graph>
class SCC
{
public:
using ElementDescriptor = typename Graph::VertexDescriptor;

private:
using Property = typename Graph::VertexProperty;
using Container = llvm::SmallVector<ElementDescriptor>;

public:
using iterator = typename Container::iterator;
using const_iterator = typename Container::const_iterator;

private:
const Graph* graph;
Container equations;

public:
template<typename It>
SCC(const Graph& graph, It equationsBegin, It equationsEnd)
: graph(&graph), equations(equationsBegin, equationsEnd)
{
}

const Graph& getGraph() const
{
assert(graph != nullptr);
return *graph;
}

/// Get the number of equations composing the SCC.
[[nodiscard]] size_t size() const
{
return equations.size();
}

const Property& operator[](size_t index) const
{
assert(index < equations.size());
return (*this)[equations[index]];
}

/// @name Forwarded methods
/// {

const Property& operator[](ElementDescriptor descriptor) const
{
return (*graph)[descriptor];
}

/// }
/// @name Iterators
/// {

iterator begin()
{
return equations.begin();
}

const_iterator begin() const
{
return equations.begin();
}

iterator end()
{
return equations.end();
}

const_iterator end() const
{
return equations.end();
}

/// }
};
/// @name Forwarded methods
/// {

const Property &operator[](ElementDescriptor descriptor) const {
return (*graph)[descriptor];
}

/// }
/// @name Iterators
/// {

iterator begin() { return equations.begin(); }

const_iterator begin() const { return equations.begin(); }

iterator end() { return equations.end(); }

const_iterator end() const { return equations.end(); }

/// }
};
} // namespace internal::dependency

namespace dependency {
// Traits specialization for the internal SCC class.
template <typename Graph>
class SCCTraits<internal::dependency::SCC<Graph>> {
private:
using Impl = internal::dependency::SCC<Graph>;

public:
using ElementRef = typename Impl::ElementDescriptor;

static std::vector<ElementRef> getElements(const Impl *SCC) {
std::vector<ElementRef> result(SCC->begin(), SCC->end());
return result;
}

namespace dependency
{
// Traits specialization for the internal SCC class.
template<typename Graph>
class SCCTraits<internal::dependency::SCC<Graph>>
{
private:
using Impl = internal::dependency::SCC<Graph>;

public:
using ElementRef = typename Impl::ElementDescriptor;

static std::vector<ElementRef> getElements(const Impl* SCC)
{
std::vector<ElementRef> result(SCC->begin(), SCC->end());
return result;
}

static std::vector<ElementRef> getDependencies(
const Impl* SCC, ElementRef element)
{
std::vector<ElementRef> result;
const auto& graph = SCC->getGraph();

for (ElementRef otherElement : llvm::make_range(
graph.verticesBegin(), graph.verticesEnd())) {
for (ElementRef connectedElement : llvm::make_range(
graph.linkedVerticesBegin(otherElement),
graph.linkedVerticesEnd(otherElement))) {
if (connectedElement == element) {
result.push_back(connectedElement);
}
}
}

return result;
}
};
static std::vector<ElementRef> getDependencies(const Impl *SCC,
ElementRef element) {
std::vector<ElementRef> result;
const auto &graph = SCC->getGraph();

for (ElementRef connectedElement :
llvm::make_range(graph.linkedVerticesBegin(element),
graph.linkedVerticesEnd(element))) {
result.push_back(connectedElement);
}

return result;
}
}
};
} // namespace dependency
} // namespace marco::modeling

#endif // MARCO_MODELING_SCC_H
Loading

0 comments on commit 827ec8e

Please sign in to comment.