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

Hoist the invariants out of multi-level nested loops #68061

Merged
merged 25 commits into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
37 changes: 19 additions & 18 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5935,13 +5935,11 @@ class Compiler
VNSet* m_pHoistedInCurLoop;

public:
// Value numbers of expressions that have been hoisted in parent loops in the loop nest.
VNSet m_hoistedInParentLoops;

// Value numbers of expressions that have been hoisted in the current (or most recent) loop in the nest.
// Previous decisions on loop-invariance of value numbers in the current loop.
VNSet m_curLoopVnInvariantCache;

// Get the VN cache for current loop
VNSet* GetHoistedInCurLoop(Compiler* comp)
{
if (m_pHoistedInCurLoop == nullptr)
Expand All @@ -5951,35 +5949,35 @@ class Compiler
return m_pHoistedInCurLoop;
}

VNSet* ExtractHoistedInCurLoop()
// Return the so far collected VNs in cache for current loop and reset it.
void ResetHoistedInCurLoop()
{
VNSet* res = m_pHoistedInCurLoop;
m_pHoistedInCurLoop = nullptr;
return res;
JITDUMP("Resetting m_pHoistedInCurLoop\n");
}

LoopHoistContext(Compiler* comp)
: m_pHoistedInCurLoop(nullptr)
, m_hoistedInParentLoops(comp->getAllocatorLoopHoist())
, m_curLoopVnInvariantCache(comp->getAllocatorLoopHoist())
: m_pHoistedInCurLoop(nullptr), m_curLoopVnInvariantCache(comp->getAllocatorLoopHoist())
{
}
};

// Do hoisting for loop "lnum" (an index into the optLoopTable), and all loops nested within it.
// Tracks the expressions that have been hoisted by containing loops by temporarily recording their
// value numbers in "m_hoistedInParentLoops". This set is not modified by the call.
// Do hoisting of all loops nested within loop "lnum" (an index into the optLoopTable), followed
// by the loop "lnum" itself.
//
// "m_pHoistedInCurLoop" helps a lot in eliminating duplicate expressions getting hoisted
// and reducing the count of total expressions hoisted out of loop. When calculating the
// profitability, we compare this with number of registers and hence, lower the number of expressions
// getting hoisted, better chances that they will get enregistered and CSE considering them.
//
void optHoistLoopNest(unsigned lnum, LoopHoistContext* hoistCtxt);

// Do hoisting for a particular loop ("lnum" is an index into the optLoopTable.)
// Assumes that expressions have been hoisted in containing loops if their value numbers are in
// "m_hoistedInParentLoops".
//
void optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt);
// Returns the new preheaders created.
void optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt, BasicBlockList* existingPreHeaders);

// Hoist all expressions in "blocks" that are invariant in loop "loopNum" (an index into the optLoopTable)
// outside of that loop. Exempt expressions whose value number is in "m_hoistedInParentLoops"; add VN's of hoisted
// expressions to "hoistInLoop".
// outside of that loop.
void optHoistLoopBlocks(unsigned loopNum, ArrayStack<BasicBlock*>* blocks, LoopHoistContext* hoistContext);

// Return true if the tree looks profitable to hoist out of loop 'lnum'.
Expand Down Expand Up @@ -6362,6 +6360,9 @@ class Compiler
// A loop contains itself.
bool optLoopContains(unsigned l1, unsigned l2) const;

// Returns the lpEntry for given preheader block of a loop
BasicBlock* optLoopEntry(BasicBlock* preHeader);

// Updates the loop table by changing loop "loopInd", whose head is required
// to be "from", to be "to". Also performs this transformation for any
// loop nested in "loopInd" that shares the same head as "loopInd".
Expand Down
Loading