Skip to content

Commit

Permalink
JIT: Type fat pointer locals precisely, and avoid unnecessary normali…
Browse files Browse the repository at this point in the history
…zation in inlining (#99806)

During call importation, for fat pointer calls we will introduce a local
and spill the call to it. This loses track of the small typedness of the
value, which can cause inlining to introduce unnecessary normalization
casts later. For tailcalls this can cause us to add IR after the call
that we do not expect, causing issues like #99798.

Fix the problem by enhancing logic in a few places:
- Make the local created for these fat pointer calls small typed like
  regular normalize-on-store locals
- Enhance `fgCastNeeded` to take into account the small-typedness of
  these locals (like `IntegralRange::ForNode`)
  • Loading branch information
jakobbotsch authored Mar 15, 2024
1 parent 813bb17 commit ad4c7c3
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
16 changes: 14 additions & 2 deletions src/coreclr/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1151,14 +1151,26 @@ bool Compiler::fgCastNeeded(GenTree* tree, var_types toType)
//
// Is the tree as GT_CAST or a GT_CALL ?
//
if (tree->OperGet() == GT_CAST)
if (tree->OperIs(GT_CAST))
{
fromType = tree->CastToType();
}
else if (tree->OperGet() == GT_CALL)
else if (tree->OperIs(GT_CALL))
{
fromType = (var_types)tree->AsCall()->gtReturnType;
}
else if (tree->OperIs(GT_LCL_VAR))
{
LclVarDsc* varDsc = lvaGetDesc(tree->AsLclVarCommon());
if (varDsc->lvNormalizeOnStore())
{
fromType = varDsc->TypeGet();
}
else
{
fromType = tree->TypeGet();
}
}
else
{
fromType = tree->TypeGet();
Expand Down
10 changes: 9 additions & 1 deletion src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1406,11 +1406,19 @@ var_types Compiler::impImportCall(OPCODE opcode,
// Such form allows to find statements with fat calls without walking through whole trees
// and removes problems with cutting trees.
assert(IsTargetAbi(CORINFO_NATIVEAOT_ABI));
if (call->OperGet() != GT_LCL_VAR) // can be already converted by impFixupCallStructReturn.
if (!call->OperIs(GT_LCL_VAR)) // can be already converted by impFixupCallStructReturn.
{
unsigned calliSlot = lvaGrabTemp(true DEBUGARG("calli"));
LclVarDsc* varDsc = lvaGetDesc(calliSlot);
// Keep the information about small typedness to avoid
// inserting unnecessary casts around normalization.
if (call->IsCall() && varTypeIsSmall(call->AsCall()->gtReturnType))
{
assert(call->AsCall()->NormalizesSmallTypesOnReturn());
varDsc->lvType = call->AsCall()->gtReturnType;
}

// TODO-Bug: CHECK_SPILL_NONE here looks wrong.
impStoreTemp(calliSlot, call, CHECK_SPILL_NONE);
// impStoreTemp can change src arg list and return type for call that returns struct.
var_types type = genActualType(lvaTable[calliSlot].TypeGet());
Expand Down

0 comments on commit ad4c7c3

Please sign in to comment.