[Libclc-dev] [PATCH 4/4] spirv: add ability to build spirv from libclc

Jan Vesely via Libclc-dev libclc-dev at lists.llvm.org
Sat Oct 12 21:58:29 PDT 2019


On Fri, 2019-09-27 at 10:59 +1000, Dave Airlie via Libclc-dev wrote:
> This adds the ability to create two new targets (spirv--.spv and spirv64--.spv)
> that contain the SPIR-V builds of the major libclc components.
> 
> It uses a separate sources file as it doesn't require any of the sources
> that directly wrap llvm intrinsics or use __builtin intrinsics.
> 
> It builds unoptimised bytecode as the llvm -> spirv translator requires it.
> It inlines only some functions, but in general we don't want inlining as
> it makes the binary quite large.
> 
> v2: drop shuffle. add vload/store_half variants
> ---
>  libclc/CMakeLists.txt              | 67 +++++++++++++++++++++---
>  libclc/generic/lib/SOURCES-SPIRV   | 82 ++++++++++++++++++++++++++++++
>  libclc/generic/lib/shared/vload.cl |  3 +-
>  3 files changed, 143 insertions(+), 9 deletions(-)
>  create mode 100644 libclc/generic/lib/SOURCES-SPIRV
> 
> diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
> index 440eab07650..7af3eaa51ee 100644
> --- a/libclc/CMakeLists.txt
> +++ b/libclc/CMakeLists.txt
> @@ -39,6 +39,13 @@ if( ${LLVM_VERSION} VERSION_GREATER "3.9.0" )
>  	set( LIBCLC_TARGETS_ALL ${LIBCLC_TARGETS_ALL} amdgcn-mesa-mesa3d )
>  endif()
>  
> +find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_BINDIR} )
> +if( NOT LLVM_SPIRV )
> +	message( "libclc won't build spir-v support." )
> +else()
> +	set ( LIBCLC_TARGETS_ALL ${LIBCLC_TARGETS_ALL} spirv-- spirv64-- )
> +endif()

No automagic dependencies please. The build should fail if spirv was
requested and llvm-spirv not found.

> +
>  if( LIBCLC_TARGETS_TO_BUILD STREQUAL "all" )
>  	set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} )
>  endif()
> @@ -81,12 +88,14 @@ find_program( LLVM_CLANG clang PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH )
>  find_program( LLVM_AS llvm-as PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH )
>  find_program( LLVM_LINK llvm-link PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH )
>  find_program( LLVM_OPT opt PATHS ${LLVM_BINDIR} NO_DEFAULT_PATH )
> +find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_BINDIR} )
>  
>  # Print toolchain
>  message( "clang: ${LLVM_CLANG}" )
>  message( "llvm-as: ${LLVM_AS}" )
>  message( "llvm-link: ${LLVM_LINK}" )
>  message( "opt: ${LLVM_OPT}" )
> +message( "llvm-spirv: ${LLVM_SPIRV}" )
>  message( "" )
>  if( NOT LLVM_CLANG OR NOT LLVM_OPT OR NOT LLVM_AS OR NOT LLVM_LINK )
>  	message( FATAL_ERROR "toolchain incomplete!" )
> @@ -125,6 +134,10 @@ set( nvptx--_devices none )
>  set( nvptx64--_devices none )
>  set( nvptx--nvidiacl_devices none )
>  set( nvptx64--nvidiacl_devices none )
> +if ( LLVM_SPIRV )
> +	set( spirv--_devices none )
> +	set( spirv64--_devices none )
> +endif()

I don't think there needs to be a conditional here.

>  
>  # Setup aliases
>  set( cedar_aliases palm sumo sumo2 redwood juniper )
> @@ -187,10 +200,14 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
>  		set( DARCH ${ARCH} )
>  	endif()
>  
> +	set( sourcefilename "SOURCES" )
> +	if ( ${ARCH} STREQUAL spirv OR ${ARCH} STREQUAL spirv64 )
> +		set( sourcefilename "SOURCES-SPIRV" )
> +	endif()

I haven't gone through the details. How many files from SOURCES are
not present in SOURCES_SPIRV?

