Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Extend escape analysis to account for arrays with non-gcref elements #104906

Open
wants to merge 94 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
1b0e3d3
initial prototype
hez2010 Jul 15, 2024
57b7e42
Morph ARR_LENGTH and INDEX_ADDR
hez2010 Jul 15, 2024
1b5b25e
Fix incorrect array length storage
hez2010 Jul 15, 2024
395b735
Use offset and correct type
hez2010 Jul 15, 2024
17de70b
handle reassignment
hez2010 Jul 15, 2024
5443c42
range check
hez2010 Jul 15, 2024
b2d07da
throw range check failure
hez2010 Jul 15, 2024
b5ae9e7
update comments
hez2010 Jul 15, 2024
87b29de
add metrics
hez2010 Jul 15, 2024
eeb681d
minor cleanup
hez2010 Jul 15, 2024
dee9f38
Introduce new temp and implement local address morphing
hez2010 Jul 16, 2024
94c103b
handle index out-of-range
hez2010 Jul 16, 2024
12b297b
Refactor to remove duplicates
hez2010 Jul 16, 2024
e0fa91e
Remove invalid asserts
hez2010 Jul 16, 2024
9e0a04f
make compiler happy
hez2010 Jul 16, 2024
ae822f8
Address review feedbacks
hez2010 Jul 16, 2024
a4588bb
Fix INDEX_ADDR and add Sub
hez2010 Jul 16, 2024
32b9e26
Support IsAddressLessThan and its friends
hez2010 Jul 16, 2024
39d1ad9
Fix assertions
hez2010 Jul 16, 2024
0df0d58
Merge remote-tracking branch 'origin/main' into value-array-stack-alloc
hez2010 Jul 16, 2024
9f408b2
Use new overload
hez2010 Jul 16, 2024
418a62b
JIT: Remove GTF_IND_INVARIANT and GTF_IND_NONFAULTING flags checking
jakobbotsch Jul 16, 2024
4572408
Remove old comment
jakobbotsch Jul 16, 2024
9255762
Expose jitconfig
hez2010 Jul 16, 2024
1af84b9
Remove another assert
jakobbotsch Jul 16, 2024
629c793
Count
jakobbotsch Jul 16, 2024
b578203
Try 2 at counting
jakobbotsch Jul 16, 2024
b4445f6
Introduce BBF_HAS_NEWARR
hez2010 Jul 16, 2024
af9c40e
Early exit on debug as well
hez2010 Jul 16, 2024
8b54f5a
Update computed flags
hez2010 Jul 16, 2024
cba4d2c
Merge remote-tracking branch 'jakobbotsch/indir-flags' into value-arr…
hez2010 Jul 17, 2024
b497fae
Merge remote-tracking branch 'origin/main' into value-array-stack-alloc
hez2010 Jul 17, 2024
6eca58d
Partially revert 39d1ad9
hez2010 Jul 17, 2024
49d8509
Reuse existing comma node
hez2010 Jul 17, 2024
4c6e359
Respect IsBoundsChecked
hez2010 Jul 17, 2024
4d84379
Check lowerbound too
hez2010 Jul 17, 2024
c0cad85
Fix assertion take 2
hez2010 Jul 18, 2024
d28553a
Remove redundant jit-ee calls
hez2010 Jul 18, 2024
f42e78f
Merge branch 'main' into value-array-stack-alloc
hez2010 Jul 18, 2024
c21c4f7
Fix assertion again
hez2010 Jul 18, 2024
18ec558
Check array length
hez2010 Jul 18, 2024
eadb4ad
Fix assertion in another way
hez2010 Jul 18, 2024
9d4021c
Unset the flag to avoid unnecessary assert
hez2010 Jul 18, 2024
1cba8c0
Merge branch 'main' into value-array-stack-alloc
hez2010 Jul 19, 2024
1fff53e
Add tests
hez2010 Jul 19, 2024
d521a94
sigh
hez2010 Jul 19, 2024
97ee2be
Support R2R/NativeAOT
hez2010 Jul 19, 2024
c66bdb8
Merge branch 'main' into value-array-stack-alloc
hez2010 Jul 19, 2024
5bcb786
Fix building
hez2010 Jul 19, 2024
a01562e
cleanup
hez2010 Jul 19, 2024
e728d4f
remove invalid assert
hez2010 Jul 19, 2024
d73c5c5
double align on 32bit platform
hez2010 Jul 19, 2024
c9fea23
Use correct alignment for align8
hez2010 Jul 19, 2024
772bee6
Fix intrinsic expansion
hez2010 Jul 20, 2024
499ac0b
Merge branch 'main' into value-array-stack-alloc
hez2010 Jul 20, 2024
ffcbd85
Merge remote-tracking branch 'origin/main' into value-array-stack-alloc
hez2010 Jul 22, 2024
4789090
Merge branch 'main' into value-array-stack-alloc
hez2010 Aug 24, 2024
1b33170
Merge branch 'main' into value-array-stack-alloc
hez2010 Sep 20, 2024
9c81c04
Address some review feedback
hez2010 Sep 21, 2024
ed6c83c
Merge branch 'main' into value-array-stack-alloc
hez2010 Oct 4, 2024
6a7e6cb
Revert workaround to fgMorphSmpOp
hez2010 Oct 4, 2024
e4d91ed
Merge branch 'main' into value-array-stack-alloc
hez2010 Nov 26, 2024
aeeb9e3
Fix build failure
hez2010 Nov 26, 2024
0e2a01d
Merge branch 'main' into value-array-stack-alloc
hez2010 Dec 6, 2024
1914e80
Try fixing remorph issue
hez2010 Dec 6, 2024
f671085
Minimize asmdiff for tier-0
hez2010 Dec 6, 2024
d4fd6ae
Check CI
hez2010 Dec 6, 2024
b3ff72d
Take INDEX as non-escape
hez2010 Dec 7, 2024
49c39b9
Early exit when optimization is disabled
hez2010 Dec 7, 2024
a696f87
Format
hez2010 Dec 7, 2024
ce2de99
Merge branch 'main' into value-array-stack-alloc
hez2010 Dec 14, 2024
cc88979
Revert "Try fixing remorph issue"
hez2010 Dec 14, 2024
8d38e0c
Merge branch 'main' into value-array-stack-alloc
AndyAyersMS Dec 18, 2024
52b32f2
Introduce a flag for stack allocated arrays
hez2010 Dec 20, 2024
1f342bd
Handle in global morph
hez2010 Dec 21, 2024
5b51919
Some special cases
hez2010 Dec 21, 2024
ce41a8d
Avoid extensive remorph
hez2010 Dec 21, 2024
47114c6
Oops
hez2010 Dec 21, 2024
66e98cd
Merge branch 'main' into value-array-stack-alloc
AndyAyersMS Jan 9, 2025
de30bdc
Alternative take on array stack allocation
AndyAyersMS Jan 9, 2025
5137a5c
basic VN support
AndyAyersMS Jan 10, 2025
315f884
Merge branch 'main' into value-array-stack-alloc
AndyAyersMS Jan 10, 2025
aa09187
restore complexity change
AndyAyersMS Jan 11, 2025
c451435
pass address of stack local to new helper
AndyAyersMS Jan 14, 2025
18d3677
Merge branch 'main' into value-array-stack-alloc-alt
AndyAyersMS Jan 14, 2025
f6b012a
temp hack to boost SPMI coverage
AndyAyersMS Jan 15, 2025
a6e7bd5
avoid pessimizing tail calls. implement configurable size limit
AndyAyersMS Jan 15, 2025
b3edc07
add missing well known arg string
AndyAyersMS Jan 15, 2025
9b63e2d
fix array length check
AndyAyersMS Jan 16, 2025
e535657
use ClrSafeInt directly
AndyAyersMS Jan 17, 2025
07cd310
bypass for R2R for now, since it may inhibit prejitting
AndyAyersMS Jan 17, 2025
2e2bdf6
Merge branch 'main' into value-array-stack-alloc
AndyAyersMS Jan 17, 2025
7f95162
Merge remote-tracking branch 'hez/value-array-stack-alloc' into value…
AndyAyersMS Jan 17, 2025
1915450
Merge branch 'main' into value-array-stack-alloc
hez2010 Jan 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5128,6 +5128,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
// Expand thread local access
DoPhase(this, PHASE_EXPAND_TLS, &Compiler::fgExpandThreadLocalAccess);

// Expand stack allocated arrays
DoPhase(this, PHASE_EXPAND_STACK_ARR, &Compiler::fgExpandStackArrayAllocations);

// Insert GC Polls
DoPhase(this, PHASE_INSERT_GC_POLLS, &Compiler::fgInsertGCPolls);

Expand Down
22 changes: 18 additions & 4 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,8 @@ class LclVarDsc
unsigned char lvSingleDefDisqualifyReason = 'H';
#endif

unsigned char lvAllDefsAreNoGc : 1; // For pinned locals: true if all defs of this local are no-gc
unsigned char lvStackAllocatedBox : 1; // Local is a stack allocated box
unsigned char lvAllDefsAreNoGc : 1; // For pinned locals: true if all defs of this local are no-gc
unsigned char lvStackAllocatedObject : 1; // Local is a stack allocated object (class, box, array, ...)

#if FEATURE_MULTIREG_ARGS
regNumber lvRegNumForSlot(unsigned slotNum)
Expand Down Expand Up @@ -807,9 +807,9 @@ class LclVarDsc
return lvIsMultiRegArg || lvIsMultiRegRet;
}

bool IsStackAllocatedBox() const
bool IsStackAllocatedObject() const
{
return lvStackAllocatedBox;
return lvStackAllocatedObject;
}

