{
#if MEASURE_NODE_SIZE
- /*
- IMPORTANT: Use the following code to check the alignment of
- GenTree members (in a retail build, of course).
- */
-
- GenTree* gtDummy = nullptr;
-
- fprintf(fout, "\n");
- fprintf(fout, "Offset / size of gtOper = %2u / %2u\n", offsetof(GenTree, gtOper), sizeof(gtDummy->gtOper));
- fprintf(fout, "Offset / size of gtType = %2u / %2u\n", offsetof(GenTree, gtType), sizeof(gtDummy->gtType));
-#if FEATURE_ANYCSE
- fprintf(fout, "Offset / size of gtCSEnum = %2u / %2u\n", offsetof(GenTree, gtCSEnum),
- sizeof(gtDummy->gtCSEnum));
-#endif // FEATURE_ANYCSE
-#if ASSERTION_PROP
- fprintf(fout, "Offset / size of gtAssertionNum = %2u / %2u\n", offsetof(GenTree, gtAssertionNum),
- sizeof(gtDummy->gtAssertionNum));
-#endif // ASSERTION_PROP
-#if FEATURE_STACK_FP_X87
- fprintf(fout, "Offset / size of gtFPlvl = %2u / %2u\n", offsetof(GenTree, gtFPlvl),
- sizeof(gtDummy->gtFPlvl));
-#endif // FEATURE_STACK_FP_X87
- // TODO: The section that report GenTree sizes should be made into a public static member function of the GenTree
- // class (see https://github.com/dotnet/coreclr/pull/493)
- // fprintf(fout, "Offset / size of gtCostEx = %2u / %2u\n", offsetof(GenTree, _gtCostEx ),
- // sizeof(gtDummy->_gtCostEx ));
- // fprintf(fout, "Offset / size of gtCostSz = %2u / %2u\n", offsetof(GenTree, _gtCostSz ),
- // sizeof(gtDummy->_gtCostSz ));
- fprintf(fout, "Offset / size of gtFlags = %2u / %2u\n", offsetof(GenTree, gtFlags),
- sizeof(gtDummy->gtFlags));
- fprintf(fout, "Offset / size of gtVNPair = %2u / %2u\n", offsetof(GenTree, gtVNPair),
- sizeof(gtDummy->gtVNPair));
- fprintf(fout, "Offset / size of gtRsvdRegs = %2u / %2u\n", offsetof(GenTree, gtRsvdRegs),
- sizeof(gtDummy->gtRsvdRegs));
-#ifdef LEGACY_BACKEND
- fprintf(fout, "Offset / size of gtUsedRegs = %2u / %2u\n", offsetof(GenTree, gtUsedRegs),
- sizeof(gtDummy->gtUsedRegs));
-#endif // LEGACY_BACKEND
-#ifndef LEGACY_BACKEND
- fprintf(fout, "Offset / size of gtLsraInfo = %2u / %2u\n", offsetof(GenTree, gtLsraInfo),
- sizeof(gtDummy->gtLsraInfo));
-#endif // !LEGACY_BACKEND
- fprintf(fout, "Offset / size of gtNext = %2u / %2u\n", offsetof(GenTree, gtNext), sizeof(gtDummy->gtNext));
- fprintf(fout, "Offset / size of gtPrev = %2u / %2u\n", offsetof(GenTree, gtPrev), sizeof(gtDummy->gtPrev));
- fprintf(fout, "\n");
-
-#if SMALL_TREE_NODES
- fprintf(fout, "Small tree node size = %3u\n", TREE_NODE_SZ_SMALL);
-#endif // SMALL_TREE_NODES
- fprintf(fout, "Large tree node size = %3u\n", TREE_NODE_SZ_LARGE);
- fprintf(fout, "\n");
- fprintf(fout, "Size of GenTree = %3u\n", sizeof(GenTree));
- fprintf(fout, "Size of GenTreeUnOp = %3u\n", sizeof(GenTreeUnOp));
- fprintf(fout, "Size of GenTreeOp = %3u\n", sizeof(GenTreeOp));
- fprintf(fout, "Size of GenTreeVal = %3u\n", sizeof(GenTreeVal));
- fprintf(fout, "Size of GenTreeIntConCommon = %3u\n", sizeof(GenTreeIntConCommon));
- fprintf(fout, "Size of GenTreePhysReg = %3u\n", sizeof(GenTreePhysReg));
-#ifndef LEGACY_BACKEND
- fprintf(fout, "Size of GenTreeJumpTable = %3u\n", sizeof(GenTreeJumpTable));
-#endif // !LEGACY_BACKEND
- fprintf(fout, "Size of GenTreeIntCon = %3u\n", sizeof(GenTreeIntCon));
- fprintf(fout, "Size of GenTreeLngCon = %3u\n", sizeof(GenTreeLngCon));
- fprintf(fout, "Size of GenTreeDblCon = %3u\n", sizeof(GenTreeDblCon));
- fprintf(fout, "Size of GenTreeStrCon = %3u\n", sizeof(GenTreeStrCon));
- fprintf(fout, "Size of GenTreeLclVarCommon = %3u\n", sizeof(GenTreeLclVarCommon));
- fprintf(fout, "Size of GenTreeLclVar = %3u\n", sizeof(GenTreeLclVar));
- fprintf(fout, "Size of GenTreeLclFld = %3u\n", sizeof(GenTreeLclFld));
- fprintf(fout, "Size of GenTreeRegVar = %3u\n", sizeof(GenTreeRegVar));
- fprintf(fout, "Size of GenTreeCast = %3u\n", sizeof(GenTreeCast));
- fprintf(fout, "Size of GenTreeJumpCC = %3u\n", sizeof(GenTreeJumpCC));
- fprintf(fout, "Size of GenTreeBox = %3u\n", sizeof(GenTreeBox));
- fprintf(fout, "Size of GenTreeField = %3u\n", sizeof(GenTreeField));
- fprintf(fout, "Size of GenTreeArgList = %3u\n", sizeof(GenTreeArgList));
- fprintf(fout, "Size of GenTreeColon = %3u\n", sizeof(GenTreeColon));
- fprintf(fout, "Size of GenTreeCall = %3u\n", sizeof(GenTreeCall));
- fprintf(fout, "Size of GenTreeCmpXchg = %3u\n", sizeof(GenTreeCmpXchg));
- fprintf(fout, "Size of GenTreeFptrVal = %3u\n", sizeof(GenTreeFptrVal));
- fprintf(fout, "Size of GenTreeQmark = %3u\n", sizeof(GenTreeQmark));
- fprintf(fout, "Size of GenTreeIntrinsic = %3u\n", sizeof(GenTreeIntrinsic));
- fprintf(fout, "Size of GenTreeIndex = %3u\n", sizeof(GenTreeIndex));
- fprintf(fout, "Size of GenTreeArrLen = %3u\n", sizeof(GenTreeArrLen));
- fprintf(fout, "Size of GenTreeBoundsChk = %3u\n", sizeof(GenTreeBoundsChk));
- fprintf(fout, "Size of GenTreeArrElem = %3u\n", sizeof(GenTreeArrElem));
- fprintf(fout, "Size of GenTreeAddrMode = %3u\n", sizeof(GenTreeAddrMode));
- fprintf(fout, "Size of GenTreeIndir = %3u\n", sizeof(GenTreeIndir));
- fprintf(fout, "Size of GenTreeStoreInd = %3u\n", sizeof(GenTreeStoreInd));
- fprintf(fout, "Size of GenTreeRetExpr = %3u\n", sizeof(GenTreeRetExpr));
- fprintf(fout, "Size of GenTreeStmt = %3u\n", sizeof(GenTreeStmt));
- fprintf(fout, "Size of GenTreeObj = %3u\n", sizeof(GenTreeObj));
- fprintf(fout, "Size of GenTreeClsVar = %3u\n", sizeof(GenTreeClsVar));
- fprintf(fout, "Size of GenTreeArgPlace = %3u\n", sizeof(GenTreeArgPlace));
- fprintf(fout, "Size of GenTreeLabel = %3u\n", sizeof(GenTreeLabel));
- fprintf(fout, "Size of GenTreePhiArg = %3u\n", sizeof(GenTreePhiArg));
- fprintf(fout, "Size of GenTreePutArgStk = %3u\n", sizeof(GenTreePutArgStk));
- fprintf(fout, "Size of GenTreeCopyOrReload = %3u\n", sizeof(GenTreeCopyOrReload));
- fprintf(fout, "Size of GenTreeAllocObj = %3u\n", sizeof(GenTreeAllocObj));
- fprintf(fout, "Size of GenTreeBlk = %3u\n", sizeof(GenTreeBlk));
- fprintf(fout, "Size of GenTreeDynBlk = %3u\n", sizeof(GenTreeDynBlk));
- fprintf(fout, "Size of GenTreeArrIndex = %3u\n", sizeof(GenTreeArrIndex));
- fprintf(fout, "Size of GenTreeArrOffs = %3u\n", sizeof(GenTreeArrOffs));
-#ifdef FEATURE_SIMD
- fprintf(fout, "Size of GenTreeSIMD = %3u\n", sizeof(GenTreeSIMD));
+ GenTree::DumpNodeSizes(fout);
#endif
- fprintf(fout, "\n");
-#endif // MEASURE_NODE_SIZE
#if MEASURE_BLOCK_SIZE
sizeof(bbDummy->bbJumpDest));
fprintf(fout, "Offset / size of bbJumpSwt = %3u / %3u\n", offsetof(BasicBlock, bbJumpSwt),
sizeof(bbDummy->bbJumpSwt));
- fprintf(fout, "Offset / size of bbTreeList = %3u / %3u\n", offsetof(BasicBlock, bbTreeList),
- sizeof(bbDummy->bbTreeList));
fprintf(fout, "Offset / size of bbEntryState = %3u / %3u\n", offsetof(BasicBlock, bbEntryState),
sizeof(bbDummy->bbEntryState));
fprintf(fout, "Offset / size of bbStkTempsIn = %3u / %3u\n", offsetof(BasicBlock, bbStkTempsIn),
GenTree* switchVal = switchTree->gtOp.gtOp1;
noway_assert(genActualTypeIsIntOrI(switchVal->TypeGet()));
+#ifndef LEGACY_BACKEND
// If we are in LIR, remove the jump table from the block.
if (block->IsLIR())
{
assert(jumpTable->OperGet() == GT_JMPTABLE);
blockRange->Remove(jumpTable);
}
+#endif
// Change the GT_SWITCH(switchVal) into GT_JTRUE(GT_EQ(switchVal==0)).
// Also mark the node as GTF_DONT_CSE as further down JIT is not capable of handling it.
//
// For the (usual) case of GT_BLK or GT_OBJ, the size is always "evaluated" (i.e.
// instantiated into a register) last. In those cases, the GTF_REVERSE_OPS flag
-// on the assignment works as usual.
+// on the assignment works as usual.
// In order to preserve previous possible orderings, the order for evaluating
// the size of a GT_DYN_BLK node is controlled by its gtEvalSizeFirst flag. If
// that is set, the size is evaluated first, and then the src and dst are evaluated
{
createDotFile = true;
}
-
+
FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx"));
if (fgxFile == nullptr)
fprintf(fgxFile, ">");
}
- static const char* kindImage[] = { "EHFINALLYRET", "EHFILTERRET", "EHCATCHRET",
+ static const char* kindImage[] = { "EHFINALLYRET", "EHFILTERRET", "EHCATCHRET",
"THROW", "RETURN", "NONE", "ALWAYS", "LEAVE",
"CALLFINALLY", "COND", "SWITCH" };
{
printf("bad prev link!\n");
}
-
+
if (block == fgFirstColdBlock)
{
printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
/* Walk the basic blocks */
- // Note that typically we have already called fgDispBasicBlocks()
+ // Note that typically we have already called fgDispBasicBlocks()
// so we don't need to print the preds and succs again here
//
for (BasicBlock* block = firstBlock; block; block = block->bbNext)
{
GenTreePtr tree = *pTree;
Compiler* pComp = data->compiler;
-
+
if (tree->gtOper != GT_MUL || tree->gtType != TYP_INT || (tree->gtOverflow())) {
return WALK_CONTINUE;
}
#ifdef DEBUG
if (pComp->verbose)
{
- printf("STRESS_64RSLT_MUL before:\n");
+ printf("STRESS_64RSLT_MUL before:\n");
pComp->gtDispTree(tree);
}
#endif // DEBUG
// To ensure optNarrowTree() doesn't fold back to the original tree.
tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, TYP_LONG);
- tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1);
+ tree->gtOp.gtOp1 = pComp->gtNewOperNode(GT_NOP, TYP_LONG, tree->gtOp.gtOp1);
tree->gtOp.gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp1, TYP_LONG);
tree->gtOp.gtOp2 = pComp->gtNewCastNode(TYP_LONG, tree->gtOp.gtOp2, TYP_LONG);
tree->gtType = TYP_LONG;
#ifdef DEBUG
if (pComp->verbose)
{
- printf("STRESS_64RSLT_MUL after:\n");
+ printf("STRESS_64RSLT_MUL after:\n");
pComp->gtDispTree(*pTree);
}
#endif // DEBUG
#endif // DEBUG
fgDebugCheckBlockLinks();
-
+
if (fgBBcount > 10000 && expensiveDebugCheckLevel < 1)
{
// The basic block checks are too expensive if there are too many blocks,
fgDebugCheckFlags(op2);
}
- if (op1)
+ if (op1)
{
chkFlags |= (op1->gtFlags & GTF_ALL_EFFECT);
}
/* See what kind of a special operator we have here */
- else
- {
+ else
+ {
switch (tree->OperGet())
{
case GT_CALL:
GenTreePtr args;
GenTreePtr argx;
GenTreeCall* call;
-
+
call = tree->AsCall();
chkFlags |= GTF_CALL;
(void *) this);
// See if stmt is of the form GT_COMMA(call, nop)
- // If yes, we can get rid of GT_COMMA.
+ // If yes, we can get rid of GT_COMMA.
if (expr->OperGet() == GT_COMMA &&
expr->gtOp.gtOp1->OperGet() == GT_CALL &&
expr->gtOp.gtOp2->OperGet() == GT_NOP)
if (tree->gtOper == GT_RET_EXPR)
{
- // We are going to copy the tree from the inlinee,
+ // We are going to copy the tree from the inlinee,
// so record the handle now.
//
if (varTypeIsStruct(tree))
#ifdef DEBUG
if (comp->verbose)
{
- printf("\nReplacing the return expression placeholder ");
+ printf("\nReplacing the return expression placeholder ");
printTreeID(tree);
printf(" with ");
printTreeID(inlineCandidate);
}
#endif // DEBUG
- tree->CopyFrom(inlineCandidate, comp);
+ tree->CopyFrom(inlineCandidate, comp);
#ifdef DEBUG
if (comp->verbose)
#endif
-#if defined(DEBUG) || NODEBASH_STATS || COUNT_AST_OPERS
+#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
static const char* opNames[] = {
#define GTNODE(en, sn, st, cm, ok) #en,
#endif
+#if MEASURE_NODE_SIZE && SMALL_TREE_NODES
+
+static const char* opStructNames[] = {
+ #define GTNODE(en, sn, st, cm, ok) #st,
+ #include "gtlist.h"
+};
+
+const char* GenTree::OpStructName(genTreeOps op)
+{
+ assert((unsigned)op < sizeof(opStructNames) / sizeof(opStructNames[0]));
+
+ return opStructNames[op];
+}
+
+#endif
+
/*****************************************************************************
*
* When 'SMALL_TREE_NODES' is enabled, we allocate tree nodes in 2 different
/* static */
unsigned char GenTree::s_gtNodeSizes[GT_COUNT + 1];
-#if NODEBASH_STATS || COUNT_AST_OPERS
+#if NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
unsigned char GenTree::s_gtTrueSizes[GT_COUNT+1]
{
#include "gtlist.h"
};
-#endif // NODEBASH_STATS || COUNT_AST_OPERS
+#endif // NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
#if COUNT_AST_OPERS
LONG GenTree::s_gtNodeCounts[GT_COUNT+1] = {0};
/*****************************************************************************/
+#if MEASURE_NODE_SIZE
+
+void GenTree::DumpNodeSizes(FILE* fp)
+{
+ // Dump the sizes of the various GenTree flavors
+
+#if SMALL_TREE_NODES
+ fprintf(fp, "Small tree node size = %3u bytes\n", TREE_NODE_SZ_SMALL);
+#endif
+ fprintf(fp, "Large tree node size = %3u bytes\n", TREE_NODE_SZ_LARGE);
+ fprintf(fp, "\n");
+
+#if SMALL_TREE_NODES
+
+ // Verify that node sizes are set kosherly and dump sizes
+ for (unsigned op = GT_NONE+1; op < GT_COUNT; op++)
+ {
+ unsigned needSize = s_gtTrueSizes[op];
+ unsigned nodeSize = s_gtNodeSizes[op];
+
+ const char* structNm = OpStructName((genTreeOps)op);
+ const char* operName = OpName((genTreeOps)op);
+
+ bool repeated = false;
+
+ // Have we seen this struct flavor before?
+ for (unsigned mop = GT_NONE+1; mop < op; mop++)
+ {
+ if (strcmp(structNm, OpStructName((genTreeOps)mop)) == 0)
+ {
+ repeated = true;
+ break;
+ }
+ }
+
+ // Don't repeat the same GenTree flavor unless we have an error
+ if (!repeated || needSize > nodeSize)
+ {
+ unsigned sizeChar = '?';
+
+ if (nodeSize == TREE_NODE_SZ_SMALL)
+ sizeChar = 'S';
+ else if (nodeSize == TREE_NODE_SZ_LARGE)
+ sizeChar = 'L';
+
+ fprintf(fp, "GT_%-16s ... %-19s = %3u bytes (%c)", operName,
+ structNm,
+ needSize,
+ sizeChar);
+ if (needSize > nodeSize)
+ {
+ fprintf(fp, " -- ERROR -- allocation is only %u bytes!", nodeSize);
+ }
+ else if (needSize <= TREE_NODE_SZ_SMALL && nodeSize == TREE_NODE_SZ_LARGE)
+ {
+ fprintf(fp, " ... could be small");
+ }
+
+ fprintf(fp, "\n");
+ }
+ }
+
+#endif
+
+}
+
+#endif // MEASURE_NODE_SIZE
+/*****************************************************************************/
+
// make sure these get instantiated, because it's not in a header file
// (emulating the c++ 'export' keyword here)
// VC appears to be somewhat unpredictable about whether they end up in the .obj file without this
case GT_STORE_OBJ:
case GT_STORE_DYN_BLK:
case GT_SWITCH:
+#ifndef LEGACY_BACKEND
case GT_JMPTABLE:
+#endif
case GT_SWITCH_TABLE:
case GT_SWAP:
case GT_LCLHEAP: