Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
2dcd5e4
Expand runtime lookups in a late phase
EgorBo Feb 4, 2023
2c7a4a3
Clean up
EgorBo Feb 4, 2023
5754331
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Feb 5, 2023
dca8140
test
EgorBo Feb 6, 2023
e303869
test2
EgorBo Feb 6, 2023
aa760e5
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Feb 25, 2023
20e79dc
Test
EgorBo Feb 25, 2023
22f34a1
Enable JitDasmWithAlignmentBoundaries in Release
EgorBo Feb 25, 2023
c3681c1
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Feb 25, 2023
2110ec0
clean up
EgorBo Feb 25, 2023
54b224c
Revert "Enable JitDasmWithAlignmentBoundaries in Release"
EgorBo Feb 25, 2023
e4d4944
add hashtable
EgorBo Feb 25, 2023
3e272e0
test
EgorBo Feb 25, 2023
2671e14
Initial version (no dynamic expansion for now)
EgorBo Feb 25, 2023
64ae149
Clean up
EgorBo Feb 25, 2023
d991533
Clean up
EgorBo Feb 26, 2023
e20dd2d
Test
EgorBo Feb 26, 2023
8fc0374
Update BB flags properly
EgorBo Feb 26, 2023
269cb36
Add dynamic expansion path
EgorBo Feb 26, 2023
3c1cb1c
Add dynamic expansion
EgorBo Feb 26, 2023
47524ed
Add comments
EgorBo Feb 26, 2023
05ae42d
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Feb 28, 2023
ba8fdc2
test
EgorBo Feb 28, 2023
5d6cf4a
test #2
EgorBo Feb 28, 2023
ec00f5b
it should be <=
EgorBo Feb 28, 2023
ec893da
Update flowgraph.cpp
EgorBo Feb 28, 2023
f81882f
test 3
EgorBo Feb 28, 2023
d1d0bc8
test 4
EgorBo Mar 1, 2023
eea468a
test 4
EgorBo Mar 1, 2023
3d5d61a
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Mar 2, 2023
9af1079
Test 5
EgorBo Mar 2, 2023
ea3bf76
Clean up
EgorBo Mar 2, 2023
8a2a8ad
Found it!
EgorBo Mar 2, 2023
777def6
fix assert
EgorBo Mar 3, 2023
b18b12e
fix assert
EgorBo Mar 3, 2023
0f7fc3d
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Mar 3, 2023
5eee49b
move to separate file + fix some diff regressions
EgorBo Mar 3, 2023
2ff3799
Clean up, address some of the feedback
EgorBo Mar 3, 2023
11cac11
Address feedback [WIP]
EgorBo Mar 3, 2023
936c7d2
Implement gtSplitTree
jakobbotsch Mar 4, 2023
a982e68
Test
EgorBo Mar 4, 2023
aad1188
fix Release
EgorBo Mar 4, 2023
f3853a7
Fix assert
EgorBo Mar 4, 2023
f2d22fe
Initial clean up
EgorBo Mar 5, 2023
3e3b15f
Mark ArrayStack ctor explicit
jakobbotsch Mar 5, 2023
0f40259
Add docs to gtSplitTree
jakobbotsch Mar 5, 2023
2a29ac3
Fix up ASG(COMMA(...), ...) handling
jakobbotsch Mar 5, 2023
598ff71
Split out uses in execution order instead
jakobbotsch Mar 5, 2023
733fcd9
Remove dead local
jakobbotsch Mar 5, 2023
a62a135
Clean up
EgorBo Mar 5, 2023
730ed35
Avoid creating statements for non address-exposed locals
jakobbotsch Mar 5, 2023
9c6c89f
More cleanup (use callUse)
EgorBo Mar 5, 2023
f2c1508
use old path for tier0 (slightly better CQ/TP for tier0)
EgorBo Mar 5, 2023
c1cc980
Code clean up
EgorBo Mar 5, 2023
6f587df
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Mar 11, 2023
2834318
resolve conflicts
EgorBo Mar 11, 2023
79b5076
Update runtimelookup.cpp
EgorBo Mar 12, 2023
f0f14a7
Update src/coreclr/jit/runtimelookup.cpp
EgorBo Mar 12, 2023
6061fa7
Merge branch 'main' of github.com:dotnet/runtime into expand-runtime-…
EgorBo Mar 13, 2023
2a3d83b
Mitigate some tier0 regressions
EgorBo Mar 13, 2023
07cf9e7
clone fastpath for tier0
EgorBo Mar 13, 2023
3a3f4ca
Remove redundant impSpillSideEffects
EgorBo Mar 13, 2023
8af93a9
test
EgorBo Mar 14, 2023
afe2dd4
Fix regressions
EgorBo Mar 14, 2023
7909435
fix tp regressions
EgorBo Mar 14, 2023
258cbae
Apply suggestions from code review
EgorBo Mar 14, 2023
1afb6f8
Address feedback
EgorBo Mar 14, 2023
a116695
Add goto SCAN_BLOCK_AGAIN
EgorBo Mar 14, 2023
386446e
Update src/coreclr/jit/runtimelookup.cpp
EgorBo Mar 14, 2023
d2f3fec
Address feedback
EgorBo Mar 14, 2023
19034d9
update side effects for fallbackBb
EgorBo Mar 14, 2023
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
1 change: 1 addition & 0 deletions src/coreclr/jit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ set( JIT_SOURCES
hwintrinsic.cpp
hostallocator.cpp
ifconversion.cpp
runtimelookup.cpp
indirectcalltransformer.cpp
importercalls.cpp
importer.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/arraystack.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ArrayStack
static const int builtinSize = 8;

public:
ArrayStack(CompAllocator alloc, int initialCapacity = builtinSize) : m_alloc(alloc)
explicit ArrayStack(CompAllocator alloc, int initialCapacity = builtinSize) : m_alloc(alloc)
{
if (initialCapacity > builtinSize)
{
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,7 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
vnStore = nullptr;
m_outlinedCompositeSsaNums = nullptr;
m_nodeToLoopMemoryBlockMap = nullptr;
m_signatureToLookupInfoMap = nullptr;
fgSsaPassesCompleted = 0;
fgSsaChecksEnabled = false;
fgVNPassesCompleted = 0;
Expand Down Expand Up @@ -5000,6 +5001,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
DoPhase(this, PHASE_STRESS_SPLIT_TREE, &Compiler::StressSplitTree);
#endif

// Expand runtime lookups (an optimization but we'd better run it in tier0 too)
DoPhase(this, PHASE_EXPAND_RTLOOKUPS, &Compiler::fgExpandRuntimeLookups);

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

Expand Down
20 changes: 13 additions & 7 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4814,6 +4814,7 @@ class Compiler
BasicBlock* fgSplitBlockAfterStatement(BasicBlock* curr, Statement* stmt);
BasicBlock* fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node); // for LIR
BasicBlock* fgSplitEdge(BasicBlock* curr, BasicBlock* succ);
BasicBlock* fgSplitBlockBeforeTree(BasicBlock* block, Statement* stmt, GenTree* splitPoint, Statement** firstNewStmt, GenTree*** splitNodeUse);

Statement* fgNewStmtFromTree(GenTree* tree, BasicBlock* block, const DebugInfo& di);
Statement* fgNewStmtFromTree(GenTree* tree);
Expand Down Expand Up @@ -4949,6 +4950,17 @@ class Compiler
return m_nodeToLoopMemoryBlockMap;
}

typedef JitHashTable<void*, JitPtrKeyFuncs<void>, CORINFO_RUNTIME_LOOKUP> SignatureToLookupInfoMap;
SignatureToLookupInfoMap* m_signatureToLookupInfoMap;
SignatureToLookupInfoMap* GetSignatureToLookupInfoMap()
{
if (m_signatureToLookupInfoMap == nullptr)
{
m_signatureToLookupInfoMap = new (getAllocator()) SignatureToLookupInfoMap(getAllocator());
}
return m_signatureToLookupInfoMap;
}

void optRecordLoopMemoryDependence(GenTree* tree, BasicBlock* block, ValueNum memoryVN);
void optCopyLoopMemoryDependence(GenTree* fromTree, GenTree* toTree);

Expand Down Expand Up @@ -5281,6 +5293,7 @@ class Compiler
PhaseStatus StressSplitTree();
void SplitTreesRandomly();
void SplitTreesRemoveCommas();
PhaseStatus fgExpandRuntimeLookups();
PhaseStatus fgInsertGCPolls();
BasicBlock* fgCreateGCPoll(GCPollType pollType, BasicBlock* block);

Expand Down Expand Up @@ -7083,13 +7096,6 @@ class Compiler
optMethodFlags |= OMF_HAS_EXPRUNTIMELOOKUP;
}

