[Beignet] [PATCH V2 3/5] Use instruction WHILE to manipulate structure.

Zhigang Gong zhigang.gong at intel.com
Tue Sep 23 00:02:55 PDT 2014


From: Luo Xionghu <xionghu.luo at intel.com>

1. WHILE instruction should be non-schedulable.
2. if this WHILE instruction jumps to an ELSE instruction, the distance
need add 2.

v2:
We also need to take care of HSW for while instruction.

Signed-off-by: Luo Xionghu <xionghu.luo at intel.com>
Signed-off-by: Zhigang Gong <zhigang.gong at intel.com>
---
 backend/src/backend/gen75_encoder.cpp       | 22 +++++++++++++++-------
 backend/src/backend/gen_context.cpp         | 10 ++++++++++
 backend/src/backend/gen_encoder.cpp         | 11 +++++++++++
 backend/src/backend/gen_encoder.hpp         |  2 ++
 backend/src/backend/gen_insn_scheduling.cpp |  2 +-
 backend/src/backend/gen_insn_selection.cpp  | 20 ++++++++++++++++++++
 backend/src/backend/gen_insn_selection.hxx  |  1 +
 backend/src/ir/structural_analysis.cpp      |  2 +-
 8 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/backend/src/backend/gen75_encoder.cpp b/backend/src/backend/gen75_encoder.cpp
index 321e07b..724865b 100644
--- a/backend/src/backend/gen75_encoder.cpp
+++ b/backend/src/backend/gen75_encoder.cpp
@@ -254,17 +254,25 @@ namespace gbe
                insn.header.opcode == GEN_OPCODE_ENDIF ||
                insn.header.opcode == GEN_OPCODE_IF ||
                insn.header.opcode == GEN_OPCODE_BRC ||
+               insn.header.opcode == GEN_OPCODE_WHILE ||
                insn.header.opcode == GEN_OPCODE_ELSE);
 
-    if (insn.header.opcode == GEN_OPCODE_IF) {
-      this->setSrc1(&insn, GenRegister::immd(jumpDistance));
-      return;
+    if( insn.header.opcode == GEN_OPCODE_WHILE ){
+      // if this WHILE instruction jump back to an ELSE instruction,
+      // need add distance to go to the next instruction.
+      GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jumpDistance];
+      if(insn_else.header.opcode == GEN_OPCODE_ELSE){
+        jumpDistance += 2;
+      }
     }
-    else if (insn.header.opcode == GEN_OPCODE_JMPI) {
-      //jumpDistance'unit is Qword, and the HSW's offset of jmpi is in byte, so multi 8
+
+    if (insn.header.opcode != GEN_OPCODE_JMPI)
+      this->setSrc1(&insn, GenRegister::immd(jumpDistance));
+    else {
+      //jumpDistance'unit is Qword, and the HSW's JMPI offset of jmpi is in byte, so multi 8
       jumpDistance = (jumpDistance - 2) * 8;
+      this->setSrc1(&insn, GenRegister::immd(jumpDistance));
     }
-
-    this->setSrc1(&insn, GenRegister::immd(jumpDistance));
+    return;
   }
 } /* End of the name space. */
diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp
index 175878d..8844233 100644
--- a/backend/src/backend/gen_context.cpp
+++ b/backend/src/backend/gen_context.cpp
@@ -255,6 +255,16 @@ namespace gbe
           p->ELSE(src);
         }
         break;
+      case SEL_OP_WHILE:
+        {
+          /*const ir::LabelIndex label0(insn.index), label1(insn.index1);
+          const LabelPair labelPair(label0, label1);
+          const GenRegister src = ra->genReg(insn.src(0));
+          this->branchPos3.push_back(std::make_pair(labelPair, p->store.size()));*/
+          insertJumpPos(insn);
+          p->WHILE(src);
+        }
+        break;
       default: NOT_IMPLEMENTED;
     }
   }
diff --git a/backend/src/backend/gen_encoder.cpp b/backend/src/backend/gen_encoder.cpp
index c67e85e..295e11d 100644
--- a/backend/src/backend/gen_encoder.cpp
+++ b/backend/src/backend/gen_encoder.cpp
@@ -1026,6 +1026,7 @@ namespace gbe
   ALU2_BRA(IF)
   ALU2_BRA(ELSE)
   ALU2_BRA(ENDIF)
+  ALU2_BRA(WHILE)
   ALU2_BRA(BRD)
   ALU2_BRA(BRC)
 
@@ -1037,8 +1038,18 @@ namespace gbe
                insn.header.opcode == GEN_OPCODE_ENDIF ||
                insn.header.opcode == GEN_OPCODE_IF ||
                insn.header.opcode == GEN_OPCODE_BRC ||
+               insn.header.opcode == GEN_OPCODE_WHILE ||
                insn.header.opcode == GEN_OPCODE_ELSE);
 
