[LSRA TP]: Skip free heuristics if no free registers are available (#83569)
authorKunal Pathak <Kunal.Pathak@microsoft.com>
Fri, 24 Mar 2023 20:44:13 +0000 (13:44 -0700)
committerGitHub <noreply@github.com>
Fri, 24 Mar 2023 20:44:13 +0000 (13:44 -0700)
* Add busy regs selection in different file to improve Release TP

* jit format

* Remove all the ifdef except in Release

* Skip the freeCandidates checks from free heuristics in Release mode

* Simplify things

src/coreclr/jit/lsra.cpp
src/coreclr/jit/lsra.h
src/coreclr/jit/lsra_score.h

index d8520dd..0980342 100644 (file)
@@ -8746,8 +8746,8 @@ const char* LinearScan::getStatName(unsigned stat)
 #include "lsra_stats.h"
 #undef LSRA_STAT_DEF
 #define REG_SEL_DEF(stat, value, shortname, orderSeqId) #stat,
+#define BUSY_REG_SEL_DEF(stat, value, shortname, orderSeqId) REG_SEL_DEF(stat, value, shortname, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
     };
 
     assert(stat < ArrLen(lsraStatNames));
@@ -8761,8 +8761,8 @@ LsraStat LinearScan::getLsraStatFromScore(RegisterScore registerScore)
 #define REG_SEL_DEF(stat, value, shortname, orderSeqId)                                                                \
     case RegisterScore::stat:                                                                                          \
         return LsraStat::STAT_##stat;
+#define BUSY_REG_SEL_DEF(stat, value, shortname, orderSeqId) REG_SEL_DEF(stat, value, shortname, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
         default:
             return LsraStat::STAT_FREE;
     }
@@ -9064,8 +9064,8 @@ const char* LinearScan::getScoreName(RegisterScore score)
 #define REG_SEL_DEF(stat, value, shortname, orderSeqId)                                                                \
     case stat:                                                                                                         \
         return shortname;
+#define BUSY_REG_SEL_DEF(stat, value, shortname, orderSeqId) REG_SEL_DEF(stat, value, shortname, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
         default:
             return "  -  ";
     }
@@ -11060,8 +11060,8 @@ LinearScan::RegisterSelection::RegisterSelection(LinearScan* linearScan)
 
 #define REG_SEL_DEF(stat, value, shortname, orderSeqId)                                                                \
     mappingTable->Set(stat, &LinearScan::RegisterSelection::try_##stat);
+#define BUSY_REG_SEL_DEF(stat, value, shortname, orderSeqId) REG_SEL_DEF(stat, value, shortname, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
 
     LPCWSTR ordering = JitConfig.JitLsraOrdering();
     if (ordering == nullptr)
@@ -11080,8 +11080,8 @@ LinearScan::RegisterSelection::RegisterSelection(LinearScan* linearScan)
     case orderSeqId:                                                                                                   \
         RegSelectionOrder[orderId] = enum_name;                                                                        \
         break;
+#define BUSY_REG_SEL_DEF(enum_name, value, shortname, orderSeqId) REG_SEL_DEF(enum_name, value, shortname, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
             default:
                 assert(!"Invalid lsraOrdering value.");
         }
@@ -12070,13 +12070,24 @@ regMaskTP LinearScan::RegisterSelection::select(Interval*    currentInterval,
         }
     }
 #else // RELEASE
-// In release, just invoke the default order
 
+    // In release, just invoke the default order
+    if (freeCandidates != RBM_NONE)
+    {
 #define REG_SEL_DEF(stat, value, shortname, orderSeqId)                                                                \
     try_##stat();                                                                                                      \
     IF_FOUND_GOTO_DONE
+
+#define BUSY_REG_SEL_DEF(stat, value, shortname, orderSeqId)
+#include "lsra_score.h"
+    }
+
+#define REG_SEL_DEF(stat, value, shortname, orderSeqId)
+#define BUSY_REG_SEL_DEF(stat, value, shortname, orderSeqId)                                                           \
+    try_##stat();                                                                                                      \
+    IF_FOUND_GOTO_DONE
 #include "lsra_score.h"
