[Beignet] [PATCH 1/2] Fix float to ulong/long fail.

Yang Rong rong.r.yang at intel.com
Mon Dec 2 01:10:26 PST 2013


Signed-off-by: Yang Rong <rong.r.yang at intel.com>
---
 backend/src/backend/gen_context.cpp                | 51 ++++++++++++++++------
 backend/src/backend/gen_context.hpp                |  1 +
 .../src/backend/gen_insn_gen7_schedule_info.hxx    |  1 +
 backend/src/backend/gen_insn_selection.cpp         | 18 +++++++-
 backend/src/backend/gen_insn_selection.hxx         |  2 +-
 5 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp
index 4902085..599a6d6 100644
--- a/backend/src/backend/gen_context.cpp
+++ b/backend/src/backend/gen_context.cpp
@@ -191,20 +191,6 @@ namespace gbe
       case SEL_OP_MOV_DF:
         p->MOV_DF(dst, src, tmp);
         break;
-      case SEL_OP_CONVF_TO_I64:
-       {
-        tmp.type = GEN_TYPE_F;
-        GenRegister d = GenRegister::retype(tmp, GEN_TYPE_D);
-        float c = (1.f / 65536.f) * (1.f / 65536.f);
-        p->MUL(tmp, src, GenRegister::immf(c));
-        p->RNDZ(tmp, tmp);
-        p->MOV(d, tmp);
-        storeTopHalf(dst, d);
-        d.type = GEN_TYPE_UD;
-        p->MOV(d, GenRegister::abs(src));
-        storeBottomHalf(dst, d);
-        break;
-       }
       case SEL_OP_CONVI_TO_I64: {
         GenRegister middle;
         if (src.type == GEN_TYPE_B || src.type == GEN_TYPE_D) {
@@ -876,6 +862,43 @@ namespace gbe
     }
   }
 
+
+  void GenContext::emitFloatToI64Instruction(const SelectionInstruction &insn) {
+    GenRegister src = ra->genReg(insn.src(0));
+    GenRegister dst = ra->genReg(insn.dst(0));
+    GenRegister high = ra->genReg(insn.dst(1));
+    GenRegister tmp = ra->genReg(insn.dst(2));
+    GenRegister flag0 = ra->genReg(insn.dst(3));
+
+    if(dst.is_signed_int())
+      high = GenRegister::retype(high, GEN_TYPE_D);
+    GenRegister low = GenRegister::retype(tmp, GEN_TYPE_UD);
+    float c = (1.f / 65536.f) * (1.f / 65536.f);
+    p->MUL(tmp, src, GenRegister::immf(c));
+    p->RNDZ(tmp, tmp);
+    p->MOV(high, tmp);
+    c = 65536.f * 65536.f;
+    p->MOV(tmp, high);  //result may not equal to tmp
+    //mov float to int/uint is sat, so must sub high*0xffffffff
+    p->MUL(tmp, tmp, GenRegister::immf(c));
+    p->ADD(tmp, src, GenRegister::negate(tmp));
+    p->MOV(low, GenRegister::abs(tmp));
+    if(dst.is_signed_int()) {
+      p->push();
+      p->curr.predicate = GEN_PREDICATE_NONE;
+      p->curr.useFlag(flag0.flag_nr(), flag0.flag_subnr());
+      p->CMP(GEN_CONDITIONAL_L, src, GenRegister::immf(0x0));
+      p->curr.predicate = GEN_PREDICATE_NORMAL;
+      p->CMP(GEN_CONDITIONAL_NEQ, low, GenRegister::immud(0x0));
+      p->ADD(high, high, GenRegister::immd(-1));
+      p->NOT(low, low);
+      p->ADD(low, low, GenRegister::immud(1));
+      p->pop();
+    }
+    storeTopHalf(dst, high);
+    storeBottomHalf(dst, low);
+  }
+
   void GenContext::emitI64CompareInstruction(const SelectionInstruction &insn) {
     GenRegister src0 = ra->genReg(insn.src(0));
     GenRegister src1 = ra->genReg(insn.src(1));
diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp
index 10e0603..f8ef8e0 100644
--- a/backend/src/backend/gen_context.hpp
+++ b/backend/src/backend/gen_context.hpp
@@ -110,6 +110,7 @@ namespace gbe
     void emitI64SATADDInstruction(const SelectionInstruction &insn);
     void emitI64SATSUBInstruction(const SelectionInstruction &insn);
     void emitI64ToFloatInstruction(const SelectionInstruction &insn);
+    void emitFloatToI64Instruction(const SelectionInstruction &insn);
     void emitCompareInstruction(const SelectionInstruction &insn);
     void emitJumpInstruction(const SelectionInstruction &insn);
     void emitIndirectMoveInstruction(const SelectionInstruction &insn);
diff --git a/backend/src/backend/gen_insn_gen7_schedule_info.hxx b/backend/src/backend/gen_insn_gen7_schedule_info.hxx
index b33112c..bb70b16 100644
--- a/backend/src/backend/gen_insn_gen7_schedule_info.hxx
+++ b/backend/src/backend/gen_insn_gen7_schedule_info.hxx
@@ -9,6 +9,7 @@ DECL_GEN7_SCHEDULE(I64Shift,        20,        4,        2)
 DECL_GEN7_SCHEDULE(I64HADD,         20,        4,        2)
 DECL_GEN7_SCHEDULE(I64RHADD,        20,        4,        2)
 DECL_GEN7_SCHEDULE(I64ToFloat,      20,        4,        2)
+DECL_GEN7_SCHEDULE(FloatToI64,      20,        4,        2)
 DECL_GEN7_SCHEDULE(I64MULHI,        20,        4,        2)
 DECL_GEN7_SCHEDULE(I64MADSAT,       20,        4,        2)
 DECL_GEN7_SCHEDULE(Compare,         20,        4,        2)
diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index 9f6e615..23e9da7 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -474,6 +474,8 @@ namespace gbe
 #undef I64Shift
     /*! Convert 64-bit integer to 32-bit float */
     void CONVI64_TO_F(Reg dst, Reg src, GenRegister tmp[4]);
+    /*! Convert 64-bit integer to 32-bit float */
+    void CONVF_TO_I64(Reg dst, Reg src, GenRegister tmp[3]);
     /*! Saturated 64bit x*y + z */
     void I64MADSAT(Reg dst, Reg src0, Reg src1, Reg src2, GenRegister tmp[10]);
     /*! High 64bit of x*y */
@@ -1138,6 +1140,14 @@ namespace gbe
       insn->dst(i + 1) = tmp[i];
   }
 