#if defined(DEBUG)
Expand Down Expand Up @@ -6106,6 +6106,9 @@ class Compiler
PhaseStatus fgExpandStaticInit();
bool fgExpandStaticInitForCall(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);

PhaseStatus fgExpandStackArrayAllocations();
bool fgExpandStackArrayAllocation(BasicBlock* pBlock, Statement* stmt, GenTreeCall* call);

PhaseStatus fgVNBasedIntrinsicExpansion();
bool fgVNBasedIntrinsicExpansionForCall(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);
bool fgVNBasedIntrinsicExpansionForCall_ReadUtf8(BasicBlock** pBlock, Statement* stmt, GenTreeCall* call);
Expand Down Expand Up @@ -7537,6 +7540,7 @@ class Compiler
#define OMF_HAS_SPECIAL_INTRINSICS 0x00020000 // Method contains special intrinsics expanded in late phases
#define OMF_HAS_RECURSIVE_TAILCALL 0x00040000 // Method contains recursive tail call
#define OMF_HAS_EXPANDABLE_CAST 0x00080000 // Method contains casts eligible for late expansion
#define OMF_HAS_STACK_ARRAY 0x00100000 // Method contains stack allocated arrays

// clang-format on

Expand Down Expand Up @@ -7627,6 +7631,16 @@ class Compiler
optMethodFlags |= OMF_HAS_RECURSIVE_TAILCALL;
}

bool doesMethodHaveStackAllocatedArray()
{
return (optMethodFlags & OMF_HAS_STACK_ARRAY) != 0;
}

void setMethodHasStackAllocatedArray()
{
optMethodFlags |= OMF_HAS_STACK_ARRAY;
}

