@@ -12255,6 +12255,9 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
12255
12255
}
12256
12256
break;
12257
12257
#endif
12258
+ case GT_LIST:
12259
+ // Special handling for the arg list.
12260
+ return fgMorphArgList(tree->AsArgList(), mac);
12258
12261
12259
12262
default:
12260
12263
break;
@@ -20024,3 +20027,64 @@ bool Compiler::fgCheckStmtAfterTailCall()
20024
20027
}
20025
20028
return nextMorphStmt == nullptr;
20026
20029
}
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