Skip to content

Commit 7f78aef

Browse files
pratikasharigcbot
authored andcommitted
Decide emission of pre-fill for spills based on presence of
corresponding pseudo kill or def count of spill.
1 parent adaa145 commit 7f78aef

File tree

2 files changed

+155
-4
lines changed

2 files changed

+155
-4
lines changed

visa/SpillManagerGMRF.cpp

Lines changed: 148 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,9 +2804,103 @@ void SpillManagerGRF::insertSpillRangeCode(
28042804
return;
28052805
}
28062806

2807+
auto IsUniqueDef = [this, inst, bb, spillDcl]()
2808+
{
2809+
// return true if spilled variable has a single def
2810+
// and it is not live-in to current bb (eg, loop, sub).
2811+
if (VarDefs[spillDcl].size() != 1)
2812+
{
2813+
// check whether multiple defs exist in program for current
2814+
// lb, rb
2815+
auto lb = inst->getDst()->getLeftBound();
2816+
auto rb = inst->getDst()->getRightBound();
2817+
unsigned int count = 0;
2818+
auto& defs = VarDefs[spillDcl];
2819+
for (auto& def : defs)
2820+
{
2821+
if (def.first <= rb &&
2822+
def.second >= lb)
2823+
++count;
2824+
}
2825+
2826+
if(count > 1)
2827+
return false;
2828+
}
2829+
2830+
// check whether variable is live-in to BB
2831+
if (lvInfo_->isLiveAtEntry(bb, spillDcl->getRegVar()->getId()))
2832+
return false;
2833+
2834+
return true;
2835+
};
2836+
2837+
auto PseudoKillFound = [spilledInstIter, bb, spillDcl]()
2838+
{
2839+
// Search upwards from spilledInstIter to find a pseudo kill.
2840+
// Return true if one is found, false otherwise.
2841+
// When a pseudo kill is found, it means read-modify-write is
2842+
// not needed.
2843+
auto bbBegin = bb->begin();
2844+
if (spilledInstIter == bbBegin)
2845+
return false;
2846+
auto it = spilledInstIter;
2847+
--it;
2848+
while (it != bbBegin)
2849+
{
2850+
auto inst = *it;
2851+
// check if adjacent instruction is a pseudo kill
2852+
if (inst->isPseudoKill())
2853+
{
2854+
if (inst->getDst()->getTopDcl() == spillDcl)
2855+
return true;
2856+
}
2857+
else
2858+
{
2859+
auto dst = inst->getDst();
2860+
if (!dst)
2861+
return false;
2862+
2863+
// recognize pattern where V10 is spilled:
2864+
// pseudo_kill V10
2865+
// op (8) V10(0,0) ...
2866+
// op (8) V10(2,0) ... <-- Current inst
2867+
//
2868+
// becomes:
2869+
// pseudo_kill V10
2870+
// op (8) SP_V10(0,0) ... [2]
2871+
// intrinsic_spill (8) ... SP_V10 ... [1]
2872+
// op (8) V10(2,0) <-- Current inst
2873+
if (inst->isSpillIntrinsic() &&
2874+
inst->asSpillIntrinsic()->getPayload() &&
2875+
inst->asSpillIntrinsic()->getPayload()->getTopDcl()->getRegVar()->isRegVarTransient())
2876+
{
2877+
auto spillBase = ((G4_RegVarTransient*)inst->asSpillIntrinsic()->getPayload()->getTopDcl()->getRegVar())->getAbsBaseRegVar();
2878+
if (spillBase->getDeclare()->getRootDeclare() != spillDcl)
2879+
return false;
2880+
// Fall through for instruction [1] above
2881+
}
2882+
else if (dst &&
2883+
dst->getTopDcl() &&
2884+
dst->getTopDcl()->getRegVar()->isRegVarTransient())
2885+
{
2886+
auto spillBase = ((G4_RegVarTransient*)dst->getTopDcl()->getRegVar())->getAbsBaseRegVar();
2887+
if (spillBase->getDeclare()->getRootDeclare() != spillDcl)
2888+
return false;
2889+
// Fall through for instruction [2] above
2890+
}
2891+
else if(inst->getDst()->getTopDcl() != spillDcl)
2892+
return false;
2893+
}
2894+
--it;
2895+
}
2896+
return false;
2897+
};
2898+
28072899
//subreg offset for new dst that replaces the spilled dst
28082900
auto newSubregOff = 0;
28092901

