From 20ba1809fb08fd046bba05d9b1c6fd9bfdccaa4d Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Mon, 1 May 2017 17:32:15 -0700 Subject: [PATCH] Refactor GT_LCL_VAR and GT_STORE_LCL_VAR Commit migrated from https://github.com/dotnet/coreclr/commit/e316b4ae0829fd75c225effe77934ef0d614158e --- src/coreclr/src/jit/codegenarm.cpp | 203 +++++++++++++++++--------------- src/coreclr/src/jit/codegenarm64.cpp | 219 +++++++++++++++++++---------------- src/coreclr/src/jit/codegenlinear.h | 4 + 3 files changed, 232 insertions(+), 194 deletions(-) diff --git a/src/coreclr/src/jit/codegenarm.cpp b/src/coreclr/src/jit/codegenarm.cpp index 1ccf06f..a96e5de 100644 --- a/src/coreclr/src/jit/codegenarm.cpp +++ b/src/coreclr/src/jit/codegenarm.cpp @@ -441,32 +441,6 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) // The per-case functions call genProduceReg() break; - case GT_LCL_VAR: - { - GenTreeLclVarCommon* lcl = treeNode->AsLclVarCommon(); - // lcl_vars are not defs - assert((treeNode->gtFlags & GTF_VAR_DEF) == 0); - - bool isRegCandidate = compiler->lvaTable[lcl->gtLclNum].lvIsRegCandidate(); - - if (isRegCandidate && !(treeNode->gtFlags & GTF_VAR_DEATH)) - { - assert((treeNode->InReg()) || (treeNode->gtFlags & GTF_SPILLED)); - } - - // If this is a register candidate that has been spilled, genConsumeReg() will - // reload it at the point of use. Otherwise, if it's not in a register, we load it here. - - if (!treeNode->InReg() && !(treeNode->gtFlags & GTF_SPILLED)) - { - assert(!isRegCandidate); - emit->emitIns_R_S(ins_Load(treeNode->TypeGet()), emitTypeSize(treeNode), treeNode->gtRegNum, - lcl->gtLclNum, 0); - genProduceReg(treeNode); - } - } - break; - case GT_LCL_FLD_ADDR: case GT_LCL_VAR_ADDR: { @@ -485,79 +459,17 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) genCodeForLclFld(treeNode->AsLclFld()); break; + case GT_LCL_VAR: + genCodeForLclVar(treeNode->AsLclVar()); + break; + case GT_STORE_LCL_FLD: genCodeForStoreLclFld(treeNode->AsLclFld()); break; case GT_STORE_LCL_VAR: - { - GenTreeLclVarCommon* varNode = treeNode->AsLclVarCommon(); - - unsigned varNum = varNode->gtLclNum; - assert(varNum < compiler->lvaCount); - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - unsigned offset = 0; - - // Ensure that lclVar nodes are typed correctly. - assert(!varDsc->lvNormalizeOnStore() || targetType == genActualType(varDsc->TypeGet())); - - GenTreePtr data = treeNode->gtOp.gtOp1->gtEffectiveVal(); - - // var = call, where call returns a multi-reg return value - // case is handled separately. - if (data->gtSkipReloadOrCopy()->IsMultiRegCall()) - { - genMultiRegCallStoreToLocal(treeNode); - break; - } - else - { - if (treeNode->TypeGet() == TYP_LONG) - { - genStoreLongLclVar(treeNode); - break; - } - - genConsumeRegs(data); - - regNumber dataReg = REG_NA; - if (data->isContainedIntOrIImmed()) - { - assert(data->IsIntegralConst(0)); - NYI_ARM("st.lclVar contained operand"); - } - else - { - assert(!data->isContained()); - dataReg = data->gtRegNum; - } - assert(dataReg != REG_NA); - - if (targetReg == REG_NA) // store into stack based LclVar - { - inst_set_SV_var(varNode); - - instruction ins = ins_Store(targetType); - emitAttr attr = emitTypeSize(targetType); - - emit->emitIns_S_R(ins, attr, dataReg, varNum, offset); - - genUpdateLife(varNode); - - varDsc->lvRegNum = REG_STK; - } - else // store into register (i.e move into register) - { - if (dataReg != targetReg) - { - // Assign into targetReg when dataReg (from op1) is not the same register - inst_RV_RV(ins_Copy(targetType), targetReg, dataReg, targetType); - } - genProduceReg(treeNode); - } - } - } - break; + genCodeForStoreLclVar(treeNode->AsLclVar()); + break; case GT_RETFILT: // A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in @@ -1554,6 +1466,36 @@ void CodeGen::genCodeForShiftLong(GenTreePtr tree) } //------------------------------------------------------------------------ +// genCodeForLclVar: Produce code for a GT_LCL_VAR node. +// +// Arguments: +// tree - the GT_LCL_VAR node +// +void CodeGen::genCodeForLclVar(GenTreeLclVar* tree) +{ + // lcl_vars are not defs + assert((tree->gtFlags & GTF_VAR_DEF) == 0); + + bool isRegCandidate = compiler->lvaTable[tree->gtLclNum].lvIsRegCandidate(); + + if (isRegCandidate && !(tree->gtFlags & GTF_VAR_DEATH)) + { + assert((tree->InReg()) || (tree->gtFlags & GTF_SPILLED)); + } + + // If this is a register candidate that has been spilled, genConsumeReg() will + // reload it at the point of use. Otherwise, if it's not in a register, we load it here. + + if (!tree->InReg() && !(tree->gtFlags & GTF_SPILLED)) + { + assert(!isRegCandidate); + getEmitter()->emitIns_R_S(ins_Load(tree->TypeGet()), emitTypeSize(tree), tree->gtRegNum, + tree->gtLclNum, 0); + genProduceReg(tree); + } +} + +//------------------------------------------------------------------------ // genCodeForStoreLclFld: Produce code for a GT_STORE_LCL_FLD node. // // Arguments: @@ -1601,6 +1543,79 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree) } //------------------------------------------------------------------------ +// genCodeForStoreLclVar: Produce code for a GT_STORE_LCL_VAR node. +// +// Arguments: +// tree - the GT_STORE_LCL_VAR node +// +void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) +{ + var_types targetType = tree->TypeGet(); + regNumber targetReg = tree->gtRegNum; + emitter* emit = getEmitter(); + + unsigned varNum = tree->gtLclNum; + assert(varNum < compiler->lvaCount); + LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); + + // Ensure that lclVar nodes are typed correctly. + assert(!varDsc->lvNormalizeOnStore() || targetType == genActualType(varDsc->TypeGet())); + + GenTreePtr data = tree->gtOp1->gtEffectiveVal(); + + // var = call, where call returns a multi-reg return value + // case is handled separately. + if (data->gtSkipReloadOrCopy()->IsMultiRegCall()) + { + genMultiRegCallStoreToLocal(tree); + } + else if (tree->TypeGet() == TYP_LONG) + { + genStoreLongLclVar(tree); + } + else + { + genConsumeRegs(data); + + regNumber dataReg = REG_NA; + if (data->isContainedIntOrIImmed()) + { + assert(data->IsIntegralConst(0)); + NYI_ARM("st.lclVar contained operand"); + } + else + { + assert(!data->isContained()); + dataReg = data->gtRegNum; + } + assert(dataReg != REG_NA); + + if (targetReg == REG_NA) // store into stack based LclVar + { + inst_set_SV_var(tree); + + instruction ins = ins_Store(targetType); + emitAttr attr = emitTypeSize(targetType); + + emit->emitIns_S_R(ins, attr, dataReg, varNum, /* offset */ 0); + + genUpdateLife(tree); + + varDsc->lvRegNum = REG_STK; + } + else // store into register (i.e move into register) + { + if (dataReg != targetReg) + { + // Assign into targetReg when dataReg (from op1) is not the same register + inst_RV_RV(ins_Copy(targetType), targetReg, dataReg, targetType); + } + genProduceReg(tree); + } + } +} + +//------------------------------------------------------------------------ // genLeaInstruction: Produce code for a GT_LEA subnode. // void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) diff --git a/src/coreclr/src/jit/codegenarm64.cpp b/src/coreclr/src/jit/codegenarm64.cpp index 9872684..96598bb 100644 --- a/src/coreclr/src/jit/codegenarm64.cpp +++ b/src/coreclr/src/jit/codegenarm64.cpp @@ -1541,6 +1541,50 @@ void CodeGen::genCodeForBinary(GenTree* treeNode) } //------------------------------------------------------------------------ +// genCodeForLclVar: Produce code for a GT_LCL_VAR node. +// +// Arguments: +// tree - the GT_LCL_VAR node +// +void CodeGen::genCodeForLclVar(GenTreeLclVar* tree) +{ + var_types targetType = tree->TypeGet(); + emitter* emit = getEmitter(); + + unsigned varNum = tree->gtLclNum; + assert(varNum < compiler->lvaCount); + LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); + bool isRegCandidate = varDsc->lvIsRegCandidate(); + + // lcl_vars are not defs + assert((tree->gtFlags & GTF_VAR_DEF) == 0); + + if (isRegCandidate && !(tree->gtFlags & GTF_VAR_DEATH)) + { + assert((tree->InReg()) || (tree->gtFlags & GTF_SPILLED)); + } + + // If this is a register candidate that has been spilled, genConsumeReg() will + // reload it at the point of use. Otherwise, if it's not in a register, we load it here. + + if (!tree->InReg() && !(tree->gtFlags & GTF_SPILLED)) + { + assert(!isRegCandidate); + + // targetType must be a normal scalar type and not a TYP_STRUCT + assert(targetType != TYP_STRUCT); + + instruction ins = ins_Load(targetType); + emitAttr attr = emitTypeSize(targetType); + + attr = emit->emitInsAdjustLoadStoreAttr(ins, attr); + + emit->emitIns_R_S(ins, attr, tree->gtRegNum, varNum, 0); + genProduceReg(tree); + } +} + +//------------------------------------------------------------------------ // genCodeForStoreLclFld: Produce code for a GT_STORE_LCL_FLD node. // // Arguments: @@ -1551,7 +1595,6 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree) var_types targetType = tree->TypeGet(); regNumber targetReg = tree->gtRegNum; emitter* emit = getEmitter(); - noway_assert(targetType != TYP_STRUCT); // record the offset @@ -1598,6 +1641,77 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree) } //------------------------------------------------------------------------ +// genCodeForStoreLclVar: Produce code for a GT_STORE_LCL_VAR node. +// +// Arguments: +// tree - the GT_STORE_LCL_VAR node +// +void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) +{ + var_types targetType = tree->TypeGet(); + regNumber targetReg = tree->gtRegNum; + emitter* emit = getEmitter(); + + unsigned varNum = tree->gtLclNum; + assert(varNum < compiler->lvaCount); + LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); + + // Ensure that lclVar nodes are typed correctly. + assert(!varDsc->lvNormalizeOnStore() || targetType == genActualType(varDsc->TypeGet())); + + GenTreePtr data = tree->gtOp1->gtEffectiveVal(); + + // var = call, where call returns a multi-reg return value + // case is handled separately. + if (data->gtSkipReloadOrCopy()->IsMultiRegCall()) + { + genMultiRegCallStoreToLocal(tree); + } + else + { + genConsumeRegs(data); + + regNumber dataReg = REG_NA; + if (data->isContainedIntOrIImmed()) + { + assert(data->IsIntegralConst(0)); + dataReg = REG_ZR; + } + else + { + assert(!data->isContained()); + dataReg = data->gtRegNum; + } + assert(dataReg != REG_NA); + + if (targetReg == REG_NA) // store into stack based LclVar + { + inst_set_SV_var(tree); + + instruction ins = ins_Store(targetType); + emitAttr attr = emitTypeSize(targetType); + + attr = emit->emitInsAdjustLoadStoreAttr(ins, attr); + + emit->emitIns_S_R(ins, attr, dataReg, varNum, /* offset */ 0); + + genUpdateLife(tree); + + varDsc->lvRegNum = REG_STK; + } + else // store into register (i.e move into register) + { + if (dataReg != targetReg) + { + // Assign into targetReg when dataReg (from op1) is not the same register + inst_RV_RV(ins_Copy(targetType), targetReg, dataReg, targetType); + } + genProduceReg(tree); + } + } +} + +//------------------------------------------------------------------------ // isStructReturn: Returns whether the 'treeNode' is returning a struct. // // Arguments: @@ -2155,111 +2269,16 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) break; case GT_LCL_VAR: - { - GenTreeLclVarCommon* varNode = treeNode->AsLclVarCommon(); - - unsigned varNum = varNode->gtLclNum; - assert(varNum < compiler->lvaCount); - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - bool isRegCandidate = varDsc->lvIsRegCandidate(); - - // lcl_vars are not defs - assert((treeNode->gtFlags & GTF_VAR_DEF) == 0); - - if (isRegCandidate && !(treeNode->gtFlags & GTF_VAR_DEATH)) - { - assert((treeNode->InReg()) || (treeNode->gtFlags & GTF_SPILLED)); - } - - // If this is a register candidate that has been spilled, genConsumeReg() will - // reload it at the point of use. Otherwise, if it's not in a register, we load it here. - - if (!treeNode->InReg() && !(treeNode->gtFlags & GTF_SPILLED)) - { - assert(!isRegCandidate); - - // targetType must be a normal scalar type and not a TYP_STRUCT - assert(targetType != TYP_STRUCT); - - instruction ins = ins_Load(targetType); - emitAttr attr = emitTypeSize(targetType); - - attr = emit->emitInsAdjustLoadStoreAttr(ins, attr); - - emit->emitIns_R_S(ins, attr, targetReg, varNum, 0); - genProduceReg(treeNode); - } - } - break; + genCodeForLclVar(treeNode->AsLclVar()); + break; case GT_STORE_LCL_FLD: genCodeForStoreLclFld(treeNode->AsLclFld()); break; case GT_STORE_LCL_VAR: - { - GenTreeLclVarCommon* varNode = treeNode->AsLclVarCommon(); - - unsigned varNum = varNode->gtLclNum; - assert(varNum < compiler->lvaCount); - LclVarDsc* varDsc = &(compiler->lvaTable[varNum]); - unsigned offset = 0; - - // Ensure that lclVar nodes are typed correctly. - assert(!varDsc->lvNormalizeOnStore() || targetType == genActualType(varDsc->TypeGet())); - - GenTreePtr data = treeNode->gtOp.gtOp1->gtEffectiveVal(); - - // var = call, where call returns a multi-reg return value - // case is handled separately. - if (data->gtSkipReloadOrCopy()->IsMultiRegCall()) - { - genMultiRegCallStoreToLocal(treeNode); - } - else - { - genConsumeRegs(data); - - regNumber dataReg = REG_NA; - if (data->isContainedIntOrIImmed()) - { - assert(data->IsIntegralConst(0)); - dataReg = REG_ZR; - } - else - { - assert(!data->isContained()); - dataReg = data->gtRegNum; - } - assert(dataReg != REG_NA); - - if (targetReg == REG_NA) // store into stack based LclVar - { - inst_set_SV_var(varNode); - - instruction ins = ins_Store(targetType); - emitAttr attr = emitTypeSize(targetType); - - attr = emit->emitInsAdjustLoadStoreAttr(ins, attr); - - emit->emitIns_S_R(ins, attr, dataReg, varNum, offset); - - genUpdateLife(varNode); - - varDsc->lvRegNum = REG_STK; - } - else // store into register (i.e move into register) - { - if (dataReg != targetReg) - { - // Assign into targetReg when dataReg (from op1) is not the same register - inst_RV_RV(ins_Copy(targetType), targetReg, dataReg, targetType); - } - genProduceReg(treeNode); - } - } - } - break; + genCodeForStoreLclVar(treeNode->AsLclVar()); + break; case GT_RETFILT: // A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in diff --git a/src/coreclr/src/jit/codegenlinear.h b/src/coreclr/src/jit/codegenlinear.h index 3f8a108..8e4c8e7 100644 --- a/src/coreclr/src/jit/codegenlinear.h +++ b/src/coreclr/src/jit/codegenlinear.h @@ -166,10 +166,14 @@ void genCodeForShiftLong(GenTreePtr tree); void genCodeForShiftRMW(GenTreeStoreInd* storeInd); #endif // _TARGET_XARCH_ +void genCodeForLclVar(GenTreeLclVar* tree); + void genCodeForLclFld(GenTreeLclFld* tree); void genCodeForStoreLclFld(GenTreeLclFld* tree); +void genCodeForStoreLclVar(GenTreeLclVar* tree); + void genCodeForCpObj(GenTreeObj* cpObjNode); void genCodeForCpBlk(GenTreeBlk* cpBlkNode); -- 2.7.4