GBE: reserve flag0.0 for large basic block.
authorZhigang Gong <zhigang.gong@gmail.com>
Fri, 25 Apr 2014 13:52:34 +0000 (21:52 +0800)
committerZhigang Gong <zhigang.gong@intel.com>
Tue, 29 Apr 2014 04:39:27 +0000 (12:39 +0800)
As in large basic block, there are more than one IF instruction which
need to use the flag0.0. We have to reserve flag 0.0 to those IF
instructions.

Signed-off-by: Zhigang Gong <zhigang.gong@gmail.com>
Reviewed-by: "Yang, Rong R" <rong.r.yang@intel.com>
backend/src/backend/gen_insn_selection.cpp
backend/src/backend/gen_insn_selection.hpp
backend/src/backend/gen_reg_allocation.cpp

index ab885f2..88ec408 100644 (file)
@@ -196,7 +196,7 @@ namespace gbe
   // SelectionBlock
   ///////////////////////////////////////////////////////////////////////////
 
-  SelectionBlock::SelectionBlock(const ir::BasicBlock *bb) : bb(bb), endifLabel( (ir::LabelIndex) 0){}
+  SelectionBlock::SelectionBlock(const ir::BasicBlock *bb) : bb(bb), isLargeBlock(false), endifLabel( (ir::LabelIndex) 0){}
 
   void SelectionBlock::append(ir::Register reg) { tmp.push_back(reg); }
 
@@ -1501,6 +1501,7 @@ namespace gbe
             this->curr.predicate = GEN_PREDICATE_NORMAL;
             this->IF(GenRegister::immd(0), jip, jip);
           this->pop();
+          this->block->isLargeBlock = true;
         }
 
         if (needEndif) {
index 018114d..150feb5 100644 (file)
@@ -190,6 +190,7 @@ namespace gbe
     void append(SelectionInstruction *insn);
     /*! Append a new selection instruction at the beginning of the block */
     void prepend(SelectionInstruction *insn);
+    bool isLargeBlock;
     ir::LabelIndex endifLabel;
     int endifOffset;
     bool hasBarrier;
index fd0c1cf..5098f34 100644 (file)
@@ -160,6 +160,7 @@ namespace gbe
     vector<GenRegInterval> intervals;
     /*! All the boolean register intervals on the corresponding BB*/
     typedef map<ir::Register, GenRegInterval> RegIntervalMap;
+    set<SelectionBlock *> flag0ReservedBlocks;
     map<SelectionBlock *, RegIntervalMap *> boolIntervalsMap;
     /*! Intervals sorting based on starting point positions */
     vector<GenRegInterval*> starting;
@@ -409,7 +410,7 @@ namespace gbe
       map<ir::Register, uint32_t> allocatedFlags;
       map<const GenRegInterval*, uint32_t> allocatedFlagIntervals;
 
-      const uint32_t flagNum = 3;
+      const uint32_t flagNum = flag0ReservedBlocks.contains(&block) ?  2 : 3;
       uint32_t freeFlags[] = {2, 3, 0};
       uint32_t freeNum = flagNum;
       if (boolIntervalsMap.find(&block) == boolIntervalsMap.end())
@@ -923,6 +924,8 @@ namespace gbe
       // Update the intervals of each used register. Note that we do not
       // register allocate R0, so we skip all sub-registers in r0
       RegIntervalMap *boolsMap = new RegIntervalMap;
+      if (block.isLargeBlock)
+        flag0ReservedBlocks.insert(&block);
       for (auto &insn : block.insnList) {
         const uint32_t srcNum = insn.srcNum, dstNum = insn.dstNum;
         insn.ID  = insnID;
@@ -977,7 +980,17 @@ namespace gbe
             // is out-of the if/endif region, so we have to borrow the f0
             // to get correct bits for all channels.
             boolsMap->find(reg)->second.minID = 0;
+            if (flag0ReservedBlocks.contains(&block))
+              flag0ReservedBlocks.erase(&block);
           }
+        } else {
+          // Make sure that instruction selection stage didn't use physiacl flags incorrectly.
+          GBE_ASSERT ((insn.opcode == SEL_OP_LABEL ||
+                       insn.opcode == SEL_OP_IF ||
+                       insn.opcode == SEL_OP_JMPI ||
+                       insn.state.predicate == GEN_PREDICATE_NONE ||
+                       (block.hasBarrier && insn.opcode == SEL_OP_MOV) ||
+                       (insn.state.flag == 0 && insn.state.subFlag == 1)));
         }
         lastID = insnID;
         insnID++;