From 16ba8b45e45acd5e47aa0883e25e8f78c6fcb14e Mon Sep 17 00:00:00 2001 From: Carol Eidt Date: Mon, 12 Oct 2020 11:25:16 -0700 Subject: [PATCH] Fix codegen for multi-reg EH vars (#42871) * Fix codegen for multi-reg EH vars Multi-reg EH vars were not properly being stored at each def. Fix the dumping of multi-reg nodes with register assignments. Temporarily enable EHWriteThru to get CI testing with it on. Fix #41232 --- src/coreclr/src/jit/codegencommon.cpp | 6 +- src/coreclr/src/jit/compiler.h | 3 + src/coreclr/src/jit/gentree.cpp | 115 ++++++++++++++++++++-------------- 3 files changed, 76 insertions(+), 48 deletions(-) diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index 22a050a..64285f1 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -11840,12 +11840,16 @@ void CodeGen::genMultiRegStoreToLocal(GenTreeLclVar* lclNode) } else { + varReg = REG_STK; + } + if ((varReg == REG_STK) || fieldVarDsc->lvLiveInOutOfHndlr) + { if (!lclNode->AsLclVar()->IsLastUse(i)) { GetEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, fieldLclNum, 0); } - fieldVarDsc->SetRegNum(REG_STK); } + fieldVarDsc->SetRegNum(varReg); } else { diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index 07bd7cb..fdb9b65 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -3058,6 +3058,9 @@ public: void gtDispConst(GenTree* tree); void gtDispLeaf(GenTree* tree, IndentStack* indentStack); void gtDispNodeName(GenTree* tree); +#if FEATURE_MULTIREG_RET + unsigned gtDispRegCount(GenTree* tree); +#endif void gtDispRegVal(GenTree* tree); void gtDispZeroFieldSeq(GenTree* tree); void gtDispVN(GenTree* tree); diff --git a/src/coreclr/src/jit/gentree.cpp b/src/coreclr/src/jit/gentree.cpp index 5da7ce2..8c9b64d 100644 --- a/src/coreclr/src/jit/gentree.cpp +++ b/src/coreclr/src/jit/gentree.cpp @@ -10534,73 +10534,94 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, __in __in_z _ } } +#if FEATURE_MULTIREG_RET +//---------------------------------------------------------------------------------- +// gtDispRegCount: determine how many registers to print for a multi-reg node +// +// Arguments: +// tree - Gentree node whose registers we want to print +// +// Return Value: +// The number of registers to print +// +// Notes: +// This is not the same in all cases as GenTree::GetMultiRegCount(). +// In particular, for COPY or RELOAD it only returns the number of *valid* registers, +// and for CALL, it will return 0 if the ReturnTypeDesc hasn't yet been initialized. +// But we want to print all register positions. +// +unsigned Compiler::gtDispRegCount(GenTree* tree) +{ + if (tree->IsCopyOrReload()) + { + // GetRegCount() will return only the number of valid regs for COPY or RELOAD, + // but we want to print all positions, so we get the reg count for op1. + return gtDispRegCount(tree->gtGetOp1()); + } + else if (!tree->IsMultiRegNode()) + { + // We can wind up here because IsMultiRegNode() always returns true for COPY or RELOAD, + // even if its op1 is not multireg. + // Note that this method won't be called for non-register-producing nodes. + return 1; + } + else if (tree->IsMultiRegLclVar()) + { + return tree->AsLclVar()->GetFieldCount(this); + } + else if (tree->OperIs(GT_CALL)) + { + unsigned regCount = tree->AsCall()->GetReturnTypeDesc()->TryGetReturnRegCount(); + // If it hasn't yet been initialized, we'd still like to see the registers printed. + if (regCount == 0) + { + regCount = MAX_RET_REG_COUNT; + } + return regCount; + } + else + { + return tree->GetMultiRegCount(); + } +} +#endif // FEATURE_MULTIREG_RET + +//---------------------------------------------------------------------------------- +// gtDispRegVal: Print the register(s) defined by the given node +// +// Arguments: +// tree - Gentree node whose registers we want to print +// void Compiler::gtDispRegVal(GenTree* tree) { switch (tree->GetRegTag()) { - // Don't display NOREG; the absence of this tag will imply this state - // case GenTree::GT_REGTAG_NONE: printf(" NOREG"); break; + // Don't display anything for the GT_REGTAG_NONE case; + // the absence of printed register values will imply this state. case GenTree::GT_REGTAG_REG: printf(" REG %s", compRegVarName(tree->GetRegNum())); break; default: - break; + return; } #if FEATURE_MULTIREG_RET - if (tree->OperIs(GT_CALL)) + if (tree->IsMultiRegNode()) { // 0th reg is GetRegNum(), which is already printed above. - // Print the remaining regs of a multi-reg call node. - // Note that, prior to the initialization of the ReturnTypeDesc we won't print - // any additional registers. - const GenTreeCall* call = tree->AsCall(); - const unsigned regCount = call->GetReturnTypeDesc()->TryGetReturnRegCount(); + // Print the remaining regs of a multi-reg node. + unsigned regCount = gtDispRegCount(tree); + + // For some nodes, e.g. COPY, RELOAD or CALL, we may not have valid regs for all positions. for (unsigned i = 1; i < regCount; ++i) { - printf(",%s", compRegVarName(call->GetRegNumByIdx(i))); - } - } - else if (tree->IsCopyOrReload()) - { - GenTree* op1 = tree->gtGetOp1(); - const GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload(); - unsigned regCount = 0; - if (op1->OperIs(GT_CALL)) - { - regCount = op1->AsCall()->GetReturnTypeDesc()->TryGetReturnRegCount(); - // If it hasn't yet been initialized, we'd still like to see the registers printed. - if (regCount == 0) - { - regCount = MAX_RET_REG_COUNT; - } - } - else if (op1->IsMultiRegLclVar()) - { - regCount = op1->AsLclVar()->GetFieldCount(this); - } - else if (op1->IsMultiRegNode()) - { - regCount = op1->GetMultiRegCount(); - } - // We will only have valid regs for positions that require copy or reload. - // But we'd like to keep track of where they are so we print all positions. - for (unsigned i = 1; i < regCount; i++) - { - regNumber reg = tree->AsCopyOrReload()->GetRegNumByIdx(i); - printf(",%s", (reg == REG_NA) ? "NA" : compRegVarName(reg)); + regNumber reg = tree->GetRegByIndex(i); + printf(",%s", genIsValidReg(reg) ? compRegVarName(reg) : "NA"); } } #endif - -#if defined(TARGET_ARM) - if (tree->OperIsMultiRegOp() && (tree->AsMultiRegOp()->gtOtherReg != REG_NA)) - { - printf(",%s", compRegVarName(tree->AsMultiRegOp()->gtOtherReg)); - } -#endif } // We usually/commonly don't expect to print anything longer than this string, -- 2.7.4