1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
18 //------------------------------------------------------------------------
19 // LIR::Flags: Defines the set of flags that may appear in the
20 // GenTree::gtLIRFlags field.
23 // Disallow the creation of values of this type.
31 Mark = 0x01, // An aribtrary "mark" bit that can be used in place of
32 // a more expensive data structure when processing a set
33 // of LIR nodes. See for example `LIR::GetTreeRange`.
35 UnusedValue = 0x02, // Set on a node if it produces a value that is not
36 // subsequently used. Should never be set on nodes
37 // that return `false` for `GenTree::IsValue`. Note
38 // that this bit should not be assumed to be valid
39 // at all points during compilation: it is currently
40 // only computed during target-dependent lowering.
42 RegOptional = 0x04, // Set on a node if it produces a value, but does not
43 // require a register (i.e. it can be used from memory).
47 //------------------------------------------------------------------------
48 // LIR::Use: Represents a use <-> def edge between two nodes in a range
49 // of LIR. Provides utilities to point the use to a different
50 // def. Note that because this type deals in edges between
51 // nodes, it represents the single use of the def.
62 Use(const Use& other);
63 Use(Range& range, GenTree** edge, GenTree* user);
65 Use& operator=(const Use& other);
66 Use& operator=(Use&& other);
68 static Use GetDummyUse(Range& range, GenTree* node);
71 GenTree* User() const;
73 bool IsInitialized() const;
74 void AssertIsValid() const;
75 bool IsDummyUse() const;
77 void ReplaceWith(Compiler* compiler, GenTree* replacement);
78 unsigned ReplaceWithLclVar(Compiler* compiler, unsigned blockWeight, unsigned lclNum = BAD_VAR_NUM);
81 //------------------------------------------------------------------------
82 // LIR::ReadOnlyRange:
84 // Represents a contiguous range of LIR nodes that may be a subrange of
85 // a containing range. Provides a small set of utilities for iteration.
86 // Instances of this type are primarily created by and provided to
87 // analysis and utility methods on LIR::Range.
89 // Although some pains have been taken to help guard against the existence
90 // of invalid subranges, it remains possible to create them. For example,
91 // consider the following:
93 // // View the block as a range
94 // LIR::Range& blockRange = LIR::AsRange(block);
96 // // Create a range from the first non-phi node in the block to the
97 // // last node in the block
98 // LIR::ReadOnlyRange nonPhis = blockRange.NonPhiNodes();
100 // // Remove the last node from the block
101 // blockRange.Remove(blockRange.LastNode());
103 // After the removal of the last node in the block, the last node of
104 // nonPhis is no longer linked to any of the other nodes in nonPhis. Due
105 // to issues such as the above, some care must be taken in order to
106 // ensure that ranges are not used once they have been invalidated.
112 friend struct BasicBlock;
115 GenTree* m_firstNode;
118 ReadOnlyRange(const ReadOnlyRange& other) = delete;
119 ReadOnlyRange& operator=(const ReadOnlyRange& other) = delete;
122 ReadOnlyRange(GenTree* firstNode, GenTree* lastNode);
126 friend class ReadOnlyRange;
130 Iterator(GenTree* begin) : m_node(begin)
135 Iterator() : m_node(nullptr)
139 inline GenTree* operator*()
144 inline GenTree* operator->()
149 inline bool operator==(const Iterator& other) const
151 return m_node == other.m_node;
154 inline bool operator!=(const Iterator& other) const
156 return m_node != other.m_node;
159 inline Iterator& operator++()
161 m_node = (m_node == nullptr) ? nullptr : m_node->gtNext;
166 class ReverseIterator
168 friend class ReadOnlyRange;
172 ReverseIterator(GenTree* begin) : m_node(begin)
177 ReverseIterator() : m_node(nullptr)
181 inline GenTree* operator*()
186 inline GenTree* operator->()
191 inline bool operator==(const ReverseIterator& other) const
193 return m_node == other.m_node;
196 inline bool operator!=(const ReverseIterator& other) const
198 return m_node != other.m_node;
201 inline ReverseIterator& operator++()
203 m_node = (m_node == nullptr) ? nullptr : m_node->gtPrev;
209 ReadOnlyRange(ReadOnlyRange&& other);
211 GenTree* FirstNode() const;
212 GenTree* LastNode() const;
214 bool IsEmpty() const;
216 Iterator begin() const;
217 Iterator end() const;
219 ReverseIterator rbegin() const;
220 ReverseIterator rend() const;
223 bool Contains(GenTree* node) const;
227 //------------------------------------------------------------------------
230 // Represents a contiguous range of LIR nodes. Provides a variety of
231 // variety of utilites that modify the LIR contained in the range. Unlike
232 // `ReadOnlyRange`, values of this type may be edited.
234 // Because it is not a final class, it is possible to slice values of this
235 // type; this is especially dangerous when the Range value is actually of
236 // type `BasicBlock`. As a result, this type is not copyable and it is
237 // not possible to view a `BasicBlock` as anything other than a `Range&`.
239 class Range : public ReadOnlyRange
242 friend struct BasicBlock;
243 friend class Rationalizer;
246 Range(GenTree* firstNode, GenTree* lastNode);
248 Range(const Range& other) = delete;
249 Range& operator=(const Range& other) = delete;
251 ReadOnlyRange GetMarkedRange(unsigned markCount, GenTree* start, bool* isClosed, unsigned* sideEffects) const;
253 void FinishInsertBefore(GenTree* insertionPoint, GenTree* first, GenTree* last);
254 void FinishInsertAfter(GenTree* insertionPoint, GenTree* first, GenTree* last);
258 Range(Range&& other);
260 GenTree* LastPhiNode() const;
261 GenTree* FirstNonPhiNode() const;
262 GenTree* FirstNonPhiOrCatchArgNode() const;
264 ReadOnlyRange PhiNodes() const;
265 ReadOnlyRange NonPhiNodes() const;
267 void InsertBefore(GenTree* insertionPoint, GenTree* node);
268 void InsertAfter(GenTree* insertionPoint, GenTree* node);
270 void InsertBefore(GenTree* insertionPoint, GenTree* node1, GenTree* node2);
271 void InsertBefore(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3);
272 void InsertBefore(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3, GenTree* node4);
274 void InsertAfter(GenTree* insertionPoint, GenTree* node1, GenTree* node2);
275 void InsertAfter(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3);
276 void InsertAfter(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3, GenTree* node4);
278 void InsertBefore(GenTree* insertionPoint, Range&& range);
279 void InsertAfter(GenTree* insertionPoint, Range&& range);
281 void InsertAtBeginning(GenTree* node);
282 void InsertAtEnd(GenTree* node);
284 void InsertAtBeginning(Range&& range);
285 void InsertAtEnd(Range&& range);
287 void Remove(GenTree* node, bool markOperandsUnused = false);
288 Range Remove(GenTree* firstNode, GenTree* lastNode);
289 Range Remove(ReadOnlyRange&& range);
291 void Delete(Compiler* compiler, BasicBlock* block, GenTree* node);
292 void Delete(Compiler* compiler, BasicBlock* block, GenTree* firstNode, GenTree* lastNode);
293 void Delete(Compiler* compiler, BasicBlock* block, ReadOnlyRange&& range);
295 bool TryGetUse(GenTree* node, Use* use);
297 ReadOnlyRange GetTreeRange(GenTree* root, bool* isClosed) const;
298 ReadOnlyRange GetTreeRange(GenTree* root, bool* isClosed, unsigned* sideEffects) const;
299 ReadOnlyRange GetRangeOfOperandTrees(GenTree* root, bool* isClosed, unsigned* sideEffects) const;
302 bool CheckLIR(Compiler* compiler, bool checkUnusedValues = false) const;
307 static Range& AsRange(BasicBlock* block);
309 static Range EmptyRange();
310 static Range SeqTree(Compiler* compiler, GenTree* tree);
312 static void InsertBeforeTerminator(BasicBlock* block, LIR::Range&& range);
315 inline void GenTree::SetUnusedValue()
317 gtLIRFlags |= LIR::Flags::UnusedValue;
318 #ifndef LEGACY_BACKEND
323 inline void GenTree::ClearUnusedValue()
325 gtLIRFlags &= ~LIR::Flags::UnusedValue;
328 inline bool GenTree::IsUnusedValue() const
330 return (gtLIRFlags & LIR::Flags::UnusedValue) != 0;
333 inline void GenTree::SetRegOptional()
335 gtLIRFlags |= LIR::Flags::RegOptional;
338 inline void GenTree::ClearRegOptional()
340 gtLIRFlags &= ~LIR::Flags::RegOptional;
343 inline bool GenTree::IsRegOptional() const
345 return (gtLIRFlags & LIR::Flags::RegOptional) != 0;