Skip to content

Commit 83442ca

Browse files
pratikasharigcbot
authored andcommitted
Bug fixes and improvements to variable splitting
around loops. Highlights of change: * Use M0 emask without WriteEnable for copy in pre-header/loop exit whenever possible. * Modified Register Pressure Estimator pass to not consider spilled variables. This is used to make splitting heuristic more accurate. * Modified variable splitting cost heuristic based on experiments. * Simplify removal of instruction inserted by split pass when split dcl spills in later RA iteration. * Copy src modifier to new operand generated by split pass.
1 parent 261c0f6 commit 83442ca

File tree

6 files changed

+217
-53
lines changed

6 files changed

+217
-53
lines changed

visa/GraphColor.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10739,7 +10739,11 @@ int GlobalRA::coloringRegAlloc()
1073910739
if (iterationNo == 0 && !fastCompile &&
1074010740
kernel.getOption(vISA_DoSplitOnSpill))
1074110741
{
10742-
LoopVarSplit loopSplit(kernel, &coloring, &rpe);
10742+
if (builder.getOption(vISA_RATrace))
10743+
{
10744+
std::cout << "\t--var split around loop\n";
10745+
}
10746+
LoopVarSplit loopSplit(kernel, &coloring, &liveAnalysis);
1074310747
kernel.fg.getLoops().computePreheaders();
1074410748
loopSplit.run();
1074510749
}

visa/RPE.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@ SPDX-License-Identifier: MIT
1414

