SPIR provisional specifciation is now available in the Khronos website

Hi All,

In continuation of the previous SPIR introduction email here is a link to the specification:
http://www.khronos.org/registry/cl/specs/spir_spec-1.0-provisional.pdf

The first topic which we would like to discuss is "SPIR portability".
I will send soon an additional mail which will help in leading the discussion on this topic.

Thanks and happy reading,
Boaz

Hi Boaz,

I have a couple of specific questions:

(a) You mention special calling conventions and adding them to LLVM.
What are their semantics? And what is their purpose?

(b) Why disallow type conversion for vector types? (ss. 3.3)

Cheers,

James

From: llvmdev-bounces@cs.uiuc.edu [mailto:llvmdev-bounces@cs.uiuc.edu]
On Behalf Of James Molloy
Sent: Tuesday, September 11, 2012 8:49 AM
To: Ouriel, Boaz
Cc: cfe-dev@cs.uiuc.edu; llvmdev@cs.uiuc.edu
Subject: Re: [LLVMdev] SPIR provisional specifciation is now available
in the Khronos website

Hi Boaz,

I have a couple of specific questions:

(a) You mention special calling conventions and adding them to LLVM.
What are their semantics? And what is their purpose?

[Villmow, Micah] One purpose is to differentiate between kernel and device functions.
Another is to differentiate between the standard calling conventions that have
device specific assumptions built into them.

(b) Why disallow type conversion for vector types? (ss. 3.3)

[Villmow, Micah] Type conversions in OpenCL between vector types is doing
via builtin functions and not via implicit conversions, so there is no OpenCL
code that can generate these conversions directly(OpenCL spec 6.2.1). In order
to be portable, library functions cannot be lowered to their IR equivalent until
after the device is known.

Hi Micah,

(a) You mention special calling conventions and adding them to LLVM.
What are their semantics? And what is their purpose?

[Villmow, Micah] One purpose is to differentiate between kernel and device functions.
Another is to differentiate between the standard calling conventions that have
device specific assumptions built into them.

Do you have an example of such a device-specific assumption? Why
wouldn't the default (no explicit) calling convention do for a
storage-only format like SPIR?

When it does come to codegen (for a CPU target), an LLVM backend would
be forced to change the calling convention back to something standard
anyway. So what's the advantage of adding a semanticless calling
convention over metadata?

(b) Why disallow type conversion for vector types? (ss. 3.3)

[Villmow, Micah] Type conversions in OpenCL between vector types is doing
via builtin functions and not via implicit conversions, so there is no OpenCL
code that can generate these conversions directly(OpenCL spec 6.2.1). In order
to be portable, library functions cannot be lowered to their IR equivalent until
after the device is known.

Is SPIR meant to be storage-only, or to allow optimisations to be done
on it (valid SPIR -> opt -> valid SPIR)?

If you allow scalar type conversions, and you allow vectors, it
follows that an optimiser may turn scalar type conversions into vector
type conversions. Why explicitly disallow this even though there is no
corollary directly from CL-C source code?

Cheers,

James

From: mankeyrabbit@gmail.com [mailto:mankeyrabbit@gmail.com] On Behalf
Of James Molloy
Sent: Tuesday, September 11, 2012 1:45 PM
To: Villmow, Micah
Cc: James Molloy; Ouriel, Boaz; cfe-dev@cs.uiuc.edu; llvmdev@cs.uiuc.edu
Subject: Re: [cfe-dev] [LLVMdev] SPIR provisional specifciation is now
available in the Khronos website

Hi Micah,

>> (a) You mention special calling conventions and adding them to LLVM.
>> What are their semantics? And what is their purpose?
> [Villmow, Micah] One purpose is to differentiate between kernel and
device functions.
> Another is to differentiate between the standard calling conventions
> that have device specific assumptions built into them.

Do you have an example of such a device-specific assumption? Why
wouldn't the default (no explicit) calling convention do for a storage-
only format like SPIR?

[Villmow, Micah] It is my understanding, and correct me if I'm wrong, clang
generates code based on the calling convention and the device. We don't want
any assumptions made about the device calling convention until SPIR loading time and
the cleanest way to do that is to introduce our own. Also the default calling convention in LLVM is C, which
does not have the same semantics as ours(for example varargs is illegal except for printf, kernels and functions are different, etc...).

When it does come to codegen (for a CPU target), an LLVM backend would
be forced to change the calling convention back to something standard
anyway. So what's the advantage of adding a semanticless calling
convention over metadata?

