在自定义functionpass中应调用getanalysis().getaaresults()获取aliasanalysis实例,因其默认按函数粒度分析且跨函数需额外机制;aliasresult含noalias、mustalias、partialalias、mayalias四值,仅前两者支持安全优化;构造memorylocation时起始地址须为非const value*,size宜用locationsize::unknown()或精确字节数。

怎么在自定义 Pass 里拿到 AliasAnalysis 实例
LLVM 的 AliasAnalysis 不是直接 new 出来的,必须通过 Pass 管理器获取。如果你写的是 FunctionPass,最稳妥的方式是用 getAnalysis<aaresultswrapperpass>().getAAResults()</aaresultswrapperpass>;如果是 ModulePass,则需先调用 getAnalysis<moduleanalysismanagerproxy>().getManager()</moduleanalysismanagerproxy> 再查 AAM,但实际中绝大多数内存分析场景都在函数粒度下进行。
注意:别名分析结果默认只对同一函数内的指针有效。跨函数的查询(比如判断 call 指令是否可能修改某全局变量)需要额外启用 MemorySSA 或使用 MemoryDependenceResults 辅助,否则会直接返回 MayAlias —— 这不是 bug,是设计使然。
AliasResult 到底有哪几种值,各自意味着什么
AliasResult 是枚举类型,只有四个取值:NoAlias、MustAlias、PartialAlias、MayAlias。其中真正能用于安全优化的只有前两个:
-
NoAlias:两个内存对象绝对不重叠,可放心重排读写顺序或合并访问 -
MustAlias:指向完全相同的地址(比如%p和gep %p, 0),可做指针折叠 -
PartialAlias:部分重叠(如数组首尾相邻字段),极少被优化 Pass 主动利用 -
MayAlias:默认 fallback,表示“无法排除冲突”,任何依赖无别名的优化都必须中止
别名分析不会告诉你“为什么是 MayAlias”,只会返回这个结果。你得结合 IR 上下文(比如是否有 addrspace 属性、是否含 noalias 元数据)去排查。
query 时传入的 Value* 和 size 怎么选才靠谱
调用 alias(const MemoryLocation &LocA, const MemoryLocation &LocB) 前,必须构造合法的 MemoryLocation。关键点在于:
- 起始地址必须是
Value*,不能是常量整数(如inttoptr结果也不行),否则分析器直接拒绝并返回MayAlias - size 推荐用
LocationSize::unknown()或具体字节数;传LocationSize::precise(N)时,N 必须与实际指令访问宽度一致(比如load i32对应 4 字节) - 如果地址来自
gep指令,确保该gep没被undef或poison污染,否则整个 query 失效
常见错误:把 alloca 指令本身当地址传进去(应该传它的返回值 Value*),或者把 bitcast 后的指针直接喂给 alias() 而不还原原始类型信息。
为什么 basic-aa 返回 NoAlias,but llvm::AAEvalPass 却报 MayAlias
这不是矛盾,而是分析精度差异导致的。basic-aa 是轻量级、上下文不敏感的分析,而 AAEvalPass 默认走的是 AAResults 统一接口,背后可能绑定了多个 AA 实现(如 scoped-aa、tti-aa),且会启用更激进的假设(比如考虑 noalias 函数属性)。
调试时建议统一用 opt -aa-eval -enable-new-pm=0 验证,避免新旧 PM 混用导致结果不一致。另外,LLVM 14+ 默认禁用 basic-aa,改用 default-aa(即 AAResults),所以你的 Pass 如果硬依赖 BasicAAResults,在新版中会编译失败或运行时 crash。
真正容易被忽略的是:AliasAnalysis 的结果不是全局缓存的,每次 query 都可能触发重新计算,尤其在 IR 被频繁修改的 Pass 中(比如 loop unrolling),务必检查你调用 alias() 的时机是否在 IR 稳定之后。











