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.
7 #include "sideeffects.h"
13 LIR::Use::Use() : m_range(nullptr), m_edge(nullptr), m_user(nullptr)
17 LIR::Use::Use(const Use& other)
22 //------------------------------------------------------------------------
23 // LIR::Use::Use: Constructs a use <-> def edge given the range that
24 // contains the use and the def, the use -> def edge, and
28 // range - The range that contains the use and the def.
29 // edge - The use -> def edge.
30 // user - The node that uses the def.
34 LIR::Use::Use(Range& range, GenTree** edge, GenTree* user) : m_range(&range), m_edge(edge), m_user(user)
39 LIR::Use& LIR::Use::operator=(const Use& other)
41 m_range = other.m_range;
42 m_user = other.m_user;
43 m_edge = other.IsDummyUse() ? &m_user : other.m_edge;
45 assert(IsDummyUse() == other.IsDummyUse());
49 LIR::Use& LIR::Use::operator=(Use&& other)
55 //------------------------------------------------------------------------
56 // LIR::Use::GetDummyUse: Returns a dummy use for a node.
58 // This method is provided as a convenience to allow transforms to work
59 // uniformly over Use values. It allows the creation of a Use given a node
63 // range - The range that contains the node.
64 // node - The node for which to create a dummy use.
68 LIR::Use LIR::Use::GetDummyUse(Range& range, GenTree* node)
70 assert(node != nullptr);
73 dummyUse.m_range = ⦥
74 dummyUse.m_user = node;
75 dummyUse.m_edge = &dummyUse.m_user;
77 assert(dummyUse.IsInitialized());
81 //------------------------------------------------------------------------
82 // LIR::Use::IsDummyUse: Indicates whether or not a use is a dummy use.
84 // This method must be called before attempting to call the User() method
85 // below: for dummy uses, the user is the same node as the def.
87 // Return Value: true if this use is a dummy use; false otherwise.
89 bool LIR::Use::IsDummyUse() const
91 return m_edge == &m_user;
94 //------------------------------------------------------------------------
95 // LIR::Use::Def: Returns the node that produces the def for this use.
97 GenTree* LIR::Use::Def() const
99 assert(IsInitialized());
104 //------------------------------------------------------------------------
105 // LIR::Use::User: Returns the node that uses the def for this use.
107 GenTree* LIR::Use::User() const
109 assert(IsInitialized());
110 assert(!IsDummyUse());
115 //------------------------------------------------------------------------
116 // LIR::Use::IsInitialized: Returns true if the use is minimally valid; false otherwise.
118 bool LIR::Use::IsInitialized() const
120 return (m_range != nullptr) && (m_user != nullptr) && (m_edge != nullptr);
123 //------------------------------------------------------------------------
124 // LIR::Use::AssertIsValid: DEBUG function to assert on many validity conditions.
126 void LIR::Use::AssertIsValid() const
128 assert(IsInitialized());
129 assert(m_range->Contains(m_user));
130 assert(Def() != nullptr);
132 GenTree** useEdge = nullptr;
133 assert(m_user->TryGetUse(Def(), &useEdge));
134 assert(useEdge == m_edge);
137 //------------------------------------------------------------------------
138 // LIR::Use::ReplaceWith: Changes the use to point to a new value.
140 // For example, given the following LIR:
142 // t15 = lclVar int arg1
143 // t16 = lclVar int arg1
152 // If we wanted to replace the use of t17 with a use of the constant "1", we
153 // might do the following (where `opEq` is a `Use` value that represents the
156 // GenTree* constantOne = compiler->gtNewIconNode(1);
157 // range.InsertAfter(opEq.Def(), constantOne);
158 // opEq.ReplaceWith(compiler, constantOne);
160 // Which would produce something like the following LIR:
162 // t15 = lclVar int arg1
163 // t16 = lclVar int arg1
174 // Elminating the now-dead compare and its operands using `LIR::Range::Remove`
175 // would then give us:
183 // compiler - The Compiler context.
184 // replacement - The replacement node.
186 void LIR::Use::ReplaceWith(Compiler* compiler, GenTree* replacement)
188 assert(IsInitialized());
189 assert(compiler != nullptr);
190 assert(replacement != nullptr);
191 assert(IsDummyUse() || m_range->Contains(m_user));
192 assert(m_range->Contains(replacement));
196 m_user->ReplaceOperand(m_edge, replacement);
200 *m_edge = replacement;
204 //------------------------------------------------------------------------
205 // LIR::Use::ReplaceWithLclVar: Assigns the def for this use to a local
206 // var and points the use to a use of that
207 // local var. If no local number is provided,
208 // creates a new local var.
210 // For example, given the following IR:
212 // t15 = lclVar int arg1
213 // t16 = lclVar int arg1
222 // If we wanted to replace the use of t17 with a use of a new local var
223 // that holds the value represented by t17, we might do the following
224 // (where `opEq` is a `Use` value that represents the use of t17):
226 // opEq.ReplaceUseWithLclVar(compiler, block->getBBWeight(compiler));
228 // This would produce the following LIR:
230 // t15 = lclVar int arg1
231 // t16 = lclVar int arg1
238 // * st.lclVar int tmp0
240 // t18 = lclVar int tmp0
246 // compiler - The Compiler context.
247 // blockWeight - The weight of the basic block that contains the use.
248 // lclNum - The local to use for temporary storage. If BAD_VAR_NUM (the
249 // default) is provided, this method will create and use a new
252 // Return Value: The number of the local var used for temporary storage.
254 unsigned LIR::Use::ReplaceWithLclVar(Compiler* compiler, unsigned blockWeight, unsigned lclNum)
256 assert(IsInitialized());
257 assert(compiler != nullptr);
258 assert(m_range->Contains(m_user));
259 assert(m_range->Contains(*m_edge));
261 GenTree* const node = *m_edge;
263 if (lclNum == BAD_VAR_NUM)
265 lclNum = compiler->lvaGrabTemp(true DEBUGARG("ReplaceWithLclVar is creating a new local variable"));
268 // Increment its lvRefCnt and lvRefCntWtd twice, one for the def and one for the use
269 compiler->lvaTable[lclNum].incRefCnts(blockWeight, compiler);
270 compiler->lvaTable[lclNum].incRefCnts(blockWeight, compiler);
272 GenTreeLclVar* const store = compiler->gtNewTempAssign(lclNum, node)->AsLclVar();
273 assert(store != nullptr);
274 assert(store->gtOp1 == node);
276 GenTree* const load =
277 new (compiler, GT_LCL_VAR) GenTreeLclVar(store->TypeGet(), store->AsLclVarCommon()->GetLclNum(), BAD_IL_OFFSET);
279 m_range->InsertAfter(node, store, load);
281 ReplaceWith(compiler, load);
283 JITDUMP("ReplaceWithLclVar created store :\n");
289 LIR::ReadOnlyRange::ReadOnlyRange() : m_firstNode(nullptr), m_lastNode(nullptr)
293 LIR::ReadOnlyRange::ReadOnlyRange(ReadOnlyRange&& other) : m_firstNode(other.m_firstNode), m_lastNode(other.m_lastNode)
296 other.m_firstNode = nullptr;
297 other.m_lastNode = nullptr;
301 //------------------------------------------------------------------------
302 // LIR::ReadOnlyRange::ReadOnlyRange:
303 // Creates a `ReadOnlyRange` value given the first and last node in
307 // firstNode - The first node in the range.
308 // lastNode - The last node in the range.
310 LIR::ReadOnlyRange::ReadOnlyRange(GenTree* firstNode, GenTree* lastNode) : m_firstNode(firstNode), m_lastNode(lastNode)
312 assert((m_firstNode == nullptr) == (m_lastNode == nullptr));
313 assert((m_firstNode == m_lastNode) || (Contains(m_lastNode)));
316 //------------------------------------------------------------------------
317 // LIR::ReadOnlyRange::FirstNode: Returns the first node in the range.
319 GenTree* LIR::ReadOnlyRange::FirstNode() const
324 //------------------------------------------------------------------------
325 // LIR::ReadOnlyRange::LastNode: Returns the last node in the range.
327 GenTree* LIR::ReadOnlyRange::LastNode() const
332 //------------------------------------------------------------------------
333 // LIR::ReadOnlyRange::IsEmpty: Returns true if the range is empty; false
336 bool LIR::ReadOnlyRange::IsEmpty() const
338 assert((m_firstNode == nullptr) == (m_lastNode == nullptr));
339 return m_firstNode == nullptr;
342 //------------------------------------------------------------------------
343 // LIR::ReadOnlyRange::begin: Returns an iterator positioned at the first
344 // node in the range.
346 LIR::ReadOnlyRange::Iterator LIR::ReadOnlyRange::begin() const
348 return Iterator(m_firstNode);
351 //------------------------------------------------------------------------
352 // LIR::ReadOnlyRange::end: Returns an iterator positioned after the last
353 // node in the range.
355 LIR::ReadOnlyRange::Iterator LIR::ReadOnlyRange::end() const
357 return Iterator(m_lastNode == nullptr ? nullptr : m_lastNode->gtNext);
360 //------------------------------------------------------------------------
361 // LIR::ReadOnlyRange::rbegin: Returns an iterator positioned at the last
362 // node in the range.
364 LIR::ReadOnlyRange::ReverseIterator LIR::ReadOnlyRange::rbegin() const
366 return ReverseIterator(m_lastNode);
369 //------------------------------------------------------------------------
370 // LIR::ReadOnlyRange::rend: Returns an iterator positioned before the first
371 // node in the range.
373 LIR::ReadOnlyRange::ReverseIterator LIR::ReadOnlyRange::rend() const
375 return ReverseIterator(m_firstNode == nullptr ? nullptr : m_firstNode->gtPrev);
380 //------------------------------------------------------------------------
381 // LIR::ReadOnlyRange::Contains: Indicates whether or not this range
382 // contains a given node.
385 // node - The node to find.
387 // Return Value: True if this range contains the given node; false
390 bool LIR::ReadOnlyRange::Contains(GenTree* node) const
392 assert(node != nullptr);
394 // TODO-LIR: derive this from the # of nodes in the function as well as
395 // the debug level. Checking small functions is pretty cheap; checking
396 // large functions is not.
397 if (JitConfig.JitExpensiveDebugCheckLevel() < 2)
402 for (GenTree* n : *this)
415 LIR::Range::Range() : ReadOnlyRange()
419 LIR::Range::Range(Range&& other) : ReadOnlyRange(std::move(other))
423 //------------------------------------------------------------------------
424 // LIR::Range::Range: Creates a `Range` value given the first and last
425 // node in the range.
428 // firstNode - The first node in the range.
429 // lastNode - The last node in the range.
431 LIR::Range::Range(GenTree* firstNode, GenTree* lastNode) : ReadOnlyRange(firstNode, lastNode)
435 //------------------------------------------------------------------------
436 // LIR::Range::LastPhiNode: Returns the last phi node in the range or
437 // `nullptr` if no phis exist.
439 GenTree* LIR::Range::LastPhiNode() const
441 GenTree* lastPhiNode = nullptr;
442 for (GenTree* node : *this)
444 if (!node->IsPhiNode())
455 //------------------------------------------------------------------------
456 // LIR::Range::FirstNonPhiNode: Returns the first non-phi node in the
457 // range or `nullptr` if no non-phi nodes
460 GenTree* LIR::Range::FirstNonPhiNode() const
462 for (GenTree* node : *this)
464 if (!node->IsPhiNode())
473 //------------------------------------------------------------------------
474 // LIR::Range::FirstNonPhiOrCatchArgNode: Returns the first node after all
475 // phi or catch arg nodes in this
478 GenTree* LIR::Range::FirstNonPhiOrCatchArgNode() const
480 for (GenTree* node : NonPhiNodes())
482 if (node->OperGet() == GT_CATCH_ARG)
486 else if ((node->OperGet() == GT_STORE_LCL_VAR) && (node->gtGetOp1()->OperGet() == GT_CATCH_ARG))
497 //------------------------------------------------------------------------
498 // LIR::Range::PhiNodes: Returns the range of phi nodes inside this range.
500 LIR::ReadOnlyRange LIR::Range::PhiNodes() const
502 GenTree* lastPhiNode = LastPhiNode();
503 if (lastPhiNode == nullptr)
505 return ReadOnlyRange();
508 return ReadOnlyRange(m_firstNode, lastPhiNode);
511 //------------------------------------------------------------------------
512 // LIR::Range::PhiNodes: Returns the range of non-phi nodes inside this
515 LIR::ReadOnlyRange LIR::Range::NonPhiNodes() const
517 GenTree* firstNonPhiNode = FirstNonPhiNode();
518 if (firstNonPhiNode == nullptr)
520 return ReadOnlyRange();
523 return ReadOnlyRange(firstNonPhiNode, m_lastNode);
526 //------------------------------------------------------------------------
527 // LIR::Range::InsertBefore: Inserts a node before another node in this range.
530 // insertionPoint - The node before which `node` will be inserted. If non-null, must be part
531 // of this range. If null, insert at the end of the range.
532 // node - The node to insert. Must not be part of any range.
534 void LIR::Range::InsertBefore(GenTree* insertionPoint, GenTree* node)
536 assert(node != nullptr);
537 assert(node->gtPrev == nullptr);
538 assert(node->gtNext == nullptr);
540 FinishInsertBefore(insertionPoint, node, node);
543 //------------------------------------------------------------------------
544 // LIR::Range::InsertBefore: Inserts 2 nodes before another node in this range.
547 // insertionPoint - The node before which the nodes will be inserted. If non-null, must be part
548 // of this range. If null, insert at the end of the range.
549 // node1 - The first node to insert. Must not be part of any range.
550 // node2 - The second node to insert. Must not be part of any range.
554 // previous insertionPoint->gtPrev <-> node1 <-> node2 <-> insertionPoint
556 void LIR::Range::InsertBefore(GenTree* insertionPoint, GenTree* node1, GenTree* node2)
558 assert(node1 != nullptr);
559 assert(node2 != nullptr);
561 assert(node1->gtNext == nullptr);
562 assert(node1->gtPrev == nullptr);
563 assert(node2->gtNext == nullptr);
564 assert(node2->gtPrev == nullptr);
566 node1->gtNext = node2;
567 node2->gtPrev = node1;
569 FinishInsertBefore(insertionPoint, node1, node2);
572 //------------------------------------------------------------------------
573 // LIR::Range::InsertBefore: Inserts 3 nodes before another node in this range.
576 // insertionPoint - The node before which the nodes will be inserted. If non-null, must be part
577 // of this range. If null, insert at the end of the range.
578 // node1 - The first node to insert. Must not be part of any range.
579 // node2 - The second node to insert. Must not be part of any range.
580 // node3 - The third node to insert. Must not be part of any range.
584 // previous insertionPoint->gtPrev <-> node1 <-> node2 <-> node3 <-> insertionPoint
586 void LIR::Range::InsertBefore(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3)
588 assert(node1 != nullptr);
589 assert(node2 != nullptr);
590 assert(node3 != nullptr);
592 assert(node1->gtNext == nullptr);
593 assert(node1->gtPrev == nullptr);
594 assert(node2->gtNext == nullptr);
595 assert(node2->gtPrev == nullptr);
596 assert(node3->gtNext == nullptr);
597 assert(node3->gtPrev == nullptr);
599 node1->gtNext = node2;
601 node2->gtPrev = node1;
602 node2->gtNext = node3;
604 node3->gtPrev = node2;
606 FinishInsertBefore(insertionPoint, node1, node3);
609 //------------------------------------------------------------------------
610 // LIR::Range::InsertBefore: Inserts 4 nodes before another node in this range.
613 // insertionPoint - The node before which the nodes will be inserted. If non-null, must be part
614 // of this range. If null, insert at the end of the range.
615 // node1 - The first node to insert. Must not be part of any range.
616 // node2 - The second node to insert. Must not be part of any range.
617 // node3 - The third node to insert. Must not be part of any range.
618 // node4 - The fourth node to insert. Must not be part of any range.
622 // previous insertionPoint->gtPrev <-> node1 <-> node2 <-> node3 <-> node4 <-> insertionPoint
624 void LIR::Range::InsertBefore(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3, GenTree* node4)
626 assert(node1 != nullptr);
627 assert(node2 != nullptr);
628 assert(node3 != nullptr);
629 assert(node4 != nullptr);
631 assert(node1->gtNext == nullptr);
632 assert(node1->gtPrev == nullptr);
633 assert(node2->gtNext == nullptr);
634 assert(node2->gtPrev == nullptr);
635 assert(node3->gtNext == nullptr);
636 assert(node3->gtPrev == nullptr);
637 assert(node4->gtNext == nullptr);
638 assert(node4->gtPrev == nullptr);
640 node1->gtNext = node2;
642 node2->gtPrev = node1;
643 node2->gtNext = node3;
645 node3->gtPrev = node2;
646 node3->gtNext = node4;
648 node4->gtPrev = node3;
650 FinishInsertBefore(insertionPoint, node1, node4);
653 //------------------------------------------------------------------------
654 // LIR::Range::FinishInsertBefore: Helper function to finalize InsertBefore processing: link the
655 // range to insertionPoint. gtNext/gtPrev links between first and last are already set.
658 // insertionPoint - The node before which the nodes will be inserted. If non-null, must be part
659 // of this range. If null, indicates to insert at the end of the range.
660 // first - The first node of the range to insert.
661 // last - The last node of the range to insert.
665 // previous insertionPoint->gtPrev <-> first <-> ... <-> last <-> insertionPoint
667 void LIR::Range::FinishInsertBefore(GenTree* insertionPoint, GenTree* first, GenTree* last)
669 assert(first != nullptr);
670 assert(last != nullptr);
671 assert(first->gtPrev == nullptr);
672 assert(last->gtNext == nullptr);
674 if (insertionPoint == nullptr)
676 if (m_firstNode == nullptr)
682 assert(m_lastNode != nullptr);
683 assert(m_lastNode->gtNext == nullptr);
684 m_lastNode->gtNext = first;
685 first->gtPrev = m_lastNode;
691 assert(Contains(insertionPoint));
693 first->gtPrev = insertionPoint->gtPrev;
694 if (first->gtPrev == nullptr)
696 assert(insertionPoint == m_firstNode);
701 first->gtPrev->gtNext = first;
704 last->gtNext = insertionPoint;
705 insertionPoint->gtPrev = last;
709 //------------------------------------------------------------------------
710 // LIR::Range::InsertAfter: Inserts a node after another node in this range.
713 // insertionPoint - The node after which `node` will be inserted. If non-null, must be part
714 // of this range. If null, insert at the beginning of the range.
715 // node - The node to insert. Must not be part of any range.
719 // insertionPoint <-> node <-> previous insertionPoint->gtNext
721 void LIR::Range::InsertAfter(GenTree* insertionPoint, GenTree* node)
723 assert(node != nullptr);
725 assert(node->gtNext == nullptr);
726 assert(node->gtPrev == nullptr);
728 FinishInsertAfter(insertionPoint, node, node);
731 //------------------------------------------------------------------------
732 // LIR::Range::InsertAfter: Inserts 2 nodes after another node in this range.
735 // insertionPoint - The node after which the nodes will be inserted. If non-null, must be part
736 // of this range. If null, insert at the beginning of the range.
737 // node1 - The first node to insert. Must not be part of any range.
738 // node2 - The second node to insert. Must not be part of any range. Inserted after node1.
742 // insertionPoint <-> node1 <-> node2 <-> previous insertionPoint->gtNext
744 void LIR::Range::InsertAfter(GenTree* insertionPoint, GenTree* node1, GenTree* node2)
746 assert(node1 != nullptr);
747 assert(node2 != nullptr);
749 assert(node1->gtNext == nullptr);
750 assert(node1->gtPrev == nullptr);
751 assert(node2->gtNext == nullptr);
752 assert(node2->gtPrev == nullptr);
754 node1->gtNext = node2;
755 node2->gtPrev = node1;
757 FinishInsertAfter(insertionPoint, node1, node2);
760 //------------------------------------------------------------------------
761 // LIR::Range::InsertAfter: Inserts 3 nodes after another node in this range.
764 // insertionPoint - The node after which the nodes will be inserted. If non-null, must be part
765 // of this range. If null, insert at the beginning of the range.
766 // node1 - The first node to insert. Must not be part of any range.
767 // node2 - The second node to insert. Must not be part of any range. Inserted after node1.
768 // node3 - The third node to insert. Must not be part of any range. Inserted after node2.
772 // insertionPoint <-> node1 <-> node2 <-> node3 <-> previous insertionPoint->gtNext
774 void LIR::Range::InsertAfter(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3)
776 assert(node1 != nullptr);
777 assert(node2 != nullptr);
778 assert(node3 != nullptr);
780 assert(node1->gtNext == nullptr);
781 assert(node1->gtPrev == nullptr);
782 assert(node2->gtNext == nullptr);
783 assert(node2->gtPrev == nullptr);
784 assert(node3->gtNext == nullptr);
785 assert(node3->gtPrev == nullptr);
787 node1->gtNext = node2;
789 node2->gtPrev = node1;
790 node2->gtNext = node3;
792 node3->gtPrev = node2;
794 FinishInsertAfter(insertionPoint, node1, node3);
797 //------------------------------------------------------------------------
798 // LIR::Range::InsertAfter: Inserts 4 nodes after another node in this range.
801 // insertionPoint - The node after which the nodes will be inserted. If non-null, must be part
802 // of this range. If null, insert at the beginning of the range.
803 // node1 - The first node to insert. Must not be part of any range.
804 // node2 - The second node to insert. Must not be part of any range. Inserted after node1.
805 // node3 - The third node to insert. Must not be part of any range. Inserted after node2.
806 // node4 - The fourth node to insert. Must not be part of any range. Inserted after node3.
810 // insertionPoint <-> node1 <-> node2 <-> node3 <-> node4 <-> previous insertionPoint->gtNext
812 void LIR::Range::InsertAfter(GenTree* insertionPoint, GenTree* node1, GenTree* node2, GenTree* node3, GenTree* node4)
814 assert(node1 != nullptr);
815 assert(node2 != nullptr);
816 assert(node3 != nullptr);
817 assert(node4 != nullptr);
819 assert(node1->gtNext == nullptr);
820 assert(node1->gtPrev == nullptr);
821 assert(node2->gtNext == nullptr);
822 assert(node2->gtPrev == nullptr);
823 assert(node3->gtNext == nullptr);
824 assert(node3->gtPrev == nullptr);
825 assert(node4->gtNext == nullptr);
826 assert(node4->gtPrev == nullptr);
828 node1->gtNext = node2;
830 node2->gtPrev = node1;
831 node2->gtNext = node3;
833 node3->gtPrev = node2;
834 node3->gtNext = node4;
836 node4->gtPrev = node3;
838 FinishInsertAfter(insertionPoint, node1, node4);
841 //------------------------------------------------------------------------
842 // LIR::Range::FinishInsertAfter: Helper function to finalize InsertAfter processing: link the
843 // range to insertionPoint. gtNext/gtPrev links between first and last are already set.
846 // insertionPoint - The node after which the nodes will be inserted. If non-null, must be part
847 // of this range. If null, insert at the beginning of the range.
848 // first - The first node of the range to insert.
849 // last - The last node of the range to insert.
853 // insertionPoint <-> first <-> ... <-> last <-> previous insertionPoint->gtNext
855 void LIR::Range::FinishInsertAfter(GenTree* insertionPoint, GenTree* first, GenTree* last)
857 assert(first != nullptr);
858 assert(last != nullptr);
859 assert(first->gtPrev == nullptr);
860 assert(last->gtNext == nullptr);
862 if (insertionPoint == nullptr)
864 if (m_lastNode == nullptr)
870 assert(m_firstNode != nullptr);
871 assert(m_firstNode->gtPrev == nullptr);
872 m_firstNode->gtPrev = last;
873 last->gtNext = m_firstNode;
879 assert(Contains(insertionPoint));
881 last->gtNext = insertionPoint->gtNext;
882 if (last->gtNext == nullptr)
884 assert(insertionPoint == m_lastNode);
889 last->gtNext->gtPrev = last;
892 first->gtPrev = insertionPoint;
893 insertionPoint->gtNext = first;
897 //------------------------------------------------------------------------
898 // LIR::Range::InsertBefore: Inserts a range before another node in `this` range.
901 // insertionPoint - The node before which the nodes will be inserted. If non-null, must be part
902 // of this range. If null, insert at the end of the range.
903 // range - The range to splice in.
905 void LIR::Range::InsertBefore(GenTree* insertionPoint, Range&& range)
907 assert(!range.IsEmpty());
908 FinishInsertBefore(insertionPoint, range.m_firstNode, range.m_lastNode);
911 //------------------------------------------------------------------------
912 // LIR::Range::InsertAfter: Inserts a range after another node in `this` range.
915 // insertionPoint - The node after which the nodes will be inserted. If non-null, must be part
916 // of this range. If null, insert at the beginning of the range.
917 // range - The range to splice in.
919 void LIR::Range::InsertAfter(GenTree* insertionPoint, Range&& range)
921 assert(!range.IsEmpty());
922 FinishInsertAfter(insertionPoint, range.m_firstNode, range.m_lastNode);
925 //------------------------------------------------------------------------
926 // LIR::Range::InsertAtBeginning: Inserts a node at the beginning of this range.
929 // node - The node to insert. Must not be part of any range.
931 void LIR::Range::InsertAtBeginning(GenTree* node)
933 InsertBefore(m_firstNode, node);
936 //------------------------------------------------------------------------
937 // LIR::Range::InsertAtEnd: Inserts a node at the end of this range.
940 // node - The node to insert. Must not be part of any range.
942 void LIR::Range::InsertAtEnd(GenTree* node)
944 InsertAfter(m_lastNode, node);
947 //------------------------------------------------------------------------
948 // LIR::Range::InsertAtBeginning: Inserts a range at the beginning of `this` range.
951 // range - The range to splice in.
953 void LIR::Range::InsertAtBeginning(Range&& range)
955 InsertBefore(m_firstNode, std::move(range));
958 //------------------------------------------------------------------------
959 // LIR::Range::InsertAtEnd: Inserts a range at the end of `this` range.
962 // range - The range to splice in.
964 void LIR::Range::InsertAtEnd(Range&& range)
966 InsertAfter(m_lastNode, std::move(range));
969 //------------------------------------------------------------------------
970 // LIR::Range::Remove: Removes a node from this range.
973 // node - The node to remove. Must be part of this range.
974 // markOperandsUnused - If true, marks the node's operands as unused.
976 void LIR::Range::Remove(GenTree* node, bool markOperandsUnused)
978 assert(node != nullptr);
979 assert(Contains(node));
981 if (markOperandsUnused)
983 node->VisitOperands([](GenTree* operand) -> GenTree::VisitResult {
984 // The operand of JTRUE does not produce a value (just sets the flags).
985 if (operand->IsValue())
987 operand->SetUnusedValue();
989 return GenTree::VisitResult::Continue;
993 GenTree* prev = node->gtPrev;
994 GenTree* next = node->gtNext;
1002 assert(node == m_firstNode);
1006 if (next != nullptr)
1008 next->gtPrev = prev;
1012 assert(node == m_lastNode);
1016 node->gtPrev = nullptr;
1017 node->gtNext = nullptr;
1020 //------------------------------------------------------------------------
1021 // LIR::Range::Remove: Removes a subrange from this range.
1023 // Both the start and the end of the subrange must be part of this range.
1026 // firstNode - The first node in the subrange.
1027 // lastNode - The last node in the subrange.
1030 // A mutable range containing the removed nodes.
1032 LIR::Range LIR::Range::Remove(GenTree* firstNode, GenTree* lastNode)
1034 assert(firstNode != nullptr);
1035 assert(lastNode != nullptr);
1036 assert(Contains(firstNode));
1037 assert((firstNode == lastNode) || firstNode->Precedes(lastNode));
1039 GenTree* prev = firstNode->gtPrev;
1040 GenTree* next = lastNode->gtNext;
1042 if (prev != nullptr)
1044 prev->gtNext = next;
1048 assert(firstNode == m_firstNode);
1052 if (next != nullptr)
1054 next->gtPrev = prev;
1058 assert(lastNode == m_lastNode);
1062 firstNode->gtPrev = nullptr;
1063 lastNode->gtNext = nullptr;
1065 return Range(firstNode, lastNode);
1068 //------------------------------------------------------------------------
1069 // LIR::Range::Remove: Removes a subrange from this range.
1072 // range - The subrange to remove. Must be part of this range.
1075 // A mutable range containing the removed nodes.
1077 LIR::Range LIR::Range::Remove(ReadOnlyRange&& range)
1079 return Remove(range.m_firstNode, range.m_lastNode);
1082 //------------------------------------------------------------------------
1083 // LIR::Range::Delete: Deletes a node from this range.
1085 // Note that the deleted node must not be used after this function has
1086 // been called. If the deleted node is part of a block, this function also
1087 // calls `Compiler::lvaDecRefCnts` as necessary.
1090 // node - The node to delete. Must be part of this range.
1091 // block - The block that contains the node, if any. May be null.
1092 // compiler - The compiler context. May be null if block is null.
1094 void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, GenTree* node)
1096 assert(node != nullptr);
1097 assert((block == nullptr) == (compiler == nullptr));
1101 if (block != nullptr)
1103 if (((node->OperGet() == GT_CALL) && ((node->gtFlags & GTF_CALL_UNMANAGED) != 0)) ||
1104 (node->OperIsLocal() && !node->IsPhiNode()))
1106 compiler->lvaDecRefCnts(block, node);
1110 DEBUG_DESTROY_NODE(node);
1113 //------------------------------------------------------------------------
1114 // LIR::Range::Delete: Deletes a subrange from this range.
1116 // Both the start and the end of the subrange must be part of this range.
1117 // Note that the deleted nodes must not be used after this function has
1118 // been called. If the deleted nodes are part of a block, this function
1119 // also calls `Compiler::lvaDecRefCnts` as necessary.
1122 // firstNode - The first node in the subrange.
1123 // lastNode - The last node in the subrange.
1124 // block - The block that contains the subrange, if any. May be null.
1125 // compiler - The compiler context. May be null if block is null.
1127 void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, GenTree* firstNode, GenTree* lastNode)
1129 assert(firstNode != nullptr);
1130 assert(lastNode != nullptr);
1131 assert((block == nullptr) == (compiler == nullptr));
1133 Remove(firstNode, lastNode);
1135 assert(lastNode->gtNext == nullptr);
1137 if (block != nullptr)
1139 for (GenTree* node = firstNode; node != nullptr; node = node->gtNext)
1141 if (((node->OperGet() == GT_CALL) && ((node->gtFlags & GTF_CALL_UNMANAGED) != 0)) ||
1142 (node->OperIsLocal() && !node->IsPhiNode()))
1144 compiler->lvaDecRefCnts(block, node);
1150 // We can't do this in the loop above because it causes `IsPhiNode` to return a false negative
1151 // for `GT_STORE_LCL_VAR` nodes that participate in phi definitions.
1152 for (GenTree* node = firstNode; node != nullptr; node = node->gtNext)
1154 DEBUG_DESTROY_NODE(node);
1159 //------------------------------------------------------------------------
1160 // LIR::Range::Delete: Deletes a subrange from this range.
1162 // Both the start and the end of the subrange must be part of this range.
1163 // Note that the deleted nodes must not be used after this function has
1164 // been called. If the deleted nodes are part of a block, this function
1165 // also calls `Compiler::lvaDecRefCnts` as necessary.
1168 // range - The subrange to delete.
1169 // block - The block that contains the subrange, if any. May be null.
1170 // compiler - The compiler context. May be null if block is null.
1172 void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, ReadOnlyRange&& range)
1174 Delete(compiler, block, range.m_firstNode, range.m_lastNode);
1177 //------------------------------------------------------------------------
1178 // LIR::Range::TryGetUse: Try to find the use for a given node.
1181 // node - The node for which to find the corresponding use.
1182 // use (out) - The use of the corresponding node, if any. Invalid if
1183 // this method returns false.
1185 // Return Value: Returns true if a use was found; false otherwise.
1187 bool LIR::Range::TryGetUse(GenTree* node, Use* use)
1189 assert(node != nullptr);
1190 assert(use != nullptr);
1191 assert(Contains(node));
1193 // Don't bother looking for uses of nodes that are not values.
1194 // If the node is the last node, we won't find a use (and we would
1195 // end up creating an illegal range if we tried).
1196 if (node->IsValue() && !node->IsUnusedValue() && (node != LastNode()))
1198 for (GenTree* n : ReadOnlyRange(node->gtNext, m_lastNode))
1201 if (n->TryGetUse(node, &edge))
1203 *use = Use(*this, edge, n);
1213 //------------------------------------------------------------------------
1214 // LIR::Range::GetTreeRange: Computes the subrange that includes all nodes
1215 // in the dataflow trees rooted at a particular
1218 // This method logically uses the following algorithm to compute the
1221 // worklist = { set }
1222 // firstNode = start
1225 // while not worklist.isEmpty:
1226 // if not worklist.contains(firstNode):
1229 // for operand in firstNode:
1230 // worklist.add(operand)
1232 // worklist.remove(firstNode)
1234 // firstNode = firstNode.previousNode
1238 // Instead of using a set for the worklist, the implementation uses the
1239 // `LIR::Mark` bit of the `GenTree::LIRFlags` field to track whether or
1240 // not a node is in the worklist.
1242 // Note also that this algorithm depends LIR nodes being SDSU, SDSU defs
1243 // and uses occurring in the same block, and correct dataflow (i.e. defs
1244 // occurring before uses).
1247 // root - The root of the dataflow tree.
1248 // isClosed - An output parameter that is set to true if the returned
1249 // range contains only nodes in the dataflow tree and false
1253 // The computed subrange.
1255 LIR::ReadOnlyRange LIR::Range::GetMarkedRange(unsigned markCount,
1258 unsigned* sideEffects) const
1260 assert(markCount != 0);
1261 assert(start != nullptr);
1262 assert(isClosed != nullptr);
1263 assert(sideEffects != nullptr);
1265 bool sawUnmarkedNode = false;
1266 unsigned sideEffectsInRange = 0;
1268 GenTree* firstNode = start;
1269 GenTree* lastNode = nullptr;
1272 if ((firstNode->gtLIRFlags & LIR::Flags::Mark) != 0)
1274 if (lastNode == nullptr)
1276 lastNode = firstNode;
1279 // Mark the node's operands
1280 firstNode->VisitOperands([&markCount](GenTree* operand) -> GenTree::VisitResult {
1281 // Do not mark nodes that do not appear in the execution order
1282 if (operand->OperGet() == GT_ARGPLACE)
1284 return GenTree::VisitResult::Continue;
1287 operand->gtLIRFlags |= LIR::Flags::Mark;
1289 return GenTree::VisitResult::Continue;
1292 // Unmark the the node and update `firstNode`
1293 firstNode->gtLIRFlags &= ~LIR::Flags::Mark;
1296 else if (lastNode != nullptr)
1298 sawUnmarkedNode = true;
1301 if (lastNode != nullptr)
1303 sideEffectsInRange |= (firstNode->gtFlags & GTF_ALL_EFFECT);
1311 firstNode = firstNode->gtPrev;
1313 // This assert will fail if the dataflow that feeds the root node
1314 // is incorrect in that it crosses a block boundary or if it involves
1315 // a use that occurs before its corresponding def.
1316 assert(firstNode != nullptr);
1319 assert(lastNode != nullptr);
1321 *isClosed = !sawUnmarkedNode;
1322 *sideEffects = sideEffectsInRange;
1323 return ReadOnlyRange(firstNode, lastNode);
1326 //------------------------------------------------------------------------
1327 // LIR::Range::GetTreeRange: Computes the subrange that includes all nodes
1328 // in the dataflow tree rooted at a particular
1332 // root - The root of the dataflow tree.
1333 // isClosed - An output parameter that is set to true if the returned
1334 // range contains only nodes in the dataflow tree and false
1338 // The computed subrange.
1339 LIR::ReadOnlyRange LIR::Range::GetTreeRange(GenTree* root, bool* isClosed) const
1342 return GetTreeRange(root, isClosed, &unused);
1345 //------------------------------------------------------------------------
1346 // LIR::Range::GetTreeRange: Computes the subrange that includes all nodes
1347 // in the dataflow tree rooted at a particular
1351 // root - The root of the dataflow tree.
1352 // isClosed - An output parameter that is set to true if the returned
1353 // range contains only nodes in the dataflow tree and false
1355 // sideEffects - An output parameter that summarizes the side effects
1356 // contained in the returned range.
1359 // The computed subrange.
1360 LIR::ReadOnlyRange LIR::Range::GetTreeRange(GenTree* root, bool* isClosed, unsigned* sideEffects) const
1362 assert(root != nullptr);
1364 // Mark the root of the tree
1365 const unsigned markCount = 1;
1366 root->gtLIRFlags |= LIR::Flags::Mark;
1368 return GetMarkedRange(markCount, root, isClosed, sideEffects);
1371 //------------------------------------------------------------------------
1372 // LIR::Range::GetTreeRange: Computes the subrange that includes all nodes
1373 // in the dataflow trees rooted by the operands
1374 // to a particular node.
1377 // root - The root of the dataflow tree.
1378 // isClosed - An output parameter that is set to true if the returned
1379 // range contains only nodes in the dataflow tree and false
1381 // sideEffects - An output parameter that summarizes the side effects
1382 // contained in the returned range.
1385 // The computed subrange.
1387 LIR::ReadOnlyRange LIR::Range::GetRangeOfOperandTrees(GenTree* root, bool* isClosed, unsigned* sideEffects) const
1389 assert(root != nullptr);
1390 assert(isClosed != nullptr);
1391 assert(sideEffects != nullptr);
1393 // Mark the root node's operands
1394 unsigned markCount = 0;
1395 root->VisitOperands([&markCount](GenTree* operand) -> GenTree::VisitResult {
1396 operand->gtLIRFlags |= LIR::Flags::Mark;
1398 return GenTree::VisitResult::Continue;
1405 return ReadOnlyRange();
1408 return GetMarkedRange(markCount, root, isClosed, sideEffects);
1413 //------------------------------------------------------------------------
1414 // CheckLclVarSemanticsHelper checks lclVar semantics.
1416 // Specifically, ensure that an unaliasable lclVar is not redefined between the
1417 // point at which a use appears in linear order and the point at which it is used by its user.
1418 // This ensures that it is always safe to treat a lclVar use as happening at the user (rather than at
1419 // the lclVar node).
1420 class CheckLclVarSemanticsHelper
1423 //------------------------------------------------------------------------
1424 // CheckLclVarSemanticsHelper constructor: Init arguments for the helper.
1426 // This needs unusedDefs because unused lclVar reads may otherwise appear as outstanding reads
1427 // and produce false indications that a write to a lclVar occurs while outstanding reads of that lclVar
1431 // compiler - A compiler context.
1432 // range - a range to do the check.
1433 // unusedDefs - map of defs that do no have users.
1435 CheckLclVarSemanticsHelper(Compiler* compiler,
1436 const LIR::Range* range,
1437 SmallHashTable<GenTree*, bool, 32U>& unusedDefs)
1438 : compiler(compiler), range(range), unusedDefs(unusedDefs), unusedLclVarReads(compiler)
1442 //------------------------------------------------------------------------
1443 // Check: do the check.
1445 // 'true' if the Local variables semantics for the specified range is legal.
1448 for (GenTree* node : *range)
1450 if (!node->isContained()) // a contained node reads operands in the parent.
1452 UseNodeOperands(node);
1455 AliasSet::NodeInfo nodeInfo(compiler, node);
1456 if (nodeInfo.IsLclVarRead() && !unusedDefs.Contains(node))
1459 unusedLclVarReads.TryGetValue(nodeInfo.LclNum(), &count);
1460 unusedLclVarReads.AddOrUpdate(nodeInfo.LclNum(), count + 1);
1463 // If this node is a lclVar write, it must be to a lclVar that does not have an outstanding read.
1464 assert(!nodeInfo.IsLclVarWrite() || !unusedLclVarReads.Contains(nodeInfo.LclNum()));
1471 //------------------------------------------------------------------------
1472 // UseNodeOperands: mark the node's operands as used.
1475 // node - the node to use operands from.
1476 void UseNodeOperands(GenTree* node)
1478 for (GenTree* operand : node->Operands())
1480 if (!operand->IsLIR())
1482 // ARGPLACE nodes are not represented in the LIR sequence. Ignore them.
1483 assert(operand->OperIs(GT_ARGPLACE));
1486 if (operand->isContained())
1488 UseNodeOperands(operand);
1490 AliasSet::NodeInfo operandInfo(compiler, operand);
1491 if (operandInfo.IsLclVarRead())
1494 const bool removed = unusedLclVarReads.TryRemove(operandInfo.LclNum(), &count);
1499 unusedLclVarReads.AddOrUpdate(operandInfo.LclNum(), count - 1);
1507 const LIR::Range* range;
1508 SmallHashTable<GenTree*, bool, 32U>& unusedDefs;
1509 SmallHashTable<int, int, 32U> unusedLclVarReads;
1512 //------------------------------------------------------------------------
1513 // LIR::Range::CheckLIR: Performs a set of correctness checks on the LIR
1514 // contained in this range.
1516 // This method checks the following properties:
1517 // - Defs are singly-used
1518 // - Uses follow defs
1519 // - Uses are correctly linked into the block
1520 // - Nodes that do not produce values are not used
1521 // - Only LIR nodes are present in the block
1522 // - If any phi nodes are present in the range, they precede all other
1525 // The first four properties are verified by walking the range's LIR in execution order,
1526 // inserting defs into a set as they are visited, and removing them as they are used. The
1527 // different cases are distinguished only when an error is detected.
1530 // compiler - A compiler context.
1533 // 'true' if the LIR for the specified range is legal.
1535 bool LIR::Range::CheckLIR(Compiler* compiler, bool checkUnusedValues) const
1539 // Nothing more to check.
1543 // Check the gtNext/gtPrev links: (1) ensure there are no circularities, (2) ensure the gtPrev list is
1544 // precisely the inverse of the gtNext list.
1546 // To detect circularity, use the "tortoise and hare" 2-pointer algorithm.
1548 GenTree* slowNode = FirstNode();
1549 assert(slowNode != nullptr); // because it's a non-empty range
1550 GenTree* fastNode1 = nullptr;
1551 GenTree* fastNode2 = slowNode;
1552 GenTree* prevSlowNode = nullptr;
1553 while (((fastNode1 = fastNode2->gtNext) != nullptr) && ((fastNode2 = fastNode1->gtNext) != nullptr))
1555 if ((slowNode == fastNode1) || (slowNode == fastNode2))
1557 assert(!"gtNext nodes have a circularity!");
1559 assert(slowNode->gtPrev == prevSlowNode);
1560 prevSlowNode = slowNode;
1561 slowNode = slowNode->gtNext;
1562 assert(slowNode != nullptr); // the fastNodes would have gone null first.
1564 // If we get here, the list had no circularities, so either fastNode1 or fastNode2 must be nullptr.
1565 assert((fastNode1 == nullptr) || (fastNode2 == nullptr));
1567 // Need to check the rest of the gtPrev links.
1568 while (slowNode != nullptr)
1570 assert(slowNode->gtPrev == prevSlowNode);
1571 prevSlowNode = slowNode;
1572 slowNode = slowNode->gtNext;
1575 SmallHashTable<GenTree*, bool, 32> unusedDefs(compiler);
1577 bool pastPhis = false;
1578 GenTree* prev = nullptr;
1579 for (Iterator node = begin(), end = this->end(); node != end; prev = *node, ++node)
1581 // Verify that the node is allowed in LIR.
1582 assert(node->IsLIR());
1584 // Some nodes should never be marked unused, as they must be contained in the backend.
1585 // These may be marked as unused during dead code elimination traversal, but they *must* be subsequently
1587 assert(!node->IsUnusedValue() || !node->OperIs(GT_FIELD_LIST, GT_LIST, GT_INIT_VAL));
1589 // Verify that the REVERSE_OPS flag is not set. NOTE: if we ever decide to reuse the bit assigned to
1590 // GTF_REVERSE_OPS for an LIR-only flag we will need to move this check to the points at which we
1591 // insert nodes into an LIR range.
1592 assert((node->gtFlags & GTF_REVERSE_OPS) == 0);
1594 // TODO: validate catch arg stores
1596 // Check that all phi nodes (if any) occur at the start of the range.
1597 if ((node->OperGet() == GT_PHI_ARG) || (node->OperGet() == GT_PHI) || node->IsPhiDefn())
1606 for (GenTree** useEdge : node->UseEdges())
1608 GenTree* def = *useEdge;
1610 assert(!(checkUnusedValues && def->IsUnusedValue()) && "operands should never be marked as unused values");
1612 if (!def->IsValue())
1614 // Stack arguments do not produce a value, but they are considered children of the call.
1615 // It may be useful to remove these from being call operands, but that may also impact
1616 // other code that relies on being able to reach all the operands from a call node.
1617 // The GT_NOP case is because sometimes we eliminate stack argument stores as dead, but
1618 // instead of removing them we replace with a NOP.
1619 // ARGPLACE nodes are not represented in the LIR sequence. Ignore them.
1620 // The argument of a JTRUE doesn't produce a value (just sets a flag).
1621 assert(((node->OperGet() == GT_CALL) &&
1622 (def->OperIsStore() || def->OperIs(GT_PUTARG_STK, GT_NOP, GT_ARGPLACE))) ||
1623 ((node->OperGet() == GT_JTRUE) && (def->TypeGet() == TYP_VOID) &&
1624 ((def->gtFlags & GTF_SET_FLAGS) != 0)));
1629 bool foundDef = unusedDefs.TryRemove(def, &v);
1632 // First, scan backwards and look for a preceding use.
1633 for (GenTree* prev = *node; prev != nullptr; prev = prev->gtPrev)
1635 // TODO: dump the users and the def
1636 GenTree** earlierUseEdge;
1637 bool foundEarlierUse = prev->TryGetUse(def, &earlierUseEdge) && earlierUseEdge != useEdge;
1638 assert(!foundEarlierUse && "found multiply-used LIR node");
1641 // The def did not precede the use. Check to see if it exists in the block at all.
1642 for (GenTree* next = node->gtNext; next != nullptr; next = next->gtNext)
1644 // TODO: dump the user and the def
1645 assert(next != def && "found def after use");
1648 // The def might not be a node that produces a value.
1649 assert(def->IsValue() && "found use of a node that does not produce a value");
1651 // By this point, the only possibility is that the def is not threaded into the LIR sequence.
1652 assert(false && "found use of a node that is not in the LIR sequence");
1656 if (node->IsValue())
1658 bool added = unusedDefs.AddOrUpdate(*node, true);
1663 assert(prev == m_lastNode);
1665 // At this point the unusedDefs map should contain only unused values.
1666 if (checkUnusedValues)
1668 for (auto kvp : unusedDefs)
1670 GenTree* node = kvp.Key();
1671 assert(node->IsUnusedValue() && "found an unmarked unused value");
1672 assert(!node->isContained() && "a contained node should have a user");
1676 CheckLclVarSemanticsHelper checkLclVarSemanticsHelper(compiler, this, unusedDefs);
1677 assert(checkLclVarSemanticsHelper.Check());
1684 //------------------------------------------------------------------------
1685 // LIR::AsRange: Returns an LIR view of the given basic block.
1687 LIR::Range& LIR::AsRange(BasicBlock* block)
1689 return *static_cast<Range*>(block);
1692 //------------------------------------------------------------------------
1693 // LIR::EmptyRange: Constructs and returns an empty range.
1696 LIR::Range LIR::EmptyRange()
1698 return Range(nullptr, nullptr);
1701 //------------------------------------------------------------------------
1703 // Given a newly created, unsequenced HIR tree, set the evaluation
1704 // order (call gtSetEvalOrder) and sequence the tree (set gtNext/gtPrev
1705 // pointers by calling fgSetTreeSeq), and return a Range representing
1706 // the list of nodes. It is expected this will later be spliced into
1710 // compiler - The Compiler context.
1711 // tree - The tree to sequence.
1713 // Return Value: The newly constructed range.
1716 LIR::Range LIR::SeqTree(Compiler* compiler, GenTree* tree)
1718 // TODO-LIR: it would be great to assert that the tree has not already been
1719 // threaded into an order, but I'm not sure that will be practical at this
1722 compiler->gtSetEvalOrder(tree);
1723 return Range(compiler->fgSetTreeSeq(tree, nullptr, true), tree);
1726 //------------------------------------------------------------------------
1727 // LIR::InsertBeforeTerminator:
1728 // Insert an LIR range before the terminating instruction in the given
1729 // basic block. If the basic block has no terminating instruction (i.e.
1730 // it has a jump kind that is not `BBJ_RETURN`, `BBJ_COND`, or
1731 // `BBJ_SWITCH`), the range is inserted at the end of the block.
1734 // block - The block in which to insert the range.
1735 // range - The range to insert.
1737 void LIR::InsertBeforeTerminator(BasicBlock* block, LIR::Range&& range)
1739 LIR::Range& blockRange = LIR::AsRange(block);
1741 GenTree* insertionPoint = nullptr;
1742 if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN))
1744 insertionPoint = blockRange.LastNode();
1745 assert(insertionPoint != nullptr);
1748 switch (block->bbJumpKind)
1751 assert(insertionPoint->OperIsConditionalJump());
1755 assert((insertionPoint->OperGet() == GT_SWITCH) || (insertionPoint->OperGet() == GT_SWITCH_TABLE));
1759 assert((insertionPoint->OperGet() == GT_RETURN) || (insertionPoint->OperGet() == GT_JMP) ||
1760 (insertionPoint->OperGet() == GT_CALL));
1769 blockRange.InsertBefore(insertionPoint, std::move(range));
1773 void GenTree::dumpLIRFlags()
1775 JITDUMP("[%c%c]", IsUnusedValue() ? 'U' : '-', IsRegOptional() ? 'O' : '-');