Skip to content

Commit 33971ae

Browse files
admitricigcbot
authored andcommitted
Improve loop sinking heuristic
Improve applicability of loop sinking optimization in cases when the loop is located in a non-kernel function and relax the threshold
1 parent 2c5d498 commit 33971ae

File tree

4 files changed

+65
-15
lines changed

4 files changed

+65
-15
lines changed

IGC/Compiler/CISACodeGen/CodeSinking.cpp

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,11 @@ namespace IGC {
235235
bool Changed = false;
236236
for (auto &L : LI->getLoopsInPreorder())
237237
{
238-
if (IGC_IS_FLAG_ENABLED(ForceLoopSink) || needLoopSink(L))
239-
Changed |= loopSink(L);
238+
LoopSinkMode SinkMode = IGC_IS_FLAG_ENABLED(ForceLoopSink) ? LoopSinkMode::FullSink : LoopSinkMode::NoSink;
239+
if (SinkMode == LoopSinkMode::NoSink)
240+
SinkMode = needLoopSink(L);
241+
if (SinkMode != LoopSinkMode::NoSink)
242+
Changed |= loopSink(L, SinkMode);
240243
}
241244
return Changed;
242245
}
@@ -1261,13 +1264,13 @@ namespace IGC {
12611264
return changed;
12621265
}
12631266

