TPDE
Loading...
Searching...
No Matches
TPDE-LLVM

TPDE-LLVM is a TPDE-based LLVM back-end focusing on fast compilation targeting x86-64 and AArch64. Typically, compile times are 10–20x faster than the LLVM -O0 back-end with similar execution time, code size is ~10-30% larger for -O0 IR and similar for -O1 IR. The focus is on supporting a commonly used subset of LLVM-IR and target platforms efficiently, therefore many IR features are not supported – in such cases, the intention is to fall back to the full LLVM back-end. Code generated by Clang (-O0/-O1) will typically compile; -O2 and higher will typically fail due to unsupported vector operations.

Usage

Standalone usage is possible through the tools tpde-llc (similar to llc), which compile LLVM IR or bitcode to an ELF object file.

Library usage is possible through tpde_llvm::LLVMCompiler, which supports compiling a module to an object file or mapping it into the memory of the current process for JIT execution. The JIT mapper only supports very typical ELF constructs (e.g., no TLS), if this is not sufficient, the object file can also be mapped through LLVM's ORC JIT (see tpde-llvm/tools/tpde-lli.cpp for an example).

llvm::Triple triple(mod->getTargetTriple());
std::unique_ptr<tpde_llvm::LLVMCompiler> compiler = tpde_llvm::LLVMCompiler::create(triple);
std::vector<uint8_t> buf;
if (compiler && compiler->compile_to_elf(*mod, buf)) {
// Compilation successful, buf contains object file
} else {
// Triple unsupported or compilation failed
}
static std::unique_ptr< LLVMCompiler > create(const llvm::Triple &triple) noexcept

Note that compilation is likely to modify the module. All constant expressions inside functions are replaced with instruction sequences and all accesses to thread-local variables are rewritten to use llvm.threadlocal.address.

Integration Into Clang/Flang

We provide a patch to integrate TPDE-LLVM into Clang/Flang. Apply the patch from the root directory of the repository and add this repository under clang/lib/CodeGen/tpde2 (e.g., via a symlink). This adds two options to the clang and flang drivers:

  • -ftpde: Use TPDE instead of the regular LLVM back-end. Inputs that TPDE can't handle will cause a fall back to LLVM and emit a warning.
  • -ftpde-abort: Abort when the input is not supported, don't fallback to LLVM.

Note: most LLVM-specific code-gen options will be ignored.

Unsupported Features

Unsupported features currently include:

  • Targets other than x86-64-v1/AArch64 (ARMv8.1) (Linux) ELF.
  • Code models other than Small-PIC.
  • Scalar types: integer types larger than i64 except i128 (i128 is supported), pointers with non-zero address space, half, bfloat, ppc_fp128, x86_fp80, x86_amx. Code with x86-64 long double needs to be compiled with -mlong-double-64.
  • Vectors: types that are not directly legal on the target (e.g., <32 x i8> on x86-64); icmp/fcmp; pointer element type; getelementptr with vector types; select with vector predicate, integer extension/truncation,
  • select aggregate type other than {i64, i64}.
  • bitcast larger than 64 bit.
  • Atomic operations might use a stronger consistency than required (e.g., always seqcst for atomicrmw).
  • Calling conventions other than the C calling convention (SysV on x86-64, AAPCS on AArch64).
  • fp128: fneg, fcmp one/ueq, many intrinsics.
  • Computed goto (blockaddress, indirectbr).
  • landingpad with non-empty filter clause.
  • Many intrinsics, and some intrinsics are only implemented for commonly used types (e.g., llvm.cttz only for 8/16/32/64-bit).
  • IFuncs.
  • Various forms of constant expressions in global initializers.
  • Non-empty inline assembly.
  • Full asynchronous unwind info (frame info only correct in prologue and at call sites).
  • Several corner cases that we didn't encounter so far.