aboutsummaryrefslogtreecommitdiff
path: root/libclc
diff options
context:
space:
mode:
authorRomaric Jodin <89833130+rjodinchr@users.noreply.github.com>2024-03-14 20:56:34 +0100
committerGitHub <noreply@github.com>2024-03-14 19:56:34 +0000
commitb6193a2dc2c7e1fb278161873e8f01f728412f4b (patch)
tree49c5a7991052992ae0cfd00727720f95c037ffc3 /libclc
parent25959310a50240c320283d1e4b23046fed152313 (diff)
downloadllvm-b6193a2dc2c7e1fb278161873e8f01f728412f4b.zip
llvm-b6193a2dc2c7e1fb278161873e8f01f728412f4b.tar.gz
llvm-b6193a2dc2c7e1fb278161873e8f01f728412f4b.tar.bz2
libclc: clspv: update gen_convert.cl for clspv (#66902)
Add a clspv switch in gen_convert.cl This is needed as Vulkan SPIR-V does not respect the assumptions needed to have the generic convert.cl compliant on many platforms. It is needed because of the conversion of TYPE_MAX and TYPE_MIN. Depending on the platform the behaviour can vary, but most of them just do not convert correctly those 2 values. Because of that, we also need to avoid having explicit function for simple conversions because it allows llvm to optimise the code, thus removing some of the added checks that are in fact needed.
Diffstat (limited to 'libclc')
-rw-r--r--libclc/CMakeLists.txt15
-rw-r--r--libclc/generic/lib/gen_convert.py129
2 files changed, 116 insertions, 28 deletions
diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index fa1d8e4..18f7794 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -174,6 +174,12 @@ add_custom_command(
DEPENDS ${script_loc} )
add_custom_target( "generate_convert.cl" DEPENDS convert.cl )
+add_custom_command(
+ OUTPUT clspv-convert.cl
+ COMMAND ${Python3_EXECUTABLE} ${script_loc} --clspv > clspv-convert.cl
+ DEPENDS ${script_loc} )
+add_custom_target( "clspv-generate_convert.cl" DEPENDS clspv-convert.cl )
+
enable_testing()
foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
@@ -218,11 +224,14 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
# Add the generated convert.cl here to prevent adding
# the one listed in SOURCES
if( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" )
- set( rel_files convert.cl )
- set( objects convert.cl )
if( NOT ENABLE_RUNTIME_SUBNORMAL AND NOT ${ARCH} STREQUAL "clspv" AND
NOT ${ARCH} STREQUAL "clspv64" )
+ set( rel_files convert.cl )
+ set( objects convert.cl )
list( APPEND rel_files generic/lib/subnormal_use_default.ll )
+ elseif(${ARCH} STREQUAL "clspv" OR ${ARCH} STREQUAL "clspv64")
+ set( rel_files clspv-convert.cl )
+ set( objects clspv-convert.cl )
endif()
else()
set( rel_files )
@@ -286,6 +295,8 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
# multiple invocations
add_dependencies( builtins.link.${arch_suffix}
generate_convert.cl )
+ add_dependencies( builtins.link.${arch_suffix}
+ clspv-generate_convert.cl )
# CMake will turn this include into absolute path
target_include_directories( builtins.link.${arch_suffix} PRIVATE
"generic/include" )
diff --git a/libclc/generic/lib/gen_convert.py b/libclc/generic/lib/gen_convert.py
index 612a918..21fc8eb 100644
--- a/libclc/generic/lib/gen_convert.py
+++ b/libclc/generic/lib/gen_convert.py
@@ -2,6 +2,7 @@
#
# Copyright (c) 2013 Victor Oliveira <victormatheus@gmail.com>
# Copyright (c) 2013 Jesse Towner <jessetowner@lavabit.com>
+# Copyright (c) 2024 Romaric Jodin <rjodin@chromium.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +27,16 @@
#
# convert_<destTypen><_sat><_roundingMode>(<sourceTypen>)
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument(
+ "--clspv", action="store_true", help="Generate the clspv variant of the code"
+)
+args = parser.parse_args()
+
+clspv = args.clspv
+
types = [
"char",
"uchar",
@@ -251,13 +262,19 @@ def generate_default_conversion(src, dst, mode):
print("#endif")
-for src in types:
- for dst in types:
- generate_default_conversion(src, dst, "")
+# Do not generate default conversion for clspv as they are handled natively
+if not clspv:
+ 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:
+ # Do not generate "_rte" conversion for clspv as they are handled
+ # natively
+ if clspv and mode == "_rte":
+ continue
generate_default_conversion(src, dst, mode)
#
@@ -304,21 +321,38 @@ def generate_saturated_conversion(src, dst, size):
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,
+ if clspv:
+ # 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:
+ # 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:
@@ -432,7 +466,10 @@ def generate_float_conversion(src, dst, size, mode, sat):
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}(r);".format(SRC=src, N=size))
+ if clspv:
+ print(" {SRC}{N} y = convert_{SRC}{N}_sat(r);".format(SRC=src, N=size))
+ else:
+ print(" {SRC}{N} y = convert_{SRC}{N}(r);".format(SRC=src, N=size))
if mode == "_rtz":
if src in int_types:
print(
@@ -448,11 +485,29 @@ def generate_float_conversion(src, dst, size, mode, sat):
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 clspv:
+ print(
+ " {BOOL}{N} c = convert_{BOOL}{N}(abs_y > abs_x);".format(
+ BOOL=bool_type[dst], N=size
+ )
+ )
+ if sizeof_type[src] >= 4 and src in int_types:
+ print(
+ " c = c || convert_{BOOL}{N}(({SRC}{N}){SRC_MAX} == x);".format(
+ BOOL=bool_type[dst], N=size, SRC=src, SRC_MAX=limit_max[src]
+ )
+ )
+ print(
+ " return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), c);".format(
+ DST=dst, N=size, BOOL=bool_type[dst], SRC=src
+ )
+ )
+ else:
+ 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(
@@ -460,11 +515,29 @@ def generate_float_conversion(src, dst, size, mode, sat):
)
)
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]
+ if clspv:
+ print(
+ " {BOOL}{N} c = convert_{BOOL}{N}(y > x);".format(
+ BOOL=bool_type[dst], N=size
+ )
+ )
+ if sizeof_type[src] >= 4 and src in int_types:
+ print(
+ " c = c || convert_{BOOL}{N}(({SRC}{N}){SRC_MAX} == x);".format(
+ BOOL=bool_type[dst], N=size, SRC=src, SRC_MAX=limit_max[src]
+ )
+ )
+ print(
+ " return select(r, nextafter(r, ({DST}{N})-INFINITY), c);".format(
+ DST=dst, N=size, BOOL=bool_type[dst], SRC=src
+ )
+ )
+ else:
+ 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("}")
@@ -484,4 +557,8 @@ for src in types:
for dst in float_types:
for size in vector_sizes:
for mode in rounding_modes:
+ # Do not generate "_rte" conversion for clspv as they are
+ # handled natively
+ if clspv and mode == "_rte":
+ continue
generate_float_conversion(src, dst, size, mode, "")