[Beignet] [PATCH 16/19] backend: Add conversion support between half and other type.

junyan.he at inbox.com junyan.he at inbox.com
Thu Jun 11 04:25:31 PDT 2015


From: Junyan He <junyan.he at linux.intel.com>

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 backend/src/backend/gen_insn_selection.cpp | 147 +++++++++++++++++++++++------
 1 file changed, 117 insertions(+), 30 deletions(-)

diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index 9ee8d52..6ea0ef8 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -4097,10 +4097,17 @@ namespace gbe
           sel.F32TO16(unpacked, src);
         sel.pop();
         sel.MOV(dst, unpacked);
-      } else if (dstFamily != FAMILY_DWORD && dstFamily != FAMILY_QWORD && srcFamily == FAMILY_DWORD) {//convert i32 to small int
+      } else if (dstFamily != FAMILY_DWORD && dstFamily != FAMILY_QWORD && srcFamily == FAMILY_DWORD) {//convert i32 to small int and half
         GenRegister unpacked;
         if (dstFamily == FAMILY_WORD) {
-          const uint32_t type = dstType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W;
+          uint32_t type = dstType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W;
+
+	  /* The special case, when dst is half, float->word->half will lose accuracy. */
+	  if (dstType == TYPE_HALF) {
+            GBE_ASSERT(sel.hasHalfType());
+            type = GEN_TYPE_HF;
+          }
+
           if (!sel.isScalarReg(dst.reg())) {
             unpacked = sel.unpacked_uw(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0))));
             unpacked = GenRegister::retype(unpacked, type);
@@ -4126,38 +4133,63 @@ namespace gbe
 
         if (unpacked.reg() != dst.reg())
           sel.MOV(dst, unpacked);
-      } else if (dstFamily == FAMILY_WORD && srcFamily == FAMILY_QWORD) { //convert i64 to i16
-        const uint32_t type = dstType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W;
-        GenRegister unpacked;
-        if (!sel.isScalarReg(dst.reg())) {
-          if (sel.hasLongType()) {
-            unpacked = sel.unpacked_uw(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
-          } else {
-            unpacked = sel.unpacked_uw(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0))));
+      } else if (dstFamily == FAMILY_WORD && srcFamily == FAMILY_QWORD) { //convert i64 to i16 and half.
+        if (dstType == TYPE_HALF) {
+          /* There is no MOV for Long <---> Half. So Long-->Float-->half. */
+          GBE_ASSERT(sel.hasLongType());
+          GBE_ASSERT(sel.hasHalfType());
+          sel.push();
+          if (sel.isScalarReg(insn.getSrc(0))) {
+            sel.curr.execWidth = 1;
+            sel.curr.predicate = GEN_PREDICATE_NONE;
+            sel.curr.noMask = 1;
           }
-          unpacked = GenRegister::retype(unpacked, type);
-        } else {
-          unpacked = GenRegister::retype(sel.unpacked_uw(dst.reg()), type);
-        }
 
-        if(!sel.hasLongType()) {
-          GenRegister tmp = sel.selReg(sel.reg(FAMILY_DWORD));
-          tmp.type = GEN_TYPE_D;
-          sel.CONVI64_TO_I(tmp, src);
-          sel.MOV(unpacked, tmp);
+          GenRegister funpacked = sel.unpacked_ud(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+          funpacked = GenRegister::retype(funpacked, GEN_TYPE_F);
+          sel.MOV(funpacked, src);
+          GenRegister ftmp = sel.selReg(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0))));
+          ftmp = GenRegister::retype(ftmp, GEN_TYPE_F);
+          sel.MOV(ftmp, funpacked);
+          GenRegister unpacked = sel.unpacked_uw(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0))));
+          unpacked = GenRegister::retype(unpacked, GEN_TYPE_HF);
+          sel.MOV(unpacked, ftmp);
+          sel.pop();
+          sel.MOV(dst, unpacked);
         } else {
-          sel.push();
-            if (sel.isScalarReg(insn.getSrc(0))) {
-              sel.curr.execWidth = 1;
-              sel.curr.predicate = GEN_PREDICATE_NONE;
-              sel.curr.noMask = 1;
+          uint32_t type = dstType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W;
+
+          GenRegister unpacked;
+          if (!sel.isScalarReg(dst.reg())) {
+            if (sel.hasLongType()) {
+              unpacked = sel.unpacked_uw(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+            } else {
+              unpacked = sel.unpacked_uw(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0))));
             }
-            sel.MOV(unpacked, src);
-          sel.pop();
-        }
+            unpacked = GenRegister::retype(unpacked, type);
+          } else {
+            unpacked = GenRegister::retype(sel.unpacked_uw(dst.reg()), type);
+          }
 
