Use and extend alias analysis in LLVM 22. Covers querying AAResults from a function pass, using IR-level hints (noalias, TBAA) as the preferred approach, writing a custom AA analysis with the New Pass Manager, and common ModRef patterns.
74
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Use this skill when you need to query whether two memory references may alias, push language-specific aliasing facts into the optimizer, or write a custom alias analysis pass.
| Goal | Recommended approach |
|---|---|
| Tell the optimizer your language's aliasing rules | IR-level hints: noalias, nocapture, TBAA metadata (no C++ needed) |
| Query alias info in an optimization pass | AAResults via the function analysis manager |
| Language-specific AA that IR hints can't express | Custom AAResultBase subclass (advanced) |
Start with IR-level hints — they are the highest-ROI approach and compose with all existing LLVM alias analyses automatically.
noalias on parametersTell the optimizer that a pointer argument does not alias any other pointer visible to the function (like C restrict):
llvm::AttrBuilder AB(Ctx);
AB.addAttribute(llvm::Attribute::NoAlias);
F->addParamAttrs(0, AB); // parameter 0 is noaliasIn IR: define void @foo(ptr noalias %p, ptr %q)
nocapture on parametersTell the optimizer that the pointer is not stored anywhere that outlives the call:
llvm::AttrBuilder AB(Ctx);
AB.addAttribute(llvm::Attribute::NoCapture);
F->addParamAttrs(0, AB);Tag loads and stores with type information so the optimizer knows accesses to different language types can't alias:
#include "llvm/IR/MDBuilder.h"
llvm::MDBuilder MDB(Ctx);
llvm::MDNode *Root = MDB.createTBAARoot("MyLang TBAA");
llvm::MDNode *IntTy = MDB.createTBAANode("int", Root);
llvm::MDNode *PtrTy = MDB.createTBAANode("object", Root);
llvm::MDNode *IntTag = MDB.createTBAAStructTagNode(IntTy, IntTy, 0);
llvm::MDNode *PtrTag = MDB.createTBAAStructTagNode(PtrTy, PtrTy, 0);
// Tag every load and store
LI->setMetadata(llvm::LLVMContext::MD_tbaa, IntTag);
SI->setMetadata(llvm::LLVMContext::MD_tbaa, PtrTag);Cache the root/type nodes — recreating them each time creates distinct trees that don't interact.
AAResults in a function passIn an NPM function pass, obtain AAResults through the analysis manager:
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/IR/PassManager.h"
struct MyOptPass : llvm::PassInfoMixin<MyOptPass> {
llvm::PreservedAnalyses run(llvm::Function &F,
llvm::FunctionAnalysisManager &FAM) {
auto &AA = FAM.getResult<llvm::AAManager>(F);
// Compare two memory locations
for (auto &I : llvm::instructions(F)) {
if (auto *LI = llvm::dyn_cast<llvm::LoadInst>(&I)) {
for (auto &J : llvm::instructions(F)) {
if (auto *SI = llvm::dyn_cast<llvm::StoreInst>(&J)) {
llvm::MemoryLocation LocL = llvm::MemoryLocation::get(LI);
llvm::MemoryLocation LocS = llvm::MemoryLocation::get(SI);
llvm::AliasResult AR = AA.alias(LocL, LocS);
if (AR == llvm::AliasResult::NoAlias) {
// Safe to reorder this load past this store
}
}
}
}
}
return llvm::PreservedAnalyses::all();
}
};AliasResult values| Value | Meaning |
|---|---|
NoAlias | Cannot overlap for the accessed sizes |
MustAlias | Always the same location |
MayAlias | Conservative unknown (default) |
PartialAlias | Overlapping but not identical |
// Does this call read or write through ptr %p?
llvm::MemoryLocation Loc = llvm::MemoryLocation::getBeforeOrAfter(Ptr);
llvm::ModRefInfo MRI = AA.getModRefInfo(CallSite, Loc);
if (llvm::isNoModRef(MRI)) {
// The call neither reads nor writes through Ptr
// Safe to hoist a load from Ptr above the call
}
if (llvm::isModSet(MRI)) {
// The call may write through Ptr
}
if (llvm::isRefSet(MRI)) {
// The call may read through Ptr
}Only needed when IR hints cannot express your language's aliasing rules. The pattern:
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/PassManager.h"
// Result type — implements the alias query
class MyAAResult : public llvm::AAResultBase {
public:
explicit MyAAResult() : AAResultBase() {}
llvm::AliasResult alias(const llvm::MemoryLocation &LocA,
const llvm::MemoryLocation &LocB,
llvm::AAQueryInfo &AAQI,
const llvm::Instruction *CtxI) {
// If both pointers are known immutable globals, they don't alias heap
if (isImmutableGlobal(LocA.Ptr) && isHeapPtr(LocB.Ptr))
return llvm::AliasResult::NoAlias;
// Delegate everything else to the chain
return AAResultBase::alias(LocA, LocB, AAQI, CtxI);
}
private:
bool isImmutableGlobal(const llvm::Value *V) { /* ... */ return false; }
bool isHeapPtr(const llvm::Value *V) { /* ... */ return false; }
};
// Analysis wrapper (NPM pattern)
class MyAA : public llvm::AnalysisInfoMixin<MyAA> {
friend llvm::AnalysisInfoMixin<MyAA>;
static llvm::AnalysisKey Key;
public:
using Result = MyAAResult;
MyAAResult run(llvm::Function &, llvm::FunctionAnalysisManager &) {
return MyAAResult();
}
};
llvm::AnalysisKey MyAA::Key;Register it in your PassBuilder callback:
PB.registerFunctionAnalyses([](llvm::FunctionAnalysisManager &FAM) {
FAM.registerPass([&] { return MyAA(); });
});
// Also register with AAManager so it participates in alias queries:
PB.registerParseAACallback([](llvm::StringRef Name,
llvm::AAManager &AAM) -> bool {
if (Name == "my-aa") { AAM.registerFunctionAnalysis<MyAA>(); return true; }
return false;
});When your pass modifies the IR in a way that affects aliasing, invalidate the AA results:
// Return from run():
llvm::PreservedAnalyses PA;
PA.preserve<llvm::DominatorTreeAnalysis>(); // keep what you didn't break
// Not preserving AAManager causes it to be recomputed next time
return PA;AAResults across IR modifications — always re-query after changes.Value* ==) with aliasing — different GEP values can MustAlias.PartialAlias in range-sensitive reasoning.ModRef before hoisting instructions past calls.noalias, TBAA) over a custom AA pass — they are simpler and compose better.noalias, nocapture in detailFAM.getResult, invalidationa251bde
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.