>  	# Enumerate SOURCES* files
>  	set( source_list )
>  	foreach( l ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS} )
> -		foreach( s "SOURCES" "SOURCES_${LLVM_MAJOR}.${LLVM_MINOR}" )
> +		foreach( s "${sourcefilename}" "${sourcefilename}_${LLVM_MAJOR}.${LLVM_MINOR}" )
>  			file( TO_CMAKE_PATH ${l}/lib/${s} file_loc )
>  			file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/${file_loc} loc )
>  			# Prepend the location to give higher priority to
> @@ -203,10 +220,15 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
>  
>  	# Add the generated convert.cl here to prevent adding
>  	# the one listed in SOURCES
> -	set( rel_files convert.cl )
> -	set( objects convert.cl )
> -	if( NOT ENABLE_RUNTIME_SUBNORMAL )
> -		list( APPEND rel_files generic/lib/subnormal_use_default.ll )
> +	if ( ${ARCH} STREQUAL spirv OR ${ARCH} STREQUAL spirv64 )
> +		set ( rel_files )
> +		set ( objects )
> +	else()
> +		set( rel_files convert.cl )
> +		set( objects convert.cl )
> +		if( NOT ENABLE_RUNTIME_SUBNORMAL )
> +			list( APPEND rel_files generic/lib/subnormal_use_default.ll )
> +		endif()
ENABLE_RUNTIME_SUBNORMAL should produce an error if spirv is the only
target.
>  	endif()
>  
>  	foreach( l ${source_list} )
> @@ -229,6 +251,20 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
>  	endforeach()
>  
>  	foreach( d ${${t}_devices} )
> +
> +	        set (dflags "")
> +	        set (oflags "")
> +		if ( ${t} STREQUAL "spirv--" )
> +			set (target "spir--")
> +			set (dflags "-DCLC_SPIRV")
> +			set (oflags -O0 -finline-hint-functions)
> +		elseif ( ${t} STREQUAL "spirv64--" )
> +		        set (target "spir64--")
> +			set (dflags "-DCLC_SPIRV")
> +			set (oflags -O0 -finline-hint-functions)
> +		else()
> +			set (target ${t})
> +		endif()
>  		# Some targets don't have a specific GPU to target
>  		if( ${d} STREQUAL "none" )
>  			set( mcpu )
> @@ -250,11 +286,12 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
>  		target_compile_definitions( builtins.link.${arch_suffix} PRIVATE
>  			"__CLC_INTERNAL" )
>  		target_compile_options( builtins.link.${arch_suffix} PRIVATE  -target
> -			${t} ${mcpu} -fno-builtin )
> +			${target} ${mcpu} -fno-builtin ${oflags} ${dflags} )
definitions should be handled in the target_compile_defitions above.
I think we can just add generic LIBCLC_TARGET_${t}, alternatively
clang defines __SPIR32__ and __SPIR64__ when targetting spir so we
don't really need a custom define.

Why -O0 necessary? is that not clang default?
-finline-hint-functions can be probably enabled for all targets, but I
need to check if it includes the always-inliner pass.

