[Beignet] [PATCH] GBE: try to avoid bank conflict in register allocator.

Ruiling Song ruiling.song at intel.com
Wed Apr 27 05:50:48 UTC 2016


Signed-off-by: Ruiling Song <ruiling.song at intel.com>
---
 backend/src/backend/gen_reg_allocation.cpp | 31 ++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/backend/src/backend/gen_reg_allocation.cpp b/backend/src/backend/gen_reg_allocation.cpp
index 89c53d4..ccb76a1 100644
--- a/backend/src/backend/gen_reg_allocation.cpp
+++ b/backend/src/backend/gen_reg_allocation.cpp
@@ -35,6 +35,7 @@
 #include <iomanip>
 
 
+#define HALF_REGISTER_FILE_OFFSET (32*64)
 namespace gbe
 {
   /////////////////////////////////////////////////////////////////////////////
@@ -48,8 +49,9 @@ namespace gbe
    */
   struct GenRegInterval {
     INLINE GenRegInterval(ir::Register reg) :
-      reg(reg), minID(INT_MAX), maxID(-INT_MAX) {}
+      reg(reg), minID(INT_MAX), maxID(-INT_MAX), conflictReg(0) {}
     ir::Register reg;     //!< (virtual) register of the interval
+    ir::Register conflictReg;
     int32_t minID, maxID; //!< Starting and ending points
   };
 
@@ -1052,7 +1054,17 @@ namespace gbe
     // and the source is a scalar Dword. If that is the case, the byte register
     // must get 4byte alignment register offset.
     alignment = (alignment + 3) & ~3;
-    while ((grfOffset = ctx.allocate(size, alignment)) == 0) {
+
+    bool direction = true;
+    if (interval.conflictReg != 0) {
+      // try to allocate conflict registers in top/bottom half.
+      if (RA.contains(interval.conflictReg)) {
+        if (RA.find(interval.conflictReg)->second < HALF_REGISTER_FILE_OFFSE) {
+          direction = false;
+        }
+      }
+    }
+    while ((grfOffset = ctx.allocate(size, alignment, direction)) == 0) {
       const bool success = this->expireGRF(interval);
       if (success == false) {
         if (spillAtInterval(interval, size, alignment) == false)
@@ -1104,6 +1116,7 @@ namespace gbe
       for (auto &insn : block.insnList) {
         const uint32_t srcNum = insn.srcNum, dstNum = insn.dstNum;
         insn.ID  = insnID;
+        bool is3SrcOp = insn.opcode == SELECTION_OP_MAD;
         for (uint32_t srcID = 0; srcID < srcNum; ++srcID) {
           const GenRegister &selReg = insn.src(srcID);
           const ir::Register reg = selReg.reg();
@@ -1113,6 +1126,20 @@ namespace gbe
               reg == ir::ocl::groupid1  ||
               reg == ir::ocl::groupid2)
             continue;
+          ir::Register conflictReg = ir::Register(0);
+          if (is3SrcOp) {
+            if (srcID == 1)
+              conflictReg = insn.src(2).reg();
+            else if (srcID == 2)
+              conflictReg = insn.src(1).reg();
+          }
+          // we only let it conflict with one register, and with smaller reg number,
+          // as smaller virtual register usually comes first,
+          // and linear scan allocator allocate from smaller to larger register
+          // so, conflict with larger register number will not make any effect.
+          if (this->intervals[reg].conflictReg == 0 ||
+              this->intervals[reg].conflictReg > conflictReg)
+          this->intervals[reg].conflictReg = conflictReg;
           this->intervals[reg].minID = std::min(this->intervals[reg].minID, insnID);
           this->intervals[reg].maxID = std::max(this->intervals[reg].maxID, insnID);
         }
-- 
2.4.1



More information about the Beignet mailing list