[Beignet] [PATCH] support converting 64-bit integer to 32-bit float

Homer Hsing homer.xing at intel.com
Sun Sep 1 19:12:26 PDT 2013


Signed-off-by: Homer Hsing <homer.xing at intel.com>
---
 backend/src/backend/gen_context.cpp        | 14 ++++++++++
 backend/src/backend/gen_insn_selection.cpp |  4 +++
 backend/src/backend/gen_insn_selection.hxx |  1 +
 kernels/compiler_long_convert.cl           |  5 ++++
 utests/compiler_long_convert.cpp           | 41 ++++++++++++++++++++++++++++++
 5 files changed, 65 insertions(+)

diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp
index 3e3a8fc..0b61c0a 100644
--- a/backend/src/backend/gen_context.cpp
+++ b/backend/src/backend/gen_context.cpp
@@ -189,6 +189,20 @@ namespace gbe
       case SEL_OP_MOV_DF:
         p->MOV_DF(dst, src, tmp);
         break;
+      case SEL_OP_CONVI64_TO_F:
+       {
+        tmp.type = src.is_signed_int() ? GEN_TYPE_D : GEN_TYPE_UD;
+        GenRegister tmp2 = GenRegister::suboffset(tmp, p->curr.execWidth);
+        tmp2.type = GEN_TYPE_F;
+        loadTopHalf(tmp, src);
+        p->MOV(dst, tmp);
+        p->MUL(dst, dst, GenRegister::immf(65536.f * 65536.f));
+        tmp.type = GEN_TYPE_UD;
+        loadBottomHalf(tmp, src);
+        p->MOV(tmp2, tmp);
+        p->ADD(dst, dst, tmp2);
+        break;
+       }
       case SEL_OP_CONVI_TO_I64: {
         GenRegister middle;
         if (src.type == GEN_TYPE_B || src.type == GEN_TYPE_D) {
diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index f1b85bb..94d0993 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -460,6 +460,7 @@ namespace gbe
     ALU2(UPSAMPLE_LONG)
     ALU1WithTemp(CONVI_TO_I64)
     ALU1(CONVI64_TO_I)
+    ALU1WithTemp(CONVI64_TO_F)
     I64Shift(I64SHL)
     I64Shift(I64SHR)
     I64Shift(I64ASR)
@@ -2362,6 +2363,9 @@ namespace gbe
         sel.MOV(dst, unpacked);
       } else if ((dstType == ir::TYPE_S32 || dstType == ir::TYPE_U32) && srcFamily == FAMILY_QWORD) {
         sel.CONVI64_TO_I(dst, src);
+      } else if (dstType == ir::TYPE_FLOAT && srcFamily == FAMILY_QWORD) {
+        GenRegister tmp = sel.selReg(sel.reg(FAMILY_QWORD));
+        sel.CONVI64_TO_F(dst, src, tmp);
       } else if (dst.isdf()) {
         ir::Register r = sel.reg(ir::RegisterFamily::FAMILY_QWORD);
         sel.MOV_DF(dst, src, sel.selReg(r));
diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx
index 5c857dd..a5e26fd 100644
--- a/backend/src/backend/gen_insn_selection.hxx
+++ b/backend/src/backend/gen_insn_selection.hxx
@@ -66,3 +66,4 @@ DECL_SELECTION_IR(UPSAMPLE_INT, BinaryInstruction)
 DECL_SELECTION_IR(UPSAMPLE_LONG, BinaryInstruction)
 DECL_SELECTION_IR(CONVI_TO_I64, UnaryWithTempInstruction)
 DECL_SELECTION_IR(CONVI64_TO_I, UnaryInstruction)
+DECL_SELECTION_IR(CONVI64_TO_F, UnaryWithTempInstruction)
diff --git a/kernels/compiler_long_convert.cl b/kernels/compiler_long_convert.cl
index 03df147..e5f7939 100644
--- a/kernels/compiler_long_convert.cl
+++ b/kernels/compiler_long_convert.cl
@@ -12,3 +12,8 @@ kernel void compiler_long_convert_2(global char *dst1, global short *dst2, globa
   dst2[i] = src[i];
   dst3[i] = src[i];
 }
+
+kernel void compiler_long_convert_to_float(global float *dst, global long *src) {
+  int i = get_global_id(0);
+  dst[i] = src[i];
+}
diff --git a/utests/compiler_long_convert.cpp b/utests/compiler_long_convert.cpp
index fe976be..8513f6d 100644
--- a/utests/compiler_long_convert.cpp
+++ b/utests/compiler_long_convert.cpp
@@ -116,3 +116,44 @@ void compiler_long_convert_2(void)
 }
 
 MAKE_UTEST_FROM_FUNCTION(compiler_long_convert_2);
+
+// convert 64-bit integer to 32-bit float
+void compiler_long_convert_to_float(void)
+{
+  const size_t n = 16;
+  int64_t src[n];
+
+  // Setup kernel and buffers
+  OCL_CREATE_KERNEL_FROM_FILE("compiler_long_convert", "compiler_long_convert_to_float");
+  OCL_CREATE_BUFFER(buf[0], 0, n * sizeof(float), NULL);
+  OCL_CREATE_BUFFER(buf[1], 0, n * sizeof(int64_t), NULL);
+  OCL_SET_ARG(0, sizeof(cl_mem), &buf[0]);
+  OCL_SET_ARG(1, sizeof(cl_mem), &buf[1]);
+  globals[0] = n;
+  locals[0] = 16;
+
+  // Run random tests
+  for (int32_t i = 0; i < (int32_t) n; ++i) {
+    src[i] = (int64_t)0x20000000 * i;
+  }
+  OCL_MAP_BUFFER(1);
+  memcpy(buf_data[1], src, sizeof(src));
+  OCL_UNMAP_BUFFER(1);
+
+  // Run the kernel on GPU
+  OCL_NDRANGE(1);
+
+  // Compare
+  OCL_MAP_BUFFER(0);
+  OCL_MAP_BUFFER(1);
+  float *dst = ((float *)buf_data[0]);
+  for (int32_t i = 0; i < (int32_t) n; ++i) {
+    //printf("%f\n", dst[i]);
+    OCL_ASSERT(dst[i] == src[i]);
+  }
+  OCL_UNMAP_BUFFER(0);
+  OCL_UNMAP_BUFFER(1);
+}
+
+MAKE_UTEST_FROM_FUNCTION(compiler_long_convert_to_float);
+
-- 
1.8.1.2



More information about the Beignet mailing list