@@ -16609,7 +16609,7 @@ GenTree* Compiler::gtNewRefCOMfield(GenTree* objPtr,
16609
16609
* It may return false even if the node has GTF_SIDE_EFFECT (because of its children).
16610
16610
*/
16611
16611
16612
- bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
16612
+ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags, bool ignoreCctors )
16613
16613
{
16614
16614
if (flags & GTF_ASG)
16615
16615
{
@@ -16636,20 +16636,20 @@ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
16636
16636
{
16637
16637
GenTreeCall* const call = potentialCall->AsCall();
16638
16638
const bool ignoreExceptions = (flags & GTF_EXCEPT) == 0;
16639
- const bool ignoreCctors = (flags & GTF_IS_IN_CSE) != 0; // We can CSE helpers that run cctors.
16640
16639
if (!call->HasSideEffects(this, ignoreExceptions, ignoreCctors))
16641
16640
{
16642
16641
// If this call is otherwise side effect free, check its arguments.
16643
16642
for (CallArg& arg : call->gtArgs.Args())
16644
16643
{
16645
16644
// I'm a little worried that args that assign to temps that are late args will look like
16646
16645
// 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))
16648
16648
{
16649
16649
return true;
16650
16650
}
16651
16651
16652
- if ((arg.GetLateNode() != nullptr) && gtTreeHasSideEffects(arg.GetLateNode(), flags))
16652
+ if ((arg.GetLateNode() != nullptr) && gtTreeHasSideEffects(arg.GetLateNode(), flags, ignoreCctors ))
16653
16653
{
16654
16654
return true;
16655
16655
}
@@ -16686,7 +16686,7 @@ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
16686
16686
* Returns true if the expr tree has any side effects.
16687
16687
*/
16688
16688
16689
- bool Compiler::gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags /* = GTF_SIDE_EFFECT*/)
16689
+ bool Compiler::gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags /* = GTF_SIDE_EFFECT*/, bool ignoreCctors )
16690
16690
{
16691
16691
// These are the side effect flags that we care about for this tree
16692
16692
GenTreeFlags sideEffectFlags = tree->gtFlags & flags;
@@ -16709,22 +16709,22 @@ bool Compiler::gtTreeHasSideEffects(GenTree* tree, GenTreeFlags flags /* = GTF_S
16709
16709
// If this node is a helper call we may not care about the side-effects.
16710
16710
// Note that gtNodeHasSideEffects checks the side effects of the helper itself
16711
16711
// as well as the side effects of its arguments.
16712
- return gtNodeHasSideEffects(tree, flags);
16712
+ return gtNodeHasSideEffects(tree, flags, ignoreCctors );
16713
16713
}
16714
16714
}
16715
16715
else if (tree->OperGet() == GT_INTRINSIC)
16716
16716
{
16717
- if (gtNodeHasSideEffects(tree, flags))
16717
+ if (gtNodeHasSideEffects(tree, flags, ignoreCctors ))
16718
16718
{
16719
16719
return true;
16720
16720
}
16721
16721
16722
- if (gtNodeHasSideEffects(tree->AsOp()->gtOp1, flags))
16722
+ if (gtNodeHasSideEffects(tree->AsOp()->gtOp1, flags, ignoreCctors ))
16723
16723
{
16724
16724
return true;
16725
16725
}
16726
16726
16727
- if ((tree->AsOp()->gtOp2 != nullptr) && gtNodeHasSideEffects(tree->AsOp()->gtOp2, flags))
16727
+ if ((tree->AsOp()->gtOp2 != nullptr) && gtNodeHasSideEffects(tree->AsOp()->gtOp2, flags, ignoreCctors ))
16728
16728
{
16729
16729
return true;
16730
16730
}
@@ -17110,81 +17110,61 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
17110
17110
{
17111
17111
GenTree* node = *use;
17112
17112
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
+ }
17114
17117
17115
- if (treeHasSideEffects )
17118
+ if (m_compiler->gtNodeHasSideEffects(node, m_flags) )
17116
17119
{
17117
- if (m_compiler->gtNodeHasSideEffects(node, m_flags ))
17120
+ if (node->OperIsBlk() && !node->OperIsStoreBlk( ))
17118
17121
{
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);
17127
17124
}
17128
17125
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
+ }
17136
17129
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.
17139
17137
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();
17143
17140
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;
17147
17144
17148
- m_result = prevSideEffects;
17145
+ m_result = nullptr;
17146
+ WalkTree(&colon->gtOp2, colon);
17147
+ GenTree* elseSideEffects = m_result;
17149
17148
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;
17162
17150
17163
- return Compiler::WALK_SKIP_SUBTREES;
17151
+ if ((thenSideEffects == nullptr) && (elseSideEffects == nullptr))
17152
+ {
17153
+ WalkTree(&qmark->gtOp1, qmark);
17164
17154
}
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
17177
17156
{
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);
17180
17162
}
17181
17163
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;
17185
17165
}
17186
17166
17187
- return treeHasSideEffects ? Compiler::WALK_CONTINUE : Compiler::WALK_SKIP_SUBTREES ;
17167
+ return Compiler::WALK_CONTINUE;
17188
17168
}
17189
17169
17190
17170
void Append(GenTree* node)
@@ -17196,7 +17176,6 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
17196
17176
}
17197
17177
17198
17178
GenTree* comma = m_compiler->gtNewOperNode(GT_COMMA, TYP_VOID, m_result, node);
17199
- comma->gtFlags |= (m_result->gtFlags | node->gtFlags) & GTF_ALL_EFFECT;
17200
17179
17201
17180
#ifdef DEBUG
17202
17181
if (m_compiler->fgGlobalMorph)
@@ -17218,52 +17197,12 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
17218
17197
//
17219
17198
if ((m_compiler->vnStore != nullptr) && m_result->gtVNPair.BothDefined() && node->gtVNPair.BothDefined())
17220
17199
{
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);
17238
17202
}
17239
17203
17240
17204
m_result = comma;
17241
17205
}
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
- }
17267
17206
};
17268
17207
17269
17208
SideEffectExtractor extractor(this, flags);
0 commit comments