>  		set_target_properties( builtins.link.${arch_suffix} PROPERTIES
>  			LINKER_LANGUAGE CLC )
>  
>  		set( obj_suffix ${arch_suffix}.bc )
> +		set( spv_suffix ${arch_suffix}.spv )
>  
>  		# Add opt target
>  		add_custom_command( OUTPUT "builtins.opt.${obj_suffix}"
> @@ -265,6 +302,12 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
>  		add_custom_target( "opt.${obj_suffix}" ALL
>  		                   DEPENDS "builtins.opt.${obj_suffix}" )
>  
> +		add_custom_command( OUTPUT "${spv_suffix}"
> +				    COMMAND ${LLVM_SPIRV} -o
> +				    "${spv_suffix}"
> +				    "builtins.link.${obj_suffix}"
> +				    DEPENDS "builtins.link.${arch_suffix}")
> +
>  		# Add prepare target
>  		add_custom_command( OUTPUT "${obj_suffix}"
>  			            COMMAND prepare_builtins -o
> @@ -274,8 +317,16 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
>  				            "builtins.opt.${obj_suffix}"
>  				            prepare_builtins )
>  		add_custom_target( "prepare-${obj_suffix}" ALL
> -		                   DEPENDS "${obj_suffix}" )
> -		install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION ${CMAKE_INSTALL_DATADIR}/clc )
> +				    DEPENDS "${obj_suffix}" )
> +
> +		if ( ${t} STREQUAL "spirv--" OR ${t} STREQUAL "spirv64--")
> +			# Add spv target
> +			add_custom_target( "spv.${spv_suffix}" ALL
> +					    DEPENDS "${spv_suffix}" )
> +			install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix} DESTINATION ${CMAKE_INSTALL_DATADIR}/clc )
> +		else()
> +			install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION ${CMAKE_INSTALL_DATADIR}/clc )
> +		endif()
>  		# nvptx-- targets don't include workitem builtins
>  		if( NOT ${t} MATCHES ".*ptx.*--$" )
>  			add_test( NAME external-calls-${obj_suffix}
> diff --git a/libclc/generic/lib/SOURCES-SPIRV b/libclc/generic/lib/SOURCES-SPIRV
> new file mode 100644
> index 00000000000..a3257a932bd
> --- /dev/null
> +++ b/libclc/generic/lib/SOURCES-SPIRV
> @@ -0,0 +1,82 @@
> +subnormal_config.cl
> +common/degrees.cl
> +common/mix.cl
> +common/radians.cl
> +common/sign.cl
> +common/smoothstep.cl
> +common/step.cl
> +geometric/cross.cl
> +geometric/distance.cl
> +geometric/dot.cl
> +geometric/fast_distance.cl
> +geometric/fast_length.cl
> +geometric/fast_normalize.cl
> +geometric/length.cl
> +geometric/normalize.cl
> +integer/rotate.cl
> +integer/mad_sat.cl
> +math/acos.cl
> +math/acosh.cl
> +math/acospi.cl
> +math/asin.cl
> +math/asinh.cl
> +math/asinpi.cl
> +math/atan.cl
> +math/atan2.cl
> +math/atan2pi.cl
> +math/atanh.cl
> +math/atanpi.cl
> +math/cbrt.cl
> +math/cos.cl
> +math/cosh.cl
> +math/cospi.cl
> +math/ep_log.cl
> +math/erf.cl
> +math/erfc.cl
> +math/exp.cl
> +math/exp_helper.cl
> +math/expm1.cl
> +math/exp2.cl
> +math/clc_exp10.cl
> +math/exp10.cl
> +math/fract.cl
> +math/frexp.cl
> +math/half_rsqrt.cl
> +math/half_sqrt.cl
> +math/clc_hypot.cl
> +math/hypot.cl
> +math/ilogb.cl
> +math/lgamma.cl
> +math/lgamma_r.cl
> +math/log.cl
> +math/log10.cl
> +math/log1p.cl
> +math/log2.cl
> +math/logb.cl
> +math/modf.cl
> +math/tables.cl
> +math/clc_pow.cl
> +math/pow.cl
> +math/clc_pown.cl
> +math/pown.cl
> +math/clc_powr.cl
> +math/powr.cl
> +math/clc_remainder.cl
> +math/remainder.cl
> +math/clc_remquo.cl
> +math/remquo.cl
> +math/clc_rootn.cl
> +math/rootn.cl
> +math/sin.cl
> +math/sincos.cl
> +math/sincos_helpers.cl
> +math/sinh.cl
> +math/sinpi.cl
> +math/clc_tan.cl
> +math/tan.cl
> +math/tanh.cl
> +math/clc_tanpi.cl
> +math/tanpi.cl
> +math/tgamma.cl
> +shared/vload.cl
> +shared/vstore.cl
> diff --git a/libclc/generic/lib/shared/vload.cl b/libclc/generic/lib/shared/vload.cl
> index 9c37fcf9981..9d28aac10c0 100644
> --- a/libclc/generic/lib/shared/vload.cl
> +++ b/libclc/generic/lib/shared/vload.cl
> @@ -33,6 +33,7 @@
>      VLOAD_VECTORIZE(__CLC_SCALAR_GENTYPE, __constant) \
>      VLOAD_VECTORIZE(__CLC_SCALAR_GENTYPE, __global) \
>  
> +#ifndef __CLC_SPIRV__
>  #define VLOAD_TYPES() \
>      VLOAD_ADDR_SPACES(char) \
>      VLOAD_ADDR_SPACES(uchar) \
> @@ -54,7 +55,7 @@ VLOAD_TYPES()
>  #pragma OPENCL EXTENSION cl_khr_fp16 : enable
>      VLOAD_ADDR_SPACES(half)
>  #endif
> -
> +#endif

can you either split the .cl files changes, or include all of them?

I plan to take a more detailed look and actually build the library
sometime this week. I think there's a way to simplify couple of things
to make this integration easier, but it can always be cleaned up
later.

Jan

>  /* vload_half are legal even without cl_khr_fp16 */
>  /* no vload_half for double */
>  #if __clang_major__ < 6

-- 
Jan Vesely <jan.vesely at rutgers.edu>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://lists.llvm.org/pipermail/libclc-dev/attachments/20191013/e6dd0d9e/attachment.sig>


More information about the Libclc-dev mailing list