1264-
bool CodeSinking::needLoopSink(Loop *L)
1267+
LoopSinkMode CodeSinking::needLoopSink(Loop *L)
12651268
{
12661269
BasicBlock *Preheader = L->getLoopPreheader();
12671270
if (!Preheader)
1268-
return false;
1271+
return LoopSinkMode::NoSink;
12691272
if (!RPE)
1270-
return false;
1273+
return LoopSinkMode::NoSink;
12711274

12721275
Function *F = Preheader->getParent();
12731276
uint GRFThresholdDelta = IGC_GET_FLAG_VALUE(LoopSinkThresholdDelta);
@@ -1293,13 +1296,58 @@ namespace IGC {
12931296
// Estimate max pressure in the loop
12941297
uint MaxLoopPressure = RPE->getMaxRegCountForLoop(*L, SIMD);
12951298

1296-
// loop sinking is needed if the loop's pressure is higher than number of GRFs by threshold
1297-
// and preheader's potential to reduce the delta is good enough
1298-
return ((MaxLoopPressure > NGRF + GRFThresholdDelta) &&
1299-
(PreheaderDefsSizeInRegs > (MaxLoopPressure - NGRF) * LOOPSINK_PREHEADER_IMPACT_THRESHOLD));
1299+
auto isSinkCriteriaMet = [&](uint MaxLoopPressure)
1300+
{
1301+
// loop sinking is needed if the loop's pressure is higher than number of GRFs by threshold
1302+
// and preheader's potential to reduce the delta is good enough
1303+
return ((MaxLoopPressure > NGRF + GRFThresholdDelta) &&
1304+
(PreheaderDefsSizeInRegs > (MaxLoopPressure - NGRF) * LOOPSINK_PREHEADER_IMPACT_THRESHOLD));
1305+
};
1306+
1307+
// Check if the real regpressure may be higher, because the function is not a kernel
1308+
// and is called not as stack call
1309+
bool MayHaveCallerRegpressure = !isEntryFunc(CTX->getMetaDataUtils(), F) &&
1310+
!F->hasFnAttribute("visaStackCall");
1311+
1312+
// If loop pressure induced in this function only is enough for the criteria, return immediately
1313+
// Otherwise try to add pressure from callsite as the real regpressure may be higher
1314+
if (isSinkCriteriaMet(MaxLoopPressure))
1315+
return MayHaveCallerRegpressure ?
1316+
LoopSinkMode::FullSink :
1317+
LoopSinkMode::SinkWhileRegpressureIsHigh;
1318+
1319+
// Look just for the direct callers while there is no cross-procedure regpressure analysis
1320+
if (MayHaveCallerRegpressure)
1321+
{
1322+
for (llvm::User *U : F->users()) {
1323+
CallInst *CI = llvm::dyn_cast<llvm::CallInst>(U);
1324+
if (CI == nullptr)
1325+
continue;
1326+
1327+
if (CI->getCalledFunction() != F)
1328+
continue;
1329+
1330+
BasicBlock *CallerBB = CI->getParent();
1331+
Function *CallerFunction = CallerBB->getParent();
1332+
1333+
// Augment liveness analysis with blocks from the caller function
1334+
bool RPEHasCallerFunctionInfo = RPE->getOutSet().count(&CallerFunction->getEntryBlock());
1335+
if (!RPEHasCallerFunctionInfo)
1336+
RPE->livenessAnalysis(*CallerFunction);
1337+
1338+
// Get call site regpressure
1339+
auto CallerBBPressureMap = RPE->getPressureMapForBB(*CallerBB, SIMD);
1340+
uint CallSitePressure = RPE->bytesToRegisters(CallerBBPressureMap[CI]);
1341+
1342+
if (isSinkCriteriaMet(MaxLoopPressure + CallSitePressure))
1343+
return LoopSinkMode::FullSink;
1344+
}
1345+
}
1346+
1347+
return LoopSinkMode::NoSink;
13001348
}
13011349

1302-
bool CodeSinking::loopSink(Loop *L)
1350+
bool CodeSinking::loopSink(Loop *L, LoopSinkMode Mode)
13031351
{
13041352
// Sink loop invariants back into the loop body if register
13051353
// pressure can be reduced.
@@ -1380,7 +1428,7 @@ namespace IGC {
13801428
RPE->rerunLivenessAnalysis(*F);
13811429
uint MaxLoopPressure = RPE->getMaxRegCountForLoop(*L, SIMD);
13821430
if (MaxLoopPressure < (NGRF - IGC_GET_FLAG_VALUE(LoopSinkRegpressureMargin))
1383-
&& IGC_IS_FLAG_DISABLED(ForceLoopSink))
1431+
&& (Mode == LoopSinkMode::SinkWhileRegpressureIsHigh))
13841432
{
13851433
if (IGC_IS_FLAG_ENABLED(EnableLoadChainLoopSink) && !LoadChains.empty())
13861434
{

IGC/Compiler/CISACodeGen/CodeSinking.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ See LICENSE.TXT for details.
2222
#include "common/LLVMWarningsPop.hpp"
2323

2424
namespace IGC {
25+
typedef enum { NoSink=0, SinkWhileRegpressureIsHigh, FullSink } LoopSinkMode;
2526

2627
class CodeSinking : public llvm::FunctionPass {
2728
llvm::DominatorTree* DT;
@@ -58,6 +59,7 @@ namespace IGC {
5859
AU.addPreservedID(WIAnalysis::ID);
5960
}
6061
private:
62+
6163
bool treeSink(llvm::Function& F);
6264
bool ProcessBlock(llvm::BasicBlock& blk);
6365
bool SinkInstruction(llvm::Instruction* I,
@@ -140,14 +142,14 @@ namespace IGC {
140142
// try loop sinking in the function if needed
141143
bool loopSink(llvm::Function& F);
142144
// move LI back into loop
143-
bool loopSink(llvm::Loop* LoopWithPressure);
145+
bool loopSink(llvm::Loop* LoopWithPressure, LoopSinkMode Mode);
144146
// pre-condition to sink an instruction into a loop
145147
bool isLoopSinkCandidate(llvm::Instruction* I, llvm::Loop* L, bool AllowLoadSinking);
146148
bool loopSinkInstructions(
147149
llvm::SmallVector<llvm::Instruction*, 64>& SinkCandidates,
148150
llvm::SmallPtrSet<llvm::Instruction*, 32>& LoadChains,
149151
llvm::Loop* L);
150-
bool needLoopSink(llvm::Loop* L);
152+
LoopSinkMode needLoopSink(llvm::Loop* L);
151153

152154
// Move referencing DbgValueInst intrinsics calls after defining instructions
153155
void ProcessDbgValueInst(llvm::BasicBlock& blk);

IGC/Compiler/CISACodeGen/IGCLivenessAnalysis.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class IGCLivenessAnalysis : public llvm::FunctionPass {
161161
releaseMemory();
162162
livenessAnalysis(F);
163163
}
164+
void livenessAnalysis(llvm::Function &F);
164165

165166
private:
166167
void dumpRegPressure(llvm::Function &F, unsigned int SIMD);
@@ -188,7 +189,6 @@ class IGCLivenessAnalysis : public llvm::FunctionPass {
188189
void combineOut(llvm::BasicBlock *BB, ValueSet *Set);
189190
void addToPhiSet(llvm::PHINode *Phi, PhiSet *InPhiSet);
190191
void processBlock(llvm::BasicBlock *BB, ValueSet &Set, PhiSet *PhiSet);
191-
void livenessAnalysis(llvm::Function &F);
192192

193193
virtual bool runOnFunction(llvm::Function &F) override;
194194
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {

IGC/common/igc_flags.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ DECLARE_IGC_REGKEY(DWORD, CodeSinkingMinSize, 32, "Don't sink if the
140140
DECLARE_IGC_REGKEY(DWORD, CodeSinkingLoadSchedulingInstr, 20, "Instructions number to step to schedule loads in advance before the load use to cover latency. 1 to insert it immediately before use", false)
141141
DECLARE_IGC_REGKEY(DWORD, LoopSinkMinSaveUniform, 6, "If loop sink can have save more scalar (uniform) values than this Minimum, do it; otherwise, skip", false)
142142
DECLARE_IGC_REGKEY(DWORD, LoopSinkMinSave, 1, "If loop sink can have save more 32-bit values than this Minimum, do it; otherwise, skip", false)
143-
DECLARE_IGC_REGKEY(DWORD, LoopSinkThresholdDelta, 50, "Do loop sink If the estimated register pressure is higher than this + #avaialble registers", false)
143+
DECLARE_IGC_REGKEY(DWORD, LoopSinkThresholdDelta, 30, "Do loop sink If the estimated register pressure is higher than this + #avaialble registers", false)
144144
DECLARE_IGC_REGKEY(bool, EnableLoopHoistConstant, false, "Enables pass to check for specific loop patterns where variables are constant across all but the last iteration, and hoist them out of the loop.", false)
145145
DECLARE_IGC_REGKEY(bool, DisableCodeHoisting, false, "Setting this to 1/true adds a compiler switch to disable code-hoisting", false)
146146
DECLARE_IGC_REGKEY(bool, EnableDeSSA, true, "Setting this to 0/false adds a compiler switch to disable De-SSA", false)

0 commit comments

Comments
 (0)