[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