1515
namespace vISA
1616
{
17-
RPE::RPE(const GlobalRA& g, const LivenessAnalysis* l) : m(1024), gra(g), liveAnalysis(l), live(l->getNumSelectedVar()),
17+
RPE::RPE(const GlobalRA& g, const LivenessAnalysis* l, DECLARE_LIST* spills) : m(1024), gra(g), liveAnalysis(l), live(l->getNumSelectedVar()),
1818
vars(l->vars)
1919
{
2020
options = g.kernel.getOptions();
21+
if (spills)
22+
{
23+
std::for_each(spills->begin(), spills->end(),
24+
[&](const G4_Declare* dcl) { spilledVars.insert(dcl); });
25+
}
2126
}
2227

2328
void RPE::run()
@@ -139,6 +144,8 @@ namespace vISA
139144
{
140145
auto range = vars[i];
141146
G4_Declare* rootDcl = range->getDeclare()->getRootDeclare();
147+
if (isSpilled(rootDcl))
148+
continue;
142149
if (rootDcl->getNumElems() > 1)
143150
{
144151
regPressure += rootDcl->getNumRows();
@@ -166,18 +173,21 @@ namespace vISA
166173
auto change = before^after;
167174
if (change)
168175
{
176+
auto dcl = vars[id]->getDeclare();
177+
if (isSpilled(dcl))
178+
return;
169179
// For <1 GRF variable we have to take alignment into consideration as well when computing register pressure.
170180
// For now we double each <1GRF variable's size if its alignment also exceeds its size.
171181
// Alternative is to simply take the alignment as the size, but it might cause performance regressions
172182
// due to being too conservative (i.e., a GRF-aligned variable may share physical GRF with several other
173-
auto dclSize = vars[id]->getDeclare()->getByteSize();
174-
if (dclSize < gra.builder.getGRFSize() && dclSize < static_cast<uint32_t>(vars[id]->getDeclare()->getSubRegAlign()) * 2)
183+
auto dclSize = dcl->getByteSize();
184+
if (dclSize < gra.builder.getGRFSize() && dclSize < static_cast<uint32_t>(dcl->getSubRegAlign()) * 2)
175185
{
176186
dclSize *= 2;
177187
}
178188

179189
double delta = dclSize < gra.builder.getGRFSize() ?
180-
dclSize / (double) gra.builder.getGRFSize() : (double) vars[id]->getDeclare()->getNumRows();
190+
dclSize / (double) gra.builder.getGRFSize() : (double) dcl->getNumRows();
181191
if (before & change)
182192
{
183193
if (regPressure < delta)

visa/RPE.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace vISA
1818
class RPE
1919
{
2020
public:
21-
RPE(const GlobalRA&, const LivenessAnalysis*);
21+
RPE(const GlobalRA&, const LivenessAnalysis*, DECLARE_LIST* spills = nullptr);
2222

2323
~RPE()
2424
{
@@ -56,10 +56,24 @@ namespace vISA
5656
const Options* options;
5757
SparseBitSet live;
5858
const std::vector<G4_RegVar*>& vars;
59+
// Variables part of spilledVars set dont contribute to
60+
// program register pressure. This is useful to model
61+
// register pressure immediately after coloring (spill
62+
// iteration).
63+
std::unordered_set<const G4_Declare*> spilledVars;
5964

6065
void regPressureBBExit(G4_BB*);
6166
void updateRegisterPressure(unsigned int, unsigned int, unsigned int);
6267
void updateLiveness(SparseBitSet&, uint32_t, bool);
68+
69+
70+
bool isSpilled(const G4_Declare* dcl) const
71+
{
72+
auto it = spilledVars.find(dcl);
73+
if (it == spilledVars.end())
74+
return false;
75+
return true;
76+
}
6377
};
6478
}
6579
#endif

visa/SpillManagerGMRF.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3268,14 +3268,6 @@ void SpillManagerGRF::insertSpillRangeCode(
32683268
return;
32693269
}
32703270

3271-
if (builder_->getOption(vISA_DoSplitOnSpill))
3272-
{
3273-
// if spilled inst is copy of original variable to it's split variable
3274-
// then simply remove the instruction.
3275-
if (LoopVarSplit::removeFromPreheader(&gra, spillDcl, bb, spilledInstIter))
3276-
return;
3277-
}
3278-
32793271
auto checkRMWNeeded = [this, spilledRegion]()
32803272
{
32813273
return noRMWNeeded.find(spilledRegion) == noRMWNeeded.end();
@@ -3553,22 +3545,6 @@ void SpillManagerGRF::insertFillGRFRangeCode(
35533545
G4_INST* fillSendInst = nullptr;
35543546
auto spillDcl = filledRegion->getTopDcl()->getRootDeclare();
35553547

3556-
if (builder_->getOption(vISA_DoSplitOnSpill))
3557-
{
3558-
// if spilled inst is copy of split variable to it's spilled variable
3559-
// then simply remove the instruction.
3560-
//
3561-
// if inst is:
3562-
// (W) mov (8|M0) SPLIT1 V10
3563-
//
3564-
// and SPLIT1 is marked as spilled then don't insert spill code for it.
3565-
// V10 is guaranteed to be spilled already so there is no point spilling
3566-
// SPLIT1. we simply remove above instruction and any fill emitted to load
3567-
// V10 and return.
3568-
if (LoopVarSplit::removeFromLoopExit(&gra, spillDcl, bb, filledInstIter))
3569-
return;
3570-
}
3571-
35723548
auto sisIt = scalarImmSpill.find(spillDcl);
35733549
if (sisIt != scalarImmSpill.end())
35743550
{
@@ -4541,6 +4517,20 @@ bool SpillManagerGRF::insertSpillFillCode(
45414517
return false;
45424518
}
45434519

4520+
if (kernel->getOption(vISA_DoSplitOnSpill))
4521+
{
4522+
// remove all spilled splits
4523+
for (const LiveRange* lr : *spilledLRs_)
4524+
{
4525+
auto dcl = lr->getDcl();
4526+
// check whether spilled variable is one of split vars
4527+
if (gra.splitResults.find(dcl) == gra.splitResults.end())
4528+
continue;
4529+
4530+
LoopVarSplit::removeAllSplitInsts(&gra, dcl);
4531+
}
4532+
}
4533+
45444534
// Insert spill/fill code for all basic blocks.
45454535
updateRMWNeeded();
45464536
FlowGraph& fg = kernel->fg;

0 commit comments

Comments
 (0)