LLVM 22.x tile for building compilers, language runtimes, and out-of-tree tooling
88
83%
Does it follow best practices?
Impact
96%
1.23xAverage score across 5 eval scenarios
Passed
No known issues
These rules apply whenever you are writing, reviewing, or modifying code that uses LLVM 22 APIs. They are always loaded into context — keep them in mind for every LLVM code generation decision.
PassManager still exists but must NOT be used for new code — always use NPM. Never emit legacy::PassManager, FunctionPass, ModulePass, getAnalysis<>(), AU.setPreservesAll(), or createXYZPass() factory functions.PassInfoMixin<T> and implement PreservedAnalyses run(IRUnit &, AnalysisManager &).PreservedAnalyses::all() when nothing is modified. Return PreservedAnalyses::none() only when the full IR may have changed.FAM.getResult<AnalysisType>(F), not via getAnalysis<>().ptr). Never use typed pointer types (i8*, i32*) or getPointerElementType().Builder.getPtrTy() or PointerType::get(Ctx, AddrSpace).LoadInst, StoreInst, and GetElementPtrInst:
Builder.CreateLoad(ElemTy, Ptr, "name")Builder.CreateGEP(ElemTy, Ptr, Indices)std::optional<T> and std::nullopt — llvm::Optional and llvm::None are removed.llvm::Expected<T> and llvm::Error for fallible operations, not raw null pointer returns.llvm::SmallVector, llvm::StringRef, llvm::ArrayRef for LLVM-internal collections.Intrinsic::getOrInsertDeclaration() or getDeclarationIfExists() — Intrinsic::getDeclaration() is removed in LLVM 22.llvm/TargetParser/Triple.h and llvm/TargetParser/Host.h — the old llvm/ADT/Triple.h and llvm/Support/Host.h paths are moved.using namespace llvm; in headers. Use it in .cpp files only.auto * for downcasts where the type is obvious from context. Use cast<T>() only when you are certain of the type; use dyn_cast<T>() for safe checked casts.llvm::PatternMatch (m_Add, m_Value, m_ConstantInt, etc.) for IR pattern matching instead of manual dyn_cast chains.llvm::errs() / llvm::outs() over std::cerr / std::cout.LLVM_DEBUG(dbgs() << ...) for debug output — controlled by -debug / DEBUG_TYPE.IRBuilder<> for all instruction emission — never construct Instruction subclasses directly via new.PoisonValue::get(T) instead of UndefValue::get(T) when modeling undefined behavior — poison is the correct LLVM 22 model for UB.verifyModule(*M, &errs()) during development to catch IR invariant violations early.IRBuilder<>::CreateNSWAdd / CreateNUWAdd / CreateFAddFMF when you know flags apply — these enable more optimization.llvm/Target/Target.td at the top of target .td files.let Namespace = "MyTarget" on all registers, register classes, and instructions.*Gen*.inc files — always regenerate via cmake --build --target XYZCommonTableGen.find_package(LLVM 22 REQUIRED CONFIG) and llvm_map_components_to_libnames — never hardcode -lLLVMCore etc.CMAKE_CXX_STANDARD 17 — LLVM 22 requires C++17.LLVM_ENABLE_RTTI=OFF (default), add -fno-rtti to your project's compile options.opt host process.BuildMI(MBB, InsertPt, DL, TII.get(Opc)) to build MachineInstrs — never construct them directly.constrainSelectedInstRegOperands after manual instruction selection in GlobalISel.PromotePass (mem2reg) only promotes entry-block allocas.getTerminator() before adding a branch — two terminators on one block is a verifier error.DBuilder.finalize() after all functions are emitted — never skip it.B.SetCurrentDebugLocation({})) for compiler-synthesized instructions with no source correspondence.AlwaysPreserve=true for parameter variables so they survive optimization.Debug Info Version and Dwarf Version module flags.LLJIT or LLLazyJIT — never MCJIT (deprecated in prior versions; MCJIT removed in LLVM 22).InitializeNativeTarget(), InitializeNativeTargetAsmPrinter() at program start, before constructing any JIT.LLVMContext per ThreadSafeModule for correct thread-safety.DynamicLibrarySearchGenerator::GetForCurrentProcess if JIT'd code calls libc.invoke (not call) for any call that may unwind in a function that has landing pads.F->setPersonalityFn() on functions with landing pads.__cxa_begin_catch / __cxa_end_catch around catch bodies (Itanium ABI).NoUnwind on all functions that never throw — it unlocks significant optimizer opportunities.NoCapture on pointer parameters that don't escape the call — critical for alias analysis.Noundef on values guaranteed to be fully initialized.!llvm.loop metadata to communicate vectorization/unroll hints; don't rely on the optimizer to infer them.docs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
skills
add-alias-analysis
add-attributes-metadata
add-calling-convention
add-debug-info
add-exception-handling
add-gc-statepoints
add-intrinsic
add-lto
add-sanitizer
add-vectorization-hint
frontend-to-ir
jit-setup
lit-filecheck
lower-struct-types
new-target
out-of-tree-setup
tessl-llvm
version-sync