CIRCT  19.0.0git
DependenceIterator.h
Go to the documentation of this file.
1 //===- DependenceIterator.h - Uniform handling of dependences ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines utilities to let algorithms iterate over different flavors
10 // of dependences in a uniform way.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef CIRCT_SCHEDULING_DEPENDENCEITERATOR_H
15 #define CIRCT_SCHEDULING_DEPENDENCEITERATOR_H
16 
17 #include "circt/Support/LLVM.h"
18 
19 #include "llvm/ADT/DenseMapInfo.h"
20 #include "llvm/ADT/SetVector.h"
21 #include "llvm/ADT/iterator.h"
22 
23 #include <optional>
24 
25 namespace circt {
26 namespace scheduling {
27 
28 class Problem;
29 
30 namespace detail {
31 
32 /// A wrapper class to uniformly handle def-use and auxiliary dependence edges.
33 /// Should be small enough (two pointers) to be passed around by value.
34 class Dependence {
35 public:
36  /// The "expanded" representation of a dependence, intended as the key for
37  /// comparisons and hashing.
38  using TupleRepr =
39  std::tuple<Operation *, Operation *, std::optional<unsigned>,
40  std::optional<unsigned>>;
41 
42  /// Wrap a def-use dependence, which is uniquely identified in the SSA graph
43  /// by an `OpOperand`.
44  Dependence(OpOperand *defUseDep) : auxSrc(nullptr), defUse(defUseDep) {}
45  /// Wrap an auxiliary dependence, identified by the pair of its endpoints.
46  Dependence(std::pair<Operation *, Operation *> auxDep)
47  : auxSrc(std::get<0>(auxDep)), auxDst(std::get<1>(auxDep)) {}
48  /// Wrap an auxiliary dependence between \p from and \p to.
49  Dependence(Operation *from, Operation *to) : auxSrc(from), auxDst(to) {}
50  /// Construct an invalid dependence.
51  Dependence() : auxSrc(nullptr), auxDst(nullptr) {}
52 
53  /// Return true if this is a valid auxiliary dependence.
54  bool isAuxiliary() const { return auxSrc && auxDst; }
55  /// Return true if this is a valid def-use dependence.
56  bool isDefUse() const { return !auxSrc && auxDst; }
57  /// Return true if this is an invalid dependence.
58  bool isInvalid() const { return !auxDst; }
59 
60  /// Return the source of the dependence.
61  Operation *getSource() const;
62  /// Return the destination of the dependence.
63  Operation *getDestination() const;
64 
65  /// Return the source operation's result number, if applicable.
66  std::optional<unsigned> getSourceIndex() const;
67  /// Return the destination operation's operand number, if applicable.
68  std::optional<unsigned> getDestinationIndex() const;
69 
70  /// Return the tuple representation of this dependence.
71  TupleRepr getAsTuple() const;
72 
73  bool operator==(const Dependence &other) const;
74 
75 private:
76  Operation *auxSrc;
77  union {
78  Operation *auxDst;
79  OpOperand *defUse;
80  };
81 };
82 
83 /// An iterator to transparently surface an operation's def-use dependences from
84 /// the SSA subgraph (induced by the registered operations), as well as
85 /// auxiliary, operation-to-operation dependences explicitly provided by the
86 /// client.
88  : public llvm::iterator_facade_base<DependenceIterator,
89  std::forward_iterator_tag, Dependence> {
90 public:
91  /// Construct an iterator over the \p op's def-use dependences (i.e. result
92  /// values of other operations registered in the scheduling problem, which are
93  /// used by one of \p op's operands), and over auxiliary dependences (i.e.
94  /// from other operation to \p op).
95  DependenceIterator(Problem &problem, Operation *op, bool end = false);
96 
97  bool operator==(const DependenceIterator &other) const {
98  return dep == other.dep;
99  }
100 
101  const Dependence &operator*() const { return dep; }
102 
105  return *this;
106  }
107 
108 private:
109  void findNextDependence();
110 
112  Operation *op;
113 
114  unsigned operandIdx;
115  unsigned auxPredIdx;
116  llvm::SmallSetVector<Operation *, 4> *auxPreds;
117 
119 };
120 
121 } // namespace detail
122 } // namespace scheduling
123 } // namespace circt
124 
125 namespace llvm {
126 
128 
129 template <>
130 struct DenseMapInfo<Dependence> {
131  static inline Dependence getEmptyKey() {
132  return Dependence(DenseMapInfo<mlir::Operation *>::getEmptyKey(), nullptr);
133  }
134  static inline Dependence getTombstoneKey() {
135  return Dependence(DenseMapInfo<mlir::Operation *>::getTombstoneKey(),
136  nullptr);
137  }
138  static unsigned getHashValue(const Dependence &val) {
139  return llvm::hash_value(val.getAsTuple());
140  }
141  static bool isEqual(const Dependence &lhs, const Dependence &rhs) {
142  return lhs == rhs;
143  }
144 };
145 
146 } // namespace llvm
147 
148 #endif // CIRCT_SCHEDULING_DEPENDENCEITERATOR_H
Problem::Dependence Dependence
This class models the most basic scheduling problem.
Definition: Problems.h:87
An iterator to transparently surface an operation's def-use dependences from the SSA subgraph (induce...
bool operator==(const DependenceIterator &other) const
llvm::SmallSetVector< Operation *, 4 > * auxPreds
DependenceIterator(Problem &problem, Operation *op, bool end=false)
Construct an iterator over the op's def-use dependences (i.e.
Definition: Problems.cpp:480
A wrapper class to uniformly handle def-use and auxiliary dependence edges.
bool isInvalid() const
Return true if this is an invalid dependence.
std::tuple< Operation *, Operation *, std::optional< unsigned >, std::optional< unsigned > > TupleRepr
The "expanded" representation of a dependence, intended as the key for comparisons and hashing.
bool operator==(const Dependence &other) const
Definition: Problems.cpp:472
std::optional< unsigned > getDestinationIndex() const
Return the destination operation's operand number, if applicable.
Definition: Problems.cpp:461
std::optional< unsigned > getSourceIndex() const
Return the source operation's result number, if applicable.
Definition: Problems.cpp:453
Operation * getDestination() const
Return the destination of the dependence.
Definition: Problems.cpp:449
bool isAuxiliary() const
Return true if this is a valid auxiliary dependence.
TupleRepr getAsTuple() const
Return the tuple representation of this dependence.
Definition: Problems.cpp:467
Dependence(std::pair< Operation *, Operation * > auxDep)
Wrap an auxiliary dependence, identified by the pair of its endpoints.
bool isDefUse() const
Return true if this is a valid def-use dependence.
Operation * getSource() const
Return the source of the dependence.
Definition: Problems.cpp:445
Dependence()
Construct an invalid dependence.
Dependence(OpOperand *defUseDep)
Wrap a def-use dependence, which is uniquely identified in the SSA graph by an OpOperand.
Dependence(Operation *from, Operation *to)
Wrap an auxiliary dependence between from and to.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
llvm::hash_code hash_value(const BundledChannel channel)
Definition: ESITypes.h:48
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
static unsigned getHashValue(const Dependence &val)
static bool isEqual(const Dependence &lhs, const Dependence &rhs)