+    if( insn.header.opcode == GEN_OPCODE_WHILE ){
+      // if this WHILE instruction jump back to an ELSE instruction,
+      // need add distance to go to the next instruction.
+      GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jumpDistance];
+      if(insn_else.header.opcode == GEN_OPCODE_ELSE){
+        jumpDistance += 2;
+      }
+    }
+
     if (insn.header.opcode != GEN_OPCODE_JMPI || (jumpDistance > -32769 && jumpDistance < 32768))  {
            if (insn.header.opcode == GEN_OPCODE_IF) {
              this->setSrc1(&insn, GenRegister::immd(jumpDistance));
diff --git a/backend/src/backend/gen_encoder.hpp b/backend/src/backend/gen_encoder.hpp
index 9844eb8..2c999ce 100644
--- a/backend/src/backend/gen_encoder.hpp
+++ b/backend/src/backend/gen_encoder.hpp
@@ -154,6 +154,8 @@ namespace gbe
     void ELSE(GenRegister src);
     /*! ENDIF indexed instruction */
     void ENDIF(GenRegister src);
+    /*! WHILE indexed instruction */
+    void WHILE(GenRegister src);
     /*! BRC indexed instruction */
     void BRC(GenRegister src);
     /*! BRD indexed instruction */
diff --git a/backend/src/backend/gen_insn_scheduling.cpp b/backend/src/backend/gen_insn_scheduling.cpp
index ead3e26..58ab69f 100644
--- a/backend/src/backend/gen_insn_scheduling.cpp
+++ b/backend/src/backend/gen_insn_scheduling.cpp
@@ -588,7 +588,7 @@ namespace gbe
     for (int32_t insnID = 0; insnID < insnNum; ++insnID) {
       ScheduleDAGNode *node = tracker.insnNodes[insnID];
       if (node->insn.isBranch() || node->insn.isLabel()
-          || node->insn.opcode == SEL_OP_EOT || node->insn.opcode == SEL_OP_IF
+          || node->insn.opcode == SEL_OP_EOT || node->insn.opcode == SEL_OP_IF || node->insn.opcode == SEL_OP_WHILE
           || node->insn.opcode == SEL_OP_READ_ARF
           || node->insn.opcode == SEL_OP_BARRIER)
         tracker.makeBarrier(insnID, insnNum);
diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index f284ae1..e3ee35d 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -544,6 +544,8 @@ namespace gbe
     void ELSE(Reg src, ir::LabelIndex jip, ir::LabelIndex elseLabel);
     /*! ENDIF indexed instruction */
     void ENDIF(Reg src, ir::LabelIndex jip, ir::LabelIndex endifLabel = ir::LabelIndex(0));
+    /*! WHILE indexed instruction */
+    void WHILE(Reg src, ir::LabelIndex jip);
     /*! BRD indexed instruction */
     void BRD(Reg src, ir::LabelIndex jip);
     /*! BRC indexed instruction */
@@ -1063,6 +1065,12 @@ namespace gbe
     insn->index = uint16_t(this->block->endifLabel);
   }
 
+  void Selection::Opaque::WHILE(Reg src, ir::LabelIndex jip) {
+    SelectionInstruction *insn = this->appendInsn(SEL_OP_WHILE, 0, 1);
+    insn->src(0) = src;
+    insn->index = uint16_t(jip);
+  }
+
   void Selection::Opaque::CMP(uint32_t conditional, Reg src0, Reg src1, Reg dst) {
     SelectionInstruction *insn = this->appendInsn(SEL_OP_CMP, 1, 2);
     insn->src(0) = src0;
@@ -4217,6 +4225,18 @@ namespace gbe
       } else if(opcode == OP_ELSE) {
         const LabelIndex label = insn.getLabelIndex();
         sel.ELSE(GenRegister::immd(0), label, insn.getParent()->thisElseLabel);
+      } else if(opcode == OP_WHILE) {
+        const Register pred = insn.getPredicateIndex();
+        const LabelIndex jip = insn.getLabelIndex();
+        sel.push();
+        sel.curr.physicalFlag = 0;
+        sel.curr.flagIndex = (uint64_t)pred;
+        sel.curr.externFlag = 1;
+        sel.curr.inversePredicate = insn.getInversePredicated();
+        sel.curr.predicate = GEN_PREDICATE_NORMAL;
+        sel.WHILE(GenRegister::immd(0), jip);
+        sel.curr.inversePredicate = 0;
+        sel.pop();
       } else
         NOT_IMPLEMENTED;
 
diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx
index 048a844..7511b84 100644
--- a/backend/src/backend/gen_insn_selection.hxx
+++ b/backend/src/backend/gen_insn_selection.hxx
@@ -86,3 +86,4 @@ DECL_SELECTION_IR(IF, UnaryInstruction)
 DECL_SELECTION_IR(ENDIF, UnaryInstruction)
 DECL_SELECTION_IR(ELSE, UnaryInstruction)
 DECL_SELECTION_IR(READ_ARF, UnaryInstruction)
+DECL_SELECTION_IR(WHILE, UnaryInstruction)
diff --git a/backend/src/ir/structural_analysis.cpp b/backend/src/ir/structural_analysis.cpp
index 1860ee9..040a7e0 100644
--- a/backend/src/ir/structural_analysis.cpp
+++ b/backend/src/ir/structural_analysis.cpp
@@ -867,7 +867,7 @@ namespace analysis
       {
         Node* p = new SelfLoopNode(node);
 
-        p->canBeHandled = false;
+        p->canBeHandled = true;
 
         return insertNode(p);
       }
-- 
1.8.3.2



More information about the Beignet mailing list