[libclc] r192385 - Port pocl's gen_convert.py script to libclc

Tom Stellard thomas.stellard at amd.com
Thu Oct 10 12:09:01 PDT 2013


Author: tstellar
Date: Thu Oct 10 14:09:01 2013
New Revision: 192385

URL: http://llvm.org/viewvc/llvm-project?rev=192385&view=rev
Log:
Port pocl's gen_convert.py script to libclc

This script generates implementations for the entire set of convert_*
functions,

Added:
    libclc/trunk/generic/lib/gen_convert.py
Removed:
    libclc/trunk/generic/lib/convert.cl
Modified:
    libclc/trunk/configure.py
    libclc/trunk/generic/include/clc/convert.h

Modified: libclc/trunk/configure.py
URL: http://llvm.org/viewvc/llvm-project/libclc/trunk/configure.py?rev=192385&r1=192384&r2=192385&view=diff
==============================================================================
--- libclc/trunk/configure.py (original)
+++ libclc/trunk/configure.py Thu Oct 10 14:09:01 2013
@@ -107,6 +107,8 @@ b.build(prepare_builtins, "LLVM_TOOL_LIN
 
 b.rule("PREPARE_BUILTINS", "%s -o $out $in" % prepare_builtins,
        'PREPARE-BUILTINS $out')
+b.rule("PYTHON_GEN", "python < $in > $out", "PYTHON_GEN $out")
+b.build('generic/lib/convert.cl', "PYTHON_GEN", ['generic/lib/gen_convert.py'])
 
 manifest_deps = set([sys.argv[0], os.path.join(srcdir, 'build', 'metabuild.py'),
                      os.path.join(srcdir, 'build', 'ninja_syntax.py')])
@@ -145,6 +147,7 @@ for target in targets:
     clang_bc_flags = "-target %s -I`dirname $in` %s " \
                      "-Dcl_clang_storage_class_specifiers " \
                      "-Dcl_khr_fp64 " \
+                     "-Dcles_khr_int64 " \
                      "-D__CLC_INTERNAL " \
                      "-emit-llvm" % (target, clang_cl_includes)
     if device['gpu'] != '':

Modified: libclc/trunk/generic/include/clc/convert.h
URL: http://llvm.org/viewvc/llvm-project/libclc/trunk/generic/include/clc/convert.h?rev=192385&r1=192384&r2=192385&view=diff
==============================================================================
--- libclc/trunk/generic/include/clc/convert.h (original)
+++ libclc/trunk/generic/include/clc/convert.h Thu Oct 10 14:09:01 2013
@@ -49,5 +49,12 @@
   _CLC_VECTOR_CONVERT_TO1(SUFFIX)
 #endif
 
-_CLC_VECTOR_CONVERT_TO()
-_CLC_VECTOR_CONVERT_TO(_sat)
+#define _CLC_VECTOR_CONVERT_TO_SUFFIX(ROUND) \
+  _CLC_VECTOR_CONVERT_TO(_sat##ROUND) \
+  _CLC_VECTOR_CONVERT_TO(ROUND)
+
+_CLC_VECTOR_CONVERT_TO_SUFFIX(_rtn)
+_CLC_VECTOR_CONVERT_TO_SUFFIX(_rte)
+_CLC_VECTOR_CONVERT_TO_SUFFIX(_rtz)
+_CLC_VECTOR_CONVERT_TO_SUFFIX(_rtp)
+_CLC_VECTOR_CONVERT_TO_SUFFIX()

Removed: libclc/trunk/generic/lib/convert.cl
URL: http://llvm.org/viewvc/llvm-project/libclc/trunk/generic/lib/convert.cl?rev=192384&view=auto
==============================================================================
--- libclc/trunk/generic/lib/convert.cl (original)
+++ libclc/trunk/generic/lib/convert.cl (removed)
@@ -1,149 +0,0 @@
-#include <clc/clc.h>
-
-#ifdef cl_khr_fp64
-#pragma OPENCL EXTENSION cl_khr_fp64 : enable
-#endif
-
-#define CONVERT_ID(FROM_TYPE, TO_TYPE, SUFFIX) \
-  _CLC_OVERLOAD _CLC_DEF TO_TYPE convert_##TO_TYPE##SUFFIX(FROM_TYPE x) { \
-    return x; \
-  }
-
-#define CONVERT_VECTORIZE(FROM_TYPE, TO_TYPE, SUFFIX) \
-  _CLC_OVERLOAD _CLC_DEF TO_TYPE##2 convert_##TO_TYPE##2##SUFFIX(FROM_TYPE##2 x) { \
-    return (TO_TYPE##2)(convert_##TO_TYPE##SUFFIX(x.x), convert_##TO_TYPE##SUFFIX(x.y)); \
-  } \
-\
-  _CLC_OVERLOAD _CLC_DEF TO_TYPE##3 convert_##TO_TYPE##3##SUFFIX(FROM_TYPE##3 x) { \
-    return (TO_TYPE##3)(convert_##TO_TYPE##SUFFIX(x.x), convert_##TO_TYPE##SUFFIX(x.y), convert_##TO_TYPE##SUFFIX(x.z)); \
-  } \
-\
-  _CLC_OVERLOAD _CLC_DEF TO_TYPE##4 convert_##TO_TYPE##4##SUFFIX(FROM_TYPE##4 x) { \
-    return (TO_TYPE##4)(convert_##TO_TYPE##2##SUFFIX(x.lo), convert_##TO_TYPE##2##SUFFIX(x.hi)); \
-  } \
-\
-  _CLC_OVERLOAD _CLC_DEF TO_TYPE##8 convert_##TO_TYPE##8##SUFFIX(FROM_TYPE##8 x) { \
-    return (TO_TYPE##8)(convert_##TO_TYPE##4##SUFFIX(x.lo), convert_##TO_TYPE##4##SUFFIX(x.hi)); \
-  } \
-\
-  _CLC_OVERLOAD _CLC_DEF TO_TYPE##16 convert_##TO_TYPE##16##SUFFIX(FROM_TYPE##16 x) { \
-    return (TO_TYPE##16)(convert_##TO_TYPE##8##SUFFIX(x.lo), convert_##TO_TYPE##8##SUFFIX(x.hi)); \
-  }
-
-#define CONVERT_ID_FROM1(FROM_TYPE) \
-  CONVERT_ID(FROM_TYPE, char, ) \
-  CONVERT_ID(FROM_TYPE, uchar, ) \
-  CONVERT_ID(FROM_TYPE, int, ) \
-  CONVERT_ID(FROM_TYPE, uint, ) \
-  CONVERT_ID(FROM_TYPE, short, ) \
-  CONVERT_ID(FROM_TYPE, ushort, ) \
-  CONVERT_ID(FROM_TYPE, long, ) \
-  CONVERT_ID(FROM_TYPE, ulong, ) \
-  CONVERT_ID(FROM_TYPE, float, )
-
-#ifdef cl_khr_fp64
-#define CONVERT_ID_FROM(FROM_TYPE) \
-  CONVERT_ID_FROM1(FROM_TYPE) \
-  CONVERT_ID(FROM_TYPE, double, )
-#else
-#define CONVERT_ID_FROM(FROM_TYPE) \
-  CONVERT_ID_FROM1(FROM_TYPE)
-#endif
-
-#define CONVERT_ID_TO1()
-  CONVERT_ID_FROM(char)
-  CONVERT_ID_FROM(uchar)
-  CONVERT_ID_FROM(int)
-  CONVERT_ID_FROM(uint)
-  CONVERT_ID_FROM(short)
-  CONVERT_ID_FROM(ushort)
-  CONVERT_ID_FROM(long)
-  CONVERT_ID_FROM(ulong)
-  CONVERT_ID_FROM(float)
-
-#ifdef cl_khr_fp64
-#define CONVERT_ID_TO() \
-  CONVERT_ID_TO1() \
-  CONVERT_ID_FROM(double)
-#else
-#define CONVERT_ID_TO() \
-  CONVERT_ID_TO1()
-#endif
-
-CONVERT_ID_TO()
-
-_CLC_OVERLOAD _CLC_DEF char convert_char_sat(long l) {
-  return l > 127 ? 127 : l < -128 ? -128 : l;
-}
-
-_CLC_OVERLOAD _CLC_DEF uchar convert_uchar_sat(ulong l) {
-  return l > 255U ? 255U : l;
-}
-
-_CLC_OVERLOAD _CLC_DEF short convert_short_sat(long l) {
-  return l > 32767 ? 32767 : l < -32768 ? -32768 : l;
-}
-
-_CLC_OVERLOAD _CLC_DEF ushort convert_ushort_sat(ulong l) {
-  return l > 65535U ? 65535U : l;
-}
-
-_CLC_OVERLOAD _CLC_DEF int convert_int_sat(long l) {
-  return l > ((1L<<31)-1) ? ((1L<<31L)-1) : l < -(1L<<31) ? -(1L<<31) : l;
-}
-
-_CLC_OVERLOAD _CLC_DEF uint convert_uint_sat(ulong l) {
-  return l > ((1UL<<32)-1) ? ((1UL<<32)-1) : l;
-}
-
-CONVERT_ID(long, long, _sat)
-CONVERT_ID(ulong, ulong, _sat)
-#ifdef cl_khr_fp64
-CONVERT_ID(double, float, _sat)
-CONVERT_ID(double, double, _sat)
-#else
-CONVERT_ID(float, float, _sat)
-#endif
-
-#define CONVERT_VECTORIZE_FROM1(FROM_TYPE, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, char, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, uchar, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, int, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, uint, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, short, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, ushort, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, long, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, ulong, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, float, SUFFIX)
-
-#ifdef cl_khr_fp64
-#define CONVERT_VECTORIZE_FROM(FROM_TYPE, SUFFIX) \
-  CONVERT_VECTORIZE_FROM1(FROM_TYPE, SUFFIX) \
-  CONVERT_VECTORIZE(FROM_TYPE, double, SUFFIX)
-#else
-#define CONVERT_VECTORIZE_FROM(FROM_TYPE, SUFFIX) \
-  CONVERT_VECTORIZE_FROM1(FROM_TYPE, SUFFIX)
-#endif
-
-#define CONVERT_VECTORIZE_TO1(SUFFIX) \
-  CONVERT_VECTORIZE_FROM(char, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(uchar, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(int, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(uint, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(short, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(ushort, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(long, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(ulong, SUFFIX) \
-  CONVERT_VECTORIZE_FROM(float, SUFFIX)
-
-#ifdef cl_khr_fp64
-#define CONVERT_VECTORIZE_TO(SUFFIX) \
-  CONVERT_VECTORIZE_TO1(SUFFIX) \
-  CONVERT_VECTORIZE_FROM(double, SUFFIX)
-#else
-#define CONVERT_VECTORIZE_TO(SUFFIX) \
-  CONVERT_VECTORIZE_TO1(SUFFIX)
-#endif
-
-CONVERT_VECTORIZE_TO()
-CONVERT_VECTORIZE_TO(_sat)

Added: libclc/trunk/generic/lib/gen_convert.py
URL: http://llvm.org/viewvc/llvm-project/libclc/trunk/generic/lib/gen_convert.py?rev=192385&view=auto
==============================================================================
--- libclc/trunk/generic/lib/gen_convert.py (added)
+++ libclc/trunk/generic/lib/gen_convert.py Thu Oct 10 14:09:01 2013
@@ -0,0 +1,390 @@
+#!/usr/bin/env python3
+
+# OpenCL built-in library: type conversion functions
+#
+# Copyright (c) 2013 Victor Oliveira <victormatheus at gmail.com>
+# Copyright (c) 2013 Jesse Towner <jessetowner at lavabit.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# This script generates the file convert_type.cl, which contains all of the
+# OpenCL functions in the form:
+#
+# convert_<destTypen><_sat><_roundingMode>(<sourceTypen>)
+
+types = ['char', 'uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong', 'float', 'double']
+int_types = ['char', 'uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
+unsigned_types = ['uchar', 'ushort', 'uint', 'ulong']
+float_types = ['float', 'double']
+int64_types = ['long', 'ulong']
+float64_types = ['double']
+vector_sizes = ['', '2', '3', '4', '8', '16']
+half_sizes = [('2',''), ('4','2'), ('8','4'), ('16','8')]
+
+saturation = ['','_sat']
+rounding_modes = ['_rtz','_rte','_rtp','_rtn']
+float_prefix = {'float':'FLT_', 'double':'DBL_'}
+float_suffix = {'float':'f', 'double':''}
+
+bool_type = {'char'  : 'char',
+             'uchar' : 'char',
+             'short' : 'short',
+             'ushort': 'short',
+             'int'   : 'int',
+             'uint'  : 'int',
+             'long'  : 'long',
+             'ulong' : 'long',
+             'float'  : 'int',
+             'double' : 'long'}
+
+unsigned_type = {'char'  : 'uchar',
+                 'uchar' : 'uchar',
+                 'short' : 'ushort',
+                 'ushort': 'ushort',
+                 'int'   : 'uint',
+                 'uint'  : 'uint',
+                 'long'  : 'ulong',
+                 'ulong' : 'ulong'}
+
+sizeof_type = {'char'  : 1, 'uchar'  : 1,
+               'short' : 2, 'ushort' : 2,
+               'int'   : 4, 'uint'   : 4,
+               'long'  : 8, 'ulong'  : 8,
+               'float' : 4, 'double' : 8}
+
+limit_max = {'char'  : 'CHAR_MAX',
+             'uchar' : 'UCHAR_MAX',
+             'short' : 'SHRT_MAX',
+             'ushort': 'USHRT_MAX',
+             'int'   : 'INT_MAX',
+             'uint'  : 'UINT_MAX',
+             'long'  : 'LONG_MAX',
+             'ulong' : 'ULONG_MAX'}
+
+limit_min = {'char'  : 'CHAR_MIN',
+             'uchar' : '0',
+             'short' : 'SHRT_MIN',
+             'ushort': '0',
+             'int'   : 'INT_MIN',
+             'uint'  : '0',
+             'long'  : 'LONG_MIN',
+             'ulong' : '0'}
+
+def conditional_guard(src, dst):
+  int64_count = 0
+  float64_count = 0
+  if src in int64_types:
+    int64_count = int64_count +1
+  elif src in float64_types:
+    float64_count = float64_count + 1
+  if dst in int64_types:
+    int64_count = int64_count +1
+  elif dst in float64_types:
+    float64_count = float64_count + 1
+  if float64_count > 0 and int64_count > 0:
+    print("#if defined(cl_khr_fp64) && defined(cles_khr_int64)")
+    return True
+  elif float64_count > 0:
+    print("#ifdef cl_khr_fp64")
+    return True
+  elif int64_count > 0:
+    print("#ifdef cles_khr_int64")
+    return True
+  return False
+
+
+print("""/* !!!! AUTOGENERATED FILE generated by convert_type.py !!!!!
+
+   DON'T CHANGE THIS FILE. MAKE YOUR CHANGES TO convert_type.py AND RUN:
+   $ ./generate-conversion-type-cl.sh
+
+   OpenCL type conversion functions
+
+   Copyright (c) 2013 Victor Oliveira <victormatheus at gmail.com>
+   Copyright (c) 2013 Jesse Towner <jessetowner at lavabit.com>
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy
+   of this software and associated documentation files (the "Software"), to deal
+   in the Software without restriction, including without limitation the rights
+   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+   copies of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+   THE SOFTWARE.
+*/
+
+#include <clc/clc.h>
+
+#ifdef cl_khr_fp64
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+#endif
+
+#define INFINITY 1.0f / 0.0f
+
+""")
+
+#
+# Default Conversions
+#
+# All conversions are in accordance with the OpenCL specification,
+# which cites the C99 conversion rules.
+#
+# Casting from floating point to integer results in conversions
+# with truncation, so it should be suitable for the default convert
+# functions.
+#
+# Conversions from integer to floating-point, and floating-point to
+# floating-point through casting is done with the default rounding
+# mode. While C99 allows dynamically changing the rounding mode
+# during runtime, it is not a supported feature in OpenCL according
+# to Section 7.1 - Rounding Modes in the OpenCL 1.2 specification.
+#
+# Therefore, we can assume for optimization purposes that the
+# rounding mode is fixed to round-to-nearest-even. Platform target
+# authors should ensure that the rounding-control registers remain
+# in this state, and that this invariant holds.
+#
+# Also note, even though the OpenCL specification isn't entirely
+# clear on this matter, we implement all rounding mode combinations
+# even for integer-to-integer conversions. When such a conversion
+# is used, the rounding mode is ignored.
+#
+
+def generate_default_conversion(src, dst, mode):
+  close_conditional = conditional_guard(src, dst)
+
+  # scalar conversions
+  print("""_CLC_DEF _CLC_OVERLOAD
+{DST} convert_{DST}{M}({SRC} x)
+{{
+  return ({DST})x;
+}}
+""".format(SRC=src, DST=dst, M=mode))
+
+  # vector conversions, done through decomposition to components
+  for size, half_size in half_sizes:
+    print("""_CLC_DEF _CLC_OVERLOAD
+{DST}{N} convert_{DST}{N}{M}({SRC}{N} x)
+{{
+  return ({DST}{N})(convert_{DST}{H}(x.lo), convert_{DST}{H}(x.hi));
+}}
+""".format(SRC=src, DST=dst, N=size, H=half_size, M=mode))
+
+  # 3-component vector conversions
+  print("""_CLC_DEF _CLC_OVERLOAD
+{DST}3 convert_{DST}3{M}({SRC}3 x)
+{{
+  return ({DST}3)(convert_{DST}2(x.s01), convert_{DST}(x.s2));
+}}""".format(SRC=src, DST=dst, M=mode))
+
+  if close_conditional:
+    print("#endif")
+
+
+for src in types:
+  for dst in types:
+    generate_default_conversion(src, dst, '')
+
+for src in int_types:
+  for dst in int_types:
+    for mode in rounding_modes:
+      generate_default_conversion(src, dst, mode)
+
+#
+# Saturated Conversions To Integers
+#
+# These functions are dependent on the unsaturated conversion functions
+# generated above, and use clamp, max, min, and select to eliminate
+# branching and vectorize the conversions.
+#
+# Again, as above, we allow all rounding modes for integer-to-integer
+# conversions with saturation.
+#
+
+def generate_saturated_conversion(src, dst, size):
+  # Header
+  close_conditional = conditional_guard(src, dst)
+  print("""_CLC_DEF _CLC_OVERLOAD
+{DST}{N} convert_{DST}{N}_sat({SRC}{N} x)
+{{""".format(DST=dst, SRC=src, N=size))
+
+  # FIXME: This is a work around for lack of select function with
+  # signed third argument when the first two arguments are unsigned types.
+  # We cast to the signed type for sign-extension, then do a bitcast to
+  # the unsigned type.
+  if dst in unsigned_types:
+    bool_prefix = "as_{DST}{N}(convert_{BOOL}{N}".format(DST=dst, BOOL=bool_type[dst], N=size);
+    bool_suffix = ")"
+  else:
+    bool_prefix = "convert_{BOOL}{N}".format(BOOL=bool_type[dst], N=size);
+    bool_suffix = ""
+
+  # Body
+  if src == dst:
+
+    # Conversion between same types
+    print("  return x;")
+
+  elif src in float_types:
+
+    # Conversion from float to int
+    print("""  {DST}{N} y = convert_{DST}{N}(x);
+  y = select(y, ({DST}{N}){DST_MIN}, {BP}(x < ({SRC}{N}){DST_MIN}){BS});
+  y = select(y, ({DST}{N}){DST_MAX}, {BP}(x > ({SRC}{N}){DST_MAX}){BS});
+  return y;""".format(SRC=src, DST=dst, N=size,
+      DST_MIN=limit_min[dst], DST_MAX=limit_max[dst],
+      BP=bool_prefix, BS=bool_suffix))
+
+  else:
+
+    # Integer to integer convesion with sizeof(src) == sizeof(dst)
+    if sizeof_type[src] == sizeof_type[dst]:
+      if src in unsigned_types:
+        print("  x = min(x, ({SRC}){DST_MAX});".format(SRC=src, DST_MAX=limit_max[dst]))
+      else:
+        print("  x = max(x, ({SRC})0);".format(SRC=src))
+
+    # Integer to integer conversion where sizeof(src) > sizeof(dst)
+    elif sizeof_type[src] > sizeof_type[dst]:
+      if src in unsigned_types:
+        print("  x = min(x, ({SRC}){DST_MAX});".format(SRC=src, DST_MAX=limit_max[dst]))
+      else:
+        print("  x = clamp(x, ({SRC}){DST_MIN}, ({SRC}){DST_MAX});"
+          .format(SRC=src, DST_MIN=limit_min[dst], DST_MAX=limit_max[dst]))
+
+    # Integer to integer conversion where sizeof(src) < sizeof(dst)
+    elif src not in unsigned_types and dst in unsigned_types:
+        print("  x = max(x, ({SRC})0);".format(SRC=src))
+
+    print("  return convert_{DST}{N}(x);".format(DST=dst, N=size))
+
+  # Footer
+  print("}")
+  if close_conditional:
+    print("#endif")
+
+
+for src in types:
+  for dst in int_types:
+    for size in vector_sizes:
+      generate_saturated_conversion(src, dst, size)
+
+
+def generate_saturated_conversion_with_rounding(src, dst, size, mode):
+  # Header
+  close_conditional = conditional_guard(src, dst)
+
+  # Body
+  print("""_CLC_DEF _CLC_OVERLOAD
+{DST}{N} convert_{DST}{N}_sat{M}({SRC}{N} x)
+{{
+  return convert_{DST}{N}_sat(x);
+}}
+""".format(DST=dst, SRC=src, N=size, M=mode))
+
+  # Footer
+  if close_conditional:
+    print("#endif")
+
+
+for src in int_types:
+  for dst in int_types:
+    for size in vector_sizes:
+      for mode in rounding_modes:
+        generate_saturated_conversion_with_rounding(src, dst, size, mode)
+
+#
+# Conversions To/From Floating-Point With Rounding
+#
+# Note that we assume as above that casts from floating-point to
+# integer are done with truncation, and that the default rounding
+# mode is fixed to round-to-nearest-even, as per C99 and OpenCL
+# rounding rules.
+#
+# These functions rely on the use of abs, ceil, fabs, floor,
+# nextafter, sign, rint and the above generated conversion functions.
+#
+# Only conversions to integers can have saturation.
+#
+
+def generate_float_conversion(src, dst, size, mode, sat):
+  # Header
+  close_conditional = conditional_guard(src, dst)
+  print("""_CLC_DEF _CLC_OVERLOAD
+{DST}{N} convert_{DST}{N}{S}{M}({SRC}{N} x)
+{{""".format(SRC=src, DST=dst, N=size, M=mode, S=sat))
+
+  # Perform conversion
+  if dst in int_types:
+    if mode == '_rte':
+      print("  x = rint(x);");
+    elif mode == '_rtp':
+      print("  x = ceil(x);");
+    elif mode == '_rtn':
+      print("  x = floor(x);");
+    print("  return convert_{DST}{N}{S}(x);".format(DST=dst, N=size, S=sat))
+  elif mode == '_rte':
+    print("  return convert_{DST}{N}(x);".format(DST=dst, N=size))
+  else:
+    print("  {DST}{N} r = convert_{DST}{N}(x);".format(DST=dst, N=size))
+    print("  {SRC}{N} y = convert_{SRC}{N}(y);".format(SRC=src, N=size))
+    if mode == '_rtz':
+      if src in int_types:
+        print("  {USRC}{N} abs_x = abs(x);".format(USRC=unsigned_type[src], N=size))
+        print("  {USRC}{N} abs_y = abs(y);".format(USRC=unsigned_type[src], N=size))
+      else:
+        print("  {SRC}{N} abs_x = fabs(x);".format(SRC=src, N=size))
+        print("  {SRC}{N} abs_y = fabs(y);".format(SRC=src, N=size))
+      print("  return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), convert_{BOOL}{N}(abs_y > abs_x));"
+        .format(DST=dst, N=size, BOOL=bool_type[dst]))
+    if mode == '_rtp':
+      print("  return select(r, nextafter(r, ({DST}{N})INFINITY), convert_{BOOL}{N}(y < x));"
+        .format(DST=dst, N=size, BOOL=bool_type[dst]))
+    if mode == '_rtn':
+      print("  return select(r, nextafter(r, ({DST}{N})-INFINITY), convert_{BOOL}{N}(y > x));"
+        .format(DST=dst, N=size, BOOL=bool_type[dst]))
+
+  # Footer
+  print("}")
+  if close_conditional:
+    print("#endif")
+
+
+for src in float_types:
+  for dst in int_types:
+    for size in vector_sizes:
+      for mode in rounding_modes:
+        for sat in saturation:
+          generate_float_conversion(src, dst, size, mode, sat)
+
+
+for src in types:
+  for dst in float_types:
+    for size in vector_sizes:
+      for mode in rounding_modes:
+        generate_float_conversion(src, dst, size, mode, '')





More information about the cfe-commits mailing list