[Beignet] [PATCH 3/7 V2] Backend: Add double conversion to insn selection.
junyan.he at inbox.com
junyan.he at inbox.com
Thu Nov 5 00:15:43 PST 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 | 197 +++++++++++++++++++++++++++--
1 file changed, 189 insertions(+), 8 deletions(-)
diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
index b66cf71..49ba499 100644
--- a/backend/src/backend/gen_insn_selection.cpp
+++ b/backend/src/backend/gen_insn_selection.cpp
@@ -4619,8 +4619,11 @@ namespace gbe
sel.pop();
sel.MOV(dst, tmp);
} else if (src.type == GEN_TYPE_DF) {
- //TODO:
- GBE_ASSERT(0);
+ GBE_ASSERT(sel.hasDoubleType());
+ GBE_ASSERT(sel.hasLongType()); //So far, if we support double, we support native long.
+
+ // Just Mov
+ sel.MOV(dst, src);
} else {
/* Invalid case. */
GBE_ASSERT(0);
@@ -4630,11 +4633,77 @@ namespace gbe
INLINE void convertBetweenFloatDouble(Selection::Opaque &sel, const ir::ConvertInstruction &insn, bool &markChildren) const
{
using namespace ir;
+ const Type dstType = insn.getDstType();
+ const Type srcType = insn.getSrcType();
+ const GenRegister dst = sel.selReg(insn.getDst(0), dstType);
+ const GenRegister src = sel.selReg(insn.getSrc(0), srcType);
+
+ GBE_ASSERT(sel.hasDoubleType());
+
+ if (sel.isScalarReg(insn.getDst(0))) {
+ // dst is scalar, just MOV and nothing more.
+ GBE_ASSERT(sel.isScalarReg(insn.getSrc(0)));
+ sel.MOV(dst, src);
+ } else if (srcType == ir::TYPE_DOUBLE) {
+ // double to float
+ GBE_ASSERT(dstType == ir::TYPE_FLOAT);
+ GenRegister unpacked;
+ unpacked = sel.unpacked_ud(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpacked = GenRegister::retype(unpacked, GEN_TYPE_F);
+
+ sel.MOV(unpacked, src);
+ sel.MOV(dst, unpacked);
+ } else {
+ // float to double, just mov
+ sel.MOV(dst, src);
+ }
+
+ return;
}
INLINE void convertBetweenHalfDouble(Selection::Opaque &sel, const ir::ConvertInstruction &insn, bool &markChildren) const
{
using namespace ir;
+ const Type dstType = insn.getDstType();
+ const Type srcType = insn.getSrcType();
+ const GenRegister dst = sel.selReg(insn.getDst(0), dstType);
+ const GenRegister src = sel.selReg(insn.getSrc(0), srcType);
+
+ GBE_ASSERT(sel.hasDoubleType());
+ GBE_ASSERT(sel.hasHalfType()); //So far, if we support double, we support half.
+
+ if (sel.isScalarReg(insn.getDst(0))) { // uniform case.
+ GBE_ASSERT(sel.isScalarReg(insn.getSrc(0)));
+ GBE_ASSERT(sel.curr.execWidth == 1);
+ GenRegister tmpFloat = GenRegister::retype(sel.selReg(sel.reg(FAMILY_DWORD)), GEN_TYPE_F);
+ sel.MOV(tmpFloat, src);
+ sel.MOV(dst, tmpFloat);
+ return;
+ }
+
+ if (dstType == ir::TYPE_DOUBLE) {
+ // half to double. There is no direct double to half MOV, need tmp float.
+ GBE_ASSERT(srcType == ir::TYPE_HALF);
+ GenRegister tmpFloat = GenRegister::retype(sel.selReg(sel.reg(FAMILY_DWORD)), GEN_TYPE_F);
+ sel.MOV(tmpFloat, src);
+ sel.MOV(dst, tmpFloat);
+ } else {
+ // double to half. No direct MOV from double to half, so double->float->half
+ GBE_ASSERT(srcType == ir::TYPE_DOUBLE);
+ GBE_ASSERT(dstType == ir::TYPE_HALF);
+
+ // double to float
+ GenRegister unpackedFloat = sel.unpacked_ud(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpackedFloat = GenRegister::retype(unpackedFloat, GEN_TYPE_F);
+ sel.MOV(unpackedFloat, src);
+
+ // float to half
+ GenRegister unpackedHalf = sel.unpacked_uw(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpackedHalf = GenRegister::retype(unpackedHalf, GEN_TYPE_HF);
+ sel.MOV(unpackedHalf, unpackedFloat);
+
+ sel.MOV(dst, unpackedHalf);
+ }
}
INLINE void convertHalfToSmallInts(Selection::Opaque &sel, const ir::ConvertInstruction &insn, bool &markChildren) const
@@ -4694,6 +4763,105 @@ namespace gbe
sel.MOV(dst, tmp);
}
+ INLINE void convertDoubleToSmallInts(Selection::Opaque &sel, const ir::ConvertInstruction &insn, bool &markChildren) const
+ {
+ using namespace ir;
+ const Type dstType = insn.getDstType();
+ const Type srcType = insn.getSrcType();
+ const GenRegister dst = sel.selReg(insn.getDst(0), dstType);
+ const GenRegister src = sel.selReg(insn.getSrc(0), srcType);
+ const RegisterFamily dstFamily = getFamily(dstType);
+
+ GBE_ASSERT(sel.hasDoubleType());
+ GBE_ASSERT(sel.hasHalfType()); //So far, if we support double, we support half.
+ if (sel.isScalarReg(insn.getDst(0))) {
+ // dst is scalar, just MOV and nothing more.
+ GBE_ASSERT(sel.isScalarReg(insn.getSrc(0)));
+ sel.MOV(dst, src);
+ } else {
+ GenRegister unpacked;
+ if (dstFamily == FAMILY_DWORD) {
+ // double to int
+ unpacked = sel.unpacked_ud(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpacked = GenRegister::retype(unpacked, dstType == TYPE_U32 ? GEN_TYPE_UD : GEN_TYPE_D);
+ } else if (dstFamily == FAMILY_WORD) {
+ // double to short
+ unpacked = sel.unpacked_uw(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpacked = GenRegister::retype(unpacked, dstType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W);
+ } else {
+ GBE_ASSERT(dstFamily == FAMILY_BYTE);
+ // double to char
+ unpacked = sel.unpacked_uw(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpacked = GenRegister::retype(unpacked, dstType == TYPE_U8 ? GEN_TYPE_UW : GEN_TYPE_W);
+ }
+
+ sel.MOV(unpacked, src);
+ sel.MOV(dst, unpacked);
+ }
+ }
+
+ INLINE void convertI64ToDouble(Selection::Opaque &sel, const ir::ConvertInstruction &insn, bool &markChildren) const
+ {
+ using namespace ir;
+ const Type dstType = insn.getDstType();
+ const Type srcType = insn.getSrcType();
+ const GenRegister dst = sel.selReg(insn.getDst(0), dstType);
+ const GenRegister src = sel.selReg(insn.getSrc(0), srcType);
+
+ GBE_ASSERT(sel.hasDoubleType());
+ GBE_ASSERT(sel.hasLongType()); //So far, if we support double, we support native long.
+ // Just Mov
+ sel.MOV(dst, src);
+ }
+
+ INLINE void convertSmallIntsToDouble(Selection::Opaque &sel, const ir::ConvertInstruction &insn, bool &markChildren) const
+ {
+ using namespace ir;
+ const Type dstType = insn.getDstType();
+ const Type srcType = insn.getSrcType();
+ const GenRegister dst = sel.selReg(insn.getDst(0), dstType);
+ const GenRegister src = sel.selReg(insn.getSrc(0), srcType);
+ const RegisterFamily srcFamily = getFamily(srcType);
+
+ GBE_ASSERT(sel.hasDoubleType());
+ GBE_ASSERT(sel.hasLongType()); //So far, if we support double, we support native long.
+
+ if (sel.hasLongType() && sel.hasLongRegRestrict()) {
+ // Convert i32/i16/i8 to i64 if hasLongRegRestrict(src and dst hstride must be aligned to the same qword).
+ GenRegister unpacked;
+ GenRegister unpacked_src = src;
+
+ sel.push();
+ if (sel.isScalarReg(insn.getSrc(0))) {
+ sel.curr.execWidth = 1;
+ sel.curr.predicate = GEN_PREDICATE_NONE;
+ sel.curr.noMask = 1;
+ }
+
+ if(srcFamily == FAMILY_DWORD) {
+ unpacked = sel.unpacked_ud(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpacked = GenRegister::retype(unpacked, srcType == TYPE_U32 ? GEN_TYPE_UD : GEN_TYPE_D);
+ } else if(srcFamily == FAMILY_WORD) {
+ unpacked = sel.unpacked_uw(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpacked = GenRegister::retype(unpacked, srcType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W);
+ } else if(srcFamily == FAMILY_BYTE) {
+ GenRegister tmp = sel.selReg(sel.reg(FAMILY_WORD, sel.isScalarReg(insn.getSrc(0))));
+ tmp = GenRegister::retype(tmp, srcType == TYPE_U8 ? GEN_TYPE_UW : GEN_TYPE_W);
+ unpacked = sel.unpacked_uw(sel.reg(FAMILY_QWORD, sel.isScalarReg(insn.getSrc(0))));
+ unpacked = GenRegister::retype(unpacked, srcType == TYPE_U8 ? GEN_TYPE_UW : GEN_TYPE_W);
+ sel.MOV(tmp, src);
+ unpacked_src = tmp;
+ } else
+ GBE_ASSERT(0);
+
+ sel.MOV(unpacked, unpacked_src);
+ sel.pop();
+ sel.MOV(dst, unpacked);
+ } else if (sel.hasLongType()) {
+ sel.MOV(dst, src);
+ }
+ }
+
INLINE bool emitOne(Selection::Opaque &sel, const ir::ConvertInstruction &insn, bool &markChildren) const
{
using namespace ir;
@@ -4713,30 +4881,39 @@ namespace gbe
if(opcode == ir::OP_SAT_CVT)
sel.curr.saturate = 1;
- if (opcode == OP_F16TO32 || opcode == OP_F32TO16) { /* Conversion between float and half. */
+ if (opcode == OP_F16TO32 || opcode == OP_F32TO16) {
+ /* Conversion between float and half. */
convertBetweenHalfFloat(sel, insn, markChildren);
} else if (dstFamily != FAMILY_DWORD && dstFamily != FAMILY_QWORD && srcFamily == FAMILY_DWORD) {
//convert i32/float to small int/half
convert32bitsToSmall(sel, insn, markChildren);
} else if (dstFamily == FAMILY_WORD && srcFamily == FAMILY_QWORD && srcType != ir::TYPE_DOUBLE) {
- //convert i64 to i16 and half.
+ //convert i64 to i16 and half.
convertI64To16bits(sel, insn, markChildren);
} else if (dstFamily == FAMILY_BYTE && srcFamily == FAMILY_QWORD && srcType != ir::TYPE_DOUBLE) {
//convert i64 to i8
convertI64ToI8(sel, insn, markChildren);
} else if ((dstType == ir::TYPE_S32 || dstType == ir::TYPE_U32) &&
- (srcType == ir::TYPE_U64 || srcType == ir::TYPE_S64)) {// Convert i64 to i32
+ (srcType == ir::TYPE_U64 || srcType == ir::TYPE_S64)) {
+ // Convert i64 to i32
convertI64ToI32(sel, insn, markChildren);
} else if (dstType == ir::TYPE_FLOAT && (srcType == ir::TYPE_U64 || srcType == ir::TYPE_S64)) {
+ // long -> float
convertI64ToFloat(sel, insn, markChildren);
} else if (dstType == ir::TYPE_DOUBLE && (srcType == ir::TYPE_U64 || srcType == ir::TYPE_S64)) {
- // TODO: long -> double
- GBE_ASSERT(0);
+ // long -> double
+ convertI64ToDouble(sel, insn, markChildren);
} else if ((dstType == ir::TYPE_U64 || dstType == ir::TYPE_S64)
&& (srcFamily != FAMILY_QWORD && srcType != ir::TYPE_FLOAT && srcType != ir::TYPE_HALF)) {
+ // int/short/char to long
convertSmallIntsToI64(sel, insn, markChildren);
+ } else if ((dstType == ir::TYPE_DOUBLE)
+ && (srcFamily != FAMILY_QWORD && srcType != ir::TYPE_FLOAT && srcType != ir::TYPE_HALF)) {
+ // int/short/char to double
+ convertSmallIntsToDouble(sel, insn, markChildren);
} else if ((dstType == ir::TYPE_U64 || dstType == ir::TYPE_S64)
&& (srcType == ir::TYPE_FLOAT || srcType == ir::TYPE_HALF || srcType == ir::TYPE_DOUBLE)) {
+ // All float type to long
convertFToI64(sel, insn, markChildren);
} else if ((srcType == ir::TYPE_FLOAT && dstType == ir::TYPE_DOUBLE) ||
(dstType == ir::TYPE_FLOAT && srcType == ir::TYPE_DOUBLE)) {
@@ -4744,8 +4921,12 @@ namespace gbe
convertBetweenFloatDouble(sel, insn, markChildren);
} else if ((srcType == ir::TYPE_HALF && dstType == ir::TYPE_DOUBLE) ||
(dstType == ir::TYPE_HALF && srcType == ir::TYPE_DOUBLE)) {
- // float and double conversion
+ // float and half conversion
convertBetweenHalfDouble(sel, insn, markChildren);
+ } else if (srcType == ir::TYPE_DOUBLE && dstType != ir::TYPE_FLOAT
+ && dstType != ir::TYPE_HALF && dstFamily != FAMILY_QWORD) {
+ // double to int/short/char
+ convertDoubleToSmallInts(sel, insn, markChildren);
} else if (srcType == ir::TYPE_HALF && (dstFamily == FAMILY_BYTE || dstFamily == FAMILY_WORD)) {
// Convert half to small int
convertHalfToSmallInts(sel, insn, markChildren);
--
1.9.1
More information about the Beignet
mailing list