From: Bruce Forstall Date: Tue, 14 Mar 2017 01:33:06 +0000 (-0700) Subject: Improve LIR dumping (dotnet/coreclr#10140) X-Git-Tag: submit/tizen/20210909.063632~11030^2~7742 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=042b1ec0fb472b37e7c1b13336b3477ed4283b59;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Improve LIR dumping (dotnet/coreclr#10140) 1. Use the LIR node dumper to display nodes to be generated by codegen, since we're in LIR form at that point. Add a new "prefix message" argument to allow "Generating: " to prefix all such lines. 2. Fix off-by-one error in LIR dump due to `#ifdef` versus `#if`. 3. Remove extra trailing line for each LIR node. This interfered with dotnet/coreclr#1. But I always thought it was unnecessarily verbose; I don't believe there is any ambiguity without that extra space. 4. Add dTreeLIR()/cTreeLIR() functions for use in the debugger. Commit migrated from https://github.com/dotnet/coreclr/commit/8d749d34e8f028580d923d8514e4926e16234551 --- diff --git a/src/coreclr/src/jit/codegenarm.cpp b/src/coreclr/src/jit/codegenarm.cpp index 36509be5..871caa5 100644 --- a/src/coreclr/src/jit/codegenarm.cpp +++ b/src/coreclr/src/jit/codegenarm.cpp @@ -501,11 +501,13 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) #ifdef DEBUG lastConsumedNode = nullptr; + if (compiler->verbose) + { + unsigned seqNum = treeNode->gtSeqNum; // Useful for setting a conditional break in Visual Studio + compiler->gtDispLIRNode(treeNode, "Generating: "); + } #endif - JITDUMP("Generating: "); - DISPNODE(treeNode); - // contained nodes are part of their parents for codegen purposes // ex : immediates, most LEAs if (treeNode->isContained()) diff --git a/src/coreclr/src/jit/codegenarm64.cpp b/src/coreclr/src/jit/codegenarm64.cpp index 0968df5..4ec4bcf 100644 --- a/src/coreclr/src/jit/codegenarm64.cpp +++ b/src/coreclr/src/jit/codegenarm64.cpp @@ -1923,8 +1923,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) if (compiler->verbose) { unsigned seqNum = treeNode->gtSeqNum; // Useful for setting a conditional break in Visual Studio - printf("Generating: "); - compiler->gtDispTree(treeNode, nullptr, nullptr, true); + compiler->gtDispLIRNode(treeNode, "Generating: "); } #endif // DEBUG diff --git a/src/coreclr/src/jit/codegenxarch.cpp b/src/coreclr/src/jit/codegenxarch.cpp index 55e0cf2..ca6c425 100644 --- a/src/coreclr/src/jit/codegenxarch.cpp +++ b/src/coreclr/src/jit/codegenxarch.cpp @@ -1266,8 +1266,7 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) if (compiler->verbose) { unsigned seqNum = treeNode->gtSeqNum; // Useful for setting a conditional break in Visual Studio - printf("Generating: "); - compiler->gtDispTree(treeNode, nullptr, nullptr, true); + compiler->gtDispLIRNode(treeNode, "Generating: "); } #endif // DEBUG diff --git a/src/coreclr/src/jit/compiler.cpp b/src/coreclr/src/jit/compiler.cpp index 4e9c4b3..b81ae24 100644 --- a/src/coreclr/src/jit/compiler.cpp +++ b/src/coreclr/src/jit/compiler.cpp @@ -8164,11 +8164,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * The versions that start with 'd' use the tlsCompiler, so don't require a Compiler*. * * Summary: - * cBlock, dBlock : Display a basic block (call fgDispBasicBlock()). + * cBlock, dBlock : Display a basic block (call fgTableDispBasicBlock()). * cBlocks, dBlocks : Display all the basic blocks of a function (call fgDispBasicBlocks()). * cBlocksV, dBlocksV : Display all the basic blocks of a function (call fgDispBasicBlocks(true)). * "V" means "verbose", and will dump all the trees. * cTree, dTree : Display a tree (call gtDispTree()). + * cTreeLIR, dTreeLIR : Display a tree in LIR form (call gtDispLIRNode()). * cTrees, dTrees : Display all the trees in a function (call fgDumpTrees()). * cEH, dEH : Display the EH handler table (call fgDispHandlerTab()). * cVar, dVar : Display a local variable given its number (call lvaDumpEntry()). @@ -8238,6 +8239,13 @@ void cTree(Compiler* comp, GenTree* tree) comp->gtDispTree(tree, nullptr, ">>>"); } +void cTreeLIR(Compiler* comp, GenTree* tree) +{ + static unsigned sequenceNumber = 0; // separate calls with a number to indicate this function has been called + printf("===================================================================== *TreeLIR %u\n", sequenceNumber++); + comp->gtDispLIRNode(tree); +} + void cTrees(Compiler* comp) { static unsigned sequenceNumber = 0; // separate calls with a number to indicate this function has been called @@ -8352,6 +8360,11 @@ void dTree(GenTree* tree) cTree(JitTls::GetCompiler(), tree); } +void dTreeLIR(GenTree* tree) +{ + cTreeLIR(JitTls::GetCompiler(), tree); +} + void dTrees() { cTrees(JitTls::GetCompiler()); diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index 6194a71..da5ebbc 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -2235,7 +2235,7 @@ public: void gtDispTreeRange(LIR::Range& containingRange, GenTree* tree); - void gtDispLIRNode(GenTree* node); + void gtDispLIRNode(GenTree* node, const char* prefixMsg = nullptr); #endif // For tree walks diff --git a/src/coreclr/src/jit/gentree.cpp b/src/coreclr/src/jit/gentree.cpp index 5150c0c..1ef2302 100644 --- a/src/coreclr/src/jit/gentree.cpp +++ b/src/coreclr/src/jit/gentree.cpp @@ -11994,16 +11994,23 @@ void Compiler::gtDispTreeRange(LIR::Range& containingRange, GenTree* tree) // // Arguments: // node - the LIR node to dump. +// prefixMsg - an optional prefix for each line of output. // -void Compiler::gtDispLIRNode(GenTree* node) +void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr */) { - auto displayOperand = [](GenTree* operand, const char* message, IndentInfo operandArc, IndentStack& indentStack) { + auto displayOperand = [](GenTree* operand, const char* message, IndentInfo operandArc, IndentStack& indentStack, + size_t prefixIndent = 0) { assert(operand != nullptr); assert(message != nullptr); + if (prefixIndent != 0) + { + printf("%*s", (int)prefixIndent, ""); + } + // 49 spaces for alignment printf("%-49s", ""); -#ifdef FEATURE_SET_FLAGS +#if FEATURE_SET_FLAGS // additional flag enlarges the flag field by one character printf(" "); #endif @@ -12014,11 +12021,16 @@ void Compiler::gtDispLIRNode(GenTree* node) operandArc = IIArc; printf(" t%-5d %-6s %s\n", operand->gtTreeID, varTypeName(operand->TypeGet()), message); - }; IndentStack indentStack(this); + size_t prefixIndent = 0; + if (prefixMsg != nullptr) + { + prefixIndent = strlen(prefixMsg); + } + const int bufLength = 256; char buf[bufLength]; @@ -12040,19 +12052,19 @@ void Compiler::gtDispLIRNode(GenTree* node) if (operand == call->gtCallObjp) { sprintf_s(buf, sizeof(buf), "this in %s", compRegVarName(REG_ARG_0)); - displayOperand(operand, buf, operandArc, indentStack); + displayOperand(operand, buf, operandArc, indentStack, prefixIndent); } else if (operand == call->gtCallAddr) { - displayOperand(operand, "calli tgt", operandArc, indentStack); + displayOperand(operand, "calli tgt", operandArc, indentStack, prefixIndent); } else if (operand == call->gtControlExpr) { - displayOperand(operand, "control expr", operandArc, indentStack); + displayOperand(operand, "control expr", operandArc, indentStack, prefixIndent); } else if (operand == call->gtCallCookie) { - displayOperand(operand, "cookie", operandArc, indentStack); + displayOperand(operand, "cookie", operandArc, indentStack, prefixIndent); } else { @@ -12074,7 +12086,7 @@ void Compiler::gtDispLIRNode(GenTree* node) gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, listIndex, buf, sizeof(buf)); } - displayOperand(operand, buf, operandArc, indentStack); + displayOperand(operand, buf, operandArc, indentStack, prefixIndent); operandArc = IIArc; } } @@ -12089,7 +12101,7 @@ void Compiler::gtDispLIRNode(GenTree* node) gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, -1, buf, sizeof(buf)); } - displayOperand(operand, buf, operandArc, indentStack); + displayOperand(operand, buf, operandArc, indentStack, prefixIndent); } } } @@ -12097,55 +12109,59 @@ void Compiler::gtDispLIRNode(GenTree* node) { if (operand == node->AsBlk()->Addr()) { - displayOperand(operand, "lhs", operandArc, indentStack); + displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent); } else if (operand == node->AsBlk()->Data()) { - displayOperand(operand, "rhs", operandArc, indentStack); + displayOperand(operand, "rhs", operandArc, indentStack, prefixIndent); } else { assert(operand == node->AsDynBlk()->gtDynamicSize); - displayOperand(operand, "size", operandArc, indentStack); + displayOperand(operand, "size", operandArc, indentStack, prefixIndent); } } else if (node->OperGet() == GT_DYN_BLK) { if (operand == node->AsBlk()->Addr()) { - displayOperand(operand, "lhs", operandArc, indentStack); + displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent); } else { assert(operand == node->AsDynBlk()->gtDynamicSize); - displayOperand(operand, "size", operandArc, indentStack); + displayOperand(operand, "size", operandArc, indentStack, prefixIndent); } } else if (node->OperIsAssignment()) { if (operand == node->gtGetOp1()) { - displayOperand(operand, "lhs", operandArc, indentStack); + displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent); } else { - displayOperand(operand, "rhs", operandArc, indentStack); + displayOperand(operand, "rhs", operandArc, indentStack, prefixIndent); } } else { - displayOperand(operand, "", operandArc, indentStack); + displayOperand(operand, "", operandArc, indentStack, prefixIndent); } operandArc = IIArc; } // Visit the operator + + if (prefixMsg != nullptr) + { + printf("%s", prefixMsg); + } + const bool topOnly = true; const bool isLIR = true; gtDispTree(node, &indentStack, nullptr, topOnly, isLIR); - - printf("\n"); } /*****************************************************************************/