-        if (unpacked.reg() != dst.reg()) {
-          sel.MOV(dst, unpacked);
+          if(!sel.hasLongType()) {
+           GenRegister tmp = sel.selReg(sel.reg(FAMILY_DWORD));
+            tmp.type = GEN_TYPE_D;
+            sel.CONVI64_TO_I(tmp, src);
+            sel.MOV(unpacked, tmp);
+          } else {
+            sel.push();
+              if (sel.isScalarReg(insn.getSrc(0))) {
+                sel.curr.execWidth = 1;
+                sel.curr.predicate = GEN_PREDICATE_NONE;
+                sel.curr.noMask = 1;
+              }
+              sel.MOV(unpacked, src);
+            sel.pop();
+          }
+
+          if (unpacked.reg() != dst.reg()) {
+            sel.MOV(dst, unpacked);
+          }
         }
       } else if (dstFamily == FAMILY_BYTE && srcFamily == FAMILY_QWORD) { //convert i64 to i8
         GenRegister unpacked;
@@ -4305,7 +4337,7 @@ namespace gbe
             sel.curr.noMask = 1;
           }
 
-          if(srcType == ir::TYPE_FLOAT) {
+          if (srcType == ir::TYPE_FLOAT) {
             unpacked = sel.unpacked_ud(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
             unpacked = GenRegister::retype(unpacked, GEN_TYPE_F);
           } else if(srcFamily == FAMILY_DWORD) {
@@ -4349,6 +4381,23 @@ namespace gbe
               }
               break;
             }
+          case GEN_TYPE_HF:
+            {
+              GBE_ASSERT(sel.hasLongType());
+              GBE_ASSERT(sel.hasHalfType());
+              uint32_t type = dstType == TYPE_U64 ? GEN_TYPE_UD : GEN_TYPE_D;
+              GenRegister tmp = GenRegister::retype(sel.selReg(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0))), TYPE_U32), type);
+              sel.push();
+              if (sel.isScalarReg(insn.getSrc(0))) {
+                sel.curr.execWidth = 1;
+                sel.curr.predicate = GEN_PREDICATE_NONE;
+                sel.curr.noMask = 1;
+              }
+              sel.MOV(tmp, src);
+              sel.pop();
+              sel.MOV(dst, tmp);
+              break;
+            }
           case GEN_TYPE_DF:
             NOT_IMPLEMENTED;
           default:
@@ -4358,6 +4407,44 @@ namespace gbe
               sel.CONVI_TO_I64(dst, src, sel.selReg(sel.reg(FAMILY_DWORD)));
             }
         }
+      } else if (srcType == ir::TYPE_HALF && (dstFamily == FAMILY_BYTE || dstFamily == FAMILY_WORD)) {
+      // Special case, half -> char/short.
+      /* [DevBDW+]:  Format conversion to or from HF (Half Float) must be DWord-aligned and
+         strided by a DWord on the destination. */
+        GBE_ASSERT(sel.hasHalfType());
+        GenRegister tmp;
+        sel.push();
+        if (sel.isScalarReg(insn.getSrc(0))) {
+          sel.curr.execWidth = 1;
+          sel.curr.predicate = GEN_PREDICATE_NONE;
+          sel.curr.noMask = 1;
+        }
+        if (dstFamily == FAMILY_BYTE) {
+          const uint32_t type = dstType == TYPE_U8 ? GEN_TYPE_UB : GEN_TYPE_B;
+          tmp = GenRegister::retype(sel.unpacked_ub(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0)))), type);
+          sel.MOV(tmp, src);
+        } else {
+          const uint32_t type = dstType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W;
+          tmp = GenRegister::retype(sel.unpacked_uw(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0)))), type);
+          sel.MOV(tmp, src);
+        }
+        sel.pop();
+        sel.MOV(dst, tmp);
+      } else if (dstType == ir::TYPE_HALF && (srcFamily == FAMILY_BYTE || srcFamily == FAMILY_WORD)) {
+        // Special case, char/uchar -> half
+        /* [DevBDW+]:  Format conversion to or from HF (Half Float) must be DWord-aligned and
+           strided by a DWord on the destination. */
+        GBE_ASSERT(sel.hasHalfType());
+        GenRegister tmp = GenRegister::retype(sel.unpacked_uw(sel.reg(FAMILY_DWORD, sel.isScalarReg(insn.getSrc(0)))), GEN_TYPE_HF);
+        sel.push();
+        if (sel.isScalarReg(insn.getSrc(0))) {
+          sel.curr.execWidth = 1;
+          sel.curr.predicate = GEN_PREDICATE_NONE;
+          sel.curr.noMask = 1;
+        }
+        sel.MOV(tmp, src);
+        sel.pop();
+        sel.MOV(dst, tmp);
       } else
         sel.MOV(dst, src);
 
-- 
1.9.1



More information about the Beignet mailing list