2902+
auto pseudoKillFound = PseudoKillFound();
2903+
auto isUniqueDef = IsUniqueDef();
28102904
if (inst->mayExceedTwoGRF())
28112905
{
28122906
// Handle send instructions (special treatment)
@@ -2821,7 +2915,9 @@ void SpillManagerGRF::insertSpillRangeCode(
28212915
createAndInitMHeader (
28222916
(G4_RegVarTransient *) spillRangeDcl->getRegVar());
28232917

2824-
bool needRMW = inst->isPartialWriteForSpill(!bb->isAllLaneActive());
2918+
bool needRMW = !pseudoKillFound &&
2919+
!isUniqueDef &&
2920+
inst->isPartialWriteForSpill(!bb->isAllLaneActive());
28252921
if (needRMW)
28262922
{
28272923
sendInSpilledRegVarPortions(
@@ -2856,7 +2952,9 @@ void SpillManagerGRF::insertSpillRangeCode(
28562952

28572953
// Unaligned region specific handling.
28582954
unsigned int spillSendOption = InstOpt_WriteEnable;
2859-
if (shouldPreloadSpillRange(*spilledInstIter, bb)) {
2955+
if (!pseudoKillFound &&
2956+
!isUniqueDef &&
2957+
shouldPreloadSpillRange(*spilledInstIter, bb)) {
28602958

28612959
// Preload the segment aligned spill range from memory to use
28622960
// as an overlay
@@ -2938,7 +3036,13 @@ void SpillManagerGRF::insertSpillRangeCode(
29383036
newSubregOff = spilledRegion->getSubRegOff();
29393037
if (!bb->isAllLaneActive())
29403038
{
2941-
spillSendOption = (*spilledInstIter)->getMaskOption();
3039+
if (!pseudoKillFound &&
3040+
!isUniqueDef)
3041+
{
3042+
// If either pseudo kill is found or if the range is a unique def,
3043+
// use WriteEnable option in spill.
3044+
spillSendOption = (*spilledInstIter)->getMaskOption();
3045+
}
29423046
}
29433047
}
29443048

@@ -3873,6 +3977,33 @@ void SpillManagerGRF::runSpillAnalysis()
38733977
}
38743978
}
38753979

3980+
void SpillManagerGRF::populateDefsTable()
3981+
{
3982+
for (auto bb : gra.kernel.fg)
3983+
{
3984+
for (auto inst : *bb)
3985+
{
3986+
if (inst->isPseudoKill())
3987+
continue;
3988+
3989+
auto dst = inst->getDst();
3990+
3991+
if (dst && !dst->isNullReg())
3992+
{
3993+
auto topdcl = dst->getTopDcl();
3994+
3995+
if (topdcl)
3996+
{
3997+
auto lb = dst->getLeftBound();
3998+
auto rb = dst->getRightBound();
3999+
VarDefs[topdcl].push_back(std::make_pair(lb, rb));
4000+
}
4001+
}
4002+
}
4003+
}
4004+
}
4005+
4006+
38764007
// Insert spill/fill code for all registers that have not been assigned
38774008
// physical registers in the current iteration of the graph coloring
38784009
// allocator.
@@ -3913,6 +4044,9 @@ bool SpillManagerGRF::insertSpillFillCode (
39134044
return false;
39144045
}
39154046

4047+
// Populate def table as it helps us decide whether read-modify-write is needed
4048+
populateDefsTable();
4049+
39164050
// Insert spill/fill code for all basic blocks.
39174051

39184052
FlowGraph& fg = kernel->fg;
@@ -3921,6 +4055,7 @@ bool SpillManagerGRF::insertSpillFillCode (
39214055
{
39224056
bbId_ = (*it)->getId();
39234057
INST_LIST::iterator jt = (*it)->begin();
4058+
std::list<INST_LIST_ITER> pseudoKills;
39244059

39254060
while (jt != (*it)->end()) {
39264061
INST_LIST::iterator kt = jt;
@@ -3950,7 +4085,11 @@ bool SpillManagerGRF::insertSpillFillCode (
39504085
{
39514086
if (inst->isPseudoKill())
39524087
{
3953-
(*it)->erase(jt);
4088+
// This pseudo kill corresponds to a spilled variable, so
4089+
// it can be removed. But it is preserved till spill code
4090+
// is inserted for the variable as it provides a hint to
4091+
// spill insertion that read-modify-write is not needed.
4092+
pseudoKills.push_back(jt);
39544093
jt = kt;
39554094
continue;
39564095
}
@@ -4003,6 +4142,11 @@ bool SpillManagerGRF::insertSpillFillCode (
40034142

40044143
jt = kt;
40054144
}
4145+
4146+
for(auto killIt : pseudoKills)
4147+
{
4148+
(*it)->erase(killIt);
4149+
}
40064150
}
40074151

40084152
bbId_ = UINT_MAX;

visa/SpillManagerGMRF.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,8 @@ class SpillManagerGRF
593593
}
594594
}
595595

596+
void populateDefsTable();
597+
596598
// Data
597599
GlobalRA& gra;
598600
IR_Builder * builder_;
@@ -623,6 +625,11 @@ class SpillManagerGRF
623625
const Interference * spillIntf_;
624626
vISA::Mem_Manager mem_;
625627

628+
// Dcl -> vector[<lb, rb>]
629+
// this data structure helps check whether a definition or part of it
630+
// has multiple definitions in the program.
631+
std::unordered_map<G4_Declare*, std::vector<std::pair<unsigned int, unsigned int>>> VarDefs;
632+
626633
// The number of GRF spill.
627634
unsigned numGRFSpill = 0;
628635

0 commit comments

Comments
 (0)