The ComputeMux Compiler is a collection of C++ interfaces that is used to implement a compiler suite for ComputeMux hardware targets. ComputeMux provides a base implementation of the various front-ends and optimization passes using LLVM which should be used by a compiler implementation for a ComputeMux device.
Each entry point required to implement a compiler targeting a specific ComputeMux device is specified in the ComputeMux Compiler Specification, containing detail on the purpose of each entry point, valid usage, and expected error codes. The LLVM intermediate representation section in particular provides detail about the LLVM IR that is generated by the oneAPI Construction Kit.
LLVM
The ComputeMux Compiler hides its usage of LLVM behind a set of virtual interfaces. This avoids the need for an open standards implementation linking with the oneAPI Construction Kit, such as OpenCL and Vulkan, to also link with LLVM, improving encapsulation.
The base implementation of the interfaces, such as BaseModule
, are
implemented using LLVM, and ComputeMux targets are expected to extend the base
implementation with their own back-end functionality. However, it is technically
possible (although not currently supported) to implement the interface classes
directly using a different compiler infrastructure. Builtin functions are
currently compiled to LLVM bitcode using clang
as part of the CMake build
process.
The list of LLVM versions supported by ComputeMux can be found here.
Building a ComputeMux Compiler
A ComputeMux compiler is responsible for taking an LLVM module representing a program under compilation and producing object code.
Since ComputeMux provides a standard set of target-agnostic IR passes to provide all required functionality, the minimum required of a ComputeMux compiler is the LLVM Code Generator, or backend. This component is responsible for translating LLVM intermediate representation to machine code for the target.
The requirements on the subset of LLVM IR that must be supported ultimately depend on the higher-level compute standard being implemented with ComputeMux. As the following sections will outline, ComputeMux shall not require anything of a compiler backend that isn’t representable with standard open-source and target-agnostic LLVM IR.
Tip
As a general rule, a compiler backend which supports C99 will provide 99% of the functionality required by the standards built on top of ComputeMux. Note that there are several features of C99 which are not required; see the list of ComputeMux Compiler Non-Requirements.
ComputeMux supports the x86, x86-64, 32-bit ARM, 64-bit ARM (AArch64) and RISC-V targets using their respective open-source LLVM compiler backends. Each target initially required minimal (or no) modifications to get them working.
A compiler backend is not required to support every source-level type or IR operation in hardware. The LLVM code generator is adept at legalizing both unsupported types and operations, re-expressing the same program using only legal types and operations. This process requires only minimal work in the target-specific code. LLVM’s documentation provides an in-depth guide to the LLVM Instruction Selector which is responsible for this process.
While targets may implement a minimal ComputeMux compiler with standard IR and using a simple C99 backend as a basis, targets may use the configurable nature of ComputeMux to write compiler passes which optimize code in a way that maximizes performance for the target. One example could be to optimize code using target-specific compiler builtin functions (intrinsics). The compiler backend in particular has a lot of scope with which to optimize the generated code.
The following sections describe the Intermediate Representation that forms ComputeMux programs, as well as any specific requirements on a backend. The list of ComputeMux Compiler Non-Requirements may help to narrow the scope of language features which are not required.