diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index d68381ad94433..282d2f3e53a7f 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -10013,8 +10013,8 @@ var_types Compiler::gtTypeForNullCheck(GenTree* tree) // gtChangeOperToNullCheck: helper to change tree oper to a NULLCHECK. // // Arguments: -// tree - the node to change; -// basicBlock - basic block of the node. +// tree - the node to change; +// block - basic block of the node. // // Notes: // the function should not be called after lowering for platforms that do not support @@ -10026,6 +10026,8 @@ void Compiler::gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block) assert(tree->OperIs(GT_FIELD, GT_IND, GT_OBJ, GT_BLK)); tree->ChangeOper(GT_NULLCHECK); tree->ChangeType(gtTypeForNullCheck(tree)); + assert(fgAddrCouldBeNull(tree->gtGetOp1())); + tree->gtFlags |= GTF_EXCEPT; block->bbFlags |= BBF_HAS_NULLCHECK; optMethodFlags |= OMF_HAS_NULLCHECK; } diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index feec2becd40ff..0a51c1c9c666e 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -16191,11 +16191,24 @@ void Compiler::gtExtractSideEffList(GenTree* expr, { if (m_compiler->gtNodeHasSideEffects(node, m_flags)) { - Append(node); if (node->OperIsBlk() && !node->OperIsStoreBlk()) { - JITDUMP("Replace an unused OBJ/BLK node [%06d] with a NULLCHECK\n", dspTreeID(node)); - m_compiler->gtChangeOperToNullCheck(node, m_compiler->compCurBB); + // Check for a guaranteed non-faulting IND, and create a NOP node instead of a NULLCHECK in that + // case. + if (m_compiler->fgAddrCouldBeNull(node->AsBlk()->Addr())) + { + Append(node); + JITDUMP("Replace an unused OBJ/BLK node [%06d] with a NULLCHECK\n", dspTreeID(node)); + m_compiler->gtChangeOperToNullCheck(node, m_compiler->compCurBB); + } + else + { + JITDUMP("Dropping non-faulting OBJ/BLK node [%06d]\n", dspTreeID(node)); + } + } + else + { + Append(node); } return Compiler::WALK_SKIP_SUBTREES; } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index d20289ea2f058..c691c64f398a9 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8215,7 +8215,15 @@ void Compiler::impImportBlockCode(BasicBlock* block) // via an underlying address, just null check the address. if (op1->OperIs(GT_FIELD, GT_IND, GT_OBJ)) { - gtChangeOperToNullCheck(op1, block); + GenTree* addr = op1->gtGetOp1(); + if ((addr != nullptr) && fgAddrCouldBeNull(addr)) + { + gtChangeOperToNullCheck(op1, block); + } + else + { + op1 = gtNewNothingNode(); + } } else { diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 93df4f3c690bf..79c6657717694 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -7283,13 +7283,16 @@ void Lowering::LowerIndir(GenTreeIndir* ind) #if defined(TARGET_ARM64) // Verify containment safety before creating an LEA that must be contained. // - const bool isContainable = IsSafeToContainMem(ind, ind->Addr()); + const bool isContainable = (ind->Addr() != nullptr) && IsSafeToContainMem(ind, ind->Addr()); #else const bool isContainable = true; #endif - TryCreateAddrMode(ind->Addr(), isContainable, ind); - ContainCheckIndir(ind); + if (!ind->OperIs(GT_NOP)) + { + TryCreateAddrMode(ind->Addr(), isContainable, ind); + ContainCheckIndir(ind); + } #ifdef TARGET_XARCH if (ind->OperIs(GT_NULLCHECK) || ind->IsUnusedValue()) @@ -7337,14 +7340,23 @@ void Lowering::TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, Bas // assert(ind->OperIs(GT_NULLCHECK, GT_IND, GT_BLK, GT_OBJ)); + GenTree* const addr = ind->Addr(); + if (!comp->fgAddrCouldBeNull(addr)) + { + addr->SetUnusedValue(); + ind->gtBashToNOP(); + JITDUMP("bash an unused indir [%06u] to NOP.\n", comp->dspTreeID(ind)); + return; + } + ind->ChangeType(comp->gtTypeForNullCheck(ind)); #if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) bool useNullCheck = true; -#elif TARGET_ARM +#elif defined(TARGET_ARM) bool useNullCheck = false; #else // TARGET_XARCH - bool useNullCheck = !ind->Addr()->isContained(); + bool useNullCheck = !addr->isContained(); ind->ClearDontExtend(); #endif // !TARGET_XARCH