Currently Clang use int32 to represent sampler_t, which have been a source of issue for some backends, because in some backends sampler_t cannot be represented by int32. They have to depend on kernel argument metadata and use IPA to find the sampler arguments and global variables and transform them to target specific sampler type.
This patch uses opaque pointer type opencl.sampler_t* for sampler_t. For each use of program-scope sampler variable, it generates a function call of __translate_sampler_initializer. For each initialization of function-scope sampler variable, it generates a function call of __translate_sampler_initializer. For example,
constant sampler_t s1 = X1; // X1 is an integer literal void f() { f1(s1); f2(s1); const sampler_t s2 = X2; // X2 is an integer literal f3(s2); f4(s2); }
=> Llvm bitcode equivalent to (assuming opencl.sampler_t is the opaque type to represent sampler_t):
// opaque struct type for sampler struct opencl.sampler_t; constant opencl.sampler_t *__attribute__((always_inline)) __translate_sampler_initializer(unsigned); // a builtin function for translating sampler literal void f() { f1(__translate_sampler_initializer(X1)); f2(__translate_sampler_initializer(X1)); constant __opencl_sampler_t *s2 = __translate_sampler_initializer(X2); f3(s2); f4(s2); }
Each builtin library can implement its own __translate_sampler_initializer(). Since the real sampler type tends to be architecture dependent, allowing it to be initialized by a library function simplifies backend design. A typical implementation of __translate_sampler_initializer could be a table lookup of real sampler literal values. Since its argument is always a literal, the returned pointer is known at compile time and easily optimized to finally become some literal values directly put into image read instructions.
The advantage of this representation is:
- Robust - can be optimized without losing information
- Easy to implement – can be implemented by library instead of pass
The implementation of the design is to introduce a opaque sampler type and translates each sampler variable to sampler type in AST, and introduces cast from integer to sampler for each variable initializer. For copy initialization with function-scope variable, create integer to sampler cast. In codegen, sampler type is translated to opaque opencl.sampler_t* type. The cast from integer to sampler is translated to function call __translate_sampler_initializer. The global variable of sampler type is not translated since they are no longer referenced.
This patch is partially based on Alexey Sotkin's work in Khronos Clang (https://github.com/KhronosGroup/SPIR/commit/3d4eec61623502fc306e8c67c9868be2b136e42b).
Could we just have only int->sampler conversion? Without having an extra type for initializer?