void clearMethodHasExpRuntimeLookup()
{
optMethodFlags &= ~OMF_HAS_EXPRUNTIMELOOKUP;
}

void addExpRuntimeLookupCandidate(GenTreeCall* call);

bool doesMethodHavePatchpoints()
{
return (optMethodFlags & OMF_HAS_PATCHPOINT) != 0;
Expand Down
21 changes: 21 additions & 0 deletions src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,27 @@ inline void GenTree::BashToZeroConst(var_types type)
}
}

//------------------------------------------------------------------------
// BashToLclVar: Bash node to a LCL_VAR.
//
// Arguments:
// comp - compiler object
// lclNum - the local's number
//
// Return Value:
// The bashed node.
//
inline GenTreeLclVar* GenTree::BashToLclVar(Compiler* comp, unsigned lclNum)
{
LclVarDsc* varDsc = comp->lvaGetDesc(lclNum);

ChangeOper(GT_LCL_VAR);
ChangeType(varDsc->lvNormalizeOnLoad() ? varDsc->TypeGet() : genActualType(varDsc));
AsLclVar()->SetLclNum(lclNum);

return AsLclVar();
}

/*****************************************************************************
*
* Returns true if the node is of the "ovf" variety, for example, add.ovf.i1.
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 @@ -92,6 +92,7 @@ CompPhaseNameMacro(PHASE_VN_BASED_DEAD_STORE_REMOVAL,"VN-based dead store remova
CompPhaseNameMacro(PHASE_OPT_UPDATE_FLOW_GRAPH, "Update flow graph opt pass", false, -1, false)
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)",false, -1, false)
CompPhaseNameMacro(PHASE_STRESS_SPLIT_TREE, "Stress gtSplitTree", false, -1, false)
CompPhaseNameMacro(PHASE_EXPAND_RTLOOKUPS, "Expand runtime lookups", false, -1, true)
CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls", false, -1, true)
CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", false, -1, true)
CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", false, -1, false)
Expand Down
44 changes: 44 additions & 0 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4618,6 +4618,50 @@ BasicBlock* Compiler::fgSplitBlockAfterStatement(BasicBlock* curr, Statement* st
return newBlock;
}

//------------------------------------------------------------------------------
// fgSplitBlockBeforeTree : Split the given block right before the given tree
//
// Arguments:
// block - The block containing the statement.
// stmt - The statement containing the tree.
// splitPoint - A tree inside the statement.
// firstNewStmt - [out] The first new statement that was introduced.
// [firstNewStmt..stmt) are the statements added by this function.
// splitNodeUse - The use of the tree to split at.
//
// Returns:
// The last block after split
//
// Notes:
// See comments in gtSplitTree
//
BasicBlock* Compiler::fgSplitBlockBeforeTree(
BasicBlock* block, Statement* stmt, GenTree* splitPoint, Statement** firstNewStmt, GenTree*** splitNodeUse)
{
gtSplitTree(block, stmt, splitPoint, firstNewStmt, splitNodeUse);

BasicBlockFlags originalFlags = block->bbFlags;
BasicBlock* prevBb = block;

if (stmt == block->firstStmt())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is checking for the case where gtSplitTree didn't do anything?

Perhaps deserves a comment to that effect.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a comment in a follow up if you don't mind to avoid re-running CI for it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really about gtSplitTree? Isn't it here because we don't have a fgSplitBlockBefore?

gtSplitTree can make changes even without introducing new statements -- the return value needs to be used for that kind of check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's here just because I need basically fgSplitBlockBefore and only have fgSplitBlockAfter API

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so when it's not the first statement in the current block I do fgSplitBlockAfter (stmt->PrevStmt())

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose I should look at what gtSplitTree does, but I'm still confused exactly what this method is supposed to be doing. Maybe an example would help?

Copy link
Member Author

@EgorBo EgorBo Mar 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose I should look at what gtSplitTree does, but I'm still confused exactly what this method is supposed to be doing. Maybe an example would help?

The general idea that we want to split a block (e.g. BB0) into two (say, BBa and BBb) at a specific node (e.g. callX) and make sure that all side-effects are moved to BBa and the actual callX is now in BBb.

We have a phase where we insert GC safe points after specific call nodes - that one didn't have to care about any execution ordering since we just wanted to make sure GC is polled (it doesn't even matter whether to emit the poll before or after the calls). The runtime lookup case is a lot more complicated since we needed to insert verbose tree in front of the call and re-use its arguments, respect all kinds of complex COMMAs,

{
block = fgSplitBlockAtBeginning(prevBb);
}
else
{
assert(stmt->GetPrevStmt() != block->lastStmt());
JITDUMP("Splitting " FMT_BB " after statement " FMT_STMT "\n", prevBb->bbNum, stmt->GetPrevStmt()->GetID());
block = fgSplitBlockAfterStatement(prevBb, stmt->GetPrevStmt());
}

// We split a block, possibly, in the middle - we need to propagate some flags
prevBb->bbFlags = originalFlags & (~(BBF_SPLIT_LOST | BBF_LOOP_PREHEADER | BBF_RETLESS_CALL) | BBF_GC_SAFE_POINT);
block->bbFlags |=
originalFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_GC_SAFE_POINT | BBF_LOOP_PREHEADER | BBF_RETLESS_CALL);

return block;
}

//------------------------------------------------------------------------------
// fgSplitBlockAfterNode - Split the given block, with all code after
// the given node going into the second block.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1947,8 +1947,8 @@ struct GenTree

template <typename T>
void BashToConst(T value, var_types type = TYP_UNDEF);

void BashToZeroConst(var_types type);
GenTreeLclVar* BashToLclVar(Compiler* comp, unsigned lclNum);

#if NODEBASH_STATS
static void RecordOperBashing(genTreeOps operOld, genTreeOps operNew);
Expand Down
157 changes: 56 additions & 101 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1780,15 +1780,36 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken
}
#endif

// Slot pointer
GenTree* slotPtrTree = ctxTree;

if (pRuntimeLookup->testForNull)
{
slotPtrTree = impCloneExpr(ctxTree, &ctxTree, NO_CLASS_HANDLE, CHECK_SPILL_ALL,
nullptr DEBUGARG("impRuntimeLookup slot"));
assert(pRuntimeLookup->indirections != 0);

// Call the helper
// - Setup argNode with the pointer to the signature returned by the lookup
GenTree* argNode =
gtNewIconEmbHndNode(pRuntimeLookup->signature, nullptr, GTF_ICON_GLOBAL_PTR, compileTimeHandle);
GenTreeCall* helperCall = gtNewHelperCallNode(pRuntimeLookup->helper, TYP_I_IMPL, ctxTree, argNode);

// No need to perform CSE/hoisting for signature node - it is expected to end up in a rarely-taken block after
// "Expand runtime lookups" phase.
argNode->gtFlags |= GTF_DONT_CSE;

// Leave a note that this method has runtime lookups we might want to expand (nullchecks, size checks) later.
// We can also consider marking current block as a runtime lookup holder to improve TP for Tier0
impInlineRoot()->setMethodHasExpRuntimeLookup();
helperCall->SetExpRuntimeLookup();
if (!impInlineRoot()->GetSignatureToLookupInfoMap()->Lookup(pRuntimeLookup->signature))
{
JITDUMP("Registering %p in SignatureToLookupInfoMap\n", pRuntimeLookup->signature)
impInlineRoot()->GetSignatureToLookupInfoMap()->Set(pRuntimeLookup->signature, *pRuntimeLookup);
}
unsigned callLclNum = lvaGrabTemp(true DEBUGARG("spilling helperCall"));
impAssignTempGen(callLclNum, helperCall);
return gtNewLclvNode(callLclNum, helperCall->TypeGet());
}

// Slot pointer
GenTree* slotPtrTree = ctxTree;
GenTree* indOffTree = nullptr;
GenTree* lastIndOfTree = nullptr;

Expand Down Expand Up @@ -1834,107 +1855,47 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken
}

// No null test required
if (!pRuntimeLookup->testForNull)
{
if (pRuntimeLookup->indirections == 0)
{
return slotPtrTree;
}

slotPtrTree = gtNewOperNode(GT_IND, TYP_I_IMPL, slotPtrTree);
slotPtrTree->gtFlags |= GTF_IND_NONFAULTING;

if (!pRuntimeLookup->testForFixup)
{
return slotPtrTree;
}

impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("bubbling QMark0"));

unsigned slotLclNum = lvaGrabTemp(true DEBUGARG("impRuntimeLookup test"));
impAssignTempGen(slotLclNum, slotPtrTree, NO_CLASS_HANDLE, CHECK_SPILL_ALL, nullptr, impCurStmtDI);

GenTree* slot = gtNewLclvNode(slotLclNum, TYP_I_IMPL);
// downcast the pointer to a TYP_INT on 64-bit targets
slot = impImplicitIorI4Cast(slot, TYP_INT);
// Use a GT_AND to check for the lowest bit and indirect if it is set
GenTree* test = gtNewOperNode(GT_AND, TYP_INT, slot, gtNewIconNode(1));
GenTree* relop = gtNewOperNode(GT_EQ, TYP_INT, test, gtNewIconNode(0));
assert(!pRuntimeLookup->testForNull);

// slot = GT_IND(slot - 1)
slot = gtNewLclvNode(slotLclNum, TYP_I_IMPL);
GenTree* add = gtNewOperNode(GT_ADD, TYP_I_IMPL, slot, gtNewIconNode(-1, TYP_I_IMPL));
GenTree* indir = gtNewOperNode(GT_IND, TYP_I_IMPL, add);
indir->gtFlags |= GTF_IND_NONFAULTING;
indir->gtFlags |= GTF_IND_INVARIANT;

slot = gtNewLclvNode(slotLclNum, TYP_I_IMPL);
GenTree* asg = gtNewAssignNode(slot, indir);
GenTreeColon* colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), asg);
GenTreeQmark* qmark = gtNewQmarkNode(TYP_VOID, relop, colon);
impAppendTree(qmark, CHECK_SPILL_NONE, impCurStmtDI);

return gtNewLclvNode(slotLclNum, TYP_I_IMPL);
if (pRuntimeLookup->indirections == 0)
{
return slotPtrTree;
}

assert(pRuntimeLookup->indirections != 0);

impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("bubbling QMark1"));

// Extract the handle
GenTree* handleForNullCheck = gtNewOperNode(GT_IND, TYP_I_IMPL, slotPtrTree);
handleForNullCheck->gtFlags |= GTF_IND_NONFAULTING;

// Call the helper
// - Setup argNode with the pointer to the signature returned by the lookup
GenTree* argNode = gtNewIconEmbHndNode(pRuntimeLookup->signature, nullptr, GTF_ICON_GLOBAL_PTR, compileTimeHandle);

GenTreeCall* helperCall = gtNewHelperCallNode(pRuntimeLookup->helper, TYP_I_IMPL, ctxTree, argNode);

// Check for null and possibly call helper
GenTree* nullCheck = gtNewOperNode(GT_NE, TYP_INT, handleForNullCheck, gtNewIconNode(0, TYP_I_IMPL));
GenTree* handleForResult = gtCloneExpr(handleForNullCheck);

GenTree* result = nullptr;
slotPtrTree = gtNewOperNode(GT_IND, TYP_I_IMPL, slotPtrTree);
slotPtrTree->gtFlags |= GTF_IND_NONFAULTING;

if (pRuntimeLookup->sizeOffset != CORINFO_NO_SIZE_CHECK)
if (!pRuntimeLookup->testForFixup)
{
// Dynamic dictionary expansion support
return slotPtrTree;
}

assert((lastIndOfTree != nullptr) && (pRuntimeLookup->indirections > 0));
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("bubbling QMark0"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any benefit to deferring expansion of the rest of this in a manner similar to the case above? Seems like this is also creating a hoistable/cseable complex.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't touch this path because it wasn't clear for me when it's hit. From what I see it's not used by R2R and NAOT. Perhaps some dynamic context

In a follow I'll see if it's worth supporting

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testForFixup was used by fragile NGen. It is not used anymore. I think it is fine to delete it - both on the JIT/EE interface and the supporting code in the JIT.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testForFixup was used by fragile NGen. It is not used anymore. I think it is fine to delete it - both on the JIT/EE interface and the supporting code in the JIT.

Thanks, will delete in #83430


// sizeValue = dictionary[pRuntimeLookup->sizeOffset]
GenTreeIntCon* sizeOffset = gtNewIconNode(pRuntimeLookup->sizeOffset, TYP_I_IMPL);
GenTree* sizeValueOffset = gtNewOperNode(GT_ADD, TYP_I_IMPL, lastIndOfTree, sizeOffset);
GenTree* sizeValue = gtNewOperNode(GT_IND, TYP_I_IMPL, sizeValueOffset);
sizeValue->gtFlags |= GTF_IND_NONFAULTING;
unsigned slotLclNum = lvaGrabTemp(true DEBUGARG("impRuntimeLookup test"));
impAssignTempGen(slotLclNum, slotPtrTree, NO_CLASS_HANDLE, CHECK_SPILL_ALL, nullptr, impCurStmtDI);

// sizeCheck fails if sizeValue < pRuntimeLookup->offsets[i]
GenTree* offsetValue = gtNewIconNode(pRuntimeLookup->offsets[pRuntimeLookup->indirections - 1], TYP_I_IMPL);
GenTree* sizeCheck = gtNewOperNode(GT_LE, TYP_INT, sizeValue, offsetValue);
GenTree* slot = gtNewLclvNode(slotLclNum, TYP_I_IMPL);
// downcast the pointer to a TYP_INT on 64-bit targets
slot = impImplicitIorI4Cast(slot, TYP_INT);
// Use a GT_AND to check for the lowest bit and indirect if it is set
GenTree* test = gtNewOperNode(GT_AND, TYP_INT, slot, gtNewIconNode(1));
GenTree* relop = gtNewOperNode(GT_EQ, TYP_INT, test, gtNewIconNode(0));

// revert null check condition.
nullCheck->ChangeOperUnchecked(GT_EQ);
// slot = GT_IND(slot - 1)
slot = gtNewLclvNode(slotLclNum, TYP_I_IMPL);
GenTree* add = gtNewOperNode(GT_ADD, TYP_I_IMPL, slot, gtNewIconNode(-1, TYP_I_IMPL));
GenTree* indir = gtNewOperNode(GT_IND, TYP_I_IMPL, add);
indir->gtFlags |= GTF_IND_NONFAULTING;
indir->gtFlags |= GTF_IND_INVARIANT;

// ((sizeCheck fails || nullCheck fails))) ? (helperCall : handle).
// Add checks and the handle as call arguments, indirect call transformer will handle this.
NewCallArg nullCheckArg = NewCallArg::Primitive(nullCheck);
NewCallArg sizeCheckArg = NewCallArg::Primitive(sizeCheck);
NewCallArg handleForResultArg = NewCallArg::Primitive(handleForResult);
helperCall->gtArgs.PushFront(this, nullCheckArg, sizeCheckArg, handleForResultArg);
result = helperCall;
addExpRuntimeLookupCandidate(helperCall);
}
else
{
GenTreeColon* colonNullCheck = new (this, GT_COLON) GenTreeColon(TYP_I_IMPL, handleForResult, helperCall);
result = gtNewQmarkNode(TYP_I_IMPL, nullCheck, colonNullCheck);
}
slot = gtNewLclvNode(slotLclNum, TYP_I_IMPL);
GenTree* asg = gtNewAssignNode(slot, indir);
GenTreeColon* colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), asg);
GenTreeQmark* qmark = gtNewQmarkNode(TYP_VOID, relop, colon);
impAppendTree(qmark, CHECK_SPILL_NONE, impCurStmtDI);

unsigned tmp = lvaGrabTemp(true DEBUGARG("spilling Runtime Lookup tree"));

impAssignTempGen(tmp, result, CHECK_SPILL_NONE);
return gtNewLclvNode(tmp, TYP_I_IMPL);
return gtNewLclvNode(slotLclNum, TYP_I_IMPL);
}

struct RecursiveGuard
Expand Down Expand Up @@ -14081,12 +14042,6 @@ methodPointerInfo* Compiler::impAllocateMethodPointerInfo(const CORINFO_RESOLVED
return memory;
}

void Compiler::addExpRuntimeLookupCandidate(GenTreeCall* call)
{
setMethodHasExpRuntimeLookup();
call->SetExpRuntimeLookup();
}

//------------------------------------------------------------------------
// impIsClassExact: check if a class handle can only describe values
// of exactly one class.
Expand Down
Loading