@@ -2804,9 +2804,103 @@ void SpillManagerGRF::insertSpillRangeCode(
2804
2804
return ;
2805
2805
}
2806
2806
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
+
2807
2899
// subreg offset for new dst that replaces the spilled dst
2808
2900
auto newSubregOff = 0 ;
2809
2901
2902
+ auto pseudoKillFound = PseudoKillFound ();
2903
+ auto isUniqueDef = IsUniqueDef ();
2810
2904
if (inst->mayExceedTwoGRF ())
2811
2905
{
2812
2906
// Handle send instructions (special treatment)
@@ -2821,7 +2915,9 @@ void SpillManagerGRF::insertSpillRangeCode(
2821
2915
createAndInitMHeader (
2822
2916
(G4_RegVarTransient *) spillRangeDcl->getRegVar ());
2823
2917
2824
- bool needRMW = inst->isPartialWriteForSpill (!bb->isAllLaneActive ());
2918
+ bool needRMW = !pseudoKillFound &&
2919
+ !isUniqueDef &&
2920
+ inst->isPartialWriteForSpill (!bb->isAllLaneActive ());
2825
2921
if (needRMW)
2826
2922
{
2827
2923
sendInSpilledRegVarPortions (
@@ -2856,7 +2952,9 @@ void SpillManagerGRF::insertSpillRangeCode(
2856
2952
2857
2953
// Unaligned region specific handling.
2858
2954
unsigned int spillSendOption = InstOpt_WriteEnable;
2859
- if (shouldPreloadSpillRange (*spilledInstIter, bb)) {
2955
+ if (!pseudoKillFound &&
2956
+ !isUniqueDef &&
2957
+ shouldPreloadSpillRange (*spilledInstIter, bb)) {
2860
2958
2861
2959
// Preload the segment aligned spill range from memory to use
2862
2960
// as an overlay
@@ -2938,7 +3036,13 @@ void SpillManagerGRF::insertSpillRangeCode(
2938
3036
newSubregOff = spilledRegion->getSubRegOff ();
2939
3037
if (!bb->isAllLaneActive ())
2940
3038
{
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
+ }
2942
3046
}
2943
3047
}
2944
3048
@@ -3873,6 +3977,33 @@ void SpillManagerGRF::runSpillAnalysis()
3873
3977
}
3874
3978
}
3875
3979
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
+
3876
4007
// Insert spill/fill code for all registers that have not been assigned
3877
4008
// physical registers in the current iteration of the graph coloring
3878
4009
// allocator.
@@ -3913,6 +4044,9 @@ bool SpillManagerGRF::insertSpillFillCode (
3913
4044
return false ;
3914
4045
}
3915
4046
4047
+ // Populate def table as it helps us decide whether read-modify-write is needed
4048
+ populateDefsTable ();
4049
+
3916
4050
// Insert spill/fill code for all basic blocks.
3917
4051
3918
4052
FlowGraph& fg = kernel->fg ;
@@ -3921,6 +4055,7 @@ bool SpillManagerGRF::insertSpillFillCode (
3921
4055
{
3922
4056
bbId_ = (*it)->getId ();
3923
4057
INST_LIST::iterator jt = (*it)->begin ();
4058
+ std::list<INST_LIST_ITER> pseudoKills;
3924
4059
3925
4060
while (jt != (*it)->end ()) {
3926
4061
INST_LIST::iterator kt = jt;
@@ -3950,7 +4085,11 @@ bool SpillManagerGRF::insertSpillFillCode (
3950
4085
{
3951
4086
if (inst->isPseudoKill ())
3952
4087
{
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);
3954
4093
jt = kt;
3955
4094
continue ;
3956
4095
}
@@ -4003,6 +4142,11 @@ bool SpillManagerGRF::insertSpillFillCode (
4003
4142
4004
4143
jt = kt;
4005
4144
}
4145
+
4146
+ for (auto killIt : pseudoKills)
4147
+ {
4148
+ (*it)->erase (killIt);
4149
+ }
4006
4150
}
4007
4151
4008
4152
bbId_ = UINT_MAX;
0 commit comments