diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 414cd0ec1db7b..535e6f49e70b7 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -1098,7 +1098,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #endif // TARGET_XARCH void genCodeForCast(GenTreeOp* tree); - void genCodeForLclAddr(GenTreeLclVarCommon* lclAddrNode); + void genCodeForLclAddr(GenTreeLclFld* lclAddrNode); void genCodeForIndexAddr(GenTreeIndexAddr* tree); void genCodeForIndir(GenTreeIndir* tree); void genCodeForNegNot(GenTree* tree); diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index b83ba8042763b..0cd7396999c72 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -821,7 +821,7 @@ void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) sourceIsLocal = true; } - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIsLocalAddr(); + bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); #ifdef DEBUG assert(!dstAddr->isContained()); diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 479c5c14668a4..6b1a20565dec2 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -3565,7 +3565,7 @@ void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) sourceIsLocal = true; } - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIsLocalAddr(); + bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); #ifdef DEBUG assert(!dstAddr->isContained()); diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index f6026fb9afe91..ee6f9e0a2d922 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -259,9 +259,8 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) genCodeForBitCast(treeNode->AsOp()); break; - case GT_LCL_FLD_ADDR: - case GT_LCL_VAR_ADDR: - genCodeForLclAddr(treeNode->AsLclVarCommon()); + case GT_LCL_ADDR: + genCodeForLclAddr(treeNode->AsLclFld()); break; case GT_LCL_FLD: @@ -1676,14 +1675,14 @@ void CodeGen::genCodeForShift(GenTree* tree) } //------------------------------------------------------------------------ -// genCodeForLclAddr: Generates the code for GT_LCL_FLD_ADDR/GT_LCL_VAR_ADDR. +// genCodeForLclAddr: Generates the code for GT_LCL_ADDR. // // Arguments: // lclAddrNode - the node. // -void CodeGen::genCodeForLclAddr(GenTreeLclVarCommon* lclAddrNode) +void CodeGen::genCodeForLclAddr(GenTreeLclFld* lclAddrNode) { - assert(lclAddrNode->OperIs(GT_LCL_FLD_ADDR, GT_LCL_VAR_ADDR)); + assert(lclAddrNode->OperIs(GT_LCL_ADDR)); var_types targetType = lclAddrNode->TypeGet(); emitAttr size = emitTypeSize(targetType); @@ -2568,7 +2567,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) } else { - assert(dstAddr->OperIsLocalAddr()); + assert(dstAddr->OperIs(GT_LCL_ADDR)); dstLclNum = dstAddr->AsLclVarCommon()->GetLclNum(); dstOffset = dstAddr->AsLclVarCommon()->GetLclOffs(); } @@ -2735,7 +2734,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) } else { - assert(dstAddr->OperIsLocalAddr()); + assert(dstAddr->OperIs(GT_LCL_ADDR)); dstLclNum = dstAddr->AsLclVarCommon()->GetLclNum(); dstOffset = dstAddr->AsLclVarCommon()->GetLclOffs(); } @@ -2768,7 +2767,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) } else { - assert(srcAddr->OperIsLocalAddr()); + assert(srcAddr->OperIs(GT_LCL_ADDR)); srcLclNum = srcAddr->AsLclVarCommon()->GetLclNum(); srcOffset = srcAddr->AsLclVarCommon()->GetLclOffs(); } diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index dda09ea43cbce..b27b8c1da1f56 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -2781,7 +2781,7 @@ void CodeGen::genGCWriteBarrier(GenTreeStoreInd* store, GCInfo::WriteBarrierForm wbKind = varDsc->lvIsParam ? CWBKind_ByRefArg : CWBKind_OtherByRefLocal; } } - else if (tgtAddr->OperIsLocalAddr()) + else if (tgtAddr->OperIs(GT_LCL_ADDR)) { // Ideally, we should have eliminated the barrier for this case. wbKind = CWBKind_AddrOfLocal; diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 403f19e49b895..f7ce053119ca4 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -2788,7 +2788,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) } else { - assert(dstAddr->OperIsLocalAddr()); + assert(dstAddr->OperIs(GT_LCL_ADDR)); dstLclNum = dstAddr->AsLclVarCommon()->GetLclNum(); dstOffset = dstAddr->AsLclVarCommon()->GetLclOffs(); } @@ -2921,7 +2921,7 @@ void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) sourceIsLocal = true; } - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIsLocalAddr(); + bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); #ifdef DEBUG assert(!dstAddr->isContained()); @@ -5000,9 +5000,8 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) genCodeForBitCast(treeNode->AsOp()); break; - case GT_LCL_FLD_ADDR: - case GT_LCL_VAR_ADDR: - genCodeForLclAddr(treeNode->AsLclVarCommon()); + case GT_LCL_ADDR: + genCodeForLclAddr(treeNode->AsLclFld()); break; case GT_LCL_FLD: @@ -5503,15 +5502,15 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) addrNode = source->AsOp()->gtOp1; - // addrNode can either be a GT_LCL_VAR_ADDR or an address expression + // addrNode can either be a GT_LCL_ADDR<0> or an address expression // - if (addrNode->OperGet() == GT_LCL_VAR_ADDR) + if (addrNode->IsLclVarAddr()) { - // We have a GT_OBJ(GT_LCL_VAR_ADDR) + // We have a GT_OBJ(GT_LCL_ADDR<0>) // // We will treat this case the same as above // (i.e if we just had this GT_LCL_VAR directly as the source) - // so update 'source' to point this GT_LCL_VAR_ADDR node + // so update 'source' to point this GT_LCL_ADDR node // and continue to the codegen for the LCL_VAR node below // varNode = addrNode->AsLclVarCommon(); @@ -5778,15 +5777,15 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) addrNode = source->AsOp()->gtOp1; - // addrNode can either be a GT_LCL_VAR_ADDR or an address expression + // addrNode can either be a GT_LCL_ADDR<0> or an address expression // - if (addrNode->OperGet() == GT_LCL_VAR_ADDR) + if (addrNode->IsLclVarAddr()) { - // We have a GT_OBJ(GT_LCL_VAR_ADDR) + // We have a GT_OBJ(GT_LCL_ADDR<0>) // // We will treat this case the same as above // (i.e if we just had this GT_LCL_VAR directly as the source) - // so update 'source' to point this GT_LCL_VAR_ADDR node + // so update 'source' to point this GT_LCL_ADDR node // and continue to the codegen for the LCL_VAR node below // varNode = addrNode->AsLclVarCommon(); @@ -6185,14 +6184,14 @@ void CodeGen::genCodeForShift(GenTree* tree) } //------------------------------------------------------------------------ -// genCodeForLclAddr: Generates the code for GT_LCL_FLD_ADDR/GT_LCL_VAR_ADDR. +// genCodeForLclAddr: Generates the code for GT_LCL_ADDR. // // Arguments: // tree - the node. // -void CodeGen::genCodeForLclAddr(GenTreeLclVarCommon* lclAddrNode) +void CodeGen::genCodeForLclAddr(GenTreeLclFld* lclAddrNode) { - assert(lclAddrNode->OperIs(GT_LCL_FLD_ADDR, GT_LCL_VAR_ADDR)); + assert(lclAddrNode->OperIs(GT_LCL_ADDR)); var_types targetType = lclAddrNode->TypeGet(); emitAttr size = emitTypeSize(targetType); @@ -6481,7 +6480,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) } else { - assert(dstAddr->OperIsLocalAddr()); + assert(dstAddr->OperIs(GT_LCL_ADDR)); dstLclNum = dstAddr->AsLclVarCommon()->GetLclNum(); dstOffset = dstAddr->AsLclVarCommon()->GetLclOffs(); } @@ -6514,7 +6513,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode) } else { - assert(srcAddr->OperIsLocalAddr()); + assert(srcAddr->OperIs(GT_LCL_ADDR)); srcLclNum = srcAddr->AsLclVarCommon()->GetLclNum(); srcOffset = srcAddr->AsLclVarCommon()->GetLclOffs(); } @@ -6661,9 +6660,9 @@ void CodeGen::genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst { emitter* emit = GetEmitter(); - if (base->OperIsLocalAddr()) + if (base->OperIs(GT_LCL_ADDR)) { - if (base->gtOper == GT_LCL_FLD_ADDR) + if (base->gtOper == GT_LCL_ADDR) { offset += base->AsLclFld()->GetLclOffs(); } diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index a50040a5ef4f2..16a84819232c2 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -1841,9 +1841,8 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) genCodeForBitCast(treeNode->AsOp()); break; - case GT_LCL_FLD_ADDR: - case GT_LCL_VAR_ADDR: - genCodeForLclAddr(treeNode->AsLclVarCommon()); + case GT_LCL_ADDR: + genCodeForLclAddr(treeNode->AsLclFld()); break; case GT_LCL_FLD: @@ -3159,7 +3158,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) } else { - assert(dstAddr->OperIsLocalAddr()); + assert(dstAddr->OperIs(GT_LCL_ADDR)); dstLclNum = dstAddr->AsLclVarCommon()->GetLclNum(); dstOffset = dstAddr->AsLclVarCommon()->GetLclOffs(); } @@ -3446,7 +3445,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) } else { - assert(dstAddr->OperIsLocalAddr()); + assert(dstAddr->OperIs(GT_LCL_ADDR)); const GenTreeLclVarCommon* lclVar = dstAddr->AsLclVarCommon(); dstLclNum = lclVar->GetLclNum(); dstOffset = lclVar->GetLclOffs(); @@ -3494,7 +3493,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) } else { - assert(srcAddr->OperIsLocalAddr()); + assert(srcAddr->OperIs(GT_LCL_ADDR)); srcLclNum = srcAddr->AsLclVarCommon()->GetLclNum(); srcOffset = srcAddr->AsLclVarCommon()->GetLclOffs(); } @@ -4145,7 +4144,7 @@ void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) GenTree* dstAddr = cpObjNode->Addr(); GenTree* source = cpObjNode->Data(); var_types srcAddrType = TYP_BYREF; - bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIsLocalAddr(); + bool dstOnStack = dstAddr->gtSkipReloadOrCopy()->OperIs(GT_LCL_ADDR); // If the GenTree node has data about GC pointers, this means we're dealing // with CpObj, so this requires special logic. @@ -5078,14 +5077,14 @@ void CodeGen::genCodeForShiftRMW(GenTreeStoreInd* storeInd) } //------------------------------------------------------------------------ -// genCodeForLclAddr: Generates the code for GT_LCL_FLD_ADDR/GT_LCL_VAR_ADDR. +// genCodeForLclAddr: Generates the code for GT_LCL_ADDR. // // Arguments: // lclAddrNode - the node. // -void CodeGen::genCodeForLclAddr(GenTreeLclVarCommon* lclAddrNode) +void CodeGen::genCodeForLclAddr(GenTreeLclFld* lclAddrNode) { - assert(lclAddrNode->OperIs(GT_LCL_FLD_ADDR, GT_LCL_VAR_ADDR)); + assert(lclAddrNode->OperIs(GT_LCL_ADDR)); var_types targetType = lclAddrNode->TypeGet(); emitAttr size = emitTypeSize(targetType); @@ -7470,13 +7469,13 @@ void CodeGen::genIntToFloatCast(GenTree* treeNode) // Since xarch emitter doesn't handle reporting gc-info correctly while casting away gc-ness we // ensure srcType of a cast is non gc-type. Codegen should never see BYREF as source type except - // for GT_LCL_VAR_ADDR and GT_LCL_FLD_ADDR that represent stack addresses and can be considered - // as TYP_I_IMPL. In all other cases where src operand is a gc-type and not known to be on stack, - // Front-end (see fgMorphCast()) ensures this by assigning gc-type local to a non gc-type - // temp and using temp as operand of cast operation. + // for GT_LCL_ADDR that represent stack addresses and can be considered as TYP_I_IMPL. In all other + // cases where src operand is a gc-type and not known to be on stack, Front-end (see fgMorphCast()) + // ensures this by assigning gc-type local to a non gc-type temp and using temp as operand of cast + // operation. if (srcType == TYP_BYREF) { - noway_assert(op1->OperGet() == GT_LCL_VAR_ADDR || op1->OperGet() == GT_LCL_FLD_ADDR); + noway_assert(op1->OperGet() == GT_LCL_ADDR); srcType = TYP_I_IMPL; } @@ -8011,12 +8010,11 @@ void CodeGen::genSSE41RoundOp(GenTreeOp* treeNode) switch (memBase->OperGet()) { - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: { assert(memBase->isContained()); - varNum = memBase->AsLclVarCommon()->GetLclNum(); - offset = memBase->AsLclVarCommon()->GetLclOffs(); + varNum = memBase->AsLclFld()->GetLclNum(); + offset = memBase->AsLclFld()->GetLclOffs(); // Ensure that all the GenTreeIndir values are set to their defaults. assert(memBase->GetRegNum() == REG_NA); diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 8134c167bd167..4e7b2a6537158 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -9605,9 +9605,8 @@ void cTreeFlags(Compiler* comp, GenTree* tree) switch (op) { case GT_LCL_VAR: - case GT_LCL_VAR_ADDR: case GT_LCL_FLD: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_STORE_LCL_FLD: case GT_STORE_LCL_VAR: if (tree->gtFlags & GTF_VAR_DEF) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 517a5fae972c9..53887fb779cb9 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -2526,8 +2526,8 @@ class Compiler GenTreeLclVar* gtNewLclvNode(unsigned lnum, var_types type DEBUGARG(IL_OFFSET offs = BAD_IL_OFFSET)); GenTreeLclVar* gtNewLclLNode(unsigned lnum, var_types type DEBUGARG(IL_OFFSET offs = BAD_IL_OFFSET)); - GenTreeLclVar* gtNewLclVarAddrNode(unsigned lclNum, var_types type = TYP_I_IMPL); - GenTreeLclFld* gtNewLclFldAddrNode(unsigned lclNum, unsigned lclOffs, var_types type = TYP_I_IMPL); + GenTreeLclFld* gtNewLclVarAddrNode(unsigned lclNum, var_types type = TYP_I_IMPL); + GenTreeLclFld* gtNewLclAddrNode(unsigned lclNum, unsigned lclOffs, var_types type = TYP_I_IMPL); GenTreeConditional* gtNewConditionalNode( genTreeOps oper, GenTree* cond, GenTree* op1, GenTree* op2, var_types type); @@ -11068,8 +11068,7 @@ class GenTreeVisitor // Leaf lclVars case GT_LCL_VAR: case GT_LCL_FLD: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: if (TVisitor::DoLclVarsOnly) { result = reinterpret_cast(this)->PreOrderVisit(use, user); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index c3d453b2ba023..247be1b63343c 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1348,6 +1348,10 @@ inline void GenTree::SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate) AsLclFld()->SetLayout(nullptr); break; + case GT_LCL_ADDR: + AsLclFld()->SetLayout(nullptr); + break; + case GT_CALL: new (&AsCall()->gtArgs, jitstd::placement_t()) CallArgs(); break; @@ -4008,8 +4012,7 @@ void GenTree::VisitOperands(TVisitor visitor) // Leaf nodes case GT_LCL_VAR: case GT_LCL_FLD: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_CATCH_ARG: case GT_LABEL: case GT_FTN_ADDR: diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index dc1ea3a71d849..81eb8ed27c26f 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -7912,7 +7912,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (addr->isContained()) { - assert(addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA)); + assert(addr->OperIs(GT_LCL_ADDR, GT_LEA)); DWORD lsl = 0; @@ -7997,7 +7997,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR } else // no Index { - if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + if (addr->OperIs(GT_LCL_ADDR)) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); unsigned lclNum = varNode->GetLclNum(); @@ -8032,7 +8032,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else { #ifdef DEBUG - if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + if (addr->OperIs(GT_LCL_ADDR)) { // If the local var is a gcref or byref, the local var better be untracked, because we have // no logic here to track local variable lifetime changes, like we do in the contained case diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index a780dfa96a5cb..15025fb728cc1 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -13804,7 +13804,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (addr->isContained()) { - assert(addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA)); + assert(addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_ADDR, GT_LEA)); int offset = 0; DWORD lsl = 0; @@ -13913,7 +13913,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR regNumber addrReg = indir->GetSingleTempReg(); emitIns_R_C(ins, attr, dataReg, addrReg, addr->AsClsVar()->gtClsVarHnd, 0); } - else if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + else if (addr->OperIs(GT_LCL_ADDR)) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); unsigned lclNum = varNode->GetLclNum(); @@ -13948,7 +13948,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else // addr is not contained, so we evaluate it into a register { #ifdef DEBUG - if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + if (addr->OperIs(GT_LCL_ADDR)) { // If the local var is a gcref or byref, the local var better be untracked, because we have // no logic here to track local variable lifetime changes, like we do in the contained case diff --git a/src/coreclr/jit/emitloongarch64.cpp b/src/coreclr/jit/emitloongarch64.cpp index 574282bdf9a99..cab014a0c50de 100644 --- a/src/coreclr/jit/emitloongarch64.cpp +++ b/src/coreclr/jit/emitloongarch64.cpp @@ -6026,7 +6026,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR if (addr->isContained()) { - assert(addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA)); + assert(addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_ADDR, GT_LEA)); int offset = 0; DWORD lsl = 0; @@ -6175,7 +6175,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR regNumber addrReg = indir->GetSingleTempReg(); emitIns_R_C(ins, attr, dataReg, addrReg, addr->AsClsVar()->gtClsVarHnd, 0); } - else if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + else if (addr->OperIs(GT_LCL_ADDR)) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); unsigned lclNum = varNode->GetLclNum(); @@ -6212,7 +6212,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else // addr is not contained, so we evaluate it into a register { #ifdef DEBUG - if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + if (addr->OperIs(GT_LCL_ADDR)) { // If the local var is a gcref or byref, the local var better be untracked, because we have // no logic here to track local variable lifetime changes, like we do in the contained case diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 586dcbdf2892c..c1772f1cdeb80 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -4623,7 +4623,7 @@ void emitter::emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, G return; } - if (addr->OperIsLocalAddr()) + if (addr->OperIs(GT_LCL_ADDR)) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); unsigned offset = varNode->GetLclOffs(); @@ -4631,10 +4631,10 @@ void emitter::emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, G // Updating variable liveness after instruction was emitted. // TODO-Review: it appears that this call to genUpdateLife does nothing because it - // returns quickly when passed GT_LCL_VAR_ADDR or GT_LCL_FLD_ADDR. Below, emitInsStoreInd - // had similar code that replaced `varNode` with `mem` (to fix a GC hole). It might be - // appropriate to do that here as well, but doing so showed no asm diffs, so it's not - // clear when this scenario gets hit, at least for GC refs. + // returns quickly when passed GT_LCL_ADDR. Below, emitInsStoreInd had similar code + // that replaced `varNode` with `mem` (to fix a GC hole). It might be appropriate to + // do that here as well, but doing so showed no asm diffs, so it's not clear when + // this scenario gets hit, at least for GC refs. codeGen->genUpdateLife(varNode); return; } @@ -4708,7 +4708,7 @@ void emitter::emitInsStoreInd(instruction ins, emitAttr attr, GenTreeStoreInd* m return; } - if (addr->OperIsLocalAddr()) + if (addr->OperIs(GT_LCL_ADDR)) { GenTreeLclVarCommon* varNode = addr->AsLclVarCommon(); unsigned offset = varNode->GetLclOffs(); @@ -4948,12 +4948,11 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G switch (memBase->OperGet()) { - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: { assert(memBase->isContained()); - varNum = memBase->AsLclVarCommon()->GetLclNum(); - offset = memBase->AsLclVarCommon()->GetLclOffs(); + varNum = memBase->AsLclFld()->GetLclNum(); + offset = memBase->AsLclFld()->GetLclOffs(); // Ensure that all the GenTreeIndir values are set to their defaults. assert(!memIndir->HasIndex()); @@ -5264,7 +5263,7 @@ void emitter::emitInsRMW(instruction ins, emitAttr attr, GenTreeStoreInd* storeI { GenTree* addr = storeInd->Addr(); addr = addr->gtSkipReloadOrCopy(); - assert(addr->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR, GT_LEA, GT_CLS_VAR_ADDR, GT_CNS_INT)); + assert(addr->OperIs(GT_LCL_VAR, GT_LEA, GT_CLS_VAR_ADDR, GT_CNS_INT) || addr->IsLclVarAddr()); instrDesc* id = nullptr; UNATIVE_OFFSET sz; @@ -5294,7 +5293,7 @@ void emitter::emitInsRMW(instruction ins, emitAttr attr, GenTreeStoreInd* storeI break; } - if (addr->isContained() && addr->OperIsLocalAddr()) + if (addr->isContained() && addr->OperIs(GT_LCL_ADDR)) { GenTreeLclVarCommon* lclVar = addr->AsLclVarCommon(); emitIns_S_I(ins, attr, lclVar->GetLclNum(), lclVar->GetLclOffs(), iconVal); @@ -5352,7 +5351,7 @@ void emitter::emitInsRMW(instruction ins, emitAttr attr, GenTreeStoreInd* storeI { GenTree* addr = storeInd->Addr(); addr = addr->gtSkipReloadOrCopy(); - assert(addr->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR, GT_CLS_VAR_ADDR, GT_LEA, GT_CNS_INT)); + assert(addr->OperIs(GT_LCL_VAR, GT_CLS_VAR_ADDR, GT_LEA, GT_CNS_INT) || addr->IsLclVarAddr()); ssize_t offset = 0; if (addr->OperGet() != GT_CLS_VAR_ADDR) @@ -5360,7 +5359,7 @@ void emitter::emitInsRMW(instruction ins, emitAttr attr, GenTreeStoreInd* storeI offset = storeInd->Offset(); } - if (addr->isContained() && addr->OperIsLocalAddr()) + if (addr->isContained() && addr->OperIs(GT_LCL_ADDR)) { GenTreeLclVarCommon* lclVar = addr->AsLclVarCommon(); emitIns_S(ins, attr, lclVar->GetLclNum(), lclVar->GetLclOffs()); diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp index 884e3e9698fc8..176f10bc8cac1 100644 --- a/src/coreclr/jit/fgdiagnostic.cpp +++ b/src/coreclr/jit/fgdiagnostic.cpp @@ -3365,7 +3365,7 @@ void Compiler::fgDebugCheckLinkedLocals() bool ShouldLink(GenTree* node) { - return node->OperIsLocal() || node->OperIsLocalAddr(); + return node->OperIsLocal() || node->OperIs(GT_LCL_ADDR); } public: @@ -3453,7 +3453,7 @@ void Compiler::fgDebugCheckLinkedLocals() int nodeIndex = 0; for (GenTree* cur = first; cur != nullptr; cur = cur->gtNext) { - success &= cur->OperIsLocal() || cur->OperIsLocalAddr(); + success &= cur->OperIsLocal() || cur->OperIs(GT_LCL_ADDR); success &= (nodeIndex < expected->Height()) && (cur == expected->Bottom(nodeIndex)); nodeIndex++; } diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 6c262942700a8..ea47ddb5869d1 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -857,8 +857,7 @@ bool Compiler::fgAddrCouldBeNull(GenTree* addr) case GT_CNS_STR: case GT_FIELD_ADDR: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_CLS_VAR_ADDR: return false; diff --git a/src/coreclr/jit/gcinfo.cpp b/src/coreclr/jit/gcinfo.cpp index 5cc69df3f3859..613f76c919b39 100644 --- a/src/coreclr/jit/gcinfo.cpp +++ b/src/coreclr/jit/gcinfo.cpp @@ -285,7 +285,7 @@ GCInfo::WriteBarrierForm GCInfo::gcIsWriteBarrierCandidate(GenTreeStoreInd* stor // GCInfo::WriteBarrierForm GCInfo::gcWriteBarrierFormFromTargetAddress(GenTree* tgtAddr) { - if (tgtAddr->OperIsLocalAddr()) + if (tgtAddr->OperIs(GT_LCL_ADDR)) { // No need for a GC barrier when writing to a local variable. return GCInfo::WBF_NoBarrier; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index e2a336fcfef6c..4f343878c5aeb 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -568,7 +568,7 @@ void GenTree::DumpNodeSizes(FILE* fp) LocalsGenTreeList::iterator LocalsGenTreeList::begin() const { GenTree* first = m_stmt->GetTreeList(); - assert((first == nullptr) || first->OperIsLocal() || first->OperIsLocalAddr()); + assert((first == nullptr) || first->OperIsLocal() || first->OperIs(GT_LCL_ADDR)); return iterator(static_cast(first)); } @@ -2639,24 +2639,25 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) { switch (oper) { - case GT_LCL_VAR: - case GT_LCL_VAR_ADDR: - if (op1->AsLclVarCommon()->GetLclNum() != op2->AsLclVarCommon()->GetLclNum()) + case GT_LCL_FLD: + if (op1->AsLclFld()->GetLayout() != op2->AsLclFld()->GetLayout()) { break; } + FALLTHROUGH; - return true; - - case GT_LCL_FLD: - case GT_LCL_FLD_ADDR: - if ((op1->AsLclFld()->GetLclNum() != op2->AsLclFld()->GetLclNum()) || - (op1->AsLclFld()->GetLclOffs() != op2->AsLclFld()->GetLclOffs()) || - (op1->AsLclFld()->GetLayout() != op2->AsLclFld()->GetLayout())) + case GT_LCL_ADDR: + if (op1->AsLclFld()->GetLclOffs() != op2->AsLclFld()->GetLclOffs()) { break; } + FALLTHROUGH; + case GT_LCL_VAR: + if (op1->AsLclVarCommon()->GetLclNum() != op2->AsLclVarCommon()->GetLclNum()) + { + break; + } return true; case GT_LABEL: @@ -2925,7 +2926,7 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) if (tree->OperIsLeaf()) { - if ((tree->OperIsLocal() || tree->OperIsLocalAddr()) && (tree->AsLclVarCommon()->GetLclNum() == lclNum)) + if ((tree->OperIsLocal() || tree->OperIs(GT_LCL_ADDR)) && (tree->AsLclVarCommon()->GetLclNum() == lclNum)) { return true; } @@ -4997,8 +4998,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) } break; - case GT_LCL_FLD_ADDR: - case GT_LCL_VAR_ADDR: + case GT_LCL_ADDR: level = 1; costEx = 3; costSz = 3; @@ -6183,8 +6183,7 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse) // Leaf nodes case GT_LCL_VAR: case GT_LCL_FLD: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_CATCH_ARG: case GT_LABEL: case GT_FTN_ADDR: @@ -7629,15 +7628,15 @@ GenTreeLclVar* Compiler::gtNewLclLNode(unsigned lnum, var_types type DEBUGARG(IL return node; } -GenTreeLclVar* Compiler::gtNewLclVarAddrNode(unsigned lclNum, var_types type) +GenTreeLclFld* Compiler::gtNewLclVarAddrNode(unsigned lclNum, var_types type) { - GenTreeLclVar* node = new (this, GT_LCL_VAR_ADDR) GenTreeLclVar(GT_LCL_VAR_ADDR, type, lclNum); + GenTreeLclFld* node = gtNewLclAddrNode(lclNum, 0, type); return node; } -GenTreeLclFld* Compiler::gtNewLclFldAddrNode(unsigned lclNum, unsigned lclOffs, var_types type) +GenTreeLclFld* Compiler::gtNewLclAddrNode(unsigned lclNum, unsigned lclOffs, var_types type) { - GenTreeLclFld* node = new (this, GT_LCL_FLD_ADDR) GenTreeLclFld(GT_LCL_FLD_ADDR, type, lclNum, lclOffs); + GenTreeLclFld* node = new (this, GT_LCL_ADDR) GenTreeLclFld(GT_LCL_ADDR, type, lclNum, lclOffs); return node; } @@ -7707,7 +7706,7 @@ GenTreeField* Compiler::gtNewFieldRef(var_types type, CORINFO_FIELD_HANDLE fldHn GenTreeField* fieldNode = new (this, GT_FIELD) GenTreeField(GT_FIELD, type, obj, fldHnd, offset); // If "obj" is the address of a local, note that a field of that struct local has been accessed. - if ((obj != nullptr) && obj->OperIs(GT_LCL_VAR_ADDR)) + if ((obj != nullptr) && obj->IsLclVarAddr()) { LclVarDsc* varDsc = lvaGetDesc(obj->AsLclVarCommon()); @@ -7754,7 +7753,7 @@ GenTreeField* Compiler::gtNewFieldAddrNode(var_types type, CORINFO_FIELD_HANDLE GenTreeField* fieldNode = new (this, GT_FIELD_ADDR) GenTreeField(GT_FIELD_ADDR, type, obj, fldHnd, offset); // If "obj" is the address of a local, note that a field of that struct local has been accessed. - if ((obj != nullptr) && obj->OperIs(GT_LCL_VAR_ADDR)) + if ((obj != nullptr) && obj->IsLclVarAddr()) { LclVarDsc* varDsc = lvaGetDesc(obj->AsLclVarCommon()); @@ -7843,7 +7842,7 @@ GenTreeObj* Compiler::gtNewObjNode(ClassLayout* layout, GenTree* addr) { // TODO-Bug: this method does not have enough information to make this determination. // The local may end up (or already is) address-exposed. - if (addr->OperIsLocalAddr()) + if (addr->OperIs(GT_LCL_ADDR)) { objNode->gtFlags |= GTF_IND_NONFAULTING; if (lvaIsImplicitByRefLocal(addr->AsLclVarCommon()->GetLclNum())) @@ -7895,9 +7894,9 @@ GenTree* Compiler::gtNewStructVal(ClassLayout* layout, GenTree* addr, GenTreeFla assert((indirFlags & ~GTF_IND_FLAGS) == 0); bool isVolatile = (indirFlags & GTF_IND_VOLATILE) != 0; - if (!isVolatile && addr->OperIs(GT_LCL_VAR_ADDR)) + if (!isVolatile && addr->IsLclVarAddr()) { - unsigned lclNum = addr->AsLclVar()->GetLclNum(); + unsigned lclNum = addr->AsLclFld()->GetLclNum(); LclVarDsc* varDsc = lvaGetDesc(lclNum); if (!lvaIsImplicitByRefLocal(lclNum) && varTypeIsStruct(varDsc) && ClassLayout::AreCompatible(layout, varDsc->GetLayout())) @@ -8212,15 +8211,15 @@ GenTree* Compiler::gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, bool isVo { // TODO-Cleanup: similar logic already exists in "gtNewAssignNode", // however, it is not enabled for x86. Fix that and delete this code. - GenTreeLclVar* dstLclNode = nullptr; + GenTreeLclVarCommon* dstLclNode = nullptr; if (dst->OperIs(GT_LCL_VAR)) { dstLclNode = dst->AsLclVar(); } - else if (dst->OperIsBlk() && dst->AsIndir()->Addr()->OperIs(GT_LCL_VAR_ADDR)) + else if (dst->OperIsBlk() && dst->AsIndir()->Addr()->IsLclVarAddr()) { - dstLclNode = dst->AsIndir()->Addr()->AsLclVar(); + dstLclNode = dst->AsIndir()->Addr()->AsLclFld(); } if ((dstLclNode != nullptr) && varTypeIsStruct(lvaGetDesc(dstLclNode))) @@ -8426,20 +8425,19 @@ GenTree* Compiler::gtClone(GenTree* tree, bool complexOK) break; } - case GT_LCL_VAR_ADDR: - if (!complexOK) - { - return nullptr; - } - FALLTHROUGH; - case GT_LCL_VAR: copy = new (this, tree->OperGet()) GenTreeLclVar(tree->OperGet(), tree->TypeGet(), tree->AsLclVar()->GetLclNum()); goto FINISH_CLONING_LCL_NODE; + case GT_LCL_ADDR: + if (!complexOK && (tree->AsLclFld()->GetLclOffs() == 0)) + { + return nullptr; + } + FALLTHROUGH; + case GT_LCL_FLD: - case GT_LCL_FLD_ADDR: copy = new (this, tree->OperGet()) GenTreeLclFld(tree->OperGet(), tree->TypeGet(), tree->AsLclFld()->GetLclNum(), tree->AsLclFld()->GetLclOffs(), tree->AsLclFld()->GetLayout()); @@ -8675,13 +8673,7 @@ GenTree* Compiler::gtCloneExpr( copy = new (this, oper) GenTreeVal(oper, tree->gtType, tree->AsVal()->gtVal1); goto DONE; - case GT_LCL_VAR_ADDR: - { - copy = new (this, oper) GenTreeLclVar(oper, tree->TypeGet(), tree->AsLclVar()->GetLclNum()); - goto DONE; - } - - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: { copy = new (this, oper) GenTreeLclFld(oper, tree->TypeGet(), tree->AsLclFld()->GetLclNum(), tree->AsLclFld()->GetLclOffs()); @@ -9538,8 +9530,7 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) // Leaf nodes case GT_LCL_VAR: case GT_LCL_FLD: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_CATCH_ARG: case GT_LABEL: case GT_FTN_ADDR: @@ -10685,8 +10676,7 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_ case GT_LCL_FLD: case GT_LCL_VAR: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_STORE_LCL_FLD: case GT_STORE_LCL_VAR: if (tree->gtFlags & GTF_VAR_USEASG) @@ -11646,14 +11636,13 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack) { case GT_LCL_FLD: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_STORE_LCL_FLD: isLclFld = true; FALLTHROUGH; case GT_PHI_ARG: case GT_LCL_VAR: - case GT_LCL_VAR_ADDR: case GT_STORE_LCL_VAR: { printf(" "); @@ -17119,6 +17108,11 @@ bool GenTree::IsPhiDefn() return res; } +bool GenTree::IsLclVarAddr() const +{ + return OperIs(GT_LCL_ADDR) && (AsLclFld()->GetLclOffs() == 0); +} + // IsPartialLclFld: Check for a GT_LCL_FLD whose type is a different size than the lclVar. // // Arguments: @@ -18142,7 +18136,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b // // This comes up during constrained callvirt on ref types. // - if (base->OperIs(GT_LCL_VAR_ADDR)) + if (base->IsLclVarAddr()) { const unsigned objLcl = base->AsLclVarCommon()->GetLclNum(); objClass = lvaTable[objLcl].lvClassHnd; @@ -18532,7 +18526,7 @@ GenTreeLclVarCommon* Compiler::gtCallGetDefinedRetBufLclAddr(GenTreeCall* call) // This may be called very late to check validity of LIR. node = node->gtSkipReloadOrCopy(); - assert(node->OperIsLocalAddr() && lvaGetDesc(node->AsLclVarCommon())->IsHiddenBufferStructArg()); + assert(node->OperIs(GT_LCL_ADDR) && lvaGetDesc(node->AsLclVarCommon())->IsHiddenBufferStructArg()); return node->AsLclVarCommon(); } @@ -18931,7 +18925,7 @@ void Compiler::SetOpLclRelatedToSIMDIntrinsic(GenTree* op) { setLclRelatedToSIMDIntrinsic(op); } - else if (op->OperIsBlk() && op->AsIndir()->Addr()->OperIs(GT_LCL_VAR_ADDR)) + else if (op->OperIsBlk() && op->AsIndir()->Addr()->IsLclVarAddr()) { setLclRelatedToSIMDIntrinsic(op->AsIndir()->Addr()); } @@ -25058,7 +25052,7 @@ bool GenTreeLclFld::IsOffsetMisaligned() const bool GenTree::IsInvariant() const { - return OperIsConst() || OperIsLocalAddr(); + return OperIsConst() || OperIs(GT_LCL_ADDR); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index be7699074135e..573fc6ef617c3 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1077,7 +1077,7 @@ struct GenTree bool IsNotGcDef() const { - return IsIntegralConst(0) || OperIsLocalAddr(); + return IsIntegralConst(0) || OperIs(GT_LCL_ADDR); } // LIR flags @@ -1155,14 +1155,16 @@ struct GenTree return (GT_PHI_ARG <= gtOper) && (gtOper <= GT_STORE_LCL_FLD); } - static bool OperIsLocalAddr(genTreeOps gtOper) + static bool OperIsAnyLocal(genTreeOps gtOper) { - return (gtOper == GT_LCL_VAR_ADDR || gtOper == GT_LCL_FLD_ADDR); + static_assert_no_msg( + AreContiguous(GT_PHI_ARG, GT_LCL_VAR, GT_LCL_FLD, GT_STORE_LCL_VAR, GT_STORE_LCL_FLD, GT_LCL_ADDR)); + return (GT_PHI_ARG <= gtOper) && (gtOper <= GT_LCL_ADDR); } static bool OperIsLocalField(genTreeOps gtOper) { - return (gtOper == GT_LCL_FLD || gtOper == GT_LCL_FLD_ADDR || gtOper == GT_STORE_LCL_FLD); + return (gtOper == GT_LCL_FLD || gtOper == GT_LCL_ADDR || gtOper == GT_STORE_LCL_FLD); } bool OperIsLocalField() const @@ -1296,9 +1298,9 @@ struct GenTree return OperIsLocal(OperGet()); } - bool OperIsLocalAddr() const + bool OperIsAnyLocal() const { - return OperIsLocalAddr(OperGet()); + return OperIsAnyLocal(OperGet()); } bool OperIsScalarLocal() const @@ -1963,6 +1965,8 @@ struct GenTree return OperIsLocal(OperGet()); } + bool IsLclVarAddr() const; + // Returns "true" iff 'this' is a GT_LCL_FLD or GT_STORE_LCL_FLD on which the type // is not the same size as the type of the GT_LCL_VAR. bool IsPartialLclFld(Compiler* comp); @@ -3684,7 +3688,7 @@ struct GenTreeLclVar : public GenTreeLclVarCommon unsigned lclNum DEBUGARG(IL_OFFSET ilOffs = BAD_IL_OFFSET) DEBUGARG(bool largeNode = false)) : GenTreeLclVarCommon(oper, type, lclNum DEBUGARG(largeNode)) DEBUGARG(gtLclILoffs(ilOffs)) { - assert(OperIsLocal(oper) || OperIsLocalAddr(oper)); + assert(OperIsScalarLocal(oper)); } #if DEBUGGABLE_GENTREE @@ -7324,7 +7328,7 @@ struct GenTreeBlk : public GenTreeIndir #ifdef TARGET_XARCH bool IsOnHeapAndContainsReferences() { - return (m_layout != nullptr) && m_layout->HasGCPtr() && !Addr()->OperIsLocalAddr(); + return (m_layout != nullptr) && m_layout->HasGCPtr() && !Addr()->OperIs(GT_LCL_ADDR); } #endif @@ -7657,14 +7661,14 @@ class LocalsGenTreeList iterator& operator++() { - assert((m_tree->gtNext == nullptr) || m_tree->gtNext->OperIsLocal() || m_tree->gtNext->OperIsLocalAddr()); + assert((m_tree->gtNext == nullptr) || m_tree->gtNext->OperIsLocal() || m_tree->gtNext->OperIs(GT_LCL_ADDR)); m_tree = static_cast(m_tree->gtNext); return *this; } iterator& operator--() { - assert((m_tree->gtPrev == nullptr) || m_tree->gtPrev->OperIsLocal() || m_tree->gtPrev->OperIsLocalAddr()); + assert((m_tree->gtPrev == nullptr) || m_tree->gtPrev->OperIsLocal() || m_tree->gtPrev->OperIs(GT_LCL_ADDR)); m_tree = static_cast(m_tree->gtPrev); return *this; } @@ -9607,8 +9611,7 @@ inline void GenTree::SetRegSpillFlagByIdx(GenTreeFlags flags, int regIndex) inline GenTreeFlags GenTree::GetLastUseBit(int fieldIndex) const { assert(fieldIndex < 4); - assert(OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR, GT_LCL_VAR_ADDR, GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_FLD_ADDR, GT_COPY, - GT_RELOAD)); + assert(OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR, GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_ADDR, GT_COPY, GT_RELOAD)); static_assert_no_msg((1 << FIELD_LAST_USE_SHIFT) == GTF_VAR_FIELD_DEATH0); return (GenTreeFlags)(1 << (FIELD_LAST_USE_SHIFT + fieldIndex)); } @@ -9627,8 +9630,7 @@ inline GenTreeFlags GenTree::GetLastUseBit(int fieldIndex) const // inline bool GenTree::IsLastUse(int fieldIndex) const { - assert(OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR, GT_LCL_VAR_ADDR, GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_FLD_ADDR, GT_COPY, - GT_RELOAD)); + assert(OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR, GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_ADDR, GT_COPY, GT_RELOAD)); return (gtFlags & GetLastUseBit(fieldIndex)) != 0; } @@ -9643,8 +9645,7 @@ inline bool GenTree::IsLastUse(int fieldIndex) const // inline bool GenTree::HasLastUse() const { - assert(OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR, GT_LCL_VAR_ADDR, GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_FLD_ADDR, GT_COPY, - GT_RELOAD)); + assert(OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR, GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_ADDR, GT_COPY, GT_RELOAD)); return (gtFlags & (GTF_VAR_DEATH_MASK)) != 0; } diff --git a/src/coreclr/jit/gschecks.cpp b/src/coreclr/jit/gschecks.cpp index 5d54373eb854e..f534a0856d98d 100644 --- a/src/coreclr/jit/gschecks.cpp +++ b/src/coreclr/jit/gschecks.cpp @@ -494,7 +494,7 @@ void Compiler::gsParamsToShadows() { GenTree* tree = *use; - if (tree->OperIsLocal() || tree->OperIsLocalAddr()) + if (tree->OperIsLocal() || tree->OperIs(GT_LCL_ADDR)) { unsigned int lclNum = tree->AsLclVarCommon()->GetLclNum(); unsigned int shadowLclNum = m_compiler->gsShadowVarInfo[lclNum].shadowCopy; diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index cb678983ad432..d6b5dede51585 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -25,8 +25,7 @@ GTNODE(LCL_VAR , GenTreeLclVar ,0,GTK_LEAF) // local v GTNODE(LCL_FLD , GenTreeLclFld ,0,GTK_LEAF) // field in a non-primitive variable GTNODE(STORE_LCL_VAR , GenTreeLclVar ,0,GTK_UNOP|GTK_NOVALUE) // store to local variable GTNODE(STORE_LCL_FLD , GenTreeLclFld ,0,GTK_UNOP|GTK_NOVALUE) // store to a part of the variable -GTNODE(LCL_VAR_ADDR , GenTreeLclVar ,0,GTK_LEAF) // address of local variable -GTNODE(LCL_FLD_ADDR , GenTreeLclFld ,0,GTK_LEAF) // address of field in a non-primitive variable +GTNODE(LCL_ADDR , GenTreeLclFld ,0,GTK_LEAF) // local address //----------------------------------------------------------------------------- // Leaf nodes (i.e. these nodes have no sub-operands): diff --git a/src/coreclr/jit/gtstructs.h b/src/coreclr/jit/gtstructs.h index b64ff20f64e7a..157bfb6b28171 100644 --- a/src/coreclr/jit/gtstructs.h +++ b/src/coreclr/jit/gtstructs.h @@ -61,9 +61,9 @@ GTSTRUCT_1(LngCon , GT_CNS_LNG) GTSTRUCT_1(DblCon , GT_CNS_DBL) GTSTRUCT_1(StrCon , GT_CNS_STR) GTSTRUCT_1(VecCon , GT_CNS_VEC) -GTSTRUCT_N(LclVarCommon, GT_LCL_VAR, GT_LCL_FLD, GT_PHI_ARG, GT_STORE_LCL_VAR, GT_STORE_LCL_FLD, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR) -GTSTRUCT_3(LclVar , GT_LCL_VAR, GT_LCL_VAR_ADDR, GT_STORE_LCL_VAR) -GTSTRUCT_3(LclFld , GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_FLD_ADDR) +GTSTRUCT_N(LclVarCommon, GT_LCL_VAR, GT_LCL_FLD, GT_PHI_ARG, GT_STORE_LCL_VAR, GT_STORE_LCL_FLD, GT_LCL_ADDR) +GTSTRUCT_2(LclVar , GT_LCL_VAR, GT_STORE_LCL_VAR) +GTSTRUCT_3(LclFld , GT_LCL_FLD, GT_STORE_LCL_FLD, GT_LCL_ADDR) GTSTRUCT_1(Cast , GT_CAST) GTSTRUCT_1(Box , GT_BOX) GTSTRUCT_2(Field , GT_FIELD, GT_FIELD_ADDR) diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 666db1e36d54a..de2e479851cdf 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -458,7 +458,7 @@ GenTree* Compiler::getArgForHWIntrinsic(var_types argType, } else { - assert(newobjThis->OperIs(GT_LCL_VAR_ADDR)); + assert(newobjThis->IsLclVarAddr()); arg = newobjThis; // push newobj result on type stack diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index cc5ae8ed9c53a..8e4365023b357 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -520,7 +520,7 @@ void Compiler::impAppendStmt(Statement* stmt, unsigned chkLevel, bool checkConsu assert(retBuf->TypeIs(TYP_I_IMPL, TYP_BYREF)); - if (retBuf->OperIs(GT_LCL_VAR_ADDR)) + if (retBuf->OperIs(GT_LCL_ADDR)) { dstVarDsc = lvaGetDesc(retBuf->AsLclVarCommon()); } @@ -1212,8 +1212,7 @@ GenTree* Compiler::impGetStructAddr(GenTree* structVal, return gtNewLclVarAddrNode(structVal->AsLclVar()->GetLclNum(), TYP_BYREF); case GT_LCL_FLD: - return gtNewLclFldAddrNode(structVal->AsLclFld()->GetLclNum(), structVal->AsLclFld()->GetLclOffs(), - TYP_BYREF); + return gtNewLclAddrNode(structVal->AsLclFld()->GetLclNum(), structVal->AsLclFld()->GetLclOffs(), TYP_BYREF); case GT_FIELD: { @@ -2556,12 +2555,12 @@ CORINFO_CLASS_HANDLE Compiler::impGetObjectClass() /* static */ void Compiler::impBashVarAddrsToI(GenTree* tree1, GenTree* tree2) { - if (tree1->OperIsLocalAddr()) + if (tree1->OperIs(GT_LCL_ADDR)) { tree1->gtType = TYP_I_IMPL; } - if (tree2 && tree2->OperIsLocalAddr()) + if (tree2 && tree2->OperIs(GT_LCL_ADDR)) { tree2->gtType = TYP_I_IMPL; } @@ -6843,7 +6842,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) // We had better assign it a value of the correct type assertImp( genActualType(lclTyp) == genActualType(op1->gtType) || - (genActualType(lclTyp) == TYP_I_IMPL && op1->OperIsLocalAddr()) || + (genActualType(lclTyp) == TYP_I_IMPL && op1->OperIs(GT_LCL_ADDR)) || (genActualType(lclTyp) == TYP_I_IMPL && (op1->gtType == TYP_BYREF || op1->gtType == TYP_REF)) || (genActualType(op1->gtType) == TYP_I_IMPL && lclTyp == TYP_BYREF) || (varTypeIsFloating(lclTyp) && varTypeIsFloating(op1->TypeGet())) || @@ -6962,7 +6961,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) } op1->ChangeType(TYP_BYREF); - op1->SetOper(GT_LCL_VAR_ADDR); + op1->SetOper(GT_LCL_ADDR); + op1->AsLclFld()->SetLclOffs(0); goto _PUSH_ADRVAR; } @@ -6987,7 +6987,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) op1 = gtNewLclVarAddrNode(lclNum, TYP_BYREF); _PUSH_ADRVAR: - assert(op1->OperIs(GT_LCL_VAR_ADDR)); + assert(op1->IsLclVarAddr()); tiRetVal = typeInfo(TI_BYTE).MakeByRef(); impPushOnStack(op1, tiRetVal); @@ -12821,7 +12821,7 @@ bool Compiler::impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut) op = op->AsField()->GetFldObj(); } - if (op->OperIs(GT_LCL_VAR_ADDR)) + if (op->OperIs(GT_LCL_ADDR)) { if (lclVarTreeOut != nullptr) { @@ -13520,7 +13520,7 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo) assert(varTypeIsIntOrI(sigType)); /* If possible bash the BYREF to an int */ - if (inlArgNode->OperIsLocalAddr()) + if (inlArgNode->OperIs(GT_LCL_ADDR)) { inlArgNode->gtType = TYP_I_IMPL; lclVarInfo[i].lclVerTypeInfo = typeInfo(varType2tiType(TYP_I_IMPL)); diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 126a0ebae45f3..b4d2a0d717700 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -1024,7 +1024,7 @@ var_types Compiler::impImportCall(OPCODE opcode, if (clsFlags & CORINFO_FLG_VALUECLASS) { - assert(newobjThis->OperIs(GT_LCL_VAR_ADDR)); + assert(newobjThis->IsLclVarAddr()); unsigned lclNum = newobjThis->AsLclVarCommon()->GetLclNum(); impPushOnStack(gtNewLclvNode(lclNum, lvaGetRealType(lclNum)), @@ -2023,7 +2023,7 @@ GenTree* Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig) argIndex++; } - assert((comma != nullptr) && comma->OperIs(GT_LCL_VAR_ADDR) && + assert((comma != nullptr) && comma->IsLclVarAddr() && (comma->AsLclVarCommon()->GetLclNum() == lvaNewObjArrayArgs)); if (argIndex != numArgs) @@ -7051,11 +7051,11 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, if (optimizedTheBox) { - assert(localCopyThis->OperIs(GT_LCL_VAR_ADDR)); + assert(localCopyThis->IsLclVarAddr()); // We may end up inlining this call, so the local copy must be marked as "aliased", // making sure the inlinee importer will know when to spill references to its value. - lvaGetDesc(localCopyThis->AsLclVar())->lvHasLdAddrOp = true; + lvaGetDesc(localCopyThis->AsLclFld())->lvHasLdAddrOp = true; #if FEATURE_TAILCALL_OPT if (call->IsImplicitTailCall()) diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index f789f58b0f785..152edb7b927f4 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -568,7 +568,7 @@ void CodeGen::inst_IV_handle(instruction ins, cnsval_ssize_t val) void CodeGen::inst_set_SV_var(GenTree* tree) { #ifdef DEBUG - assert((tree != nullptr) && tree->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR, GT_STORE_LCL_VAR)); + assert((tree != nullptr) && (tree->OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR) || tree->IsLclVarAddr())); assert(tree->AsLclVarCommon()->GetLclNum() < compiler->lvaCount); GetEmitter()->emitVarRefOffs = tree->AsLclVar()->gtLclILoffs; @@ -804,12 +804,11 @@ CodeGen::OperandDesc CodeGen::genOperandDesc(GenTree* op) switch (addr->OperGet()) { - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: { assert(addr->isContained()); - varNum = addr->AsLclVarCommon()->GetLclNum(); - offset = addr->AsLclVarCommon()->GetLclOffs(); + varNum = addr->AsLclFld()->GetLclNum(); + offset = addr->AsLclFld()->GetLclOffs(); break; } diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 3d969ae620268..29aa57705f8db 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -65,7 +65,7 @@ class LocalSequencer final : public GenTreeVisitor else { assert(lastNode->gtNext == nullptr); - assert(lastNode->OperIsLocal() || lastNode->OperIsLocalAddr()); + assert(lastNode->OperIsLocal() || lastNode->OperIs(GT_LCL_ADDR)); } firstNode->gtPrev = nullptr; @@ -78,7 +78,7 @@ class LocalSequencer final : public GenTreeVisitor fgWalkResult PostOrderVisit(GenTree** use, GenTree* user) { GenTree* node = *use; - if (node->OperIsLocal() || node->OperIsLocalAddr()) + if (node->OperIsLocal() || node->OperIs(GT_LCL_ADDR)) { SequenceLocal(node->AsLclVarCommon()); } @@ -309,26 +309,6 @@ class LocalAddressVisitor final : public GenTreeVisitor assert(m_offset == 0); } - //------------------------------------------------------------------------ - // Address: Produce an address value from a GT_LCL_VAR_ADDR node. - // - // Arguments: - // lclVar - a GT_LCL_VAR_ADDR node that defines the address - // - // Notes: - // - (lclnum) => ADDRESS(lclNum, 0) - // - void Address(GenTreeLclVar* lclVar) - { - assert(lclVar->OperIs(GT_LCL_VAR_ADDR)); - assert(!IsLocation() && !IsAddress()); - - m_lclNum = lclVar->GetLclNum(); - m_address = true; - - assert(m_offset == 0); - } - //------------------------------------------------------------------------ // Location: Produce a location value. // @@ -348,21 +328,21 @@ class LocalAddressVisitor final : public GenTreeVisitor } //------------------------------------------------------------------------ - // Address: Produce an address value from a LCL_FLD_ADDR node. + // Address: Produce an address value from a LCL_ADDR node. // // Arguments: - // lclFld - a GT_LCL_FLD_ADDR node that defines the address + // lclAddr - a GT_LCL_ADDR node that defines the address // // Notes: // - (lclnum, lclOffs) => ADDRESS(lclNum, offset) // - void Address(GenTreeLclFld* lclFld) + void Address(GenTreeLclFld* lclAddr) { - assert(lclFld->OperIs(GT_LCL_FLD_ADDR)); + assert(lclAddr->OperIs(GT_LCL_ADDR)); assert(!IsLocation() && !IsAddress()); - m_lclNum = lclFld->GetLclNum(); - m_offset = lclFld->GetLclOffs(); + m_lclNum = lclAddr->GetLclNum(); + m_offset = lclAddr->GetLclOffs(); m_address = true; } @@ -584,7 +564,7 @@ class LocalAddressVisitor final : public GenTreeVisitor MorphLocalField(node, user); } - if (node->OperIsLocal() || node->OperIsLocalAddr()) + if (node->OperIsLocal() || node->OperIs(GT_LCL_ADDR)) { unsigned const lclNum = node->AsLclVarCommon()->GetLclNum(); LclVarDsc* const varDsc = m_compiler->lvaGetDesc(lclNum); @@ -633,13 +613,6 @@ class LocalAddressVisitor final : public GenTreeVisitor SequenceLocal(node->AsLclVarCommon()); break; - case GT_LCL_VAR_ADDR: - assert(TopValue(0).Node() == node); - - TopValue(0).Address(node->AsLclVar()); - SequenceLocal(node->AsLclVarCommon()); - break; - case GT_LCL_FLD: assert(TopValue(0).Node() == node); @@ -647,7 +620,7 @@ class LocalAddressVisitor final : public GenTreeVisitor SequenceLocal(node->AsLclVarCommon()); break; - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: assert(TopValue(0).Node() == node); TopValue(0).Address(node->AsLclFld()); @@ -1057,17 +1030,11 @@ class LocalAddressVisitor final : public GenTreeVisitor assert(addr->TypeIs(TYP_BYREF, TYP_I_IMPL)); assert(m_compiler->lvaVarAddrExposed(lclNum) || m_compiler->lvaGetDesc(lclNum)->IsHiddenBufferStructArg()); - if (offset == 0) + if (IsValidLclAddr(lclNum, offset)) { - addr->ChangeOper(GT_LCL_VAR_ADDR); - addr->AsLclVar()->SetLclNum(lclNum); - } - else if (IsValidLclAddr(lclNum, offset)) - { - addr->ChangeOper(GT_LCL_FLD_ADDR); + addr->ChangeOper(GT_LCL_ADDR); addr->AsLclFld()->SetLclNum(lclNum); addr->AsLclFld()->SetLclOffs(offset); - addr->AsLclFld()->SetLayout(nullptr); } else { @@ -1431,7 +1398,7 @@ class LocalAddressVisitor final : public GenTreeVisitor GenTree* objRef = node->AsUnOp()->gtOp1; // TODO-Bug: this code does not pay attention to "GTF_IND_VOLATILE". - if ((objRef != nullptr) && objRef->OperIs(GT_LCL_VAR_ADDR)) + if ((objRef != nullptr) && objRef->IsLclVarAddr()) { const LclVarDsc* varDsc = m_compiler->lvaGetDesc(objRef->AsLclVarCommon()); @@ -1453,8 +1420,9 @@ class LocalAddressVisitor final : public GenTreeVisitor if (node->OperIs(GT_FIELD_ADDR)) { - node->ChangeOper(GT_LCL_VAR_ADDR); - node->AsLclVar()->SetLclNum(fieldLclNum); + node->ChangeOper(GT_LCL_ADDR); + node->AsLclFld()->SetLclNum(fieldLclNum); + node->AsLclFld()->SetLclOffs(0); } else if (node->TypeGet() == fieldType) { @@ -1507,7 +1475,7 @@ class LocalAddressVisitor final : public GenTreeVisitor node->SetOper(GT_IND); } - objRef->AsLclVar()->SetLclNum(fieldLclNum); + objRef->AsLclFld()->SetLclNum(fieldLclNum); } JITDUMP("Replacing the field in promoted struct with local var V%02u\n", fieldLclNum); @@ -1595,7 +1563,7 @@ class LocalAddressVisitor final : public GenTreeVisitor { node = m_ancestors.Top(1); } - else if (node->OperIs(GT_LCL_VAR_ADDR)) + else if (node->IsLclVarAddr()) { if (m_ancestors.Height() < 3) { diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index da54964aaaa73..97ede22410654 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -4230,7 +4230,7 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, } } - if (tree->OperIsLocalAddr()) + if (tree->OperIs(GT_LCL_ADDR)) { LclVarDsc* varDsc = lvaGetDesc(tree->AsLclVarCommon()); assert(varDsc->IsAddressExposed() || varDsc->IsHiddenBufferStructArg()); @@ -4704,40 +4704,28 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) const weight_t weight = block->getBBWeight(this); for (GenTree* node : LIR::AsRange(block)) { - switch (node->OperGet()) + if (node->OperIsAnyLocal()) { - case GT_LCL_VAR: - case GT_LCL_FLD: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: - case GT_STORE_LCL_VAR: - case GT_STORE_LCL_FLD: + LclVarDsc* varDsc = lvaGetDesc(node->AsLclVarCommon()); + // If this is an EH var, use a zero weight for defs, so that we don't + // count those in our heuristic for register allocation, since they always + // must be stored, so there's no value in enregistering them at defs; only + // if there are enough uses to justify it. + if (varDsc->lvLiveInOutOfHndlr && !varDsc->lvDoNotEnregister && + ((node->gtFlags & GTF_VAR_DEF) != 0)) { - LclVarDsc* varDsc = lvaGetDesc(node->AsLclVarCommon()); - // If this is an EH var, use a zero weight for defs, so that we don't - // count those in our heuristic for register allocation, since they always - // must be stored, so there's no value in enregistering them at defs; only - // if there are enough uses to justify it. - if (varDsc->lvLiveInOutOfHndlr && !varDsc->lvDoNotEnregister && - ((node->gtFlags & GTF_VAR_DEF) != 0)) - { - varDsc->incRefCnts(0, this); - } - else - { - varDsc->incRefCnts(weight, this); - } - - if ((node->gtFlags & GTF_VAR_CONTEXT) != 0) - { - assert(node->OperIs(GT_LCL_VAR)); - lvaGenericsContextInUse = true; - } - break; + varDsc->incRefCnts(0, this); + } + else + { + varDsc->incRefCnts(weight, this); } - default: - break; + if ((node->gtFlags & GTF_VAR_CONTEXT) != 0) + { + assert(node->OperIs(GT_LCL_VAR)); + lvaGenericsContextInUse = true; + } } } } @@ -8194,7 +8182,7 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData* GenTree* const tree = *pTree; GenTreeLclVarCommon* lcl = nullptr; - if (tree->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR, GT_LCL_FLD, GT_LCL_FLD_ADDR)) + if (tree->OperIs(GT_LCL_VAR, GT_LCL_FLD, GT_LCL_ADDR)) { lcl = tree->AsLclVarCommon(); } @@ -8220,7 +8208,7 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData* if (bFirstPass) { // Ignore locals that already have field appearances - if (lcl->OperIs(GT_LCL_FLD, GT_LCL_FLD_ADDR)) + if (lcl->OperIs(GT_LCL_FLD) || (lcl->OperIs(GT_LCL_ADDR) && (lcl->AsLclFld()->GetLclOffs() != 0))) { varDsc->lvNoLclFldStress = true; return WALK_SKIP_SUBTREES; @@ -8338,13 +8326,9 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData* if (tree->OperIs(GT_LCL_VAR)) { tree->ChangeOper(GT_LCL_FLD); - tree->AsLclFld()->SetLclOffs(padding); - } - else if (tree->OperIs(GT_LCL_VAR_ADDR)) - { - tree->ChangeOper(GT_LCL_FLD_ADDR); - tree->AsLclFld()->SetLclOffs(padding); } + + tree->AsLclFld()->SetLclOffs(padding); } return WALK_SKIP_SUBTREES; diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index 5e2f4621edd7d..4e93f035f362f 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -22,7 +22,7 @@ */ void Compiler::fgMarkUseDef(GenTreeLclVarCommon* tree) { - assert((tree->OperIsLocal() && (tree->OperGet() != GT_PHI_ARG)) || tree->OperIsLocalAddr()); + assert((tree->OperIsLocal() && (tree->OperGet() != GT_PHI_ARG)) || tree->OperIs(GT_LCL_ADDR)); const unsigned lclNum = tree->GetLclNum(); LclVarDsc* const varDsc = lvaGetDesc(lclNum); @@ -214,8 +214,7 @@ void Compiler::fgPerNodeLocalVarLiveness(GenTree* tree) case GT_LCL_VAR: case GT_LCL_FLD: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: case GT_STORE_LCL_VAR: case GT_STORE_LCL_FLD: fgMarkUseDef(tree->AsLclVarCommon()); @@ -1853,7 +1852,7 @@ void Compiler::fgComputeLife(VARSET_TP& life, { fgComputeLifeCall(life, tree->AsCall()); } - else if (tree->OperIsNonPhiLocal() || tree->OperIsLocalAddr()) + else if (tree->OperIsNonPhiLocal() || tree->OperIs(GT_LCL_ADDR)) { bool isDeadStore = fgComputeLifeLocal(life, keepAliveVars, tree); if (isDeadStore) @@ -1992,8 +1991,7 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR break; } - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: if (node->IsUnusedValue()) { JITDUMP("Removing dead LclVar address:\n"); @@ -2717,7 +2715,7 @@ void Compiler::fgInterBlockLocalVarLiveness() { for (GenTree* cur = stmt->GetTreeListEnd(); cur != nullptr;) { - assert(cur->OperIsLocal() || cur->OperIsLocalAddr()); + assert(cur->OperIsLocal() || cur->OperIs(GT_LCL_ADDR)); bool isDef = ((cur->gtFlags & GTF_VAR_DEF) != 0) && ((cur->gtFlags & GTF_VAR_USEASG) == 0); bool conditional = cur != dst; // Ignore conditional defs that would otherwise @@ -2743,7 +2741,7 @@ void Compiler::fgInterBlockLocalVarLiveness() { for (GenTree* cur = stmt->GetTreeListEnd(); cur != nullptr;) { - assert(cur->OperIsLocal() || cur->OperIsLocalAddr()); + assert(cur->OperIsLocal() || cur->OperIs(GT_LCL_ADDR)); if (!fgComputeLifeLocal(life, keepAliveVars, cur)) { cur = cur->gtPrev; diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 766683d692aa0..8b00440e919ff 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -665,10 +665,8 @@ GenTree* Lowering::LowerNode(GenTree* node) node->gtGetOp1()->SetRegOptional(); break; - case GT_LCL_FLD_ADDR: - case GT_LCL_VAR_ADDR: + case GT_LCL_ADDR: { - const GenTreeLclVarCommon* lclAddr = node->AsLclVarCommon(); const LclVarDsc* varDsc = comp->lvaGetDesc(lclAddr); if (!varDsc->lvDoNotEnregister) @@ -2615,7 +2613,7 @@ void Lowering::RehomeArgForFastTailCall(unsigned int lclNum, unsigned int tmpLclNum = BAD_VAR_NUM; for (GenTree* treeNode = lookForUsesStart; treeNode != callNode; treeNode = treeNode->gtNext) { - if (!treeNode->OperIsLocal() && !treeNode->OperIsLocalAddr()) + if (!treeNode->OperIsLocal() && !treeNode->OperIs(GT_LCL_ADDR)) { continue; } @@ -4286,7 +4284,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) { ClassLayout* layout = lclStore->GetLayout(comp); const unsigned lclNum = lclStore->GetLclNum(); - GenTreeLclFld* addr = comp->gtNewLclFldAddrNode(lclNum, lclStore->GetLclOffs(), TYP_BYREF); + GenTreeLclFld* addr = comp->gtNewLclAddrNode(lclNum, lclStore->GetLclOffs(), TYP_BYREF); comp->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::BlockOp)); addr->gtFlags |= lclStore->gtFlags & (GTF_VAR_DEF | GTF_VAR_USEASG); @@ -5020,8 +5018,8 @@ GenTree* Lowering::CreateFrameLinkUpdate(FrameLinkAction action) if (action == PushFrame) { // Thread->m_pFrame = &inlinedCallFrame; - data = new (comp, GT_LCL_FLD_ADDR) - GenTreeLclFld(GT_LCL_FLD_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + data = new (comp, GT_LCL_ADDR) + GenTreeLclFld(GT_LCL_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); } else { @@ -5101,8 +5099,8 @@ void Lowering::InsertPInvokeMethodProlog() const LclVarDsc* inlinedPInvokeDsc = comp->lvaGetDesc(comp->lvaInlinedPInvokeFrameVar); assert(inlinedPInvokeDsc->IsAddressExposed()); #endif // DEBUG - GenTree* frameAddr = new (comp, GT_LCL_FLD_ADDR) - GenTreeLclFld(GT_LCL_FLD_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); + GenTree* frameAddr = new (comp, GT_LCL_ADDR) + GenTreeLclFld(GT_LCL_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfFrameVptr); // Call runtime helper to fill in our InlinedCallFrame and push it on the Frame list: // TCB = CORINFO_HELP_INIT_PINVOKE_FRAME(&symFrameStart, secretArg); @@ -5283,8 +5281,7 @@ void Lowering::InsertPInvokeCallProlog(GenTreeCall* call) if (comp->opts.ShouldUsePInvokeHelpers()) { // First argument is the address of the frame variable. - GenTree* frameAddr = - new (comp, GT_LCL_VAR_ADDR) GenTreeLclVar(GT_LCL_VAR_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar); + GenTree* frameAddr = comp->gtNewLclVarAddrNode(comp->lvaInlinedPInvokeFrameVar, TYP_BYREF); #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) // On x86 targets, PInvoke calls need the size of the stack args in InlinedCallFrame.m_Datum. @@ -7294,15 +7291,14 @@ void Lowering::CheckNode(Compiler* compiler, GenTree* node) } break; - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: { const GenTreeLclVarCommon* lclVarAddr = node->AsLclVarCommon(); const LclVarDsc* varDsc = compiler->lvaGetDesc(lclVarAddr); if (((lclVarAddr->gtFlags & GTF_VAR_DEF) != 0) && varDsc->HasGCPtr()) { - // Emitter does not correctly handle live updates for LCL_VAR_ADDR - // when they are not contained, for example, `STOREIND byref(GT_LCL_VAR_ADDR not-contained)` + // Emitter does not correctly handle live updates for LCL_ADDR + // when they are not contained, for example, `STOREIND byref(GT_LCL_ADDR not-contained)` // would generate: // add r1, sp, 48 // r1 contains address of a lclVar V01. // str r0, [r1] // a gc ref becomes live in V01, but emitter would not report it. @@ -7436,9 +7432,15 @@ bool Lowering::IndirsAreEquivalent(GenTree* candidate, GenTree* storeInd) oper = pTreeA->OperGet(); switch (oper) { + case GT_LCL_ADDR: + if (pTreeA->AsLclFld()->GetLclOffs() != 0) + { + // TODO-CQ: support arbitrary local addresses here. + return false; + } + FALLTHROUGH; + case GT_LCL_VAR: - case GT_LCL_VAR_ADDR: - case GT_CLS_VAR_ADDR: case GT_CNS_INT: return NodesAreEquivalentLeaves(pTreeA, pTreeB); @@ -7501,8 +7503,13 @@ bool Lowering::NodesAreEquivalentLeaves(GenTree* tree1, GenTree* tree2) case GT_CNS_INT: return tree1->AsIntCon()->IconValue() == tree2->AsIntCon()->IconValue() && tree1->IsIconHandle() == tree2->IsIconHandle(); + case GT_LCL_ADDR: + if (tree1->AsLclFld()->GetLclOffs() != tree2->AsLclFld()->GetLclOffs()) + { + return false; + } + FALLTHROUGH; case GT_LCL_VAR: - case GT_LCL_VAR_ADDR: return tree1->AsLclVarCommon()->GetLclNum() == tree2->AsLclVarCommon()->GetLclNum(); case GT_CLS_VAR_ADDR: return tree1->AsClsVar()->gtClsVarHnd == tree2->AsClsVar()->gtClsVarHnd; diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 3f603fcf95437..0a9f57f546926 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -512,7 +512,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) GenTree* src = blkNode->Data(); unsigned size = blkNode->Size(); - const bool isDstAddrLocal = dstAddr->OperIsLocalAddr(); + const bool isDstAddrLocal = dstAddr->OperIs(GT_LCL_ADDR); if (blkNode->OperIsInitBlkOp()) { @@ -647,7 +647,7 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT assert(blkNode->OperIs(GT_STORE_BLK) && (blkNode->gtBlkOpKind == GenTreeBlk::BlkOpKindUnroll)); assert(size < INT32_MAX); - if (addr->OperIsLocalAddr()) + if (addr->OperIs(GT_LCL_ADDR)) { addr->SetContained(); return; @@ -2003,10 +2003,10 @@ void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) MakeSrcContained(indirNode, addr); } } - else if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + else if (addr->OperIs(GT_LCL_ADDR)) { // These nodes go into an addr mode: - // - GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR is a stack addr mode. + // - GT_LCL_ADDR is a stack addr mode. MakeSrcContained(indirNode, addr); } #ifdef TARGET_ARM64 diff --git a/src/coreclr/jit/lowerloongarch64.cpp b/src/coreclr/jit/lowerloongarch64.cpp index e4ca0c78f0f99..011d6eb45ed8b 100644 --- a/src/coreclr/jit/lowerloongarch64.cpp +++ b/src/coreclr/jit/lowerloongarch64.cpp @@ -356,7 +356,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { blkNode->SetOper(GT_STORE_BLK); } - else if (dstAddr->OperIsLocalAddr() && (size <= copyBlockUnrollLimit)) + else if (dstAddr->OperIs(GT_LCL_ADDR) && (size <= copyBlockUnrollLimit)) { // If the size is small enough to unroll then we need to mark the block as non-interruptible // to actually allow unrolling. The generated code does not report GC references loaded in the @@ -408,7 +408,7 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT assert(blkNode->OperIs(GT_STORE_BLK) && (blkNode->gtBlkOpKind == GenTreeBlk::BlkOpKindUnroll)); assert(size < INT32_MAX); - if (addr->OperIsLocalAddr()) + if (addr->OperIs(GT_LCL_ADDR)) { addr->SetContained(); return; @@ -475,7 +475,7 @@ void Lowering::LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode) else { layout = src->AsLclFld()->GetLayout(); - lclAddr = comp->gtNewLclFldAddrNode(lclNum, src->AsLclFld()->GetLclOffs()); + lclAddr = comp->gtNewLclAddrNode(lclNum, src->AsLclFld()->GetLclOffs()); } src->ChangeOper(GT_OBJ); @@ -486,9 +486,9 @@ void Lowering::LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode) } // Codegen supports containment of local addresses under OBJs. - if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIs(GT_LCL_VAR_ADDR)) + if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->IsLclVarAddr()) { - // TODO-LOONGARCH64-CQ: support containment of LCL_FLD_ADDR too. + // TODO-LOONGARCH64-CQ: support containment of LCL_ADDR with non-zero offset too. MakeSrcContained(src, src->AsObj()->Addr()); } } @@ -705,10 +705,10 @@ void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) { MakeSrcContained(indirNode, addr); } - else if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + else if (addr->OperIs(GT_LCL_ADDR)) { // These nodes go into an addr mode: - // - GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR is a stack addr mode. + // - GT_LCL_ADDR is a stack addr mode. MakeSrcContained(indirNode, addr); } else if (addr->OperIs(GT_CLS_VAR_ADDR)) diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 8e323fa3e1f98..619eb4b75b447 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -430,7 +430,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) blkNode->SetOper(GT_STORE_BLK); } #ifndef JIT32_GCENCODER - else if (dstAddr->OperIsLocalAddr() && + else if (dstAddr->OperIs(GT_LCL_ADDR) && (size <= comp->getUnrollThreshold(Compiler::UnrollKind::Memcpy, false))) { // If the size is small enough to unroll then we need to mark the block as non-interruptible @@ -453,7 +453,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) // the entire operation takes 20 cycles and encodes in 5 bytes (loading RCX and REP MOVSD/Q). unsigned nonGCSlots = 0; - if (dstAddr->OperIsLocalAddr()) + if (dstAddr->OperIs(GT_LCL_ADDR)) { // If the destination is on the stack then no write barriers are needed. nonGCSlots = blkNode->GetLayout()->GetSlotCount(); @@ -531,7 +531,7 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT assert(blkNode->OperIs(GT_STORE_BLK) && (blkNode->gtBlkOpKind == GenTreeBlk::BlkOpKindUnroll)); assert(size < INT32_MAX); - if (addr->OperIsLocalAddr()) + if (addr->OperIs(GT_LCL_ADDR)) { addr->SetContained(); return; @@ -5101,7 +5101,7 @@ bool Lowering::IsRMWMemOpRootedAtStoreInd(GenTree* tree, GenTree** outIndirCandi assert(storeInd->IsRMWStatusUnknown()); // Early out if indirDst is not one of the supported memory operands. - if (!indirDst->OperIs(GT_LEA, GT_LCL_VAR, GT_LCL_VAR_ADDR, GT_CLS_VAR_ADDR, GT_CNS_INT)) + if (!indirDst->OperIs(GT_LEA, GT_LCL_VAR, GT_CLS_VAR_ADDR, GT_CNS_INT) && !indirDst->IsLclVarAddr()) { storeInd->SetRMWStatus(STOREIND_RMW_UNSUPPORTED_ADDR); return false; @@ -5440,11 +5440,11 @@ void Lowering::ContainCheckIndir(GenTreeIndir* node) // The address of an indirection that requires its address in a reg. // Skip any further processing that might otherwise make it contained. } - else if (addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR)) + else if (addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_ADDR)) { // These nodes go into an addr mode: // - GT_CLS_VAR_ADDR turns into a constant. - // - GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR is a stack addr mode. + // - GT_LCL_ADDR is a stack addr mode. // make this contained, it turns into a constant that goes into an addr mode MakeSrcContained(node, addr); @@ -6248,13 +6248,14 @@ bool Lowering::LowerRMWMemOp(GenTreeIndir* storeInd) } else { - assert(indirCandidateChild->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR, GT_CLS_VAR_ADDR, GT_CNS_INT)); + assert(indirCandidateChild->OperIs(GT_LCL_VAR, GT_CLS_VAR_ADDR, GT_CNS_INT) || + indirCandidateChild->IsLclVarAddr()); // If it is a GT_LCL_VAR, it still needs the reg to hold the address. // We would still need a reg for GT_CNS_INT if it doesn't fit within addressing mode base. // For GT_CLS_VAR_ADDR, we don't need a reg to hold the address, because field address value is known at jit // time. Also, we don't need a reg for GT_CLS_VAR_ADDR. - if (indirCandidateChild->OperIs(GT_LCL_VAR_ADDR, GT_CLS_VAR_ADDR)) + if (indirCandidateChild->OperIs(GT_LCL_ADDR, GT_CLS_VAR_ADDR)) { indirDst->SetContained(); } @@ -6982,7 +6983,7 @@ void Lowering::ContainCheckHWIntrinsicAddr(GenTreeHWIntrinsic* node, GenTree* ad { assert((addr->TypeGet() == TYP_I_IMPL) || (addr->TypeGet() == TYP_BYREF)); TryCreateAddrMode(addr, true, node); - if ((addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA) || + if ((addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_ADDR, GT_LEA) || (addr->IsCnsIntOrI() && addr->AsIntConCommon()->FitsInAddrBase(comp))) && IsInvariantInRange(addr, node)) { diff --git a/src/coreclr/jit/lsraarm.cpp b/src/coreclr/jit/lsraarm.cpp index 9cf163c66f07e..e61e583a420e6 100644 --- a/src/coreclr/jit/lsraarm.cpp +++ b/src/coreclr/jit/lsraarm.cpp @@ -755,8 +755,7 @@ int LinearScan::BuildNode(GenTree* tree) } break; - case GT_LCL_FLD_ADDR: - case GT_LCL_VAR_ADDR: + case GT_LCL_ADDR: case GT_PHYSREG: case GT_CLS_VAR_ADDR: case GT_IL_OFFSET: diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 2955b457971a1..11892bdbcfae9 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -699,8 +699,8 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } const bool isSrcAddrLocal = src->OperIs(GT_LCL_VAR, GT_LCL_FLD) || - ((srcAddrOrFill != nullptr) && srcAddrOrFill->OperIsLocalAddr()); - const bool isDstAddrLocal = dstAddr->OperIsLocalAddr(); + ((srcAddrOrFill != nullptr) && srcAddrOrFill->OperIs(GT_LCL_ADDR)); + const bool isDstAddrLocal = dstAddr->OperIs(GT_LCL_ADDR); // CodeGen can use 16-byte SIMD ldp/stp for larger block sizes. // This is the case, when both registers are either sp or fp. diff --git a/src/coreclr/jit/lsraloongarch64.cpp b/src/coreclr/jit/lsraloongarch64.cpp index 0611b1d5e162d..0f1fcbc582f34 100644 --- a/src/coreclr/jit/lsraloongarch64.cpp +++ b/src/coreclr/jit/lsraloongarch64.cpp @@ -977,9 +977,9 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) { assert(putArgChild->isContained()); GenTree* objChild = putArgChild->gtGetOp1(); - if (objChild->OperGet() == GT_LCL_VAR_ADDR) + if (objChild->IsLclVarAddr()) { - // We will generate all of the code for the GT_PUTARG_STK, the GT_OBJ and the GT_LCL_VAR_ADDR + // We will generate all of the code for the GT_PUTARG_STK, the GT_OBJ and the GT_LCL_ADDR<0> // as one contained operation, and there are no source registers. // assert(objChild->isContained()); @@ -1079,9 +1079,9 @@ int LinearScan::BuildPutArgSplit(GenTreePutArgSplit* argNode) buildInternalIntRegisterDefForNode(argNode, allRegs(TYP_INT) & ~argMask); GenTree* objChild = putArgChild->gtGetOp1(); - if (objChild->OperGet() == GT_LCL_VAR_ADDR) + if (objChild->IsLclVarAddr()) { - // We will generate all of the code for the GT_PUTARG_SPLIT, the GT_OBJ and the GT_LCL_VAR_ADDR + // We will generate all of the code for the GT_PUTARG_SPLIT, the GT_OBJ and the GT_LCL_ADDR<0> // as one contained operation // assert(objChild->isContained()); @@ -1139,7 +1139,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) buildInternalIntRegisterDefForNode(blkNode); } - const bool isDstRegAddrAlignmentKnown = dstAddr->OperIsLocalAddr(); + const bool isDstRegAddrAlignmentKnown = dstAddr->OperIs(GT_LCL_ADDR); if (isDstRegAddrAlignmentKnown && (size > FP_REGSIZE_BYTES)) { diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 2fcef45f90616..9e321025f7e71 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -2228,7 +2228,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call // TODO-Cleanup: this is duplicative with the code in args morphing, however, also kicks in for // "non-standard" (return buffer on ARM64) arguments. Fix args morphing and delete this code. - if (argx->OperIsLocalAddr()) + if (argx->OperIs(GT_LCL_ADDR)) { argx->gtType = TYP_I_IMPL; } @@ -3179,7 +3179,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) // For pointers to locals we can skip reporting GC info and also skip zero initialization. // NOTE: We deferred this from the importer because of the inliner. - if (argx->OperIsLocalAddr()) + if (argx->OperIs(GT_LCL_ADDR)) { argx->gtType = TYP_I_IMPL; } @@ -3993,16 +3993,8 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg) else { uint16_t offs = lcl->GetLclOffs(); - if (offs == 0) - { - lcl->ChangeOper(GT_LCL_VAR_ADDR); - } - else - { - lcl->ChangeOper(GT_LCL_FLD_ADDR); - lcl->AsLclFld()->SetLclOffs(offs); - } - + lcl->ChangeOper(GT_LCL_ADDR); + lcl->AsLclFld()->SetLclOffs(offs); lcl->gtType = TYP_I_IMPL; lvaSetVarAddrExposed(varNum DEBUGARG(AddressExposedReason::ESCAPE_ADDRESS)); @@ -4674,7 +4666,7 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) // GenTree* Compiler::fgMorphLocal(GenTreeLclVarCommon* lclNode) { - assert(lclNode->OperIs(GT_LCL_VAR, GT_LCL_FLD) || lclNode->OperIsLocalAddr()); + assert(lclNode->OperIs(GT_LCL_VAR, GT_LCL_FLD) || lclNode->OperIs(GT_LCL_ADDR)); GenTree* expandedTree = nullptr; #ifdef TARGET_X86 @@ -4690,7 +4682,7 @@ GenTree* Compiler::fgMorphLocal(GenTreeLclVarCommon* lclNode) return expandedTree; } - if (lclNode->OperIsLocalAddr()) + if (lclNode->OperIs(GT_LCL_ADDR)) { // No further morphing necessary. return lclNode; @@ -4740,7 +4732,7 @@ GenTree* Compiler::fgMorphExpandStackArgForVarArgs(GenTreeLclVarCommon* lclNode) GenTree* offsetNode = gtNewIconNode(offset, TYP_I_IMPL); GenTree* argAddr = gtNewOperNode(GT_SUB, TYP_I_IMPL, argsBaseAddr, offsetNode); - if (lclNode->OperIsLocalAddr()) + if (lclNode->OperIs(GT_LCL_ADDR)) { return argAddr; } @@ -4850,7 +4842,7 @@ GenTree* Compiler::fgMorphExpandImplicitByRefArg(GenTreeLclVarCommon* lclNode) // Add a level of indirection to this node. The "base" will be a local node referring to "newLclNum". // We will also add an offset, and, if the original "lclNode" represents a location, a dereference. - bool isAddress = lclNode->OperIsLocalAddr(); + bool isAddress = lclNode->OperIs(GT_LCL_ADDR); unsigned offset = lclNode->GetLclOffs() + fieldOffset; var_types argNodeType = lclNode->TypeGet(); ClassLayout* argNodeLayout = nullptr; @@ -5047,7 +5039,7 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) if (tree->OperIs(GT_FIELD)) { - noway_assert(((objRef != nullptr) && objRef->OperIsLocalAddr()) || ((tree->gtFlags & GTF_GLOB_REF) != 0)); + noway_assert(((objRef != nullptr) && objRef->OperIs(GT_LCL_ADDR)) || ((tree->gtFlags & GTF_GLOB_REF) != 0)); } if (fieldNode->IsInstance()) @@ -6667,9 +6659,9 @@ void Compiler::fgValidateIRForTailCall(GenTreeCall* call) // {args} // GT_COMMA // GT_CALL Dispatcher -// GT_LCL_VAR_ADDR ReturnAddress +// GT_LCL_ADDR ReturnAddress // {CallTargetStub} -// GT_LCL_VAR_ADDR ReturnValue +// GT_LCL_ADDR ReturnValue // GT_LCL ReturnValue // whenever the call node returns a value. If the call node does not return a // value the last comma will not be there. @@ -8238,7 +8230,7 @@ GenTree* Compiler::fgMorphLeaf(GenTree* tree) { assert(tree->OperIsLeaf()); - if (tree->OperIsNonPhiLocal() || tree->OperIsLocalAddr()) + if (tree->OperIsNonPhiLocal() || tree->OperIs(GT_LCL_ADDR)) { tree = fgMorphLocal(tree->AsLclVarCommon()); } @@ -8363,7 +8355,7 @@ GenTree* Compiler::getSIMDStructFromField(GenTree* tree, if (tree->OperIs(GT_FIELD) && tree->AsField()->IsInstance()) { GenTree* objRef = tree->AsField()->GetFldObj(); - if (objRef->OperIs(GT_LCL_VAR_ADDR)) + if (objRef->IsLclVarAddr()) { LclVarDsc* varDsc = lvaGetDesc(objRef->AsLclVarCommon()); if (varTypeIsSIMD(varDsc) && (varDsc->lvIsUsedInSIMDIntrinsic() || ignoreUsedInSIMDIntrinsic)) @@ -9827,7 +9819,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA tree->gtFlags |= (GTF_IND_INVARIANT | GTF_IND_NONFAULTING | GTF_IND_NONNULL); } - if (!tree->AsIndir()->IsVolatile() && !tree->TypeIs(TYP_STRUCT) && op1->OperIsLocalAddr() && + if (!tree->AsIndir()->IsVolatile() && !tree->TypeIs(TYP_STRUCT) && op1->OperIs(GT_LCL_ADDR) && !optValnumCSE_phase) { unsigned loadSize = tree->AsIndir()->Size(); @@ -11076,7 +11068,7 @@ GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add) { // Reduce local addresses: "ADD(LCL_ADDR, OFFSET)" => "LCL_FLD_ADDR". // - if (op1->OperIsLocalAddr() && op2->IsCnsIntOrI()) + if (op1->OperIs(GT_LCL_ADDR) && op2->IsCnsIntOrI()) { GenTreeLclVarCommon* lclAddrNode = op1->AsLclVarCommon(); GenTreeIntCon* offsetNode = op2->AsIntCon(); @@ -11087,7 +11079,7 @@ GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add) // Note: the emitter does not expect out-of-bounds access for LCL_FLD_ADDR. if (FitsIn(offset) && (offset < lvaLclExactSize(lclAddrNode->GetLclNum()))) { - lclAddrNode->SetOper(GT_LCL_FLD_ADDR); + lclAddrNode->SetOper(GT_LCL_ADDR); lclAddrNode->AsLclFld()->SetLclOffs(offset); assert(lvaGetDesc(lclAddrNode)->lvDoNotEnregister); diff --git a/src/coreclr/jit/objectalloc.cpp b/src/coreclr/jit/objectalloc.cpp index 76c5aeb7894ff..e9c6df3e2410a 100644 --- a/src/coreclr/jit/objectalloc.cpp +++ b/src/coreclr/jit/objectalloc.cpp @@ -839,7 +839,7 @@ void ObjectAllocator::RewriteUses() Compiler::fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) { GenTree* tree = *use; - assert(tree->IsLocal() || tree->OperIsLocalAddr()); + assert(tree->IsLocal() || tree->OperIs(GT_LCL_ADDR)); const unsigned int lclNum = tree->AsLclVarCommon()->GetLclNum(); unsigned int newLclNum = BAD_VAR_NUM; diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index b9963af5554f4..c1ded57299068 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -9106,8 +9106,7 @@ void Compiler::optRemoveRedundantZeroInits() { case GT_LCL_VAR: case GT_LCL_FLD: - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: { unsigned lclNum = tree->AsLclVarCommon()->GetLclNum(); unsigned* pRefCount = refCounts.LookupPointer(lclNum); diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp index 46c5d5fd9638f..c35a42afb5a43 100644 --- a/src/coreclr/jit/rationalize.cpp +++ b/src/coreclr/jit/rationalize.cpp @@ -21,21 +21,6 @@ genTreeOps storeForm(genTreeOps loadForm) } } -// return op that is the addr equivalent of the given load opcode -genTreeOps addrForm(genTreeOps loadForm) -{ - switch (loadForm) - { - case GT_LCL_VAR: - return GT_LCL_VAR_ADDR; - case GT_LCL_FLD: - return GT_LCL_FLD_ADDR; - default: - noway_assert(!"not a data load opcode\n"); - unreached(); - } -} - // copy the flags determined by mask from src to dst void copyFlags(GenTree* dst, GenTree* src, GenTreeFlags mask) { @@ -82,15 +67,14 @@ void Rationalizer::RewriteSIMDIndir(LIR::Use& use) GenTree* addr = indir->Addr(); - if (addr->OperIs(GT_LCL_VAR_ADDR) && varTypeIsSIMD(comp->lvaGetDesc(addr->AsLclVar()))) + if (addr->IsLclVarAddr() && varTypeIsSIMD(comp->lvaGetDesc(addr->AsLclFld()))) { - // If we have GT_IND(GT_LCL_VAR_ADDR) and the var is a SIMD type, + // If we have GT_IND(GT_LCL_ADDR<0>) and the var is a SIMD type, // replace the expression by GT_LCL_VAR or GT_LCL_FLD. BlockRange().Remove(indir); - const GenTreeLclVar* lclAddr = addr->AsLclVar(); - const unsigned lclNum = lclAddr->GetLclNum(); - LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); + const unsigned lclNum = addr->AsLclFld()->GetLclNum(); + LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); var_types lclType = varDsc->TypeGet(); @@ -101,7 +85,6 @@ void Rationalizer::RewriteSIMDIndir(LIR::Use& use) else { addr->SetOper(GT_LCL_FLD); - addr->AsLclFld()->SetLclOffs(0); if (((addr->gtFlags & GTF_VAR_DEF) != 0) && (genTypeSize(simdType) < genTypeSize(lclType))) { diff --git a/src/coreclr/jit/sideeffects.cpp b/src/coreclr/jit/sideeffects.cpp index 3b67153f27b37..4badf579e260f 100644 --- a/src/coreclr/jit/sideeffects.cpp +++ b/src/coreclr/jit/sideeffects.cpp @@ -203,7 +203,7 @@ AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node) // If the indirection targets a lclVar, we can be more precise with regards to aliasing by treating the // indirection as a lclVar access. GenTree* address = node->AsIndir()->Addr(); - if (address->OperIsLocalAddr()) + if (address->OperIs(GT_LCL_ADDR)) { isLclVarAccess = true; lclNum = address->AsLclVarCommon()->GetLclNum(); diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index 4adf44420730d..e7775e32a6dba 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -521,9 +521,9 @@ GenTree* Compiler::impSIMDPopStack(var_types type, bool expectAddr, CORINFO_CLAS tree = gtNewOperNode(GT_IND, type, tree); } - if (tree->OperIsIndir() && tree->AsIndir()->Addr()->OperIs(GT_LCL_VAR_ADDR)) + if (tree->OperIsIndir() && tree->AsIndir()->Addr()->IsLclVarAddr()) { - GenTreeLclVar* lclAddr = tree->AsIndir()->Addr()->AsLclVar(); + GenTreeLclFld* lclAddr = tree->AsIndir()->Addr()->AsLclFld(); LclVarDsc* varDsc = lvaGetDesc(lclAddr); if (varDsc->TypeGet() == type) { @@ -557,7 +557,7 @@ GenTree* Compiler::impSIMDPopStack(var_types type, bool expectAddr, CORINFO_CLAS else if (tree->gtType == TYP_BYREF) { assert(tree->IsLocal() || tree->OperIs(GT_RET_EXPR, GT_CALL) || - (tree->OperIs(GT_LCL_VAR_ADDR) && varTypeIsSIMD(lvaGetDesc(tree->AsLclVar())))); + (tree->IsLclVarAddr() && varTypeIsSIMD(lvaGetDesc(tree->AsLclFld())))); } return tree; @@ -571,7 +571,7 @@ GenTree* Compiler::impSIMDPopStack(var_types type, bool expectAddr, CORINFO_CLAS // void Compiler::setLclRelatedToSIMDIntrinsic(GenTree* tree) { - assert(tree->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR)); + assert(tree->OperIs(GT_LCL_VAR) || tree->IsLclVarAddr()); LclVarDsc* lclVarDsc = lvaGetDesc(tree->AsLclVarCommon()); lclVarDsc->lvUsedInSIMDIntrinsic = true; } @@ -599,7 +599,7 @@ bool areFieldsParentsLocatedSame(GenTree* op1, GenTree* op2) break; } - if (op1ObjRef->OperIs(GT_LCL_VAR, GT_LCL_VAR_ADDR) && + if ((op1ObjRef->OperIs(GT_LCL_VAR) || op1ObjRef->IsLclVarAddr()) && (op1ObjRef->AsLclVarCommon()->GetLclNum() == op2ObjRef->AsLclVarCommon()->GetLclNum())) { return true; @@ -775,7 +775,7 @@ GenTree* Compiler::CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_ if (tree->OperIs(GT_FIELD)) { GenTree* objRef = tree->AsField()->GetFldObj(); - if ((objRef != nullptr) && objRef->OperIs(GT_LCL_VAR_ADDR)) + if ((objRef != nullptr) && objRef->IsLclVarAddr()) { // If the field is directly from a struct, then in this case, // we should set this struct's lvUsedInSIMDIntrinsic as true, @@ -788,7 +788,7 @@ GenTree* Compiler::CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_ // TODO-CQ: // In future, we should optimize this case so that if there is a nested field like s1.s2.x and s1.s2.x's // address is used for initializing the vector, then s1 can be promoted but s2 can't. - if (varTypeIsSIMD(lvaGetDesc(objRef->AsLclVar()))) + if (varTypeIsSIMD(lvaGetDesc(objRef->AsLclFld()))) { setLclRelatedToSIMDIntrinsic(objRef); } @@ -887,7 +887,7 @@ void Compiler::impMarkContiguousSIMDFieldAssignments(Statement* stmt) if (curDst->OperIs(GT_FIELD) && curDst->AsField()->IsInstance()) { GenTree* objRef = curDst->AsField()->GetFldObj(); - if (objRef->OperIs(GT_LCL_VAR_ADDR) && varTypeIsStruct(lvaGetDesc(objRef->AsLclVar()))) + if (objRef->IsLclVarAddr() && varTypeIsStruct(lvaGetDesc(objRef->AsLclFld()))) { setLclRelatedToSIMDIntrinsic(objRef); } diff --git a/src/coreclr/jit/treelifeupdater.cpp b/src/coreclr/jit/treelifeupdater.cpp index d5aabff93d7e9..c86460aa05ae2 100644 --- a/src/coreclr/jit/treelifeupdater.cpp +++ b/src/coreclr/jit/treelifeupdater.cpp @@ -123,7 +123,7 @@ bool TreeLifeUpdater::UpdateLifeFieldVar(GenTreeLclVar* lclNode, uns template void TreeLifeUpdater::UpdateLifeVar(GenTree* tree, GenTreeLclVarCommon* lclVarTree) { - assert(lclVarTree->OperIsNonPhiLocal() || lclVarTree->OperIsLocalAddr()); + assert(lclVarTree->OperIsNonPhiLocal() || lclVarTree->OperIs(GT_LCL_ADDR)); unsigned int lclNum = lclVarTree->GetLclNum(); LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum); @@ -300,7 +300,7 @@ void TreeLifeUpdater::UpdateLife(GenTree* tree) { lclVarTree = tree->AsLclVarCommon(); } - else if (tree->OperIsIndir() && tree->AsIndir()->Addr()->OperIsLocalAddr()) + else if (tree->OperIsIndir() && tree->AsIndir()->Addr()->OperIs(GT_LCL_ADDR)) { lclVarTree = tree->AsIndir()->Addr()->AsLclVarCommon(); } diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 250cbdf571338..aefa8201113b4 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -10321,11 +10321,10 @@ void Compiler::fgValueNumberTree(GenTree* tree) { switch (oper) { - case GT_LCL_VAR_ADDR: - case GT_LCL_FLD_ADDR: + case GT_LCL_ADDR: { - unsigned lclNum = tree->AsLclVarCommon()->GetLclNum(); - unsigned lclOffs = tree->AsLclVarCommon()->GetLclOffs(); + unsigned lclNum = tree->AsLclFld()->GetLclNum(); + unsigned lclOffs = tree->AsLclFld()->GetLclOffs(); tree->gtVNPair.SetBoth(vnStore->VNForFunc(TYP_BYREF, VNF_PtrToLoc, vnStore->VNForIntCon(lclNum), vnStore->VNForIntPtrCon(lclOffs))); assert(lvaGetDesc(lclNum)->IsAddressExposed() || lvaGetDesc(lclNum)->IsHiddenBufferStructArg());