[Villmow, Micah] I wouldn't say it is semantic-less, just that its semantics are different than the calling conventions that LLVM currently supports.

>> (b) Why disallow type conversion for vector types? (ss. 3.3)
> [Villmow, Micah] Type conversions in OpenCL between vector types is
> doing via builtin functions and not via implicit conversions, so there
> is no OpenCL code that can generate these conversions directly(OpenCL
> spec 6.2.1). In order to be portable, library functions cannot be
> lowered to their IR equivalent until after the device is known.

Is SPIR meant to be storage-only, or to allow optimisations to be done
on it (valid SPIR -> opt -> valid SPIR)?

[Villmow, Micah] While you can optimize SPIR, you run the chance of reducing portability by optimizing in a non-portable manner. The SPIR spec does not specify how the SPIR is generated or what is done to the binary format before generation, only what is and isn't valid. It is quite possible to generate valid SPIR that is non-portable, but in this case, there is no reason for using SPIR.

If you allow scalar type conversions, and you allow vectors, it follows
that an optimiser may turn scalar type conversions into vector type
conversions. Why explicitly disallow this even though there is no
corollary directly from CL-C source code?

[Villmow, Micah] SPIR in its current form is limited to OpenCL C(being an OpenCL extension). So things that are disallowed in OpenCL C are disallowed in SPIR at this time.

Boaz,

The current specification provides a mechanism for handling
FP_CONTRACT, but does so only at the module level. After much debate,
we have adopted and implemented a way of handling FP_CONTRACT in
clang/LLVM through the llvm.fmuladd intrinsic (currently in trunk). I
suggest that the proposed spir.disable.FP CONTRACT metadata be replaced
with the current llvm.fmuladd-based mechanism.

-Hal

James, here are our updated answers after discussing this.

From: llvmdev-bounces@cs.uiuc.edu [mailto:llvmdev-bounces@cs.uiuc.edu]
On Behalf Of James Molloy
Sent: Tuesday, September 11, 2012 8:49 AM
To: Ouriel, Boaz
Cc: cfe-dev@cs.uiuc.edu; llvmdev@cs.uiuc.edu
Subject: Re: [LLVMdev] SPIR provisional specifciation is now available
in the Khronos website

Hi Boaz,

I have a couple of specific questions:

(a) You mention special calling conventions and adding them to LLVM.
What are their semantics? And what is their purpose?

[Villmow, Micah] The semantics of the new calling conventions are as follows:
spirfunc calling convention -
All arguments are passed as is to the function with the exception of structures, no lowering or expansion is allowed.
Structures are passed as a pointer to struct with the byval attribute set.
Functions marked with spirfunc calling convention can only be called by another function marked with either spirfunc or spirkrnl calling conventions.
Functions marked with spirfunc calling convention can only call functions marked with spirfunc or spirkrnl calling conventions.
Functions marked with spirfunc calling convention can only have zero or 1 return values.
Functions marked with spirfunc calling convention are only visible to the device.
Variable arguments are not allowed, except for printf.
This calling convention does not specify the how it is lowered to registers or how the return value is specified.

spirkrnl calling convention -
Inherits the definition of spirfunc calling convention.
Functions marked with spirkrnl calling convention cannot have any return values.
Functions marked with spirkrnl calling convention cannot have variable arguments.
Functions marked with spirkrnl calling convention can be called by the host.
Functions marked with spirkrnl calling convention are externally visible.

(b) Why disallow type conversion for vector types? (ss. 3.3)

[Villmow, Micah] There are a few reasons.
1) SPIR wants to map as close to OpenCL as possible and while the vector type conversions are well defined in LLVM and properly converts to scalar when needed, SPIR needs to be able to work with people who don't use LLVM. By adhering as close as possible to OpenCL C, the amount of work to support SPIR is reduced.
2) From what I've been iformed of by Aaftab Munshi, when OpenCL C was developed, there were many different implementations that supported vector casts, but they were not conversion casts(e.g. Altivec/Cell C extensions). So OpenCL requires explicit vector conversion functions, and as such SPIR inherits those rules.
3) Since many compilers already had the vector casts that weren't conversions, the function calls were required so that code could not be written expecting the prior behavior of other compilers in OpenCL.

Hope that helps answer the questions,
Micah

Hi Micah,

As we discussed on the conference call, those solutions all seem great
to me. Thanks for defining the semantics of the spirkrnl and spirfunc
calling conventions - they make more sense to me now.

Thanks for taking my feedback on board! :slight_smile:

Cheers,

James