March 23, 2022·5 min read·engineeringcclangopencl

Clang 14 completes experimental OpenCL C 3.0 support

OpenCL C 3.0 requires a compiler to understand absent capabilities as well as available ones. Clang 14 completes its experimental implementation and adds a SPIR-V route through external translation tools.

Supporting a language with optional capabilities requires the compiler to handle programs for devices that lack them. Clang 14's OpenCL work makes this explicit. Its release notes describe completed OpenCL C 3.0 support, still experimental, and identify missing optionality checks among the changes that complete the implementation. The LLVM 14.0.0 release became available on March 23.

The word experimental remains part of the claim. Completion here describes the frontend's implementation work. It does not announce that every device, driver, and deployment can execute every program accepted by the compiler. The same release adds a route to SPIR-V binaries, but that route explicitly depends on external tools.

My interest in C includes the contracts between source code and the systems that execute it. OpenCL makes those contracts unusually visible because the compiler must account for device capabilities alongside the program's types. A statement that the frontend supports a language version is useful only when its restrictions remain visible too.

Optionality affects parsing and builtins

The OpenCL section identifies new parsing support for optional device-side enqueue and blocks. It also records missing optionality support for several builtin groups. In the default header, these include read-write images, pipes, and collective workgroup operations. In the internal opencl-c.h header, the changes cover read-write images and named-address-space atomics.

These are concrete pieces of frontend behaviour. Recognizing the grammar of a construct is one part of support. Making the corresponding builtin declarations available under the correct capabilities is another. A compiler that parses an operation but exposes incompatible declarations can still accept or reject the wrong program for the selected device environment.

The notes name -finclude-default-header as the frontend flag associated with the internal header. That is useful detail because language support often depends on declarations supplied by the compiler itself. Looking only at a parser change would miss a class of failures in which the required operation has no suitable visible declaration.

Optionality also changes what a completion claim means. The compiler needs to model permitted absence, not merely accumulate syntax and builtin functions. For an application that distributes kernels across different devices, this is a source-compatibility concern before any discussion of generated-code performance. The documented change makes the frontend's handling of the capability model more complete.

SPIR-V output uses external translation

Clang 14 adds the spirv32 and spirv64 triples for the corresponding SPIR-V address widths. Its release notes say binary generation uses the external llvm-spirv tool. Linking separate SPIR-V object files likewise uses an external tool, spirv-link.

The distinction between a driver-supported target and an internal code generator matters for installation. A Clang binary alone does not establish that this entire route is available. The requested output depends on translator and linker executables outside the frontend. Build environments need to account for those tools as actual dependencies when they use the new route.

The notes describe this output route as usable for HIP or OpenCL. That establishes its intended compiler integration without implying that SPIR-V removes runtime requirements. Producing an intermediate binary and arranging for a device implementation to consume it remain different stages. The release's specific contribution is connecting Clang's compilation flow to those external translation and linking steps.

This division also gives a practical way to interpret a build failure. Failure to parse an OpenCL construct belongs to a different stage from failure to find the translator. A SPIR-V link failure concerns another stage again. Keeping those distinctions in the build description makes the new target easier to reason about than treating all failures as evidence of incomplete language support.

C++ for OpenCL shares the capability model

The release also adds experimental C++ for OpenCL 2021 support. Its optional capabilities align with OpenCL 3.0. That alignment is part of the announced functionality, while the two language modes remain separate choices for kernel source.

Several fixes concern address spaces. Temporaries now use the private address space, and the release adds a __remove_address_space utility. It also prohibits static kernel functions and fixes an implicit definition of the __cpp_threadsafe_static_init macro. These details concern the meaning of source programs and the facilities they are told are available.

The OpenCL work includes improvements to vload and vstore, and a correction to as_type support for three-element vectors. The notes do not provide a general performance number for these changes. Their value is in correcting or completing the compiler's treatment of specific language operations. An application depending on one of those operations has a more precise reason to investigate the release than a generic expectation of faster kernels.

Ordinary C has separate changes

For host-side C, Clang 14 changes the value of __STDC_VERSION__ in -std=c2x mode to 202000L. The release notes explicitly call it a value that distinguishes this mode from C17, and say it is expected to change again when the revision is published. It should therefore be read as the compiler's identification of its current draft mode.

The frontend also supports _BitInt(N), with _ExtInt(N) retained as a deprecated alias. The notes say the types are otherwise identical and explain that diagnostics use the newer spelling. At this release, the supported width is at most 128 bits because backend support for some arithmetic operations on larger widths is incomplete. BITINT_MAXWIDTH exposes the supported maximum through limits.h.

I value C's usefulness at binary interfaces, which makes the accompanying ABI qualification important. Clang's notes say the _BitInt ABI is still being stabilized and advise against using it in interfaces requiring ABI stability. Source-level acceptance and a settled binary contract are different properties of this addition.

Other changes address source policy. -Wdeclaration-after-statement now works in C99 and later modes, allowing projects to retain a declaration-ordering convention while choosing newer language rules. Wide multicharacter literals such as L'ab' become ill-formed instead of being interpreted as L'b'. These changes affect existing source without depending on the OpenCL implementation.

Clang 14 consequently contains several distinct forms of progress. The OpenCL implementation completes its experimental capability handling. SPIR-V gains a compilation route with explicit external dependencies. Host-side C gains draft-language facilities whose implementation limits and ABI status are documented separately. A build can describe each choice directly by specifying its language mode, output target, and required tools.