diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 968d9eb9716413..d0f775b9efc157 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -9539,6 +9539,11 @@ void cTreeFlags(Compiler* comp, GenTree* tree) { chars += printf("[BOX_VALUE]"); } + + if (tree->gtFlags & GTF_BOX_CLONED) + { + chars += printf("[BOX_CLONED]"); + } break; case GT_ARR_ADDR: diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 8381c11b026c51..65809969a120b2 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -8508,6 +8508,8 @@ GenTree* Compiler::gtCloneExpr( copy = new (this, GT_BOX) GenTreeBox(tree->TypeGet(), tree->AsOp()->gtOp1, tree->AsBox()->gtAsgStmtWhenInlinedBoxValue, tree->AsBox()->gtCopyStmtWhenInlinedBoxValue); + tree->AsBox()->SetCloned(); + copy->AsBox()->SetCloned(); break; case GT_INTRINSIC: @@ -13612,6 +13614,13 @@ GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions return nullptr; } + // If this box is no longer single-use, bail. + if (box->WasCloned()) + { + JITDUMP(" bailing; unsafe to remove box that has been cloned\n"); + return nullptr; + } + // If we're eventually going to return the type handle, remember it now. GenTree* boxTypeHandle = nullptr; if ((options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE) || (options == BR_DONT_REMOVE_WANT_TYPE_HANDLE)) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index a088f4c2241b70..e9d512e16c6d18 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -543,6 +543,7 @@ enum GenTreeFlags : unsigned int GTF_QMARK_CAST_INSTOF = 0x80000000, // GT_QMARK -- Is this a top (not nested) level qmark created for // castclass or instanceof? + GTF_BOX_CLONED = 0x40000000, // GT_BOX -- this box and its operand has been cloned, cannot assume it to be single-use anymore GTF_BOX_VALUE = 0x80000000, // GT_BOX -- "box" is on a value type GTF_ARR_ADDR_NONNULL = 0x80000000, // GT_ARR_ADDR -- this array's address is not null @@ -3874,6 +3875,16 @@ struct GenTreeBox : public GenTreeUnOp { } #endif + + bool WasCloned() + { + return (gtFlags & GTF_BOX_CLONED) != 0; + } + + void SetCloned() + { + gtFlags |= GTF_BOX_CLONED; + } }; // GenTreeField -- data member ref (GT_FIELD)