@@ -2804,6 +2804,47 @@ void SpillManagerGRF::insertSpillRangeCode(
2804
2804
return ;
2805
2805
}
2806
2806
2807
+ auto IsUniqueDef = [this , 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] != 1 )
2812
+ return false ;
2813
+
2814
+ // check whether variable is live-in to BB
2815
+ if (lvInfo_->isLiveAtEntry (bb, spillDcl->getRegVar ()->getId ()))
2816
+ return false ;
2817
+
2818
+ return true ;
2819
+ };
2820
+
2821
+ auto PseudoKillFound = [spilledInstIter, bb, spillDcl]()
2822
+ {
2823
+ // Search upwards from spilledInstIter to find a pseudo kill.
2824
+ // Return true if one is found, false otherwise.
2825
+ // When a pseudo kill is found, it means read-modify-write is
2826
+ // not needed.
2827
+ auto bbBegin = bb->begin ();
2828
+ if (spilledInstIter == bbBegin)
2829
+ return false ;
2830
+ auto it = spilledInstIter;
2831
+ --it;
2832
+ while (it != bbBegin)
2833
+ {
2834
+ auto inst = *it;
2835
+ // check if adjacent instruction is a pseudo kill
2836
+ if (inst->isPseudoKill ())
2837
+ {
2838
+ if (inst->getDst ()->getTopDcl () == spillDcl)
2839
+ return true ;
2840
+ }
2841
+ else
2842
+ return false ;
2843
+ --it;
2844
+ }
2845
+ return false ;
2846
+ };
2847
+
2807
2848
// subreg offset for new dst that replaces the spilled dst
2808
2849
auto newSubregOff = 0 ;
2809
2850
@@ -2821,7 +2862,9 @@ void SpillManagerGRF::insertSpillRangeCode(
2821
2862
createAndInitMHeader (
2822
2863
(G4_RegVarTransient *) spillRangeDcl->getRegVar ());
2823
2864
2824
- bool needRMW = inst->isPartialWriteForSpill (!bb->isAllLaneActive ());
2865
+ bool needRMW = !PseudoKillFound () &&
2866
+ !IsUniqueDef () &&
2867
+ inst->isPartialWriteForSpill (!bb->isAllLaneActive ());
2825
2868
if (needRMW)
2826
2869
{
2827
2870
sendInSpilledRegVarPortions (
@@ -2856,7 +2899,9 @@ void SpillManagerGRF::insertSpillRangeCode(
2856
2899
2857
2900
// Unaligned region specific handling.
2858
2901
unsigned int spillSendOption = InstOpt_WriteEnable;
2859
- if (shouldPreloadSpillRange (*spilledInstIter, bb)) {
2902
+ if (!PseudoKillFound () &&
2903
+ !IsUniqueDef () &&
2904
+ shouldPreloadSpillRange (*spilledInstIter, bb)) {
2860
2905
2861
2906
// Preload the segment aligned spill range from memory to use
2862
2907
// as an overlay
@@ -3873,6 +3918,31 @@ void SpillManagerGRF::runSpillAnalysis()
3873
3918
}
3874
3919
}
3875
3920
3921
+ void SpillManagerGRF::populateDefsTable ()
3922
+ {
3923
+ for (auto bb : gra.kernel .fg )
3924
+ {
3925
+ for (auto inst : *bb)
3926
+ {
3927
+ if (inst->isPseudoKill ())
3928
+ continue ;
3929
+
3930
+ auto dst = inst->getDst ();
3931
+
3932
+ if (dst && !dst->isNullReg ())
3933
+ {
3934
+ auto topdcl = dst->getTopDcl ();
3935
+
3936
+ if (topdcl)
3937
+ {
3938
+ VarDefs[topdcl] += 1 ;
3939
+ }
3940
+ }
3941
+ }
3942
+ }
3943
+ }
3944
+
3945
+
3876
3946
// Insert spill/fill code for all registers that have not been assigned
3877
3947
// physical registers in the current iteration of the graph coloring
3878
3948
// allocator.
@@ -3913,6 +3983,9 @@ bool SpillManagerGRF::insertSpillFillCode (
3913
3983
return false ;
3914
3984
}
3915
3985
3986
+ // Populate def table as it helps us decide whether read-modify-write is needed
3987
+ populateDefsTable ();
3988
+
3916
3989
// Insert spill/fill code for all basic blocks.
3917
3990
3918
3991
FlowGraph& fg = kernel->fg ;
@@ -3921,6 +3994,7 @@ bool SpillManagerGRF::insertSpillFillCode (
3921
3994
{
3922
3995
bbId_ = (*it)->getId ();
3923
3996
INST_LIST::iterator jt = (*it)->begin ();
3997
+ std::list<INST_LIST_ITER> pseudoKills;
3924
3998
3925
3999
while (jt != (*it)->end ()) {
3926
4000
INST_LIST::iterator kt = jt;
@@ -3950,7 +4024,11 @@ bool SpillManagerGRF::insertSpillFillCode (
3950
4024
{
3951
4025
if (inst->isPseudoKill ())
3952
4026
{
3953
- (*it)->erase (jt);
4027
+ // This pseudo kill corresponds to a spilled variable, so
4028
+ // it can be removed. But it is preserved till spill code
4029
+ // is inserted for the variable as it provides a hint to
4030
+ // spill insertion that read-modify-write is not needed.
4031
+ pseudoKills.push_back (jt);
3954
4032
jt = kt;
3955
4033
continue ;
3956
4034
}
@@ -4003,6 +4081,11 @@ bool SpillManagerGRF::insertSpillFillCode (
4003
4081
4004
4082
jt = kt;
4005
4083
}
4084
+
4085
+ for (auto killIt : pseudoKills)
4086
+ {
4087
+ (*it)->erase (killIt);
4088
+ }
4006
4089
}
4007
4090
4008
4091
bbId_ = UINT_MAX;
0 commit comments