Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 2ac939e

Browse files
committed
Fix CSE side effect and definition extraction
1 parent 5d31194 commit 2ac939e

File tree

6 files changed

+260
-431
lines changed

6 files changed

+260
-431
lines changed

src/jit/compiler.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,12 +5740,6 @@ class Compiler
57405740
bool optCSE_canSwap(GenTree* firstNode, GenTree* secondNode);
57415741
bool optCSE_canSwap(GenTree* tree);
57425742

5743-
static fgWalkPostFn optPropagateNonCSE;
5744-
static fgWalkPreFn optHasNonCSEChild;
5745-
5746-
static fgWalkPreFn optUnmarkCSEs;
5747-
static fgWalkPreFn optHasCSEdefWithSideeffect;
5748-
57495743
static int __cdecl optCSEcostCmpEx(const void* op1, const void* op2);
57505744
static int __cdecl optCSEcostCmpSz(const void* op1, const void* op2);
57515745

@@ -5773,7 +5767,6 @@ class Compiler
57735767
void optValnumCSE_DataFlow();
57745768
void optValnumCSE_Availablity();
57755769
void optValnumCSE_Heuristic();
5776-
bool optValnumCSE_UnmarkCSEs(GenTree* deadTree, GenTree** wbKeepList);
57775770

57785771
#endif // FEATURE_VALNUM_CSE
57795772

src/jit/gentree.cpp

Lines changed: 86 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15161,52 +15161,105 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
1516115161
{
1516215162
GenTree* node = *use;
1516315163

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);
1516815165

15169-
if (m_compiler->gtNodeHasSideEffects(node, m_flags))
15166+
if (treeHasSideEffects)
1517015167
{
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+
}
1517415173

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+
}
1518615185

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)
1519215187
{
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))
1519515191
{
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+
}
1519815197
#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+
{
1519915215
m_sideEffects.Push(node);
1520015216
return Compiler::WALK_SKIP_SUBTREES;
1520115217
}
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;
1520215235
}
1520315236

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);
1520815244

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+
}
1521015263
}
1521115264
};
1521215265

src/jit/gentree.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,6 @@ struct GenTree
706706
// The only requirement of this flag is that it not overlap any of the
707707
// side-effect flags. The actual bit used is otherwise arbitrary.
708708
#define GTF_IS_IN_CSE GTF_BOOLEAN
709-
#define GTF_PERSISTENT_SIDE_EFFECTS_IN_CSE (GTF_ASG | GTF_CALL | GTF_IS_IN_CSE)
710709

711710
// Can any side-effects be observed externally, say by a caller method?
712711
// For assignments, only assignments to global memory can be observed

0 commit comments

Comments
 (0)