@@ -16609,7 +16609,7 @@ GenTree* Compiler::gtNewRefCOMfield(GenTree* objPtr,
1660916609 * It may return false even if the node has GTF_SIDE_EFFECT (because of its children).
1661016610 */
1661116611
16612- bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
16612+ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags, bool ignoreCctors )
1661316613{
1661416614 if (flags & GTF_ASG)
1661516615 {
@@ -16636,20 +16636,20 @@ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
1663616636 {
1663716637 GenTreeCall* const call = potentialCall->AsCall();
1663816638 const bool ignoreExceptions = (flags & GTF_EXCEPT) == 0;
16639- const bool ignoreCctors = (flags & GTF_IS_IN_CSE) != 0; // We can CSE helpers that run cctors.
1664016639 if (!call->HasSideEffects(this, ignoreExceptions, ignoreCctors))
1664116640 {
1664216641 // If this call is otherwise side effect free, check its arguments.
1664316642 for (CallArg& arg : call->gtArgs.Args())
1664416643 {
1664516644 // I'm a little worried that args that assign to temps that are late args will look like
1664616645 // side effects...but better to be conservative for now.
16647- if ((arg.GetEarlyNode() != nullptr) && gtTreeHasSideEffects(arg.GetEarlyNode(), flags))
16646+ if ((arg.GetEarlyNode() != nullptr) &&
16647+ gtTreeHasSideEffects(arg.GetEarlyNode(), flags, ignoreCctors))
1664816648 {
1664916649 return true;
1665016650 }
1665116651
16652- if ((arg.GetLateNode() != nullptr) && gtTreeHasSideEffects(arg.GetLateNode(), flags))
16652+ if ((arg.GetLateNode() != nullptr) && gtTreeHasSideEffects(arg.GetLateNode(), flags, ignoreCctors ))
1665316653 {
1665416654 return true;
1665516655 }
@@ -16686,7 +16686,7 @@ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
1668616686 * Returns true if the expr tree has any side effects.
1668716687 */
1668816688
16689- bool Compiler::gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags /* = GTF_SIDE_EFFECT*/)
16689+ bool Compiler::gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags /* = GTF_SIDE_EFFECT*/, bool ignoreCctors )
1669016690{
1669116691 // These are the side effect flags that we care about for this tree
1669216692 GenTreeFlags sideEffectFlags = tree->gtFlags & flags;
@@ -16709,22 +16709,22 @@ bool Compiler::gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags /* = GTF_S
1670916709 // If this node is a helper call we may not care about the side-effects.
1671016710 // Note that gtNodeHasSideEffects checks the side effects of the helper itself
1671116711 // as well as the side effects of its arguments.
16712- return gtNodeHasSideEffects(tree, flags);
16712+ return gtNodeHasSideEffects(tree, flags, ignoreCctors );
1671316713 }
1671416714 }
1671516715 else if (tree->OperGet() == GT_INTRINSIC)
1671616716 {
16717- if (gtNodeHasSideEffects(tree, flags))
16717+ if (gtNodeHasSideEffects(tree, flags, ignoreCctors ))
1671816718 {
1671916719 return true;
1672016720 }
1672116721
16722- if (gtNodeHasSideEffects(tree->AsOp()->gtOp1, flags))
16722+ if (gtNodeHasSideEffects(tree->AsOp()->gtOp1, flags, ignoreCctors ))
1672316723 {
1672416724 return true;
1672516725 }
1672616726
16727- if ((tree->AsOp()->gtOp2 != nullptr) && gtNodeHasSideEffects(tree->AsOp()->gtOp2, flags))
16727+ if ((tree->AsOp()->gtOp2 != nullptr) && gtNodeHasSideEffects(tree->AsOp()->gtOp2, flags, ignoreCctors ))
1672816728 {
1672916729 return true;
1673016730 }
@@ -17110,81 +17110,61 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
1711017110 {
1711117111 GenTree* node = *use;
1711217112
17113- bool treeHasSideEffects = m_compiler->gtTreeHasSideEffects(node, m_flags);
17113+ if (!m_compiler->gtTreeHasSideEffects(node, m_flags))
17114+ {
17115+ return Compiler::WALK_SKIP_SUBTREES;
17116+ }
1711417117
17115- if (treeHasSideEffects )
17118+ if (m_compiler->gtNodeHasSideEffects(node, m_flags) )
1711617119 {
17117- if (m_compiler->gtNodeHasSideEffects(node, m_flags ))
17120+ if (node->OperIsBlk() && !node->OperIsStoreBlk( ))
1711817121 {
17119- if (node->OperIsBlk() && !node->OperIsStoreBlk())
17120- {
17121- JITDUMP("Replace an unused BLK node [%06d] with a NULLCHECK\n", dspTreeID(node));
17122- m_compiler->gtChangeOperToNullCheck(node, m_compiler->compCurBB);
17123- }
17124-
17125- Append(node);
17126- return Compiler::WALK_SKIP_SUBTREES;
17122+ JITDUMP("Replace an unused BLK node [%06d] with a NULLCHECK\n", dspTreeID(node));
17123+ m_compiler->gtChangeOperToNullCheck(node, m_compiler->compCurBB);
1712717124 }
1712817125
17129- if (node->OperIs(GT_QMARK))
17130- {
17131- GenTree* prevSideEffects = m_result;
17132- // Visit children out of order so we know if we can
17133- // completely remove the qmark. We cannot modify the
17134- // condition if we cannot completely remove the qmark, so
17135- // we cannot visit it first.
17126+ Append(node);
17127+ return Compiler::WALK_SKIP_SUBTREES;
17128+ }
1713617129
17137- GenTreeQmark* qmark = node->AsQmark();
17138- GenTreeColon* colon = qmark->gtGetOp2()->AsColon();
17130+ if (node->OperIs(GT_QMARK))
17131+ {
17132+ GenTree* prevSideEffects = m_result;
17133+ // Visit children out of order so we know if we can
17134+ // completely remove the qmark. We cannot modify the
17135+ // condition if we cannot completely remove the qmark, so
17136+ // we cannot visit it first.
1713917137
17140- m_result = nullptr;
17141- WalkTree(&colon->gtOp1, colon);
17142- GenTree* thenSideEffects = m_result;
17138+ GenTreeQmark* qmark = node->AsQmark();
17139+ GenTreeColon* colon = qmark->gtGetOp2()->AsColon();
1714317140
17144- m_result = nullptr;
17145- WalkTree(&colon->gtOp2 , colon);
17146- GenTree* elseSideEffects = m_result;
17141+ m_result = nullptr;
17142+ WalkTree(&colon->gtOp1 , colon);
17143+ GenTree* thenSideEffects = m_result;
1714717144
17148- m_result = prevSideEffects;
17145+ m_result = nullptr;
17146+ WalkTree(&colon->gtOp2, colon);
17147+ GenTree* elseSideEffects = m_result;
1714917148
17150- if ((thenSideEffects == nullptr) && (elseSideEffects == nullptr))
17151- {
17152- WalkTree(&qmark->gtOp1, qmark);
17153- }
17154- else
17155- {
17156- colon->gtOp1 = (thenSideEffects != nullptr) ? thenSideEffects : m_compiler->gtNewNothingNode();
17157- colon->gtOp2 = (elseSideEffects != nullptr) ? elseSideEffects : m_compiler->gtNewNothingNode();
17158- qmark->gtType = TYP_VOID;
17159- colon->gtType = TYP_VOID;
17160- Append(qmark);
17161- }
17149+ m_result = prevSideEffects;
1716217150
17163- return Compiler::WALK_SKIP_SUBTREES;
17151+ if ((thenSideEffects == nullptr) && (elseSideEffects == nullptr))
17152+ {
17153+ WalkTree(&qmark->gtOp1, qmark);
1716417154 }
17165-
17166- // Generally all GT_CALL nodes are considered to have side-effects.
17167- // So if we get here it must be a helper call that we decided it does
17168- // not have side effects that we needed to keep.
17169- assert(!node->OperIs(GT_CALL) || node->AsCall()->IsHelperCall());
17170- }
17171-
17172- if ((m_flags & GTF_IS_IN_CSE) != 0)
17173- {
17174- // If we're doing CSE then we also need to unmark CSE nodes. This will fail for CSE defs,
17175- // those need to be extracted as if they're side effects.
17176- if (!UnmarkCSE(node))
17155+ else
1717717156 {
17178- Append(node);
17179- return Compiler::WALK_SKIP_SUBTREES;
17157+ colon->gtOp1 = (thenSideEffects != nullptr) ? thenSideEffects : m_compiler->gtNewNothingNode();
17158+ colon->gtOp2 = (elseSideEffects != nullptr) ? elseSideEffects : m_compiler->gtNewNothingNode();
17159+ qmark->gtType = TYP_VOID;
17160+ colon->gtType = TYP_VOID;
17161+ Append(qmark);
1718017162 }
1718117163
17182- // The existence of CSE defs and uses is not propagated up the tree like side
17183- // effects are. We need to continue visiting the tree as if it has side effects.
17184- treeHasSideEffects = true;
17164+ return Compiler::WALK_SKIP_SUBTREES;
1718517165 }
1718617166
17187- return treeHasSideEffects ? Compiler::WALK_CONTINUE : Compiler::WALK_SKIP_SUBTREES ;
17167+ return Compiler::WALK_CONTINUE;
1718817168 }
1718917169
1719017170 void Append(GenTree* node)
@@ -17196,7 +17176,6 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
1719617176 }
1719717177
1719817178 GenTree* comma = m_compiler->gtNewOperNode(GT_COMMA, TYP_VOID, m_result, node);
17199- comma->gtFlags |= (m_result->gtFlags | node->gtFlags) & GTF_ALL_EFFECT;
1720017179
1720117180#ifdef DEBUG
1720217181 if (m_compiler->fgGlobalMorph)
@@ -17218,52 +17197,12 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
1721817197 //
1721917198 if ((m_compiler->vnStore != nullptr) && m_result->gtVNPair.BothDefined() && node->gtVNPair.BothDefined())
1722017199 {
17221- // The result of a GT_COMMA node is op2, the normal value number is op2vnp
17222- // But we also need to include the union of side effects from op1 and op2.
17223- // we compute this value into exceptions_vnp.
17224- ValueNumPair op1vnp;
17225- ValueNumPair op1Xvnp = ValueNumStore::VNPForEmptyExcSet();
17226- ValueNumPair op2vnp;
17227- ValueNumPair op2Xvnp = ValueNumStore::VNPForEmptyExcSet();
17228-
17229- m_compiler->vnStore->VNPUnpackExc(node->gtVNPair, &op1vnp, &op1Xvnp);
17230- m_compiler->vnStore->VNPUnpackExc(m_result->gtVNPair, &op2vnp, &op2Xvnp);
17231-
17232- ValueNumPair exceptions_vnp = ValueNumStore::VNPForEmptyExcSet();
17233-
17234- exceptions_vnp = m_compiler->vnStore->VNPExcSetUnion(exceptions_vnp, op1Xvnp);
17235- exceptions_vnp = m_compiler->vnStore->VNPExcSetUnion(exceptions_vnp, op2Xvnp);
17236-
17237- comma->gtVNPair = m_compiler->vnStore->VNPWithExc(op2vnp, exceptions_vnp);
17200+ ValueNumPair op1Exceptions = m_compiler->vnStore->VNPExceptionSet(m_result->gtVNPair);
17201+ comma->gtVNPair = m_compiler->vnStore->VNPWithExc(node->gtVNPair, op1Exceptions);
1723817202 }
1723917203
1724017204 m_result = comma;
1724117205 }
17242-
17243- private:
17244- bool UnmarkCSE(GenTree* node)
17245- {
17246- assert(m_compiler->optValnumCSE_phase);
17247-
17248- if (m_compiler->optUnmarkCSE(node))
17249- {
17250- // The call to optUnmarkCSE(node) should have cleared any CSE info.
17251- assert(!IS_CSE_INDEX(node->gtCSEnum));
17252- return true;
17253- }
17254- else
17255- {
17256- assert(IS_CSE_DEF(node->gtCSEnum));
17257- #ifdef DEBUG
17258- if (m_compiler->verbose)
17259- {
17260- printf("Preserving the CSE def #%02d at ", GET_CSE_INDEX(node->gtCSEnum));
17261- m_compiler->printTreeID(node);
17262- }
17263- #endif
17264- return false;
17265- }
17266- }
1726717206 };
1726817207
1726917208 SideEffectExtractor extractor(this, flags);
0 commit comments