-#undef REG_SEL_DEF
+
 #endif // DEBUG
 #undef IF_FOUND_GOTO_DONE
 
index 9170ec7..1c04f60 100644 (file)
@@ -368,8 +368,8 @@ enum LsraStat
 #include "lsra_stats.h"
 #undef LSRA_STAT_DEF
 #define REG_SEL_DEF(enum_name, value, short_str, orderSeqId) STAT_##enum_name,
+#define BUSY_REG_SEL_DEF(enum_name, value, short_str, orderSeqId) REG_SEL_DEF(enum_name, value, short_str, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
     COUNT
 };
 #endif // TRACK_LSRA_STATS
@@ -395,8 +395,8 @@ struct LsraBlockInfo
 enum RegisterScore
 {
 #define REG_SEL_DEF(enum_name, value, short_str, orderSeqId) enum_name = value,
+#define BUSY_REG_SEL_DEF(enum_name, value, short_str, orderSeqId) REG_SEL_DEF(enum_name, value, short_str, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
     NONE = 0
 };
 
@@ -1313,8 +1313,8 @@ private:
         FORCEINLINE void reset(Interval* interval, RefPosition* refPosition);
 
 #define REG_SEL_DEF(stat, value, shortname, orderSeqId) FORCEINLINE void try_##stat();
+#define BUSY_REG_SEL_DEF(stat, value, shortname, orderSeqId) REG_SEL_DEF(stat, value, shortname, orderSeqId)
 #include "lsra_score.h"
-#undef REG_SEL_DEF
     };
 
     RegisterSelection* regSelector;
index 9b3b182..9a68193 100644 (file)
@@ -9,6 +9,9 @@
 #ifndef REG_SEL_DEF
 #error  Must define REG_SEL_DEF macro before including this file
 #endif
+#ifndef BUSY_REG_SEL_DEF
+#error  Must define BUSY_REG_SEL_DEF macro before including this file
+#endif
 
 // Register selection stats
 // Each register will receive a score which takes into account the scoring criteria below.
@@ -35,12 +38,13 @@ REG_SEL_DEF(BEST_FIT,           0x00040,    "BSFIT",        'K')   // The availa
 REG_SEL_DEF(IS_PREV_REG,        0x00020,    "PRVRG",        'L')   // This register was previously assigned to the interval.
 REG_SEL_DEF(REG_ORDER,          0x00010,    "ORDER",        'M')   // Tie-breaker
 
-// These are the original criteria for comparing registers that are in use.
-REG_SEL_DEF(SPILL_COST,         0x00008,    "SPILL",        'N')   // It has the lowest cost of all the candidates.
-REG_SEL_DEF(FAR_NEXT_REF,       0x00004,    "FNREF",        'O')   // It has a farther next reference than the best candidate thus far.
-REG_SEL_DEF(PREV_REG_OPT,       0x00002,    "PRGOP",        'P')   // The previous RefPosition of its current assigned interval is RegOptional.
+BUSY_REG_SEL_DEF(SPILL_COST,         0x00008,    "SPILL",        'N')   // It has the lowest cost of all the candidates.
+BUSY_REG_SEL_DEF(FAR_NEXT_REF,       0x00004,    "FNREF",        'O')   // It has a farther next reference than the best candidate thus far.
+BUSY_REG_SEL_DEF(PREV_REG_OPT,       0x00002,    "PRGOP",        'P')   // The previous RefPosition of its current assigned interval is RegOptional.
 
 // TODO-CQ: Consider using REG_ORDER as a tie-breaker even for busy registers.
-REG_SEL_DEF(REG_NUM,            0x00001,    "RGNUM",        'Q')   // It has a lower register number.
+BUSY_REG_SEL_DEF(REG_NUM,            0x00001,    "RGNUM",        'Q')   // It has a lower register number.
 
 // clang-format on
+#undef BUSY_REG_SEL_DEF
+#undef REG_SEL_DEF