@@ -7534,7 +7534,17 @@ bool GraphColor::regAlloc(
7534
7534
if (reserveSpillReg)
7535
7535
{
7536
7536
failSafeIter = reserveSpillReg;
7537
- gra.determineSpillRegSize (spillRegSize, indrSpillRegSize);
7537
+
7538
+ if (kernel.getOption (vISA_NewFailSafeRA))
7539
+ {
7540
+ spillRegSize = gra.getNumReservedGRFs ();
7541
+ indrSpillRegSize = 0 ;
7542
+ }
7543
+ else
7544
+ {
7545
+ gra.determineSpillRegSize (spillRegSize, indrSpillRegSize);
7546
+ }
7547
+
7538
7548
reserveSpillSize = spillRegSize + indrSpillRegSize;
7539
7549
MUST_BE_TRUE (reserveSpillSize < kernel.getNumCalleeSaveRegs (), " Invalid reserveSpillSize in fail-safe RA!" );
7540
7550
totalGRFRegCount -= reserveSpillSize;
@@ -10908,6 +10918,36 @@ int GlobalRA::coloringRegAlloc()
10908
10918
loopSplit.run ();
10909
10919
}
10910
10920
10921
+ // Very few spills in this iter. Check if we can convert this to fail safe iter.
10922
+ // By converting this iter to fail safe we can save (at least) 1 additional iter
10923
+ // to allocate spilled temps. But converting to fail safe needs extra checks
10924
+ // because no reserved GRF may exist at this point. So push/pop needs to succeed
10925
+ // without additional GRF potentially.
10926
+ if (!kernel.getOption (vISA_Debug) &&
10927
+ iterationNo >= 1 && kernel.getOption (vISA_NewFailSafeRA) && !reserveSpillReg &&
10928
+ coloring.getSpilledLiveRanges ().size () <= BoundedRA::MaxSpillNumVars &&
10929
+ liveAnalysis.getNumSelectedVar () > BoundedRA::LargeProgramSize)
10930
+ {
10931
+ // Stack call always has free GRF so it is safe to convert this iter to fail safe
10932
+ if (builder.usesStack () ||
10933
+ // If LSC has to be used for spill/fill then we need to ensure spillHeader is created
10934
+ (!useLscForNonStackCallSpillFill || builder.hasValidSpillFillHeader ()) ||
10935
+ // If scratch is to be used then max spill offset must be within addressable range
10936
+ ((nextSpillOffset + BoundedRA::getNumPhyVarSlots (kernel)) < SCRATCH_MSG_LIMIT))
10937
+ {
10938
+ // Few ranges are spilled but this was not executed as fail
10939
+ // safe iteration. However, we've the capability of doing
10940
+ // push/pop with new fail safe RA implementation. So for very
10941
+ // few spills, we insert push/pop to free up some GRFs rather
10942
+ // than executing a new RA iteration. When doing so, we mark
10943
+ // this RA iteration as fail safe.
10944
+ reserveSpillReg = true ;
10945
+ coloring.markFailSafeIter (true );
10946
+ // No reserved GRFs
10947
+ setNumReservedGRFsFailSafe (0 );
10948
+ }
10949
+ }
10950
+
10911
10951
// Calculate the spill caused by send to decide if global splitting is required or not
10912
10952
for (auto spilled : coloring.getSpilledLiveRanges ())
10913
10953
{
@@ -11037,6 +11077,10 @@ int GlobalRA::coloringRegAlloc()
11037
11077
11038
11078
if (!reserveSpillReg && !disableSpillCoalecse && builder.useSends ())
11039
11079
{
11080
+ if (builder.getOption (vISA_RATrace))
11081
+ {
11082
+ std::cout << " \t --spill/fill cleanup\n " ;
11083
+ }
11040
11084
CoalesceSpillFills c (kernel, liveAnalysis, coloring, spillGRF, iterationNo, rpe, *this );
11041
11085
c.run ();
11042
11086
}
0 commit comments