如何从LLVM SCEV数组访问分析结果中提取常量'3'?
SCEV表达式结构拆解
你拿到的SCEV表达式分层结构如下:
- 最外层是
SCEVAddExpr:两个操作数分别是基址%6、字节偏移量(4 * (sext i32 (3 + %7) to i64))<nsw> - 偏移量是
SCEVMulExpr:两个操作数分别是i32类型的字节宽度4、符号扩展节点 - 符号扩展是
SCEVSignExtendExpr:操作数是内层加法表达式3 + %7 - 内层加法是
SCEVAddExpr:两个操作数分别是常量3、变量%7
提取常量的实现步骤(LLVM C++ API)
你可以按照分层结构逐层解析SCEV节点即可取出目标常量:
- 先将GEP指令对应的SCEV对象转换为
SCEVAddExpr类型,取出偏移量操作数 - 把偏移量操作数转换为
SCEVMulExpr类型,取出符号扩展节点 - 取符号扩展节点的操作数,转换为
SCEVAddExpr类型 - 遍历内层加法节点的所有操作数,匹配
SCEVConstant类型的节点,读取常量值
示例代码片段
// 假设SE是你当前的ScalarEvolution实例,GEP是目标getelementptr指令 const SCEV *GepSCEV = SE.getSCEV(GEP); if (const auto *AddExpr = dyn_cast<SCEVAddExpr>(GepSCEV)) { // 取偏移操作数 const SCEV *OffsetSCEV = AddExpr->getOperand(1); if (const auto *MulExpr = dyn_cast<SCEVMulExpr>(OffsetSCEV)) { const SCEV *SextSCEV = MulExpr->getOperand(1); if (const auto *SextExpr = dyn_cast<SCEVSignExtendExpr>(SextSCEV)) { const SCEV *InnerAddSCEV = SextExpr->getOperand(); if (const auto *InnerAddExpr = dyn_cast<SCEVAddExpr>(InnerAddSCEV)) { // 遍历内层加法的操作数找常量 for (const SCEV *Op : InnerAddExpr->operands()) { if (const auto *ConstSCEV = dyn_cast<SCEVConstant>(Op)) { APInt ConstVal = ConstSCEV->getAPInt(); if (ConstVal == 3) { // 找到目标常量3 errs() << "找到常量:" << ConstVal << "\n"; } } } } } } }
通用优化方案
如果要适配更多SCEV变形场景,可以用SCEVVisitor递归遍历所有SCEV节点,全局匹配常量值,不需要硬编码分层结构。
内容的提问来源于stack exchange,提问作者Darshan Bhat
相关产品推荐
相关产品推荐

