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

Commit ddf5d3d

Browse files
author
Sergey Andreenko
committed
optimize fgMorphTree for GenTreeArgList (#18582)
* add fgMorphArgList * hide the call inside fgMorphSmpOp * fix grammar mistakes
1 parent 916f553 commit ddf5d3d

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

src/jit/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4923,6 +4923,7 @@ class Compiler
49234923
GenTree* fgMorphCast(GenTree* tree);
49244924
GenTree* fgUnwrapProxy(GenTree* objRef);
49254925
GenTreeCall* fgMorphArgs(GenTreeCall* call);
4926+
GenTreeArgList* fgMorphArgList(GenTreeArgList* args, MorphAddrContext* mac);
49264927

49274928
void fgMakeOutgoingStructArgCopy(GenTreeCall* call,
49284929
GenTree* args,

src/jit/morph.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12255,6 +12255,9 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
1225512255
}
1225612256
break;
1225712257
#endif
12258+
case GT_LIST:
12259+
// Special handling for the arg list.
12260+
return fgMorphArgList(tree->AsArgList(), mac);
1225812261

1225912262
default:
1226012263
break;
@@ -20024,3 +20027,64 @@ bool Compiler::fgCheckStmtAfterTailCall()
2002420027
}
2002520028
return nextMorphStmt == nullptr;
2002620029
}
20030+
20031+
//------------------------------------------------------------------------
20032+
// fgMorphArgList: morph argument list tree without recursion.
20033+
//
20034+
// Arguments:
20035+
// args - argument list tree to morph;
20036+
// mac - morph address context, used to morph children.
20037+
//
20038+
// Return Value:
20039+
// morphed argument list.
20040+
//
20041+
GenTreeArgList* Compiler::fgMorphArgList(GenTreeArgList* args, MorphAddrContext* mac)
20042+
{
20043+
// Use a non-recursive algorithm that morphs all actual list values,
20044+
// memorizes the last node for each effect flag and resets
20045+
// them during the second iteration.
20046+
constexpr int numberOfTrackedFlags = 5;
20047+
constexpr unsigned trackedFlags[numberOfTrackedFlags] = {GTF_ASG, GTF_CALL, GTF_EXCEPT, GTF_GLOB_REF,
20048+
GTF_ORDER_SIDEEFF};
20049+
static_assert_no_msg((trackedFlags[0] | trackedFlags[1] | trackedFlags[2] | trackedFlags[3] | trackedFlags[4]) ==
20050+
GTF_ALL_EFFECT);
20051+
20052+
GenTree* memorizedLastNodes[numberOfTrackedFlags] = {nullptr};
20053+
20054+
for (GenTreeArgList* listNode = args; listNode != nullptr; listNode = listNode->Rest())
20055+
{
20056+
// Morph actual list values.
20057+
GenTree*& arg = listNode->Current();
20058+
arg = fgMorphTree(arg, mac);
20059+
20060+
// Remember the last list node with each flag.
20061+
for (int i = 0; i < numberOfTrackedFlags; ++i)
20062+
{
20063+
if ((arg->gtFlags & trackedFlags[i]) != 0)
20064+
{
20065+
memorizedLastNodes[i] = listNode;
20066+
}
20067+
}
20068+
}
20069+
20070+
for (GenTreeArgList* listNode = args; listNode != nullptr; listNode = listNode->Rest())
20071+
{
20072+
// Clear all old effects from the list node.
20073+
listNode->gtFlags &= ~GTF_ALL_EFFECT;
20074+
20075+
// Spread each flag to all list nodes (to the prefix) before the memorized last node.
20076+
for (int i = 0; i < numberOfTrackedFlags; ++i)
20077+
{
20078+
if (memorizedLastNodes[i] != nullptr)
20079+
{
20080+
listNode->gtFlags |= trackedFlags[i];
20081+
}
20082+
if (listNode == memorizedLastNodes[i])
20083+
{
20084+
memorizedLastNodes[i] = nullptr;
20085+
}
20086+
}
20087+
}
20088+
20089+
return args;
20090+
}

0 commit comments

Comments
 (0)