diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index fa1d8e4adbcc4..18f77940e7666 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 612a9184f4b27..21fc8ebc80d15 100644 --- a/libclc/generic/lib/gen_convert.py +++ b/libclc/generic/lib/gen_convert.py @@ -2,6 +2,7 @@ # # Copyright (c) 2013 Victor Oliveira # Copyright (c) 2013 Jesse Towner +# Copyright (c) 2024 Romaric Jodin # # 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_<_sat><_roundingMode>() +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 @@ def generate_float_conversion(src, dst, size, mode, sat): 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, "")