void pickGDV(GenTreeCall* call,
IL_OFFSET ilOffset,
bool isInterface,
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compphases.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ CompPhaseNameMacro(PHASE_EXPAND_RTLOOKUPS, "Expand runtime lookups",
CompPhaseNameMacro(PHASE_EXPAND_STATIC_INIT, "Expand static init", false, -1, true)
CompPhaseNameMacro(PHASE_EXPAND_CASTS, "Expand casts", false, -1, true)
CompPhaseNameMacro(PHASE_EXPAND_TLS, "Expand TLS access", false, -1, true)
CompPhaseNameMacro(PHASE_EXPAND_STACK_ARR, "Expand stack array allocation", false, -1, true)
CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls", false, -1, true)
CompPhaseNameMacro(PHASE_CREATE_THROW_HELPERS, "Create throw helper blocks", false, -1, true)
CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", false, -1, true)
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/fgdiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,10 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
{
fprintf(fgxFile, "\n hot=\"true\"");
}
if (block->HasFlag(BBF_HAS_NEWARR))
{
fprintf(fgxFile, "\n callsNewArr=\"true\"");
}
if (block->HasFlag(BBF_HAS_NEWOBJ))
{
fprintf(fgxFile, "\n callsNew=\"true\"");
Expand Down
9 changes: 7 additions & 2 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13192,6 +13192,8 @@ const char* Compiler::gtGetWellKnownArgNameForArgMsg(WellKnownArg arg)
return "swift self";
case WellKnownArg::X86TailCallSpecialArg:
return "tail call";
case WellKnownArg::StackArrayLocal:
return "stack array local";
default:
return nullptr;
}
Expand Down Expand Up @@ -19814,7 +19816,10 @@ void GenTreeArrAddr::ParseArrayAddress(Compiler* comp, GenTree** pArr, ValueNum*
/* static */ void GenTreeArrAddr::ParseArrayAddressWork(
GenTree* tree, Compiler* comp, target_ssize_t inputMul, GenTree** pArr, ValueNum* pInxVN, target_ssize_t* pOffset)
{
if (tree->TypeIs(TYP_REF))
ValueNum vn = comp->GetValueNumStore()->VNLiberalNormalValue(tree->gtVNPair);
VNFuncApp vnf;

if (tree->TypeIs(TYP_REF) || comp->GetValueNumStore()->IsVNNewArr(vn, &vnf))
{
// This must be the array pointer.
assert(*pArr == nullptr);
Expand Down Expand Up @@ -19917,7 +19922,7 @@ void GenTreeArrAddr::ParseArrayAddress(Compiler* comp, GenTree** pArr, ValueNum*
// If we didn't return above, must be a contribution to the non-constant part of the index VN.
// We don't get here for GT_CNS_INT, GT_ADD, or GT_SUB, or for GT_MUL by constant, or GT_LSH of
// constant shift. Thus, the generated index VN does not include the parsed constant offset.
ValueNum vn = comp->GetValueNumStore()->VNLiberalNormalValue(tree->gtVNPair);
//
if (inputMul != 1)
{
ValueNum mulVN = comp->GetValueNumStore()->VNForLongCon(inputMul);
Expand Down
8 changes: 5 additions & 3 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3586,7 +3586,7 @@ class SsaNumInfo final
}
};

// Common supertype of [STORE_]LCL_VAR, [STORE_]LCL_FLD, PHI_ARG, LCL_VAR_ADDR, LCL_FLD_ADDR.
// Common supertype of [STORE_]LCL_VAR, [STORE_]LCL_FLD, PHI_ARG, LCL_ADDR, FIELD_ADDR.
// This inherits from UnOp because lclvar stores are unary.
//
struct GenTreeLclVarCommon : public GenTreeUnOp
Expand Down Expand Up @@ -4227,6 +4227,7 @@ enum GenTreeCallFlags : unsigned int
GTF_CALL_M_CAST_CAN_BE_EXPANDED = 0x04000000, // this cast (helper call) can be expanded if it's profitable. To be removed.
GTF_CALL_M_CAST_OBJ_NONNULL = 0x08000000, // if we expand this specific cast we don't need to check the input object for null
// NOTE: if needed, this flag can be removed, and we can introduce new _NONNUL cast helpers
GTF_CALL_M_STACK_ARRAY = 0x10000000, // this call is a new array helper for a stack allocated array.
};

inline constexpr GenTreeCallFlags operator ~(GenTreeCallFlags a)
Expand Down Expand Up @@ -4566,6 +4567,7 @@ enum class WellKnownArg : unsigned
SwiftError,
SwiftSelf,
X86TailCallSpecialArg,
StackArrayLocal,
};

#ifdef DEBUG
Expand Down Expand Up @@ -7586,12 +7588,12 @@ struct GenTreeArrAddr : GenTreeUnOp

public:
GenTreeArrAddr(GenTree* addr, var_types elemType, CORINFO_CLASS_HANDLE elemClassHandle, uint8_t firstElemOffset)
: GenTreeUnOp(GT_ARR_ADDR, TYP_BYREF, addr DEBUGARG(/* largeNode */ false))
: GenTreeUnOp(GT_ARR_ADDR, addr->TypeGet(), addr DEBUGARG(/* largeNode */ false))
, m_elemClassHandle(elemClassHandle)
, m_elemType(elemType)
, m_firstElemOffset(firstElemOffset)
{
assert(addr->TypeIs(TYP_BYREF));
assert(addr->TypeIs(TYP_BYREF, TYP_I_IMPL));
assert(((elemType == TYP_STRUCT) && (elemClassHandle != NO_CLASS_HANDLE)) ||
hez2010 marked this conversation as resolved.
Show resolved Hide resolved
(elemClassHandle == NO_CLASS_HANDLE));
}
Expand Down
163 changes: 163 additions & 0 deletions src/coreclr/jit/helperexpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2712,3 +2712,166 @@ bool Compiler::fgLateCastExpansionForCall(BasicBlock** pBlock, Statement* stmt,

return true;
}

//------------------------------------------------------------------------------
// fgExpandStackArrayAllocations : expand "new helpers" for stack arrays
//
// Returns:
// PhaseStatus indicating what, if anything, was changed.
//
PhaseStatus Compiler::fgExpandStackArrayAllocations()
{
PhaseStatus result = PhaseStatus::MODIFIED_NOTHING;

if (!doesMethodHaveStackAllocatedArray())
{
// The method being compiled doesn't have any stack allocated arrays.
return result;
}

// Find allocation sites, and transform them into initializations of the
// array method table and length, and replace the allocation call with
// the address of the local array.
//
bool modified = false;

for (BasicBlock* const block : Blocks())
{
for (Statement* const stmt : block->Statements())
{
if ((stmt->GetRootNode()->gtFlags & GTF_CALL) == 0)
{
continue;
}

for (GenTree* const tree : stmt->TreeList())
{
if (!tree->IsCall())
{
continue;
}

if (fgExpandStackArrayAllocation(block, stmt, tree->AsCall()))
{
// If we expand, we split the statement's tree
// so will be done with this statment.
//
modified = true;
break;
}
}
}
}

// we cant assert(modified) here as array allocation sites may
// have been unreachable or dead-coded.
//
return modified ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING;
}

//------------------------------------------------------------------------------
// fgExpandStackArrayAllocation: expand new array helpers for stack allocated arrays
//
// Arguments:
// block - block containing the helper call to expand
// stmt - Statement containing the helper call
// call - The helper call
//
// Returns:
// true if a runtime lookup was found and expanded.
//
bool Compiler::fgExpandStackArrayAllocation(BasicBlock* block, Statement* stmt, GenTreeCall* call)
{
if (!call->IsHelperCall())
{
return false;
}

const CorInfoHelpFunc helper = eeGetHelperNum(call->gtCallMethHnd);
int lengthArgIndex = -1;

switch (helper)
{
case CORINFO_HELP_NEWARR_1_DIRECT:
case CORINFO_HELP_NEWARR_1_VC:
case CORINFO_HELP_NEWARR_1_OBJ:
case CORINFO_HELP_NEWARR_1_ALIGN8:
lengthArgIndex = 1;
break;

case CORINFO_HELP_READYTORUN_NEWARR_1:
lengthArgIndex = 0;
break;

default:
return false;
}

if ((call->gtCallMoreFlags & GTF_CALL_M_STACK_ARRAY) == 0)
{
return false;
}

CallArg* const stackLocalAddressArg = call->gtArgs.FindWellKnownArg(WellKnownArg::StackArrayLocal);
GenTreeLclVarCommon* const stackLocalAddressNode = stackLocalAddressArg->GetNode()->AsLclVarCommon();
const unsigned lclNum = stackLocalAddressNode->GetLclNum();

JITDUMP("Expanding new array helper for stack allocated array V%20u [%06d] in " FMT_BB ":\n", dspTreeID(call),
lclNum, block->bbNum);
DISPTREE(call);
JITDUMP("\n");

Statement* newStmt = nullptr;
GenTree** callUse = nullptr;
bool split = gtSplitTree(block, stmt, call, &newStmt, &callUse);

if (!split)
{
newStmt = stmt;
}

// Initialize the array method table pointer.
//
CORINFO_CLASS_HANDLE arrayHnd = (CORINFO_CLASS_HANDLE)call->compileTimeHelperArgumentHandle;

// Hack to reduce SPMI failures
GenTree* mt = nullptr;

if (opts.IsReadyToRun())
{
mt = gtNewIconEmbClsHndNode(arrayHnd);
}
else
{
mt = gtNewIconHandleNode((size_t)arrayHnd, GTF_ICON_CLASS_HDL);
}

GenTree* const mtStore = gtNewStoreLclFldNode(lclNum, TYP_I_IMPL, 0, mt);
Statement* const mtStmt = gtNewStmt(mtStore);

fgInsertStmtBefore(block, newStmt, mtStmt);
gtSetStmtInfo(mtStmt);
fgSetStmtSeq(mtStmt);

// Initialize the array length.
//
GenTree* const lengthArg = call->gtArgs.GetArgByIndex(lengthArgIndex)->GetNode();
GenTree* const lengthArgInt = fgOptimizeCast(gtNewCastNode(TYP_INT, lengthArg, false, TYP_INT));
GenTree* const lengthStore = gtNewStoreLclFldNode(lclNum, TYP_INT, OFFSETOF__CORINFO_Array__length, lengthArgInt);
Statement* const lenStmt = gtNewStmt(lengthStore);

fgInsertStmtBefore(block, newStmt, lenStmt);
gtSetStmtInfo(lenStmt);
fgSetStmtSeq(lenStmt);

// Replace call with &lclNum.
//
*callUse = stackLocalAddressNode;
DEBUG_DESTROY_NODE(call);

gtUpdateStmtSideEffects(stmt);
gtSetStmtInfo(stmt);
fgSetStmtSeq(stmt);

return true;
}
2 changes: 2 additions & 0 deletions src/coreclr/jit/jitconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,8 @@ CONFIG_STRING(JitObjectStackAllocationRange, "JitObjectStackAllocationRange")
RELEASE_CONFIG_INTEGER(JitObjectStackAllocation, "JitObjectStackAllocation", 1)
RELEASE_CONFIG_INTEGER(JitObjectStackAllocationRefClass, "JitObjectStackAllocationRefClass", 1)
RELEASE_CONFIG_INTEGER(JitObjectStackAllocationBoxedValueClass, "JitObjectStackAllocationBoxedValueClass", 1)
RELEASE_CONFIG_INTEGER(JitObjectStackAllocationArray, "JitObjectStackAllocationArray", 1)
RELEASE_CONFIG_INTEGER(JitObjectStackAllocationSize, "JitObjectStackAllocationSize", 528)

RELEASE_CONFIG_INTEGER(JitEECallTimingInfo, "JitEECallTimingInfo", 0)

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/jitmetadatalist.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ JITMETADATAMETRIC(NewRefClassHelperCalls, int, 0)
JITMETADATAMETRIC(StackAllocatedRefClasses, int, 0)
JITMETADATAMETRIC(NewBoxedValueClassHelperCalls, int, 0)
JITMETADATAMETRIC(StackAllocatedBoxedValueClasses, int, 0)
JITMETADATAMETRIC(NewArrayHelperCalls, int, 0)
JITMETADATAMETRIC(StackAllocatedArrays, int, 0)
JITMETADATAMETRIC(LocalAssertionCount, int, 0)
JITMETADATAMETRIC(LocalAssertionOverflow, int, 0)
JITMETADATAMETRIC(MorphTrackedLocals, int, 0)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2503,9 +2503,9 @@ bool Compiler::StructPromotionHelper::CanPromoteStructVar(unsigned lclNum)
return false;
}

if (varDsc->lvStackAllocatedBox)
if (varDsc->lvStackAllocatedObject)
{
JITDUMP(" struct promotion of V%02u is disabled because it is a stack allocated box\n", lclNum);
JITDUMP(" struct promotion of V%02u is disabled because it is a stack allocated object\n", lclNum);
return false;
}

Expand Down
9 changes: 8 additions & 1 deletion src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,8 @@ const char* getWellKnownArgName(WellKnownArg arg)
return "SwiftSelf";
case WellKnownArg::X86TailCallSpecialArg:
return "X86TailCallSpecialArg";
case WellKnownArg::StackArrayLocal:
return "StackArrayLocal";
}

return "N/A";
Expand Down Expand Up @@ -3633,7 +3635,7 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr)
}

if (((index->gtFlags & (GTF_ASG | GTF_CALL | GTF_GLOB_REF)) != 0) ||
gtComplexityExceeds(index, MAX_ARR_COMPLEXITY) || index->OperIs(GT_LCL_FLD) ||
gtComplexityExceeds(index, MAX_INDEX_COMPLEXITY) || index->OperIs(GT_LCL_FLD) ||
(index->OperIs(GT_LCL_VAR) && lvaIsLocalImplicitlyAccessedByRef(index->AsLclVar()->GetLclNum())))
{
unsigned indexTmpNum = lvaGrabTemp(true DEBUGARG("index expr"));
Expand Down Expand Up @@ -5137,6 +5139,11 @@ GenTree* Compiler::fgMorphPotentialTailCall(GenTreeCall* call)
assert(lvaIsImplicitByRefLocal(lvaTable[varDsc->lvFieldLclStart].lvParentLcl));
assert(fgGlobalMorph);
}
else if (varDsc->IsStackAllocatedObject())
{
// Stack allocated objects currently cannot be passed to callees
// so won't be live at tail call sites.
}
#if FEATURE_FIXED_OUT_ARGS
else if (varNum == lvaOutgoingArgSpaceVar)
{
Expand Down
Loading
Loading