From 29c26bce96f32441409206e98871988c99f7a231 Mon Sep 17 00:00:00 2001 From: Homer Hsing Date: Fri, 18 Oct 2013 10:26:55 +0800 Subject: [PATCH] support saturated converting from 64-bit int This patch supports saturated converting from 64-bit int to shorter int, and from 32-bit float to 64-bit int. This patch also contains test case. version 2: ulong had been declared in some platform Signed-off-by: Homer Hsing Reviewed-by: "Yang, Rong R" --- backend/src/backend/gen_context.cpp | 14 ++++++++++++ backend/src/backend/gen_insn_selection.cpp | 3 +++ backend/src/backend/gen_insn_selection.hxx | 1 + backend/src/ocl_stdlib.tmpl.h | 35 ++++++++++++++++++++++++++++++ kernels/builtin_convert_sat.cl | 16 ++++++++++++++ utests/builtin_convert_sat.cpp | 6 +++++ 6 files changed, 75 insertions(+) diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp index 858105a..43b3bc7 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_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) { diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp index 84b9983..7eae7ca 100644 --- a/backend/src/backend/gen_insn_selection.cpp +++ b/backend/src/backend/gen_insn_selection.cpp @@ -459,6 +459,7 @@ namespace gbe ALU2(UPSAMPLE_INT) ALU2(UPSAMPLE_LONG) ALU1WithTemp(CONVI_TO_I64) + ALU1WithTemp(CONVF_TO_I64) ALU1(CONVI64_TO_I) I64Shift(I64SHL) I64Shift(I64SHR) @@ -2579,6 +2580,8 @@ 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))); + 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 21b0a43..4499006 100644 --- a/backend/src/backend/gen_insn_selection.hxx +++ b/backend/src/backend/gen_insn_selection.hxx @@ -73,6 +73,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(I64MADSAT, I64MADSATInstruction) diff --git a/backend/src/ocl_stdlib.tmpl.h b/backend/src/ocl_stdlib.tmpl.h index 84214d1..34379b3 100644 --- a/backend/src/ocl_stdlib.tmpl.h +++ b/backend/src/ocl_stdlib.tmpl.h @@ -247,6 +247,41 @@ DEF(uint, int); DEF(uint, float); #undef DEF +#define DEF(DSTTYPE, SRCTYPE, MIN, MAX) \ + INLINE_OVERLOADABLE DSTTYPE convert_ ## DSTTYPE ## _sat(SRCTYPE x) { \ + return x > MAX ? (DSTTYPE)MAX : x < MIN ? (DSTTYPE)MIN : x; \ + } +DEF(char, long, -128, 127); +DEF(uchar, long, 0, 255); +DEF(short, long, -32768, 32767); +DEF(ushort, long, 0, 65535); +DEF(int, long, -0x7fffffff-1, 0x7fffffff); +DEF(uint, long, 0, 0xffffffffu); +DEF(long, float, -9.223372036854776e+18f, 9.223372036854776e+18f); +DEF(ulong, float, 0, 1.8446744073709552e+19f); +#undef DEF + +#define DEF(DSTTYPE, SRCTYPE, MAX) \ + INLINE_OVERLOADABLE DSTTYPE convert_ ## DSTTYPE ## _sat(SRCTYPE x) { \ + return x > MAX ? (DSTTYPE)MAX : x; \ + } +DEF(char, ulong, 127); +DEF(uchar, ulong, 255); +DEF(short, ulong, 32767); +DEF(ushort, ulong, 65535); +DEF(int, ulong, 0x7fffffff); +DEF(uint, ulong, 0xffffffffu); +#undef DEF + +INLINE_OVERLOADABLE long convert_long_sat(ulong x) { + ulong MAX = 0x7ffffffffffffffful; + return x > MAX ? MAX : x; +} + +INLINE_OVERLOADABLE ulong convert_ulong_sat(long x) { + return x < 0 ? 0 : x; +} + INLINE_OVERLOADABLE int isfinite(float x) { return __builtin_isfinite(x); } INLINE_OVERLOADABLE int isinf(float x) { return __builtin_isinf(x); } INLINE_OVERLOADABLE int isnan(float x) { diff --git a/kernels/builtin_convert_sat.cl b/kernels/builtin_convert_sat.cl index 281c890..1485f1d 100644 --- a/kernels/builtin_convert_sat.cl +++ b/kernels/builtin_convert_sat.cl @@ -9,24 +9,40 @@ DEF(char, short); DEF(char, ushort); DEF(char, int); DEF(char, uint); +DEF(char, long); +DEF(char, ulong); DEF(char, float); DEF(uchar, char); DEF(uchar, short); DEF(uchar, ushort); DEF(uchar, int); DEF(uchar, uint); +DEF(uchar, long); +DEF(uchar, ulong); DEF(uchar, float); DEF(short, ushort); DEF(short, int); DEF(short, uint); +DEF(short, long); +DEF(short, ulong); DEF(short, float); DEF(ushort, short); DEF(ushort, int); DEF(ushort, uint); +DEF(ushort, long); +DEF(ushort, ulong); DEF(ushort, float); DEF(int, uint); +DEF(int, long); +DEF(int, ulong); DEF(int, float); DEF(uint, int); +DEF(uint, long); +DEF(uint, ulong); DEF(uint, float); +DEF(long, ulong); +DEF(long, float); +DEF(ulong, long); +DEF(ulong, float); #undef DEF diff --git a/utests/builtin_convert_sat.cpp b/utests/builtin_convert_sat.cpp index e16ce16..3c96226 100644 --- a/utests/builtin_convert_sat.cpp +++ b/utests/builtin_convert_sat.cpp @@ -49,23 +49,29 @@ DEF(char, short, -128, 127); DEF(char, ushort, -128, 127); DEF(char, int, -128, 127); DEF(char, uint, -128, 127); +DEF(char, long, -128, 127); DEF(char, float, -128, 127); DEF(uchar, char, 0, 255); DEF(uchar, short, 0, 255); DEF(uchar, ushort, 0, 255); DEF(uchar, int, 0, 255); DEF(uchar, uint, 0, 255); +DEF(uchar, long, 0, 255); DEF(uchar, float, 0, 255); DEF(short, ushort, -32768, 32767); DEF(short, int, -32768, 32767); DEF(short, uint, -32768, 32767); +DEF(short, long, -32768, 32767); DEF(short, float, -32768, 32767); DEF(ushort, short, 0, 65535); DEF(ushort, int, 0, 65535); DEF(ushort, uint, 0, 65535); +DEF(ushort, long, 0, 65535); DEF(ushort, float, 0, 65535); DEF(int, uint, -0x7FFFFFFF-1, 0x7FFFFFFF); +DEF(int, long, -0x7FFFFFFF-1, 0x7FFFFFFF); DEF(int, float, -0x7FFFFFFF-1, 0x7FFFFFFF); DEF(uint, int, 0, 0xffffffffu); +DEF(uint, long, 0, 0xffffffffu); DEF(uint, float, 0, 0xffffffffu); #undef DEF -- 2.7.4