@@ -15161,52 +15161,105 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
15161
15161
{
15162
15162
GenTree* node = *use;
15163
15163
15164
- if (!m_compiler->gtTreeHasSideEffects(node, m_flags))
15165
- {
15166
- return Compiler::WALK_SKIP_SUBTREES;
15167
- }
15164
+ bool treeHasSideEffects = m_compiler->gtTreeHasSideEffects(node, m_flags);
15168
15165
15169
- if (m_compiler->gtNodeHasSideEffects(node, m_flags) )
15166
+ if (treeHasSideEffects )
15170
15167
{
15171
- m_sideEffects.Push(node);
15172
- return Compiler::WALK_SKIP_SUBTREES;
15173
- }
15168
+ if (m_compiler->gtNodeHasSideEffects(node, m_flags))
15169
+ {
15170
+ m_sideEffects.Push(node);
15171
+ return Compiler::WALK_SKIP_SUBTREES;
15172
+ }
15174
15173
15175
- // TODO-Cleanup: These have GTF_ASG set but for some reason gtNodeHasSideEffects ignores
15176
- // them. See the related gtNodeHasSideEffects comment as well.
15177
- // Also, these nodes must always be preserved, no matter what side effect flags are passed
15178
- // in. But then it should never be the case that gtExtractSideEffList gets called without
15179
- // specifying GTF_ASG so there doesn't seem to be any reason to be inconsistent with
15180
- // gtNodeHasSideEffects and make this check unconditionally.
15181
- if (node->OperIsAtomicOp())
15182
- {
15183
- m_sideEffects.Push(node);
15184
- return Compiler::WALK_SKIP_SUBTREES;
15185
- }
15174
+ // TODO-Cleanup: These have GTF_ASG set but for some reason gtNodeHasSideEffects ignores
15175
+ // them. See the related gtNodeHasSideEffects comment as well.
15176
+ // Also, these nodes must always be preserved, no matter what side effect flags are passed
15177
+ // in. But then it should never be the case that gtExtractSideEffList gets called without
15178
+ // specifying GTF_ASG so there doesn't seem to be any reason to be inconsistent with
15179
+ // gtNodeHasSideEffects and make this check unconditionally.
15180
+ if (node->OperIsAtomicOp())
15181
+ {
15182
+ m_sideEffects.Push(node);
15183
+ return Compiler::WALK_SKIP_SUBTREES;
15184
+ }
15186
15185
15187
- if ((m_flags & GTF_EXCEPT) != 0)
15188
- {
15189
- // Special case - GT_ADDR of GT_IND nodes of TYP_STRUCT have to be kept together.
15190
- if (node->OperIs(GT_ADDR) && node->gtGetOp1()->OperIsIndir() &&
15191
- (node->gtGetOp1()->TypeGet() == TYP_STRUCT))
15186
+ if ((m_flags & GTF_EXCEPT) != 0)
15192
15187
{
15193
- #ifdef DEBUG
15194
- if (m_compiler->verbose)
15188
+ // Special case - GT_ADDR of GT_IND nodes of TYP_STRUCT have to be kept together.
15189
+ if (node->OperIs(GT_ADDR) && node->gtGetOp1()->OperIsIndir() &&
15190
+ (node->gtGetOp1()->TypeGet() == TYP_STRUCT))
15195
15191
{
15196
- printf("Keep the GT_ADDR and GT_IND together:\n");
15197
- }
15192
+ #ifdef DEBUG
15193
+ if (m_compiler->verbose)
15194
+ {
15195
+ printf("Keep the GT_ADDR and GT_IND together:\n");
15196
+ }
15198
15197
#endif
15198
+ m_sideEffects.Push(node);
15199
+ return Compiler::WALK_SKIP_SUBTREES;
15200
+ }
15201
+ }
15202
+
15203
+ // Generally all GT_CALL nodes are considered to have side-effects.
15204
+ // So if we get here it must be a helper call that we decided it does
15205
+ // not have side effects that we needed to keep.
15206
+ assert(!node->OperIs(GT_CALL) || (node->AsCall()->gtCallType == CT_HELPER));
15207
+ }
15208
+
15209
+ if ((m_flags & GTF_IS_IN_CSE) != 0)
15210
+ {
15211
+ // If we're doing CSE then we also need to unmark CSE nodes. This will fail for CSE defs,
15212
+ // those need to be extracted as if they're side effects.
15213
+ if (!UnmarkCSE(node))
15214
+ {
15199
15215
m_sideEffects.Push(node);
15200
15216
return Compiler::WALK_SKIP_SUBTREES;
15201
15217
}
15218
+
15219
+ // This node is going away, decrement the ref count if it's a GT_LCL_VAR.
15220
+ // TODO-Cleanup: This seems incorrect, the ref count should also be decremented for
15221
+ // GT_LCL_FLD nodes. This won't be needed anymore if the JIT stops doing incremental
15222
+ // ref count updates.
15223
+ if (node->OperIs(GT_LCL_VAR))
15224
+ {
15225
+ unsigned lclNum = node->AsLclVar()->GetLclNum();
15226
+ assert(lclNum < m_compiler->lvaCount);
15227
+ LclVarDsc* varDsc = &m_compiler->lvaTable[lclNum];
15228
+ assert(m_compiler->optCSEweight <= BB_MAX_WEIGHT);
15229
+ varDsc->decRefCnts(m_compiler->optCSEweight, m_compiler);
15230
+ }
15231
+
15232
+ // The existence of CSE defs and uses is not propagated up the tree like side
15233
+ // effects are. We need to continue visiting the tree as if it has side effects.
15234
+ treeHasSideEffects = true;
15202
15235
}
15203
15236
15204
- // Generally all GT_CALL nodes are considered to have side-effects.
15205
- // So if we get here it must be a helper call that we decided it does
15206
- // not have side effects that we needed to keep.
15207
- assert(!node->OperIs(GT_CALL) || (node->AsCall()->gtCallType == CT_HELPER));
15237
+ return treeHasSideEffects ? Compiler::WALK_CONTINUE : Compiler::WALK_SKIP_SUBTREES;
15238
+ }
15239
+
15240
+ private:
15241
+ bool UnmarkCSE(GenTree* node)
15242
+ {
15243
+ assert(m_compiler->optValnumCSE_phase);
15208
15244
15209
- return Compiler::WALK_CONTINUE;
15245
+ if (m_compiler->optUnmarkCSE(node))
15246
+ {
15247
+ // The call to optUnmarkCSE(node) should have cleared any CSE info.
15248
+ assert(!IS_CSE_INDEX(node->gtCSEnum));
15249
+ return true;
15250
+ }
15251
+ else
15252
+ {
15253
+ assert(IS_CSE_DEF(node->gtCSEnum));
15254
+ #ifdef DEBUG
15255
+ if (m_compiler->verbose)
15256
+ {
15257
+ printf("Preserving the CSE def #%02d at ", GET_CSE_INDEX(node->gtCSEnum));
15258
+ m_compiler->printTreeID(node);
15259
+ }
15260
+ #endif
15261
+ return false;
15262
+ }
15210
15263
}
15211
15264
};
15212
15265
0 commit comments