1/**
2 * Copyright (c) Glow Contributors. See CONTRIBUTORS file.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef GLOW_IR_IRUTILS_H
17#define GLOW_IR_IRUTILS_H
18
19#include "glow/IR/IR.h"
20#include "glow/IR/Instrs.h"
21
22#include <iterator>
23
24namespace glow {
25
26/// \returns true if the value \v is a tensor view.
27bool isTensorView(Value *v);
28
29/// \returns the offset for \p TVI into the underlying alloc activation.
30size_t calculateTensorViewOffset(const TensorViewInst *TVI);
31
32/// A helper class to iterate over all uses of a given Value.
33/// It also recursively iterates over uses of any tensorview
34/// instructions aliasing this value.
35/// Iteration is performed by means of const iterators.
36class ValueUses {
37 /// The value whose uses are to be iterated over.
38 const Value *v_;
39
40public:
41 /// The actual iterator implementation.
42 template <bool is_const_iter = true>
43 class ValueUsesIterator
44 : public std::iterator<
45 std::forward_iterator_tag,
46 typename std::conditional<is_const_iter, const Use, Use>::type> {
47 friend ValueUses;
48 using BASE = std::iterator<
49 std::forward_iterator_tag,
50 typename std::conditional<is_const_iter, const Use, Use>::type>;
51 using reference = typename BASE::reference;
52 using UseList = std::list<Use>;
53 using value =
54 typename std::conditional<is_const_iter, const Value, Value>::type;
55 using iterator =
56 typename std::conditional<is_const_iter, UseList::const_iterator,
57 UseList::iterator>::type;
58
59 private:
60 /// Set of values to iterate over. It includes the original value and
61 /// eventually any tensor views directly or indirectly based on it.
62 llvm::SmallVector<value *, 4> vals_;
63 /// Current iterator.
64 iterator it_;
65 /// End of the use-list for the current value.
66 iterator end_;
67 /// Index of the value whose use-list is being iterated.
68 int idx_;
69
70 /// This constructor is used to create the begin iterator.
71 ValueUsesIterator(value *v)
72 : vals_{v}, it_(v->getUsers().begin()), end_(v->getUsers().end()),
73 idx_(v->getUsers().begin() == v->getUsers().end() ? -1 : 0) {}
74
75 /// This constructor is used to create the end iterator.
76 ValueUsesIterator(value *v, int)
77 : vals_{v}, it_(v->getUsers().end()), end_(v->getUsers().end()),
78 idx_(-1) {}
79
80 public:
81 ValueUsesIterator &operator++() {
82 if (it_ == end_) {
83 llvm_unreachable("Cannot increment the end iterator");
84 }
85 ++it_;
86 if (it_ != end_)
87 return *this;
88 for (; it_ == end_;) {
89 // Reached the end of uses for the current value.
90 // Try to iterate over another value if available.
91 if (++idx_ >= (int)vals_.size()) {
92 // Form the end iterator.
93 *this = ValueUsesIterator{vals_[0], 1};
94 return *this;
95 }
96 it_ = vals_[idx_]->getUsers().begin();
97 end_ = vals_[idx_]->getUsers().end();
98 }
99 return *this;
100 }
101
102 reference operator*() {
103 if (it_ == end_) {
104 llvm_unreachable("An attempt to dereference the end iterator");
105 }
106 // If it is a tensorview instruction, add it is the set of
107 // values to be procssed, because all uses of a tensorview
108 // are considered to be uses of the tensorview's original
109 // allocation.
110 if (isTensorView(it_->get()) && vals_.back() != it_->get()) {
111 vals_.push_back(it_->get());
112 }
113 return *it_;
114 }
115
116 bool operator!=(const ValueUsesIterator &Other) const {
117 return idx_ != Other.idx_ || it_ != Other.it_ || end_ != Other.end_ ||
118 vals_ != Other.vals_;
119 }
120 };
121
122 using const_iterator = ValueUsesIterator<true>;
123
124 ValueUses(const Value *v) : v_(v) {}
125 ValueUses(ValueUses &VU) = default;
126 const_iterator begin() const { return const_iterator{v_}; }
127 const_iterator end() const { return const_iterator{v_, 1}; }
128};
129
130/// Get the allocation corrsponding to th value \p V. It can look through
131/// tensorview instructions. \returns found allocation or nullptr.
132Value *getAllocationOrigin(Value *V);
133
134/// \returns peels off the layers of tensorviews from a value \p V.
135Value *getOrigin(Value *V);
136
137/// \returns the offset into the Value returned by getOrigin.
138size_t getOriginOffset(Value *V);
139
140/// \returns peels off the layers of tensorviews from a value \p V.
141const Value *getOrigin(const Value *V);
142} // namespace glow
143
144#endif // GLOW_IR_IRUTILS_H
145