diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index ebdf680fb10feb..2f63f7ceba7d2d 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2260,7 +2260,6 @@ void Compiler::optAssertionGen(GenTree* tree) } break; - case GT_OBJ: case GT_BLK: case GT_IND: // R-value indirections create non-null assertions, but not all indirections are R-values. @@ -4723,7 +4722,6 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, case GT_RETURN: return optAssertionProp_Return(assertions, tree->AsUnOp(), stmt); - case GT_OBJ: case GT_BLK: case GT_IND: case GT_NULLCHECK: @@ -5702,7 +5700,6 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Sta case GT_ARR_LENGTH: break; - case GT_OBJ: case GT_BLK: case GT_IND: { diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 55d2410f7d2248..cc96c1e8f659bc 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -1131,7 +1131,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void genCodeForReturnTrap(GenTreeOp* tree); void genCodeForStoreInd(GenTreeStoreInd* tree); void genCodeForSwap(GenTreeOp* tree); - void genCodeForCpObj(GenTreeObj* cpObjNode); + void genCodeForCpObj(GenTreeBlk* cpObjNode); void genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode); void genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode); #ifndef TARGET_X86 diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 0cd7396999c72c..59f3210a0f58aa 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -799,7 +799,7 @@ void CodeGen::genCodeForNegNot(GenTree* tree) // bl CORINFO_HELP_ASSIGN_BYREF // ldr tempReg, [R13, #8] // str tempReg, [R14, #8] -void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) +void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { GenTree* dstAddr = cpObjNode->Addr(); GenTree* source = cpObjNode->Data(); diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 6b1a20565dec2c..15c18c475a5695 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -3545,7 +3545,7 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree) // bl CORINFO_HELP_ASSIGN_BYREF // ldr tempReg, [R13, #8] // str tempReg, [R14, #8] -void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) +void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { GenTree* dstAddr = cpObjNode->Addr(); GenTree* source = cpObjNode->Data(); diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 44a30a310e60f6..e53cd66eb7958b 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -886,7 +886,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) } else { - noway_assert(source->OperIsLocalRead() || source->OperIs(GT_OBJ)); + noway_assert(source->OperIsLocalRead() || source->OperIs(GT_BLK)); var_types targetType = source->TypeGet(); noway_assert(varTypeIsStruct(targetType)); @@ -914,10 +914,10 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // This struct must live on the stack frame. assert(varDsc->lvOnFrame && !varDsc->lvRegister); } - else // we must have a GT_OBJ + else // we must have a GT_BLK { - layout = source->AsObj()->GetLayout(); - addrReg = genConsumeReg(source->AsObj()->Addr()); + layout = source->AsBlk()->GetLayout(); + addrReg = genConsumeReg(source->AsBlk()->Addr()); #ifdef TARGET_ARM64 // If addrReg equal to loReg, swap(loReg, hiReg) @@ -1244,11 +1244,11 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) firstRegToPlace = 0; valueReg = treeNode->GetRegNumByIdx(0); } - else // we must have a GT_OBJ + else // we must have a GT_BLK { - layout = source->AsObj()->GetLayout(); - addrReg = genConsumeReg(source->AsObj()->Addr()); - addrType = source->AsObj()->Addr()->TypeGet(); + layout = source->AsBlk()->GetLayout(); + addrReg = genConsumeReg(source->AsBlk()->Addr()); + addrType = source->AsBlk()->Addr()->TypeGet(); regNumber allocatedValueReg = REG_NA; if (treeNode->gtNumRegs == 1) @@ -4472,8 +4472,8 @@ void CodeGen::genCodeForStoreBlk(GenTreeBlk* blkOp) { assert(!blkOp->gtBlkOpGcUnsafe); assert(blkOp->OperIsCopyBlkOp()); - assert(blkOp->AsObj()->GetLayout()->HasGCPtr()); - genCodeForCpObj(blkOp->AsObj()); + assert(blkOp->AsBlk()->GetLayout()->HasGCPtr()); + genCodeForCpObj(blkOp->AsBlk()); return; } @@ -5639,82 +5639,4 @@ void CodeGen::genFnEpilog(BasicBlock* block) compiler->unwindEndEpilog(); } - -// return size -// alignmentWB is out param -unsigned CodeGenInterface::InferOpSizeAlign(GenTree* op, unsigned* alignmentWB) -{ - unsigned alignment = 0; - unsigned opSize = 0; - - if (op->gtType == TYP_STRUCT || op->OperIsCopyBlkOp()) - { - opSize = InferStructOpSizeAlign(op, &alignment); - } - else - { - alignment = genTypeAlignments[op->TypeGet()]; - opSize = genTypeSizes[op->TypeGet()]; - } - - assert(opSize != 0); - assert(alignment != 0); - - (*alignmentWB) = alignment; - return opSize; -} - -// return size -// alignmentWB is out param -unsigned CodeGenInterface::InferStructOpSizeAlign(GenTree* op, unsigned* alignmentWB) -{ - unsigned alignment = 0; - unsigned opSize = 0; - - while (op->gtOper == GT_COMMA) - { - op = op->AsOp()->gtOp2; - } - - if (op->gtOper == GT_OBJ) - { - CORINFO_CLASS_HANDLE clsHnd = op->AsObj()->GetLayout()->GetClassHandle(); - opSize = op->AsObj()->GetLayout()->GetSize(); - alignment = roundUp(compiler->info.compCompHnd->getClassAlignmentRequirement(clsHnd), TARGET_POINTER_SIZE); - } - else if (op->gtOper == GT_LCL_VAR) - { - const LclVarDsc* varDsc = compiler->lvaGetDesc(op->AsLclVarCommon()); - assert(varDsc->lvType == TYP_STRUCT); - opSize = varDsc->lvSize(); -#ifndef TARGET_64BIT - if (varDsc->lvStructDoubleAlign) - { - alignment = TARGET_POINTER_SIZE * 2; - } - else -#endif // !TARGET_64BIT - { - alignment = TARGET_POINTER_SIZE; - } - } - else if (op->gtOper == GT_MKREFANY) - { - opSize = TARGET_POINTER_SIZE * 2; - alignment = TARGET_POINTER_SIZE; - } - else - { - assert(!"Unhandled gtOper"); - opSize = TARGET_POINTER_SIZE; - alignment = TARGET_POINTER_SIZE; - } - - assert(opSize != 0); - assert(alignment != 0); - - (*alignmentWB) = alignment; - return opSize; -} - #endif // TARGET_ARMARCH diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index 86bc7a7573adf5..1f8f4c6b0c7fe4 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -299,9 +299,6 @@ class CodeGenInterface #endif public: - unsigned InferStructOpSizeAlign(GenTree* op, unsigned* alignmentWB); - unsigned InferOpSizeAlign(GenTree* op, unsigned* alignmentWB); - // Methods to abstract target information bool validImmForInstr(instruction ins, target_ssize_t val, insFlags flags = INS_FLAGS_DONT_CARE); diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index dda65073c893b7..b5e63e27f7c7ad 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1746,7 +1746,7 @@ void CodeGen::genConsumeMultiOpOperands(GenTreeMultiOp* tree) // Notes: // sizeReg can be REG_NA when this function is used to consume the dstReg and srcReg // for copying on the stack a struct with references. -// The source address/offset is determined from the address on the GT_OBJ node, while +// The source address/offset is determined from the address on the GT_BLK node, while // the destination address is the address contained in 'm_stkArgVarNum' plus the offset // provided in the 'putArgNode'. // m_stkArgVarNum must be set to the varnum for the local used for placing the "by-value" args on the stack. @@ -1763,7 +1763,7 @@ void CodeGen::genConsumePutStructArgStk(GenTreePutArgStk* putArgNode, GenTree* src = putArgNode->Data(); regNumber srcAddrReg = REG_NA; assert(varTypeIsStruct(src)); - assert(src->OperIs(GT_OBJ) || src->OperIsLocalRead() || (src->OperIs(GT_IND) && varTypeIsSIMD(src))); + assert(src->OperIs(GT_BLK) || src->OperIsLocalRead() || (src->OperIs(GT_IND) && varTypeIsSIMD(src))); assert(dstReg != REG_NA); assert(srcReg != REG_NA); diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index f7ce053119ca41..a2178c784a14da 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -2901,7 +2901,7 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) // bl CORINFO_HELP_ASSIGN_BYREF // ld tempReg, 8(A5) // sd tempReg, 8(A6) -void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) +void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { GenTree* dstAddr = cpObjNode->Addr(); GenTree* source = cpObjNode->Data(); @@ -5477,9 +5477,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) { genPutArgStkFieldList(treeNode, varNumOut); } - else // We must have a GT_OBJ or a GT_LCL_VAR + else // We must have a GT_BLK or a GT_LCL_VAR { - noway_assert((source->OperGet() == GT_LCL_VAR) || (source->OperGet() == GT_OBJ)); + noway_assert((source->OperGet() == GT_LCL_VAR) || (source->OperGet() == GT_BLK)); var_types targetType = source->TypeGet(); noway_assert(varTypeIsStruct(targetType)); @@ -5496,9 +5496,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) { varNode = source->AsLclVarCommon(); } - else // we must have a GT_OBJ + else // we must have a GT_BLK { - assert(source->OperGet() == GT_OBJ); + assert(source->OperGet() == GT_BLK); addrNode = source->AsOp()->gtOp1; @@ -5506,7 +5506,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // if (addrNode->IsLclVarAddr()) { - // We have a GT_OBJ(GT_LCL_ADDR<0>) + // We have a GT_BLK(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) @@ -5549,18 +5549,16 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // as that is how much stack is allocated for this LclVar layout = varDsc->GetLayout(); } - else // we must have a GT_OBJ + else // we must have a GT_BLK { - assert(source->OperGet() == GT_OBJ); + assert(source->OperGet() == GT_BLK); - // If the source is an OBJ node then we need to use the type information + // If the source is an BLK node then we need to use the type information // it provides (size and GC layout) even if the node wraps a lclvar. Due // to struct reinterpretation (e.g. Unsafe.As) it is possible that - // the OBJ node has a different type than the lclvar. - CORINFO_CLASS_HANDLE objClass = source->AsObj()->GetLayout()->GetClassHandle(); - - srcSize = compiler->info.compCompHnd->getClassSize(objClass); - layout = source->AsObj()->GetLayout(); + // the BLK node has a different type than the lclvar. + layout = source->AsBlk()->GetLayout(); + srcSize = layout->GetSize(); } unsigned structSize; @@ -5766,7 +5764,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) else { var_types targetType = source->TypeGet(); - assert(source->OperGet() == GT_OBJ); + assert(source->OperGet() == GT_BLK); assert(varTypeIsStruct(targetType)); regNumber baseReg = treeNode->ExtractTempReg(); @@ -5781,7 +5779,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) // if (addrNode->IsLclVarAddr()) { - // We have a GT_OBJ(GT_LCL_ADDR<0>) + // We have a GT_BLK(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) @@ -5818,12 +5816,9 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) // Because the candidate mask for the internal baseReg does not include any of the target register, // we can ensure that baseReg, addrReg, and the last target register are not all same. assert(baseReg != addrReg); - - // We don't split HFA struct - assert(!compiler->IsHfa(source->AsObj()->GetLayout()->GetClassHandle())); } - ClassLayout* layout = source->AsObj()->GetLayout(); + ClassLayout* layout = source->AsBlk()->GetLayout(); // Put on stack first unsigned structOffset = treeNode->gtNumRegs * TARGET_POINTER_SIZE; @@ -7562,8 +7557,8 @@ void CodeGen::genCodeForStoreBlk(GenTreeBlk* blkOp) { assert(!blkOp->gtBlkOpGcUnsafe); assert(blkOp->OperIsCopyBlkOp()); - assert(blkOp->AsObj()->GetLayout()->HasGCPtr()); - genCodeForCpObj(blkOp->AsObj()); + assert(blkOp->AsBlk()->GetLayout()->HasGCPtr()); + genCodeForCpObj(blkOp->AsBlk()); return; } if (blkOp->gtBlkOpGcUnsafe) @@ -9112,75 +9107,4 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) return; } } - -// return size -// alignmentWB is out param -unsigned CodeGenInterface::InferOpSizeAlign(GenTree* op, unsigned* alignmentWB) -{ - unsigned alignment = 0; - unsigned opSize = 0; - - if (op->gtType == TYP_STRUCT || op->OperIsCopyBlkOp()) - { - opSize = InferStructOpSizeAlign(op, &alignment); - } - else - { - alignment = genTypeAlignments[op->TypeGet()]; - opSize = genTypeSizes[op->TypeGet()]; - } - - assert(opSize != 0); - assert(alignment != 0); - - (*alignmentWB) = alignment; - return opSize; -} - -// return size -// alignmentWB is out param -unsigned CodeGenInterface::InferStructOpSizeAlign(GenTree* op, unsigned* alignmentWB) -{ - unsigned alignment = 0; - unsigned opSize = 0; - - while (op->gtOper == GT_COMMA) - { - op = op->AsOp()->gtOp2; - } - - if (op->gtOper == GT_OBJ) - { - CORINFO_CLASS_HANDLE clsHnd = op->AsObj()->GetLayout()->GetClassHandle(); - opSize = op->AsObj()->GetLayout()->GetSize(); - alignment = roundUp(compiler->info.compCompHnd->getClassAlignmentRequirement(clsHnd), TARGET_POINTER_SIZE); - } - else if (op->gtOper == GT_LCL_VAR) - { - const LclVarDsc* varDsc = compiler->lvaGetDesc(op->AsLclVarCommon()); - assert(varDsc->lvType == TYP_STRUCT); - opSize = varDsc->lvSize(); - { - alignment = TARGET_POINTER_SIZE; - } - } - else if (op->gtOper == GT_MKREFANY) - { - opSize = TARGET_POINTER_SIZE * 2; - alignment = TARGET_POINTER_SIZE; - } - else - { - assert(!"Unhandled gtOper"); - opSize = TARGET_POINTER_SIZE; - alignment = TARGET_POINTER_SIZE; - } - - assert(opSize != 0); - assert(alignment != 0); - - (*alignmentWB) = alignment; - return opSize; -} - #endif // TARGET_LOONGARCH64 diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index e7dd04576d1937..9fec01517ecc11 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -4805,9 +4805,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) { genPutArgStkFieldList(treeNode, varNumOut); } - else // We must have a GT_OBJ or a GT_LCL_VAR + else // We must have a GT_BLK or a GT_LCL_VAR { - noway_assert((source->OperGet() == GT_LCL_VAR) || (source->OperGet() == GT_OBJ)); + noway_assert((source->OperGet() == GT_LCL_VAR) || (source->OperGet() == GT_BLK)); var_types targetType = source->TypeGet(); noway_assert(varTypeIsStruct(targetType)); @@ -4824,9 +4824,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) { varNode = source->AsLclVarCommon(); } - else // we must have a GT_OBJ + else // we must have a GT_BLK { - assert(source->OperGet() == GT_OBJ); + assert(source->OperGet() == GT_BLK); addrNode = source->AsOp()->gtOp1; @@ -4834,7 +4834,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // if (addrNode->OperGet() == GT_LCL_ADDR) { - // We have a GT_OBJ(GT_LCL_ADDR) + // We have a GT_BLK(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) @@ -4877,18 +4877,16 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) // as that is how much stack is allocated for this LclVar layout = varDsc->GetLayout(); } - else // we must have a GT_OBJ + else // we must have a GT_BLK { - assert(source->OperGet() == GT_OBJ); + assert(source->OperGet() == GT_BLK); - // If the source is an OBJ node then we need to use the type information + // If the source is an BLK node then we need to use the type information // it provides (size and GC layout) even if the node wraps a lclvar. Due // to struct reinterpretation (e.g. Unsafe.As) it is possible that - // the OBJ node has a different type than the lclvar. - CORINFO_CLASS_HANDLE objClass = source->AsObj()->GetLayout()->GetClassHandle(); - - srcSize = compiler->info.compCompHnd->getClassSize(objClass); - layout = source->AsObj()->GetLayout(); + // the BLK node has a different type than the lclvar. + layout = source->AsBlk()->GetLayout(); + srcSize = layout->GetSize(); } unsigned structSize; @@ -6409,8 +6407,8 @@ void CodeGen::genCodeForStoreBlk(GenTreeBlk* blkOp) { assert(!blkOp->gtBlkOpGcUnsafe); assert(blkOp->OperIsCopyBlkOp()); - assert(blkOp->AsObj()->GetLayout()->HasGCPtr()); - genCodeForCpObj(blkOp->AsObj()); + assert(blkOp->AsBlk()->GetLayout()->HasGCPtr()); + genCodeForCpObj(blkOp->AsBlk()); return; } if (blkOp->gtBlkOpGcUnsafe) @@ -7695,21 +7693,4 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) return; } } - -// return size -// alignmentWB is out param -unsigned CodeGenInterface::InferOpSizeAlign(GenTree* op, unsigned* alignmentWB) -{ - NYI_RISCV64("CodeGenInterface::InferOpSizeAlign-----unimplemented/unused on RISCV64 yet----"); - return 0; -} - -// return size -// alignmentWB is out param -unsigned CodeGenInterface::InferStructOpSizeAlign(GenTree* op, unsigned* alignmentWB) -{ - NYI_RISCV64("CodeGenInterface::InferStructOpSizeAlign-----unimplemented/unused on RISCV64 yet----"); - return 0; -} - #endif // TARGET_RISCV64 diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index c3d1efd1d1e31c..0cba2a18583394 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -2986,8 +2986,8 @@ void CodeGen::genCodeForStoreBlk(GenTreeBlk* storeBlkNode) assert(!storeBlkNode->gtBlkOpGcUnsafe); #endif assert(storeBlkNode->OperIsCopyBlkOp()); - assert(storeBlkNode->AsObj()->GetLayout()->HasGCPtr()); - genCodeForCpObj(storeBlkNode->AsObj()); + assert(storeBlkNode->AsBlk()->GetLayout()->HasGCPtr()); + genCodeForCpObj(storeBlkNode->AsBlk()); return; } @@ -3782,15 +3782,15 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) { GenTree* src = putArgNode->Data(); // We will never call this method for SIMD types, which are stored directly in genPutStructArgStk(). - assert(src->isContained() && src->TypeIs(TYP_STRUCT) && (src->OperIs(GT_OBJ) || src->OperIsLocalRead())); + assert(src->isContained() && src->TypeIs(TYP_STRUCT) && (src->OperIs(GT_BLK) || src->OperIsLocalRead())); #ifdef TARGET_X86 assert(!m_pushStkArg); #endif - if (src->OperIs(GT_OBJ)) + if (src->OperIs(GT_BLK)) { - genConsumeReg(src->AsObj()->Addr()); + genConsumeReg(src->AsBlk()->Addr()); } unsigned loadSize = putArgNode->GetArgLoadSize(); @@ -3906,7 +3906,7 @@ void CodeGen::genStructPutArgPush(GenTreePutArgStk* putArgNode) } else { - srcAddrReg = genConsumeReg(src->AsObj()->Addr()); + srcAddrReg = genConsumeReg(src->AsBlk()->Addr()); } ClassLayout* layout = src->GetLayout(compiler); @@ -4093,7 +4093,7 @@ void CodeGen::genClearStackVec3ArgUpperBits() // The register assignments have been set appropriately. // This is validated by genConsumeBlockOp(). // -void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode) +void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { // Make sure we got the arguments of the cpobj operation in the right registers GenTree* dstAddr = cpObjNode->Addr(); diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 9c4b574e647d72..92bdfa5ea4340b 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -9936,9 +9936,8 @@ void cTreeFlags(Compiler* comp, GenTree* tree) } break; - case GT_OBJ: case GT_STORE_OBJ: - if (tree->AsObj()->GetLayout()->HasGCPtr()) + if (tree->AsBlk()->GetLayout()->HasGCPtr()) { chars += printf("[BLK_HASGCPTR]"); } @@ -10315,7 +10314,7 @@ var_types Compiler::gtTypeForNullCheck(GenTree* tree) // void Compiler::gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block) { - assert(tree->OperIs(GT_FIELD, GT_IND, GT_OBJ, GT_BLK)); + assert(tree->OperIs(GT_FIELD, GT_IND, GT_BLK)); tree->ChangeOper(GT_NULLCHECK); tree->ChangeType(gtTypeForNullCheck(tree)); assert(fgAddrCouldBeNull(tree->gtGetOp1())); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 394f9d96076f3f..0c2797bae35382 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -2511,8 +2511,6 @@ class Compiler GenTree* gtNewBitCastNode(var_types type, GenTree* arg); public: - GenTreeObj* gtNewObjNode(ClassLayout* layout, GenTree* addr); - GenTreeObj* gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr); GenTree* gtNewStructVal(ClassLayout* layout, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY); GenTreeCall* gtNewCallNode(gtCallTypes callType, @@ -2826,6 +2824,8 @@ class Compiler GenTreeMDArr* gtNewMDArrLowerBound(GenTree* arrayOp, unsigned dim, unsigned rank, BasicBlock* block); + GenTreeBlk* gtNewBlkIndir(ClassLayout* layout, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY); + GenTreeIndir* gtNewIndir(var_types typ, GenTree* addr, GenTreeFlags indirFlags = GTF_EMPTY); GenTree* gtNewNullCheck(GenTree* addr, BasicBlock* basicBlock); @@ -11013,7 +11013,6 @@ class GenTreeVisitor case GT_CKFINITE: case GT_LCLHEAP: case GT_IND: - case GT_OBJ: case GT_BLK: case GT_BOX: case GT_ALLOCOBJ: diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index b1807629442855..53f80fce301292 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1076,7 +1076,7 @@ inline GenTreeIndir* Compiler::gtNewIndexIndir(GenTreeIndexAddr* indexAddr) GenTreeIndir* index; if (varTypeIsStruct(indexAddr->gtElemType)) { - index = gtNewObjNode(indexAddr->gtStructElemClass, indexAddr); + index = gtNewBlkIndir(typGetObjLayout(indexAddr->gtStructElemClass), indexAddr); } else { @@ -1177,16 +1177,58 @@ inline GenTreeMDArr* Compiler::gtNewMDArrLowerBound(GenTree* arrayOp, unsigned d return arrOp; } -//------------------------------------------------------------------------------ -// gtNewIndir : Helper to create an indirection node. +//------------------------------------------------------------------------ +// gtNewBlkIndir: Create a struct indirection node. // // Arguments: -// typ - Type of the node -// addr - Address of the indirection +// layout - The struct layout +// addr - Address of the indirection +// indirFlags - Indirection flags // // Return Value: -// New GT_IND node +// The created GT_BLK node. +// +inline GenTreeBlk* Compiler::gtNewBlkIndir(ClassLayout* layout, GenTree* addr, GenTreeFlags indirFlags) +{ + assert((indirFlags & ~GTF_IND_FLAGS) == GTF_EMPTY); + + GenTreeBlk* blkNode = new (this, GT_BLK) GenTreeBlk(GT_BLK, layout->GetType(), addr, layout); + blkNode->gtFlags |= indirFlags; + blkNode->SetIndirExceptionFlags(this); + // 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->OperIs(GT_LCL_ADDR)) + { + if (lvaIsImplicitByRefLocal(addr->AsLclVarCommon()->GetLclNum())) + { + blkNode->gtFlags |= GTF_GLOB_REF; + } + } + else + { + blkNode->gtFlags |= GTF_GLOB_REF; + } + + if ((indirFlags & GTF_IND_VOLATILE) != 0) + { + blkNode->gtFlags |= GTF_ORDER_SIDEEFF; + } + + return blkNode; +} + +//------------------------------------------------------------------------------ +// gtNewIndir : Create an indirection node. +// +// Arguments: +// typ - Type of the node +// addr - Address of the indirection +// indirFlags - Indirection flags +// +// Return Value: +// The created GT_IND node. +// inline GenTreeIndir* Compiler::gtNewIndir(var_types typ, GenTree* addr, GenTreeFlags indirFlags) { assert((indirFlags & ~GTF_IND_FLAGS) == GTF_EMPTY); @@ -4128,7 +4170,6 @@ void GenTree::VisitOperands(TVisitor visitor) case GT_CKFINITE: case GT_LCLHEAP: case GT_IND: - case GT_OBJ: case GT_BLK: case GT_BOX: case GT_ALLOCOBJ: diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index cb03e0b604f8d6..8cd1afbcbfd01c 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -1641,8 +1641,8 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) if ((argSingleUseNode != nullptr) && !(argSingleUseNode->gtFlags & GTF_VAR_CLONED) && argIsSingleDef) { // Change the temp in-place to the actual argument. - // We currently do not support this for struct arguments, so it must not be a GT_OBJ. - assert(argNode->gtOper != GT_OBJ); + // We currently do not support this for struct arguments, so it must not be a GT_BLK. + assert(argNode->gtOper != GT_BLK); argSingleUseNode->ReplaceWith(argNode, this); continue; } @@ -1698,9 +1698,9 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) newStmt = nullptr; bool append = true; - if (argNode->gtOper == GT_OBJ || argNode->gtOper == GT_MKREFANY) + if (argNode->gtOper == GT_BLK || argNode->gtOper == GT_MKREFANY) { - // Don't put GT_OBJ node under a GT_COMMA. + // Don't put GT_BLK node under a GT_COMMA. // Codegen can't deal with it. // Just hang the address here in case there are side-effect. newStmt = gtNewStmt(gtUnusedValNode(argNode->AsOp()->gtOp1), callDI); diff --git a/src/coreclr/jit/forwardsub.cpp b/src/coreclr/jit/forwardsub.cpp index bd1730b697e4ef..a2636938ef446b 100644 --- a/src/coreclr/jit/forwardsub.cpp +++ b/src/coreclr/jit/forwardsub.cpp @@ -743,7 +743,7 @@ bool Compiler::fgForwardSubStatement(Statement* stmt) // Don't substitute nodes args morphing doesn't handle into struct args. // if (fsv.IsCallArg() && fsv.GetNode()->TypeIs(TYP_STRUCT) && - !fwdSubNode->OperIs(GT_OBJ, GT_FIELD, GT_LCL_VAR, GT_LCL_FLD, GT_MKREFANY)) + !fwdSubNode->OperIs(GT_BLK, GT_FIELD, GT_LCL_VAR, GT_LCL_FLD, GT_MKREFANY)) { JITDUMP(" use is a struct arg; fwd sub node is not OBJ/LCL_VAR/LCL_FLD/MKREFANY\n"); return false; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index aeea5d349313ca..d6bf616d7d95bf 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -337,7 +337,6 @@ void GenTree::InitNodeSize() static_assert_no_msg(sizeof(GenTreeIndir) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeStoreInd) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeAddrMode) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeObj) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeBlk) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeStoreDynBlk) <= TREE_NODE_SZ_LARGE); // *** large node static_assert_no_msg(sizeof(GenTreeRetExpr) <= TREE_NODE_SZ_LARGE); // *** large node @@ -736,7 +735,6 @@ ClassLayout* GenTree::GetLayout(Compiler* compiler) const case GT_LCL_FLD: return AsLclFld()->GetLayout(); - case GT_OBJ: case GT_BLK: return AsBlk()->GetLayout(); @@ -2704,7 +2702,6 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) break; case GT_BLK: - case GT_OBJ: if (op1->AsBlk()->GetLayout() != op2->AsBlk()->GetLayout()) { return false; @@ -3218,7 +3215,6 @@ unsigned Compiler::gtHashValue(GenTree* tree) reinterpret_cast(tree->AsRuntimeLookup()->gtHnd))); break; case GT_BLK: - case GT_OBJ: hash = genTreeHashAdd(hash, static_cast(reinterpret_cast(tree->AsBlk()->GetLayout()))); @@ -5293,8 +5289,8 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) break; case GT_MKREFANY: - case GT_OBJ: - // We estimate the cost of a GT_OBJ or GT_MKREFANY to be two loads (GT_INDs) + case GT_BLK: + // We estimate the cost of a GT_BLK or GT_MKREFANY to be two loads (GT_INDs) costEx = 2 * IND_COST_EX; costSz = 2 * 2; break; @@ -5317,7 +5313,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) } break; - case GT_BLK: case GT_IND: { /* An indirection should always have a non-zero level. @@ -5582,7 +5577,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) { case GT_IND: case GT_BLK: - case GT_OBJ: { // In an ASG(IND(addr), ...), the "IND" is a pure syntactical element, // the actual indirection will only be realized at the point of the ASG @@ -6278,7 +6272,6 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse) case GT_CKFINITE: case GT_LCLHEAP: case GT_IND: - case GT_OBJ: case GT_BLK: case GT_BOX: case GT_ALLOCOBJ: @@ -6674,7 +6667,6 @@ bool GenTree::OperIsImplicitIndir() const case GT_XCHG: case GT_CMPXCHG: case GT_BLK: - case GT_OBJ: case GT_STORE_BLK: case GT_STORE_OBJ: case GT_STORE_DYN_BLK: @@ -6761,7 +6753,6 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp) case GT_IND: case GT_BLK: - case GT_OBJ: case GT_NULLCHECK: case GT_STORE_BLK: case GT_STORE_DYN_BLK: @@ -6974,7 +6965,7 @@ GenTree::VtablePtr GenTree::GetVtableForOper(genTreeOps oper) // Handle the special cases. // The following opers are in GTSTRUCT_N but no other place (namely, no subtypes). - + case GT_STORE_OBJ: case GT_STORE_BLK: case GT_BLK: { @@ -7845,62 +7836,6 @@ GenTreeOp* Compiler::gtNewAssignNode(GenTree* dst, GenTree* src) return asg; } -//------------------------------------------------------------------------ -// gtNewObjNode: Creates a new Obj node with the given layout. -// -// Arguments: -// layout - The struct layout -// addr - The address of the struct -// -// Return Value: -// Returns a node representing the struct value at the given address. -// -GenTreeObj* Compiler::gtNewObjNode(ClassLayout* layout, GenTree* addr) -{ - assert(layout != nullptr); - - GenTreeObj* objNode = new (this, GT_OBJ) GenTreeObj(layout->GetType(), addr, layout); - - // An Obj is not a global reference, if it is known to be a local struct. - if ((addr->gtFlags & GTF_GLOB_REF) == 0) - { - // 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->OperIs(GT_LCL_ADDR)) - { - objNode->gtFlags |= GTF_IND_NONFAULTING; - if (lvaIsImplicitByRefLocal(addr->AsLclVarCommon()->GetLclNum())) - { - objNode->gtFlags |= GTF_GLOB_REF; - } - } - else - { - objNode->gtFlags |= GTF_GLOB_REF; - } - } - - return objNode; -} - -//------------------------------------------------------------------------ -// gtNewObjNode: Creates a new Obj node with the layout for the given handle. -// -// Arguments: -// structHnd - The class handle of the struct type -// addr - The address of the struct -// -// Return Value: -// Returns a node representing the struct value at the given address. -// -GenTreeObj* Compiler::gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr) -{ - ClassLayout* layout = typGetObjLayout(structHnd); - GenTreeObj* objNode = gtNewObjNode(layout, addr); - - return objNode; -} - //------------------------------------------------------------------------ // gtNewStructVal: Return a node that represents a struct or block value // @@ -7917,8 +7852,7 @@ GenTree* Compiler::gtNewStructVal(ClassLayout* layout, GenTree* addr, GenTreeFla { assert((indirFlags & ~GTF_IND_FLAGS) == 0); - bool isVolatile = (indirFlags & GTF_IND_VOLATILE) != 0; - if (!isVolatile && addr->IsLclVarAddr()) + if (((indirFlags & GTF_IND_VOLATILE) == 0) && addr->IsLclVarAddr()) { unsigned lclNum = addr->AsLclFld()->GetLclNum(); LclVarDsc* varDsc = lvaGetDesc(lclNum); @@ -7929,24 +7863,7 @@ GenTree* Compiler::gtNewStructVal(ClassLayout* layout, GenTree* addr, GenTreeFla } } - GenTreeBlk* blkNode; - if (layout->IsBlockLayout()) - { - blkNode = new (this, GT_BLK) GenTreeBlk(GT_BLK, layout->GetType(), addr, layout); - } - else - { - blkNode = gtNewObjNode(layout, addr); - } - - blkNode->gtFlags |= indirFlags; - if (isVolatile) - { - blkNode->gtFlags |= GTF_ORDER_SIDEEFF; - } - blkNode->SetIndirExceptionFlags(this); - - return blkNode; + return gtNewBlkIndir(layout, addr, indirFlags); } //------------------------------------------------------------------------ @@ -8821,11 +8738,6 @@ GenTree* Compiler::gtCloneExpr( GenTreeQmark(tree->TypeGet(), tree->AsOp()->gtGetOp1(), tree->AsOp()->gtGetOp2()->AsColon()); break; - case GT_OBJ: - copy = - new (this, GT_OBJ) GenTreeObj(tree->TypeGet(), tree->AsObj()->Addr(), tree->AsObj()->GetLayout()); - break; - case GT_BLK: copy = new (this, GT_BLK) GenTreeBlk(GT_BLK, tree->TypeGet(), tree->AsBlk()->Addr(), tree->AsBlk()->GetLayout()); @@ -9603,7 +9515,6 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) case GT_CKFINITE: case GT_LCLHEAP: case GT_IND: - case GT_OBJ: case GT_BLK: case GT_BOX: case GT_ALLOCOBJ: @@ -10566,7 +10477,6 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_ { case GT_LEA: case GT_BLK: - case GT_OBJ: case GT_STORE_BLK: case GT_STORE_OBJ: case GT_STORE_DYN_BLK: @@ -10880,7 +10790,7 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_ { ClassLayout* layout = nullptr; - if (tree->OperIs(GT_BLK, GT_OBJ, GT_STORE_BLK, GT_STORE_OBJ)) + if (tree->OperIs(GT_BLK, GT_STORE_BLK, GT_STORE_OBJ)) { layout = tree->AsBlk()->GetLayout(); } @@ -14269,7 +14179,7 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions // over in impImportAndPushBox for the inlined box case. GenTree* copyDst = copy->AsOp()->gtOp1; - if (!copyDst->OperIs(GT_BLK, GT_IND, GT_OBJ)) + if (!copyDst->OperIs(GT_BLK, GT_IND)) { JITDUMP("Unexpected copy dest operator %s\n", GenTree::OpName(copyDst->gtOper)); return nullptr; @@ -14339,7 +14249,7 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions { isStructCopy = true; - if ((copySrc->gtOper != GT_OBJ) && (copySrc->gtOper != GT_IND) && (copySrc->gtOper != GT_FIELD)) + if ((copySrc->gtOper != GT_BLK) && (copySrc->gtOper != GT_IND) && (copySrc->gtOper != GT_FIELD)) { // We don't know how to handle other cases, yet. JITDUMP(" bailing; unexpected copy source struct op with side effect %s\n", @@ -14391,7 +14301,7 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions // For struct types read the first byte of the // source struct; there's no need to read the // entire thing, and no place to put it. - assert(copySrc->OperIs(GT_OBJ, GT_IND, GT_FIELD)); + assert(copySrc->OperIs(GT_BLK, GT_IND, GT_FIELD)); copyStmt->SetRootNode(copySrc); if (options == BR_REMOVE_AND_NARROW || options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE) @@ -16025,7 +15935,7 @@ GenTree* Compiler::gtNewRefCOMfield(GenTree* objPtr, { if (varTypeIsStruct(lclTyp)) { - result = gtNewObjNode(structType, result); + result = gtNewBlkIndir(typGetObjLayout(structType), result); } else { @@ -16387,7 +16297,7 @@ bool Compiler::gtSplitTree( if (IsLocation(useInf)) { // Only a handful of nodes can be location, and they are all unary or nullary. - assert((*use)->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_LCL_VAR, GT_LCL_FLD)); + assert((*use)->OperIs(GT_IND, GT_BLK, GT_LCL_VAR, GT_LCL_FLD)); if ((*use)->OperIsUnary()) { SplitOutUse(UseInfo{&(*use)->AsUnOp()->gtOp1, user}, false); diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index fcd83c40969be8..b2842814858978 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1215,7 +1215,7 @@ struct GenTree static bool OperIsBlk(genTreeOps gtOper) { - return (gtOper == GT_BLK) || (gtOper == GT_OBJ) || OperIsStoreBlk(gtOper); + return (gtOper == GT_BLK) || OperIsStoreBlk(gtOper); } bool OperIsBlk() const @@ -1547,8 +1547,8 @@ struct GenTree // OperIsIndir() returns true also for indirection nodes such as GT_BLK, etc. as well as GT_NULLCHECK. static bool OperIsIndir(genTreeOps gtOper) { - static_assert_no_msg(AreContiguous(GT_IND, GT_STOREIND, GT_OBJ, GT_STORE_OBJ, GT_BLK, GT_STORE_BLK, - GT_STORE_DYN_BLK, GT_NULLCHECK)); + static_assert_no_msg( + AreContiguous(GT_IND, GT_STOREIND, GT_STORE_OBJ, GT_BLK, GT_STORE_BLK, GT_STORE_DYN_BLK, GT_NULLCHECK)); return (GT_IND <= gtOper) && (gtOper <= GT_NULLCHECK); } @@ -7353,30 +7353,6 @@ struct GenTreeBlk : public GenTreeIndir #endif // DEBUGGABLE_GENTREE }; -// gtObj -- 'object' (GT_OBJ). -// -// This node is used for block values that may have GC pointers. - -struct GenTreeObj : public GenTreeBlk -{ - GenTreeObj(var_types type, GenTree* addr, ClassLayout* layout) : GenTreeBlk(GT_OBJ, type, addr, layout) - { - noway_assert(GetLayout()->GetClassHandle() != NO_CLASS_HANDLE); - } - - GenTreeObj(var_types type, GenTree* addr, GenTree* data, ClassLayout* layout) - : GenTreeBlk(GT_STORE_OBJ, type, addr, data, layout) - { - noway_assert(GetLayout()->GetClassHandle() != NO_CLASS_HANDLE); - } - -#if DEBUGGABLE_GENTREE - GenTreeObj() : GenTreeBlk() - { - } -#endif -}; - // GenTreeStoreDynBlk -- 'dynamic block store' (GT_STORE_DYN_BLK). // // This node is used to represent stores that have a dynamic size - the "cpblk" and "initblk" diff --git a/src/coreclr/jit/gschecks.cpp b/src/coreclr/jit/gschecks.cpp index f534a0856d98da..d4f5cb497b3f0b 100644 --- a/src/coreclr/jit/gschecks.cpp +++ b/src/coreclr/jit/gschecks.cpp @@ -162,7 +162,6 @@ Compiler::fgWalkResult Compiler::gsMarkPtrsAndAssignGroups(GenTree** pTree, fgWa // Indirections - look for *p uses and defs case GT_IND: case GT_BLK: - case GT_OBJ: case GT_ARR_ELEM: case GT_ARR_INDEX: case GT_ARR_OFFSET: diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index d6b5dede51585b..4482d7e6f9e0d4 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -80,10 +80,9 @@ GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) GTNODE(IND , GenTreeIndir ,0,GTK_UNOP) // Load indirection GTNODE(STOREIND , GenTreeStoreInd ,0,GTK_BINOP|GTK_NOVALUE) // Store indirection -GTNODE(OBJ , GenTreeObj ,0,GTK_UNOP|GTK_EXOP) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. -GTNODE(STORE_OBJ , GenTreeObj ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. -GTNODE(BLK , GenTreeBlk ,0,GTK_UNOP|GTK_EXOP) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) -GTNODE(STORE_BLK , GenTreeBlk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields) +GTNODE(STORE_OBJ , GenTreeBlk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Store for struct objects with GC pointers +GTNODE(BLK , GenTreeBlk ,0,GTK_UNOP|GTK_EXOP) // Block/struct object +GTNODE(STORE_BLK , GenTreeBlk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // Block/struct object store GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block store, with native uint size GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // Null checks the source diff --git a/src/coreclr/jit/gtstructs.h b/src/coreclr/jit/gtstructs.h index 157bfb6b281711..58e00276724219 100644 --- a/src/coreclr/jit/gtstructs.h +++ b/src/coreclr/jit/gtstructs.h @@ -89,14 +89,13 @@ GTSTRUCT_2(CopyOrReload, GT_COPY, GT_RELOAD) GTSTRUCT_1(ClsVar , GT_CLS_VAR_ADDR) GTSTRUCT_1(CmpXchg , GT_CMPXCHG) GTSTRUCT_1(AddrMode , GT_LEA) -GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_STORE_DYN_BLK) -GTSTRUCT_2(Obj , GT_OBJ, GT_STORE_OBJ) +GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYN_BLK) GTSTRUCT_1(StoreDynBlk , GT_STORE_DYN_BLK) GTSTRUCT_1(Qmark , GT_QMARK) GTSTRUCT_1(PhiArg , GT_PHI_ARG) GTSTRUCT_1(Phi , GT_PHI) GTSTRUCT_1(StoreInd , GT_STOREIND) -GTSTRUCT_N(Indir , GT_STOREIND, GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_STORE_DYN_BLK) +GTSTRUCT_N(Indir , GT_STOREIND, GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYN_BLK) GTSTRUCT_N(Conditional , GT_SELECT) #if FEATURE_ARG_SPLIT GTSTRUCT_2_SPECIAL(PutArgStk, GT_PUTARG_STK, GT_PUTARG_SPLIT) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index a91ab29e439d95..7c2189e766ebf9 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -1200,7 +1200,6 @@ GenTree* Compiler::impGetStructAddr(GenTree* structVal, switch (structVal->OperGet()) { case GT_BLK: - case GT_OBJ: case GT_IND: if (willDeref) { @@ -1335,7 +1334,7 @@ var_types Compiler::impNormStructType(CORINFO_CLASS_HANDLE structHnd, CorInfoTyp // Given struct value 'structVal', make sure it is 'canonical', that is // it is either: // - a known struct type (non-TYP_STRUCT, e.g. TYP_SIMD8) -// - an OBJ or a MKREFANY node, or +// - a BLK or a MKREFANY node, or // - a node (e.g. GT_FIELD) that will be morphed. // If the node is a CALL or RET_EXPR, a copy will be made to a new temp. // @@ -1361,7 +1360,6 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str case GT_LCL_VAR: case GT_LCL_FLD: case GT_IND: - case GT_OBJ: case GT_BLK: case GT_FIELD: case GT_CNS_VEC: @@ -1441,7 +1439,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str if (structLcl != nullptr) { - // A OBJ on a ADDR(LCL_VAR) can never raise an exception + // A BLK on a ADDR(LCL_VAR) can never raise an exception // so we don't set GTF_EXCEPT here. if (!lvaIsImplicitByRefLocal(structLcl->GetLclNum())) { @@ -1450,7 +1448,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str } else if (structVal->OperIsBlk()) { - // In general a OBJ is an indirection and could raise an exception. + // In general a BLK is an indirection and could raise an exception. structVal->gtFlags |= GTF_EXCEPT; } return structVal; @@ -3227,8 +3225,7 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, if ((treeToBox->gtFlags & GTF_SIDE_EFFECT) != 0) { // Is this a side effect we can replicate cheaply? - if (((treeToBox->gtFlags & GTF_SIDE_EFFECT) == GTF_EXCEPT) && - treeToBox->OperIs(GT_OBJ, GT_BLK, GT_IND)) + if (((treeToBox->gtFlags & GTF_SIDE_EFFECT) == GTF_EXCEPT) && treeToBox->OperIs(GT_BLK, GT_IND)) { // If the only side effect comes from the dereference itself, yes. GenTree* const addr = treeToBox->AsOp()->gtGetOp1(); @@ -4328,10 +4325,10 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT if (!(access & CORINFO_ACCESS_ADDRESS)) { + // TODO-CQ: mark the indirections non-faulting. if (varTypeIsStruct(lclTyp)) { - // Constructor adds GTF_GLOB_REF. Note that this is *not* GTF_EXCEPT. - op1 = gtNewObjNode(pFieldInfo->structType, op1); + op1 = gtNewBlkIndir(typGetObjLayout(pFieldInfo->structType), op1); } else { @@ -8330,7 +8327,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) { // If the value being produced comes from loading // via an underlying address, just null check the address. - if (op1->OperIs(GT_FIELD, GT_IND, GT_OBJ)) + if (op1->OperIs(GT_FIELD, GT_IND, GT_BLK)) { GenTree* addr = op1->gtGetOp1(); if ((addr != nullptr) && fgAddrCouldBeNull(addr)) @@ -9401,8 +9398,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) { if (varTypeIsStruct(lclTyp)) { - op1 = gtNewObjNode(fieldInfo.structType, op1); - op1->gtFlags |= GTF_IND_NONFAULTING; + op1 = gtNewBlkIndir(typGetObjLayout(fieldInfo.structType), op1, GTF_IND_NONFAULTING); } else { @@ -9493,7 +9489,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (!usesHelper) { - assert(op1->OperIs(GT_FIELD, GT_IND, GT_OBJ)); + assert(op1->OperIs(GT_FIELD, GT_IND, GT_BLK)); op1->gtFlags |= GTF_IND_VOLATILE; } } @@ -9502,7 +9498,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) { if (!usesHelper) { - assert(op1->OperIs(GT_FIELD, GT_IND, GT_OBJ)); + assert(op1->OperIs(GT_FIELD, GT_IND, GT_BLK)); op1->gtFlags |= GTF_IND_UNALIGNED; } } @@ -9681,8 +9677,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (varTypeIsStruct(lclTyp)) { - op1 = gtNewObjNode(fieldInfo.structType, op1); - op1->gtFlags |= GTF_IND_NONFAULTING; + op1 = gtNewBlkIndir(typGetObjLayout(fieldInfo.structType), op1, GTF_IND_NONFAULTING); } else { @@ -10198,8 +10193,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* Pop the object and create the unbox helper call */ /* You might think that for UNBOX_ANY we need to push a different */ /* (non-byref) type, but here we're making the tiRetVal that is used */ - /* for the intermediate pointer which we then transfer onto the OBJ */ - /* instruction. OBJ then creates the appropriate tiRetVal. */ + /* for the intermediate pointer which we then transfer onto the BLK */ + /* instruction. BLK then creates the appropriate tiRetVal. */ op1 = impPopStack().val; assertImp(op1->gtType == TYP_REF); @@ -10259,7 +10254,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) GenTree* boxPayloadOffset = gtNewIconNode(TARGET_POINTER_SIZE, TYP_I_IMPL); GenTree* boxPayloadAddress = gtNewOperNode(GT_ADD, TYP_BYREF, op1, boxPayloadOffset); impPushOnStack(boxPayloadAddress, tiRetVal); - oper = GT_OBJ; + oper = GT_BLK; goto OBJ; } else @@ -10345,7 +10340,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) | UNBOX | push the BYREF | spill the STRUCT to a local, | | | | push the BYREF to this local | |--------------------------------------------------------------------- - | UNBOX_ANY | push a GT_OBJ of | push the STRUCT | + | UNBOX_ANY | push a GT_BLK of | push the STRUCT | | | the BYREF | For Linux when the | | | | struct is returned in two | | | | registers create a temp | @@ -10384,7 +10379,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) { // Normal unbox helper returns a TYP_BYREF. impPushOnStack(op1, tiRetVal); - oper = GT_OBJ; + oper = GT_BLK; goto OBJ; } @@ -10415,7 +10410,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) impPushOnStack(op1, tiRetVal); // Load the struct. - oper = GT_OBJ; + oper = GT_BLK; assert(op1->gtType == TYP_BYREF); @@ -10812,7 +10807,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_LDOBJ: { - oper = GT_OBJ; + oper = GT_BLK; assertImp(sz == sizeof(unsigned)); _impResolveToken(CORINFO_TOKENKIND_Class); @@ -10828,17 +10823,13 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto LDIND; } - op1 = impPopStack().val; + GenTreeFlags indirFlags = impPrefixFlagsToIndirFlags(prefixFlags); + op1 = impPopStack().val; assertImp((genActualType(op1) == TYP_I_IMPL) || op1->TypeIs(TYP_BYREF)); - op1 = gtNewObjNode(resolvedToken.hClass, op1); - op1->gtFlags |= GTF_EXCEPT; - op1->gtFlags |= impPrefixFlagsToIndirFlags(prefixFlags); - if (op1->AsIndir()->IsVolatile()) - { - op1->gtFlags |= GTF_ORDER_SIDEEFF; - } + op1 = gtNewBlkIndir(typGetObjLayout(resolvedToken.hClass), op1, indirFlags); + op1->gtFlags |= GTF_EXCEPT; // TODO-1stClassStructs-Cleanup: delete this zero-diff quirk. impPushOnStack(op1, tiRetVal); break; diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index afff217f6a8b79..00928ccce1374f 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -2827,7 +2827,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, var_types resultType = JITtype2varType(sig->retType); if (resultType == TYP_STRUCT) { - retNode = gtNewObjNode(sig->retTypeClass, lclVarAddr); + retNode = gtNewBlkIndir(typGetObjLayout(sig->retTypeClass), lclVarAddr); } else { @@ -5175,8 +5175,7 @@ GenTree* Compiler::impTransformThis(GenTree* thisPtr, GenTree* obj = thisPtr; assert(obj->TypeGet() == TYP_BYREF || obj->TypeGet() == TYP_I_IMPL); - obj = gtNewObjNode(pConstrainedResolvedToken->hClass, obj); - obj->gtFlags |= GTF_EXCEPT; + obj = gtNewBlkIndir(typGetObjLayout(pConstrainedResolvedToken->hClass), obj); CorInfoType jitTyp = info.compCompHnd->asCorInfoType(pConstrainedResolvedToken->hClass); if (impIsPrimitive(jitTyp)) @@ -8895,7 +8894,7 @@ GenTree* Compiler::impArrayAccessIntrinsic( { if (varTypeIsStruct(elemType)) { - arrElem = gtNewObjNode(sig->retTypeClass, arrElem); + arrElem = gtNewBlkIndir(typGetObjLayout(sig->retTypeClass), arrElem); } else { diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 715b8b0211c997..a615159f68df25 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -724,7 +724,6 @@ class LocalAddressVisitor final : public GenTreeVisitor } break; - case GT_OBJ: case GT_BLK: case GT_IND: assert(TopValue(1).Node() == node); @@ -1028,7 +1027,7 @@ class LocalAddressVisitor final : public GenTreeVisitor // unsigned GetIndirSize(GenTree* indir) { - assert(indir->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_FIELD)); + assert(indir->OperIs(GT_IND, GT_BLK, GT_FIELD)); if (indir->TypeGet() != TYP_STRUCT) { @@ -1102,7 +1101,7 @@ class LocalAddressVisitor final : public GenTreeVisitor if (node->TypeIs(TYP_STRUCT)) { ClassLayout* layout = node->GetLayout(m_compiler); - node->SetOper(GT_OBJ); + node->SetOper(GT_BLK); node->AsBlk()->Initialize(layout); } else @@ -1294,7 +1293,7 @@ class LocalAddressVisitor final : public GenTreeVisitor // We don't expect indirections that cannot be turned into local nodes here. assert(val.Offset() <= UINT16_MAX); - assert(indir->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_FIELD) && ((indir->gtFlags & GTF_IND_VOLATILE) == 0)); + assert(indir->OperIs(GT_IND, GT_BLK, GT_FIELD) && ((indir->gtFlags & GTF_IND_VOLATILE) == 0)); if (IsUnused(indir, user)) { @@ -1492,7 +1491,7 @@ class LocalAddressVisitor final : public GenTreeVisitor if (node->TypeIs(TYP_STRUCT)) { - node->SetOper(GT_OBJ); + node->SetOper(GT_BLK); node->AsBlk()->Initialize(layout); } else @@ -1597,7 +1596,7 @@ class LocalAddressVisitor final : public GenTreeVisitor node = m_ancestors.Top(1); - if (!node->OperIs(GT_OBJ)) + if (!node->OperIs(GT_BLK)) { return; } diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 2bf9ae4217155b..ebc3a46426fa57 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -8307,11 +8307,9 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData* #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // We need to support alignment requirements to access memory. - unsigned alignment = 1; - pComp->codeGen->InferOpSizeAlign(lcl, &alignment); - alignment = roundUp(alignment, TARGET_POINTER_SIZE); - padding = roundUp(padding, alignment); -#endif // TARGET_ARMARCH || TARGET_LOONGARCH64 || TARGET_RISCV64 + // Be conservative and use the maximally aligned type here. + padding = roundUp(padding, genTypeSize(TYP_DOUBLE)); +#endif // defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) if (varType != TYP_STRUCT) { diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index c0dbf7959c1d80..006c3239493361 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -221,7 +221,6 @@ void Compiler::fgPerNodeLocalVarLiveness(GenTree* tree) break; case GT_IND: - case GT_OBJ: case GT_BLK: // For Volatile indirection, first mutate GcHeap/ByrefExposed // see comments in ValueNum.cpp (under the memory read case) @@ -2149,13 +2148,12 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR break; case GT_BLK: - case GT_OBJ: { bool removed = fgTryRemoveNonLocal(node, &blockRange); if (!removed && node->IsUnusedValue()) { - // IR doesn't expect dummy uses of `GT_OBJ/BLK/DYN_BLK`. - JITDUMP("Transform an unused OBJ/BLK node [%06d]\n", dspTreeID(node)); + // IR doesn't expect dummy uses of `GT_BLK`. + JITDUMP("Transform an unused BLK node [%06d]\n", dspTreeID(node)); Lowering::TransformUnusedIndirection(node->AsIndir(), this, block); } } diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 87ea617fff8d4f..793c2a1a051726 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -1342,7 +1342,7 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, // Struct can be split into register(s) and stack on ARM if (compFeatureArgSplit() && callArg->AbiInfo.IsSplit()) { - assert(arg->OperIs(GT_OBJ, GT_FIELD_LIST) || arg->OperIsLocalRead()); + assert(arg->OperIs(GT_BLK, GT_FIELD_LIST) || arg->OperIsLocalRead()); // TODO: Need to check correctness for FastTailCall if (call->IsFastTailCall()) { @@ -1482,8 +1482,8 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, #if defined(DEBUG) && defined(FEATURE_PUT_STRUCT_ARG_STK) if (callArg->AbiInfo.IsStruct) { - // We use GT_OBJ only for non-SIMD struct arguments. - if (arg->OperIs(GT_OBJ)) + // We use GT_BLK only for non-SIMD struct arguments. + if (arg->OperIs(GT_BLK)) { assert(!varTypeIsSIMD(arg)); } @@ -1829,9 +1829,9 @@ GenTree* Lowering::LowerCallMemmove(GenTreeCall* call) GenTreeBlk(GT_STORE_BLK, TYP_STRUCT, dstAddr, srcBlk, comp->typGetBlkLayout((unsigned)cnsSize)); storeBlk->gtFlags |= (GTF_IND_UNALIGNED | GTF_ASG | GTF_EXCEPT | GTF_GLOB_REF); - // TODO-CQ: Use GenTreeObj::BlkOpKindUnroll here if srcAddr and dstAddr don't overlap, thus, we can + // TODO-CQ: Use GenTreeBlk::BlkOpKindUnroll here if srcAddr and dstAddr don't overlap, thus, we can // unroll this memmove as memcpy - it doesn't require lots of temp registers - storeBlk->gtBlkOpKind = GenTreeObj::BlkOpKindUnrollMemmove; + storeBlk->gtBlkOpKind = GenTreeBlk::BlkOpKindUnrollMemmove; BlockRange().InsertBefore(call, srcBlk); BlockRange().InsertBefore(call, storeBlk); @@ -4247,16 +4247,16 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) { convertToStoreObj = false; } - else if (src->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_LCL_FLD)) + else if (src->OperIs(GT_IND, GT_BLK, GT_LCL_FLD)) { #if !defined(TARGET_ARM64) if (src->TypeIs(TYP_STRUCT)) { src->ChangeType(lclRegType); - if (src->OperIs(GT_IND, GT_OBJ, GT_BLK)) + if (src->OperIs(GT_IND, GT_BLK)) { - if (src->OperIs(GT_OBJ, GT_BLK)) + if (src->OperIs(GT_BLK)) { src->SetOper(GT_IND); } @@ -4298,7 +4298,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) // Create the assignment node. lclStore->ChangeOper(GT_STORE_OBJ); - GenTreeBlk* objStore = lclStore->AsObj(); + GenTreeBlk* objStore = lclStore->AsBlk(); objStore->gtFlags = GTF_ASG | GTF_IND_NONFAULTING | GTF_IND_TGT_NOT_HEAP; objStore->Initialize(layout); objStore->SetAddr(addr); @@ -4404,7 +4404,6 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret) } case GT_BLK: - case GT_OBJ: case GT_IND: { // Spill to a local if sizes don't match so we can avoid the "load more than requested" @@ -4666,7 +4665,7 @@ void Lowering::LowerStoreSingleRegCallStruct(GenTreeBlk* store) { store->SetOper(GT_STORE_BLK); } - store->gtBlkOpKind = GenTreeObj::BlkOpKindUnroll; + store->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; GenTreeLclVar* spilledCall = SpillStructCallResult(call); store->SetData(spilledCall); @@ -7961,7 +7960,7 @@ void Lowering::TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, Bas // For structs we conservatively lower it to BYTE. For 8-byte primitives we lower it to TYP_INT // on XARCH as an optimization. // - assert(ind->OperIs(GT_NULLCHECK, GT_IND, GT_BLK, GT_OBJ)); + assert(ind->OperIs(GT_NULLCHECK, GT_IND, GT_BLK)); GenTree* const addr = ind->Addr(); if (!comp->fgAddrCouldBeNull(addr)) @@ -8070,7 +8069,7 @@ void Lowering::LowerBlockStoreCommon(GenTreeBlk* blkNode) assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK, GT_STORE_OBJ)); // Lose the type information stored in the source - we no longer need it. - if (blkNode->Data()->OperIs(GT_OBJ, GT_BLK)) + if (blkNode->Data()->OperIs(GT_BLK)) { blkNode->Data()->SetOper(GT_IND); LowerIndir(blkNode->Data()->AsIndir()); diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 0a9f57f5469264..d48db15d65cfc6 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -596,7 +596,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) unsigned copyBlockUnrollLimit = comp->getUnrollThreshold(Compiler::UnrollKind::Memcpy); if (blkNode->OperIs(GT_STORE_OBJ)) { - if (!blkNode->AsObj()->GetLayout()->HasGCPtr()) + if (!blkNode->AsBlk()->GetLayout()->HasGCPtr()) { blkNode->SetOper(GT_STORE_BLK); } @@ -701,7 +701,7 @@ void Lowering::LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode) if (src->TypeIs(TYP_STRUCT)) { - // STRUCT args (FIELD_LIST / OBJ / LCL_VAR / LCL_FLD) will always be contained. + // STRUCT args (FIELD_LIST / BLK / LCL_VAR / LCL_FLD) will always be contained. MakeSrcContained(putArgNode, src); if (src->OperIs(GT_LCL_VAR)) diff --git a/src/coreclr/jit/lowerloongarch64.cpp b/src/coreclr/jit/lowerloongarch64.cpp index 011d6eb45ed8b4..a354979a803d14 100644 --- a/src/coreclr/jit/lowerloongarch64.cpp +++ b/src/coreclr/jit/lowerloongarch64.cpp @@ -352,7 +352,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) unsigned copyBlockUnrollLimit = comp->getUnrollThreshold(Compiler::UnrollKind::Memcpy); if (blkNode->OperIs(GT_STORE_OBJ)) { - if (!blkNode->AsObj()->GetLayout()->HasGCPtr()) + if (!blkNode->AsBlk()->GetLayout()->HasGCPtr()) { blkNode->SetOper(GT_STORE_BLK); } @@ -478,18 +478,18 @@ void Lowering::LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode) lclAddr = comp->gtNewLclAddrNode(lclNum, src->AsLclFld()->GetLclOffs()); } - src->ChangeOper(GT_OBJ); - src->AsObj()->SetAddr(lclAddr); - src->AsObj()->Initialize(layout); + src->ChangeOper(GT_BLK); + src->AsBlk()->SetAddr(lclAddr); + src->AsBlk()->Initialize(layout); BlockRange().InsertBefore(src, lclAddr); } - // Codegen supports containment of local addresses under OBJs. - if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->IsLclVarAddr()) + // Codegen supports containment of local addresses under BLKs. + if (src->OperIs(GT_BLK) && src->AsBlk()->Addr()->IsLclVarAddr()) { // TODO-LOONGARCH64-CQ: support containment of LCL_ADDR with non-zero offset too. - MakeSrcContained(src, src->AsObj()->Addr()); + MakeSrcContained(src, src->AsBlk()->Addr()); } } } diff --git a/src/coreclr/jit/lowerriscv64.cpp b/src/coreclr/jit/lowerriscv64.cpp index bb21011e967b0c..ddbb213a8be2e8 100644 --- a/src/coreclr/jit/lowerriscv64.cpp +++ b/src/coreclr/jit/lowerriscv64.cpp @@ -335,7 +335,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } if (blkNode->OperIs(GT_STORE_OBJ)) { - if (!blkNode->AsObj()->GetLayout()->HasGCPtr()) + if (!blkNode->AsBlk()->GetLayout()->HasGCPtr()) { blkNode->SetOper(GT_STORE_BLK); } @@ -461,20 +461,18 @@ void Lowering::LowerPutArgStkOrSplit(GenTreePutArgStk* putArgNode) lclAddr = comp->gtNewLclAddrNode(lclNum, src->AsLclFld()->GetLclOffs()); } - src->ChangeOper(GT_OBJ); - src->AsObj()->SetAddr(lclAddr); - src->AsObj()->SetLayout(layout); - src->AsObj()->gtBlkOpKind = GenTreeBlk::BlkOpKindInvalid; - src->AsObj()->gtBlkOpGcUnsafe = false; + src->ChangeOper(GT_BLK); + src->AsBlk()->SetAddr(lclAddr); + src->AsBlk()->Initialize(layout); BlockRange().InsertBefore(src, lclAddr); } // Codegen supports containment of local addresses under OBJs. - if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIs(GT_LCL_ADDR)) + if (src->OperIs(GT_BLK) && src->AsBlk()->Addr()->IsLclVarAddr()) { - // TODO-RISCV64-CQ: support containment of LCL_FLD_ADDR too. - MakeSrcContained(src, src->AsObj()->Addr()); + // TODO-RISCV64-CQ: support containment of LCL_ADDR with non-zero offset too. + MakeSrcContained(src, src->AsBlk()->Addr()); } } } diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 7e21041683ff64..816dfe66ddd3c5 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -425,7 +425,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) if (blkNode->OperIs(GT_STORE_OBJ)) { - if (!blkNode->AsObj()->GetLayout()->HasGCPtr()) + if (!blkNode->AsBlk()->GetLayout()->HasGCPtr()) { blkNode->SetOper(GT_STORE_BLK); } @@ -652,7 +652,7 @@ void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) #ifdef FEATURE_PUT_STRUCT_ARG_STK if (src->TypeIs(TYP_STRUCT)) { - assert(src->OperIs(GT_OBJ) || src->OperIsLocalRead()); + assert(src->OperIs(GT_BLK) || src->OperIsLocalRead()); ClassLayout* layout = src->GetLayout(comp); var_types regType = layout->GetRegisterType(); @@ -724,7 +724,7 @@ void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) src->ChangeType(regType); - if (src->OperIs(GT_OBJ)) + if (src->OperIs(GT_BLK)) { src->SetOper(GT_IND); LowerIndir(src->AsIndir()); diff --git a/src/coreclr/jit/lsraarm.cpp b/src/coreclr/jit/lsraarm.cpp index e61e583a420e65..87326e41605eae 100644 --- a/src/coreclr/jit/lsraarm.cpp +++ b/src/coreclr/jit/lsraarm.cpp @@ -764,7 +764,6 @@ int LinearScan::BuildNode(GenTree* tree) case GT_JCC: case GT_SETCC: case GT_MEMORYBARRIER: - case GT_OBJ: srcCount = BuildSimple(tree); break; diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 11892bdbcfae93..925906210a5ffd 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -448,11 +448,11 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) assert(src->isContained()); - if (src->OperIs(GT_OBJ)) + if (src->OperIs(GT_BLK)) { // Build uses for the address to load from. // - srcCount = BuildOperandUses(src->AsObj()->Addr()); + srcCount = BuildOperandUses(src->AsBlk()->Addr()); } else { @@ -558,7 +558,7 @@ int LinearScan::BuildPutArgSplit(GenTreePutArgSplit* argNode) { assert(src->TypeIs(TYP_STRUCT) && src->isContained()); - if (src->OperIs(GT_OBJ)) + if (src->OperIs(GT_BLK)) { // If the PUTARG_SPLIT clobbers only one register we may need an // extra internal register in case there is a conflict between the @@ -570,7 +570,7 @@ int LinearScan::BuildPutArgSplit(GenTreePutArgSplit* argNode) } // We will generate code that loads from the OBJ's address, which must be in a register. - srcCount = BuildOperandUses(src->AsObj()->Addr()); + srcCount = BuildOperandUses(src->AsBlk()->Addr()); } else { diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 006b948626a60e..7ed53b7920a7d5 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -927,7 +927,7 @@ regMaskTP LinearScan::getKillSetForBlockStore(GenTreeBlk* blkNode) if ((blkNode->OperGet() == GT_STORE_OBJ) && blkNode->OperIsCopyBlkOp()) { - assert(blkNode->AsObj()->GetLayout()->HasGCPtr()); + assert(blkNode->AsBlk()->GetLayout()->HasGCPtr()); killMask = compiler->compHelperCallKillSet(CORINFO_HELP_ASSIGN_BYREF); } else diff --git a/src/coreclr/jit/lsraloongarch64.cpp b/src/coreclr/jit/lsraloongarch64.cpp index 0f1fcbc582f343..57da8a1eefd66e 100644 --- a/src/coreclr/jit/lsraloongarch64.cpp +++ b/src/coreclr/jit/lsraloongarch64.cpp @@ -973,13 +973,13 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) buildInternalIntRegisterDefForNode(argNode); buildInternalIntRegisterDefForNode(argNode); - if (putArgChild->OperGet() == GT_OBJ) + if (putArgChild->OperGet() == GT_BLK) { assert(putArgChild->isContained()); GenTree* objChild = putArgChild->gtGetOp1(); if (objChild->IsLclVarAddr()) { - // We will generate all of the code for the GT_PUTARG_STK, the GT_OBJ and the GT_LCL_ADDR<0> + // We will generate all of the code for the GT_PUTARG_STK, the GT_BLK and the GT_LCL_ADDR<0> // as one contained operation, and there are no source registers. // assert(objChild->isContained()); @@ -1073,7 +1073,7 @@ int LinearScan::BuildPutArgSplit(GenTreePutArgSplit* argNode) else { assert(putArgChild->TypeGet() == TYP_STRUCT); - assert(putArgChild->OperGet() == GT_OBJ); + assert(putArgChild->OperGet() == GT_BLK); // We can use a ld/st sequence so we need an internal register buildInternalIntRegisterDefForNode(argNode, allRegs(TYP_INT) & ~argMask); @@ -1081,7 +1081,7 @@ int LinearScan::BuildPutArgSplit(GenTreePutArgSplit* argNode) GenTree* objChild = putArgChild->gtGetOp1(); if (objChild->IsLclVarAddr()) { - // We will generate all of the code for the GT_PUTARG_SPLIT, the GT_OBJ and the GT_LCL_ADDR<0> + // We will generate all of the code for the GT_PUTARG_SPLIT, the GT_BLK and the GT_LCL_ADDR<0> // as one contained operation // assert(objChild->isContained()); diff --git a/src/coreclr/jit/lsrariscv64.cpp b/src/coreclr/jit/lsrariscv64.cpp index 0401deac8a7331..a25c41bd3079e2 100644 --- a/src/coreclr/jit/lsrariscv64.cpp +++ b/src/coreclr/jit/lsrariscv64.cpp @@ -999,13 +999,13 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) buildInternalIntRegisterDefForNode(argNode); buildInternalIntRegisterDefForNode(argNode); - if (putArgChild->OperGet() == GT_OBJ) + if (putArgChild->OperGet() == GT_BLK) { assert(putArgChild->isContained()); GenTree* objChild = putArgChild->gtGetOp1(); if (objChild->OperGet() == GT_LCL_ADDR) { - // We will generate all of the code for the GT_PUTARG_STK, the GT_OBJ and the GT_LCL_ADDR + // We will generate all of the code for the GT_PUTARG_STK, the GT_BLK and the GT_LCL_ADDR // as one contained operation, and there are no source registers. // assert(objChild->isContained()); diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 1e71060a025375..5e62513fd2e539 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -484,7 +484,6 @@ int LinearScan::BuildNode(GenTree* tree) } break; - case GT_OBJ: case GT_BLK: // These should all be eliminated prior to Lowering. assert(!"Non-store block node in Lowering"); @@ -1301,12 +1300,12 @@ int LinearScan::BuildCall(GenTreeCall* call) #ifdef FEATURE_PUT_STRUCT_ARG_STK // If the node is TYP_STRUCT and it is put on stack with // putarg_stk operation, we consume and produce no registers. - // In this case the embedded Obj node should not produce + // In this case the embedded Blk node should not produce // registers too since it is contained. // Note that if it is a SIMD type the argument will be in a register. if (argNode->TypeGet() == TYP_STRUCT) { - assert(argNode->gtGetOp1() != nullptr && argNode->gtGetOp1()->OperGet() == GT_OBJ); + assert(argNode->gtGetOp1() != nullptr && argNode->gtGetOp1()->OperGet() == GT_BLK); assert(argNode->gtGetOp1()->isContained()); } #endif // FEATURE_PUT_STRUCT_ARG_STK diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 34ff0903e7d020..ac2826ccec4c5b 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -1136,15 +1136,14 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) } } - // We are only able to expand certain "OBJ"s into field lists, so here we spill all the + // We are only able to expand certain "BLK"s into field lists, so here we spill all the // "mis-sized" ones. We could in theory support them directly with some arithmetic and // shifts, but these cases are rare enough that it is probably not worth the complexity. - // No need to do this for stack args as they are directly supported by codegen. Likewise - // for "local" "OBJ"s - we can safely load "too much" for them. + // No need to do this for stack args as they are directly supported by codegen. // - if (argx->OperIs(GT_OBJ) && (arg.AbiInfo.GetRegNum() != REG_STK)) + if (argx->OperIs(GT_BLK) && (arg.AbiInfo.GetRegNum() != REG_STK)) { - GenTreeObj* argObj = argx->AsObj(); + GenTreeBlk* argObj = argx->AsBlk(); unsigned structSize = argObj->Size(); unsigned lastLoadSize = structSize % TARGET_POINTER_SIZE; @@ -3186,7 +3185,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) unsigned originalSize; if (argObj->TypeGet() == TYP_STRUCT) { - assert(argObj->OperIs(GT_OBJ, GT_LCL_VAR, GT_LCL_FLD)); + assert(argObj->OperIs(GT_BLK, GT_LCL_VAR, GT_LCL_FLD)); originalSize = argObj->GetLayout(this)->GetSize(); } else @@ -3210,7 +3209,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) unsigned structSize = originalSize; unsigned passingSize = originalSize; - // Check to see if we can transform this struct load (GT_OBJ) into a GT_IND of the appropriate size. + // Check to see if we can transform this struct load (GT_BLK) into a GT_IND of the appropriate size. // When it can do this is platform-dependent: // - In general, it can be done for power of 2 structs that fit in a single register. // - For ARM and ARM64 it must also be a non-HFA struct, or have a single field. @@ -3259,7 +3258,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) // actually passed in registers. if (arg.AbiInfo.IsPassedInRegisters()) { - if (argObj->OperIs(GT_OBJ)) + if (argObj->OperIs(GT_BLK)) { if (passingSize != structSize) { @@ -3562,7 +3561,7 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call) // arg - The argument containing a struct node. // // Notes: -// The arg node must be a GT_OBJ or GT_LCL_VAR or GT_LCL_FLD of TYP_STRUCT. +// The arg node must be a GT_BLK or GT_LCL_VAR or GT_LCL_FLD of TYP_STRUCT. // If arg node is a lclVar passed on the stack, we will ensure that any lclVars that must be on the // stack are marked as doNotEnregister, and then we return. // @@ -3575,7 +3574,7 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call) // If we have a GT_LCL_VAR that isn't struct promoted or doesn't meet the requirements // we will use a set of GT_LCL_FLDs nodes to access the various portions of the struct // this also forces the struct to be stack allocated into the local frame. -// For the GT_OBJ case will clone the address expression and generate two (or more) +// For the GT_BLK case will clone the address expression and generate two (or more) // indirections. // GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) @@ -3693,7 +3692,7 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) // if (!argNode->OperIs(GT_LCL_VAR, GT_LCL_FLD)) { - assert(argNode->OperIs(GT_OBJ)); + assert(argNode->OperIs(GT_BLK)); unsigned lastElemExactSize = structSize - lastElem.Offset; @@ -5106,7 +5105,7 @@ GenTree* Compiler::fgMorphExpandInstanceField(GenTree* tree, MorphAddrContext* m We want to make it like this (when fldOffset is <= MAX_UNCHECKED_OFFSET_FOR_NULL_OBJECT): +--------------------+ - | GT_IND/GT_OBJ | tree (for FIELD) + | GT_IND/GT_BLK | tree (for FIELD) +---------+----------+ | | @@ -5127,7 +5126,7 @@ GenTree* Compiler::fgMorphExpandInstanceField(GenTree* tree, MorphAddrContext* m +--------------------+ - | GT_IND/GT_OBJ | tree (for FIELD) + | GT_IND/GT_BLK | tree (for FIELD) +----------+---------+ | +----------+---------+ @@ -5270,7 +5269,7 @@ GenTree* Compiler::fgMorphExpandInstanceField(GenTree* tree, MorphAddrContext* m if (tree->TypeIs(TYP_STRUCT)) { ClassLayout* layout = tree->GetLayout(this); - tree->SetOper(GT_OBJ); + tree->SetOper(GT_BLK); tree->AsBlk()->Initialize(layout); } else @@ -9801,7 +9800,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA fgSetRngChkTarget(tree); break; - case GT_OBJ: case GT_BLK: case GT_IND: { @@ -15030,9 +15028,9 @@ PhaseStatus Compiler::fgRetypeImplicitByRefArgs() // LHS is a simple reference to the temp. fgEnsureFirstBBisScratch(); GenTree* lhs = gtNewLclvNode(newLclNum, varDsc->lvType); - // RHS is an indirection (using GT_OBJ) off the parameter. + // RHS is an indirection (using GT_BLK) off the parameter. GenTree* addr = gtNewLclvNode(lclNum, TYP_BYREF); - GenTree* rhs = (varDsc->TypeGet() == TYP_STRUCT) ? gtNewObjNode(varDsc->GetLayout(), addr) + GenTree* rhs = (varDsc->TypeGet() == TYP_STRUCT) ? gtNewBlkIndir(varDsc->GetLayout(), addr) : gtNewIndir(varDsc->TypeGet(), addr); GenTree* assign = gtNewAssignNode(lhs, rhs); fgNewStmtAtBeg(fgFirstBB, assign); diff --git a/src/coreclr/jit/morphblock.cpp b/src/coreclr/jit/morphblock.cpp index 6f60165a1295e8..ad20697c2cc743 100644 --- a/src/coreclr/jit/morphblock.cpp +++ b/src/coreclr/jit/morphblock.cpp @@ -218,7 +218,7 @@ void MorphInitBlockHelper::PrepareDst() else { assert(m_dst == m_dst->gtEffectiveVal() && "the commas were skipped in MorphBlock"); - assert(m_dst->OperIs(GT_IND, GT_BLK, GT_OBJ) && (!m_dst->OperIs(GT_IND) || !m_dst->TypeIs(TYP_STRUCT))); + assert(m_dst->OperIs(GT_IND, GT_BLK) && (!m_dst->OperIs(GT_IND) || !m_dst->TypeIs(TYP_STRUCT))); } if (m_dst->TypeIs(TYP_STRUCT)) diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index e236346bfb055b..d47364b45c7dff 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -3645,7 +3645,7 @@ bool Compiler::optIsCSEcandidate(GenTree* tree) case GT_INTRINSIC: return true; // allow Intrinsics to be CSE-ed - case GT_OBJ: + case GT_BLK: case GT_LCL_FLD: // TODO-1stClassStructs: support CSE for enregisterable TYP_STRUCTs. return varTypeIsEnregisterable(type); diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp index c35a42afb5a43b..c2e0216f6a7dbc 100644 --- a/src/coreclr/jit/rationalize.cpp +++ b/src/coreclr/jit/rationalize.cpp @@ -36,11 +36,11 @@ void copyFlags(GenTree* dst, GenTree* src, GenTreeFlags mask) void Rationalizer::RewriteIndir(LIR::Use& use) { GenTreeIndir* indir = use.Def()->AsIndir(); - assert(indir->OperIs(GT_IND, GT_BLK, GT_OBJ)); + assert(indir->OperIs(GT_IND, GT_BLK)); if (varTypeIsSIMD(indir)) { - if (indir->OperIs(GT_BLK, GT_OBJ)) + if (indir->OperIs(GT_BLK)) { indir->SetOper(GT_IND); } @@ -413,22 +413,11 @@ void Rationalizer::RewriteAssignment(LIR::Use& use) break; case GT_BLK: - case GT_OBJ: { assert(varTypeIsStruct(location)); - GenTreeBlk* storeBlk = location->AsBlk(); - genTreeOps storeOper; - switch (location->gtOper) - { - case GT_BLK: - storeOper = GT_STORE_BLK; - break; - case GT_OBJ: - storeOper = GT_STORE_OBJ; - break; - default: - unreached(); - } + GenTreeBlk* storeBlk = location->AsBlk(); + genTreeOps storeOper = location->AsBlk()->GetLayout()->HasGCPtr() ? GT_STORE_OBJ : GT_STORE_BLK; + JITDUMP("Rewriting GT_ASG(%s(X), Y) to %s(X,Y):\n", GenTree::OpName(location->gtOper), GenTree::OpName(storeOper)); storeBlk->SetOperRaw(storeOper); @@ -482,7 +471,6 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, Compiler::Ge case GT_IND: case GT_BLK: - case GT_OBJ: RewriteIndir(use); break; diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp index fcad21a11166c3..b3428e93891fc1 100644 --- a/src/coreclr/jit/ssabuilder.cpp +++ b/src/coreclr/jit/ssabuilder.cpp @@ -740,7 +740,7 @@ void SsaBuilder::RenameDef(GenTree* defNode, BasicBlock* block) // This is perhaps temporary -- maybe should be done elsewhere. Label GT_INDs on LHS of assignments, so we // can skip these during (at least) value numbering. GenTree* lhs = defNode->gtGetOp1()->gtEffectiveVal(/*commaOnly*/ true); - if (lhs->OperIs(GT_IND, GT_OBJ, GT_BLK)) + if (lhs->OperIs(GT_IND, GT_BLK)) { lhs->gtFlags |= GTF_IND_ASG_LHS; } diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index c7fc36be22843e..f5c200b3ec788f 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -8666,7 +8666,6 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo // These need special semantics: GT_COMMA, // == second argument (but with exception(s) from first). GT_ARR_ADDR, GT_BOUNDS_CHECK, - GT_OBJ, // May reference heap memory. GT_BLK, // May reference heap memory. GT_INIT_VAL, // Not strictly a pass-through. GT_MDARR_LENGTH, @@ -9999,7 +9998,6 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) } break; - case GT_OBJ: case GT_BLK: case GT_IND: { @@ -10693,7 +10691,7 @@ void Compiler::fgValueNumberTree(GenTree* tree) { tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, loadType)); } - else if (tree->OperIs(GT_IND, GT_BLK, GT_OBJ) && fgValueNumberConstLoad(tree->AsIndir())) + else if (tree->OperIs(GT_IND, GT_BLK) && fgValueNumberConstLoad(tree->AsIndir())) { // VN is assigned inside fgValueNumberConstLoad } @@ -12801,7 +12799,6 @@ void Compiler::fgValueNumberAddExceptionSet(GenTree* tree) case GT_IND: case GT_BLK: - case GT_OBJ: case GT_NULLCHECK: fgValueNumberAddExceptionSetForIndirection(tree, tree->AsIndir()->Addr()); break;