[Beignet] [PATCH 3/5] Backend: Add double conversion to insn selection.
Yang, Rong R
rong.r.yang at intel.com
Mon Nov 2 23:32:58 PST 2015
One comment.
> -----Original Message-----
> From: Beignet [mailto:beignet-bounces at lists.freedesktop.org] On Behalf Of
> junyan.he at inbox.com
> Sent: Tuesday, October 27, 2015 18:36
> To: beignet at lists.freedesktop.org
> Subject: [Beignet] [PATCH 3/5] Backend: Add double conversion to insn
> selection.
>
> 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 b027ca8..7c000ef 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);
isScalarReg(src) and isScalarReg(dst) is not always same, suppose src is scalar and dst is vector.
So unpacked is scalar and execwidth is 8/16, it is not correct. So other functions have the same problem.
> + 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
>
>
>
> _______________________________________________
> Beignet mailing list
> Beignet at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/beignet
More information about the Beignet
mailing list