+  void Selection::Opaque::CONVF_TO_I64(Reg dst, Reg src, GenRegister tmp[3]) {
+    SelectionInstruction *insn = this->appendInsn(SEL_OP_CONVF_TO_I64, 4, 1);
+    insn->dst(0) = dst;
+    insn->src(0) = src;
+    for(int i = 0; i < 3; i ++)
+      insn->dst(i + 1) = tmp[i];
+  }
+
   void Selection::Opaque::I64MADSAT(Reg dst, Reg src0, Reg src1, Reg src2, GenRegister tmp[10]) {
     SelectionInstruction *insn = this->appendInsn(SEL_OP_I64MADSAT, 11, 3);
     insn->dst(0) = dst;
@@ -2700,8 +2710,14 @@ namespace gbe
       } else if (dst.isint64()) {
         switch(src.type) {
           case GEN_TYPE_F:
-            sel.CONVF_TO_I64(dst, src, sel.selReg(sel.reg(FAMILY_DWORD)));
+          {
+            GenRegister tmp[3];
+            tmp[0] = sel.selReg(sel.reg(FAMILY_DWORD), TYPE_U32);
+            tmp[1] = sel.selReg(sel.reg(FAMILY_DWORD), TYPE_FLOAT);
+            tmp[2] = sel.selReg(sel.reg(FAMILY_BOOL), TYPE_BOOL);
+            sel.CONVF_TO_I64(dst, src, tmp);
             break;
+          }
           case GEN_TYPE_DF:
             NOT_IMPLEMENTED;
           default:
diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx
index 9fb5da7..0118619 100644
--- a/backend/src/backend/gen_insn_selection.hxx
+++ b/backend/src/backend/gen_insn_selection.hxx
@@ -75,7 +75,7 @@ DECL_SELECTION_IR(UPSAMPLE_SHORT, BinaryInstruction)
 DECL_SELECTION_IR(UPSAMPLE_INT, BinaryInstruction)
 DECL_SELECTION_IR(UPSAMPLE_LONG, BinaryInstruction)
 DECL_SELECTION_IR(CONVI_TO_I64, UnaryWithTempInstruction)
-DECL_SELECTION_IR(CONVF_TO_I64, UnaryWithTempInstruction)
 DECL_SELECTION_IR(CONVI64_TO_I, UnaryInstruction)
 DECL_SELECTION_IR(CONVI64_TO_F, I64ToFloatInstruction)
+DECL_SELECTION_IR(CONVF_TO_I64, FloatToI64Instruction)
 DECL_SELECTION_IR(I64MADSAT, I64MADSATInstruction)
-- 
1.8.1.2



More information about the Beignet mailing list