[midend-Alias]应用别名分析结果,sccp现在能简单传播数组元素了

This commit is contained in:
rain2133
2025-08-08 02:12:32 +08:00
parent b1a46b7d58
commit a406e44df3
7 changed files with 590 additions and 38 deletions

View File

@ -1,10 +1,12 @@
#include "SCCP.h"
#include "Dom.h"
#include "Liveness.h"
#include "SideEffectAnalysis.h"
#include <algorithm>
#include <cassert>
#include <cmath> // For std::fmod, std::fabs
#include <limits> // For std::numeric_limits
#include <set> // For std::set in isKnownPureFunction
namespace sysy {
@ -263,6 +265,192 @@ SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVa
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数:检查是否为已知的纯函数
bool SCCPContext::isKnownPureFunction(const std::string &funcName) const {
// SysY中一些已知的纯函数不修改全局状态结果只依赖参数
static const std::set<std::string> knownPureFunctions = {
// 数学函数(如果有的话)
// "abs", "fabs", "sqrt", "sin", "cos"
// SysY标准中基本没有纯函数大多数都有I/O副作用
};
return knownPureFunctions.find(funcName) != knownPureFunctions.end();
}
// 辅助函数:计算纯函数的常量结果
SSAPValue SCCPContext::computePureFunctionResult(CallInst *call, const std::vector<SSAPValue> &argValues) {
Function *calledFunc = call->getCallee();
if (!calledFunc) {
return SSAPValue(LatticeVal::Bottom);
}
std::string funcName = calledFunc->getName();
// 目前SysY中没有标准的纯函数这里预留扩展空间
// 未来可以添加数学函数的常量折叠
/*
if (funcName == "abs" && argValues.size() == 1) {
if (argValues[0].constant_type == ValueType::Integer) {
int val = std::get<int>(argValues[0].constantVal);
return SSAPValue(std::abs(val));
}
}
*/
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数:查找存储到指定位置的常量值
SSAPValue SCCPContext::findStoredConstantValue(Value *ptr, BasicBlock *currentBB) {
if (!aliasAnalysis) {
if (DEBUG) {
std::cout << "SCCP: No alias analysis available" << std::endl;
}
return SSAPValue(LatticeVal::Bottom);
}
if (DEBUG) {
std::cout << "SCCP: Searching for stored constant value for ptr" << std::endl;
}
// 从当前块的指令列表末尾向前查找最近的Store
std::vector<Instruction*> instructions;
for (auto it = currentBB->begin(); it != currentBB->end(); ++it) {
instructions.push_back(it->get());
}
for (int i = instructions.size() - 1; i >= 0; --i) {
Instruction *prevInst = instructions[i];
if (prevInst->isStore()) {
StoreInst *storeInst = static_cast<StoreInst *>(prevInst);
Value *storePtr = storeInst->getPointer();
if (DEBUG) {
std::cout << "SCCP: Checking store instruction" << std::endl;
}
// 使用别名分析检查Store是否针对相同的内存位置
auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr);
if (DEBUG) {
std::cout << "SCCP: Alias result: " << (int)aliasResult << std::endl;
}
if (aliasResult == AliasType::SELF_ALIAS) {
// 找到了对相同位置的Store获取存储的值
Value *storedValue = storeInst->getValue();
if (DEBUG) {
std::cout << "SCCP: Found matching store, checking value type" << std::endl;
}
// 检查存储的值是否为常量
if (auto constInt = dynamic_cast<ConstantInteger *>(storedValue)) {
int val = std::get<int>(constInt->getVal());
if (DEBUG) {
std::cout << "SCCP: Found constant integer value: " << val << std::endl;
}
return SSAPValue(val);
} else if (auto constFloat = dynamic_cast<ConstantFloating *>(storedValue)) {
float val = std::get<float>(constFloat->getVal());
if (DEBUG) {
std::cout << "SCCP: Found constant float value: " << val << std::endl;
}
return SSAPValue(val);
} else {
// 存储的值不是常量检查其SCCP状态
SSAPValue storedState = GetValueState(storedValue);
if (storedState.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Found SCCP constant value" << std::endl;
}
return storedState;
} else {
if (DEBUG) {
std::cout << "SCCP: Stored value is not constant" << std::endl;
}
}
}
// 找到了最近的Store但不是常量停止查找
if (DEBUG) {
std::cout << "SCCP: Found non-constant store, stopping search" << std::endl;
}
break;
}
}
}
if (DEBUG) {
std::cout << "SCCP: No constant value found" << std::endl;
}
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数动态检查数组访问是否为常量索引考虑SCCP状态
bool SCCPContext::hasRuntimeConstantAccess(Value *ptr) {
if (auto gep = dynamic_cast<GetElementPtrInst *>(ptr)) {
if (DEBUG) {
std::cout << "SCCP: Checking runtime constant access for GEP instruction" << std::endl;
}
// 检查所有索引是否为常量或SCCP传播的常量
bool allConstantIndices = true;
for (auto indexUse : gep->getIndices()) {
Value* index = indexUse->getValue();
// 首先检查是否为编译时常量
if (auto constInt = dynamic_cast<ConstantInteger *>(index)) {
if (DEBUG) {
std::cout << "SCCP: Index is compile-time constant integer: " << std::get<int>(constInt->getVal()) << std::endl;
}
continue;
}
if (auto constFloat = dynamic_cast<ConstantFloating *>(index)) {
if (DEBUG) {
std::cout << "SCCP: Index is compile-time constant float: " << std::get<float>(constFloat->getVal()) << std::endl;
}
continue;
}
// 检查是否为SCCP传播的常量
SSAPValue indexState = GetValueState(index);
if (indexState.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Index is SCCP constant: ";
if (indexState.constant_type == ValueType::Integer) {
std::cout << std::get<int>(indexState.constantVal);
} else {
std::cout << std::get<float>(indexState.constantVal);
}
std::cout << std::endl;
}
continue;
}
// 如果任何一个索引不是常量返回false
if (DEBUG) {
std::cout << "SCCP: Index is not constant, access is not constant" << std::endl;
}
allConstantIndices = false;
break;
}
if (DEBUG) {
std::cout << "SCCP: hasRuntimeConstantAccess result: " << (allConstantIndices ? "true" : "false") << std::endl;
}
return allConstantIndices;
}
// 对于非GEP指令回退到别名分析的静态结果
if (aliasAnalysis) {
return aliasAnalysis->hasConstantAccess(ptr);
}
return false;
}
// 辅助函数:处理单条指令
void SCCPContext::ProcessInstruction(Instruction *inst) {
SSAPValue oldState = GetValueState(inst);
@ -380,27 +568,237 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
break;
}
case Instruction::kLoad: {
// 对于 Load 指令,除非我们有特殊的别名分析,否则假定为 Bottom
// 或者如果它加载的是一个已知常量地址的全局常量
// 使用别名分析和副作用分析改进Load指令的处理
Value *ptr = inst->getOperand(0);
// 首先检查是否是全局常量
if (auto globalVal = dynamic_cast<GlobalValue *>(ptr)) {
// 如果 GlobalValue 有初始化器,并且它是常量,我们可以传播
// 这需要额外的逻辑来检查 globalVal 的初始化器
// 暂时保守地设置为 Bottom
// TODO: 检查全局变量的初始化器进行常量传播
newState = SSAPValue(LatticeVal::Bottom);
} else if (aliasAnalysis && sideEffectAnalysis) {
// 使用别名分析和副作用分析进行更精确的Load分析
if (aliasAnalysis->isLocalArray(ptr) && (aliasAnalysis->hasConstantAccess(ptr) || hasRuntimeConstantAccess(ptr))) {
// 对于局部数组的常量索引访问检查是否有影响该位置的Store
bool mayBeModified = false;
if (DEBUG) {
std::cout << "SCCP: Analyzing local array with constant access for modification" << std::endl;
}
// 遍历指令所在块之前的所有指令查找可能修改该内存位置的Store
BasicBlock *currentBB = inst->getParent();
auto instPos = currentBB->findInstIterator(inst);
SSAPValue foundConstantValue = SSAPValue(LatticeVal::Bottom);
bool hasFoundDefinitiveStore = false;
for (auto it = currentBB->begin(); it != instPos; ++it) {
Instruction *prevInst = it->get();
if (prevInst->isStore()) {
StoreInst *storeInst = static_cast<StoreInst *>(prevInst);
Value *storePtr = storeInst->getPointer();
// 使用别名分析判断Store是否可能影响当前Load
auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr);
if (DEBUG) {
std::cout << "SCCP: Checking store with alias result: " << (int)aliasResult << std::endl;
}
if (aliasResult == AliasType::SELF_ALIAS) {
// 找到对相同位置的精确Store
Value *storedValue = storeInst->getValue();
if (DEBUG) {
std::cout << "SCCP: Found exact store to same location, checking value" << std::endl;
}
// 检查存储的值是否为常量
if (auto constInt = dynamic_cast<ConstantInteger *>(storedValue)) {
int val = std::get<int>(constInt->getVal());
if (DEBUG) {
std::cout << "SCCP: Store contains constant integer: " << val << std::endl;
}
foundConstantValue = SSAPValue(val);
hasFoundDefinitiveStore = true;
// 继续遍历查找是否有更后面的Store覆盖这个值
} else if (auto constFloat = dynamic_cast<ConstantFloating *>(storedValue)) {
float val = std::get<float>(constFloat->getVal());
if (DEBUG) {
std::cout << "SCCP: Store contains constant float: " << val << std::endl;
}
foundConstantValue = SSAPValue(val);
hasFoundDefinitiveStore = true;
} else {
// 存储的值不是编译时常量检查其SCCP状态
SSAPValue storedState = GetValueState(storedValue);
if (storedState.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Store contains SCCP constant" << std::endl;
}
foundConstantValue = storedState;
hasFoundDefinitiveStore = true;
} else {
if (DEBUG) {
std::cout << "SCCP: Store contains non-constant value" << std::endl;
}
// 非常量Store覆盖了之前的常量无法传播
foundConstantValue = SSAPValue(LatticeVal::Bottom);
hasFoundDefinitiveStore = true;
}
}
} else if (aliasResult != AliasType::NO_ALIAS) {
// 可能有别名,但不确定
if (DEBUG) {
std::cout << "SCCP: Found store with uncertain alias, stopping propagation" << std::endl;
}
mayBeModified = true;
break;
}
} else if (prevInst->isCall()) {
// 检查函数调用是否可能修改该内存位置
if (sideEffectAnalysis->mayModifyMemory(prevInst)) {
// 进一步检查是否可能影响局部数组
if (!aliasAnalysis->isLocalArray(ptr) ||
sideEffectAnalysis->mayModifyGlobal(prevInst)) {
mayBeModified = true;
break;
}
}
} else if (prevInst->isMemset()) {
// Memset指令可能影响内存但只有在它在相关Store之前时才阻止常量传播
MemsetInst *memsetInst = static_cast<MemsetInst *>(prevInst);
Value *memsetPtr = memsetInst->getOperand(0);
auto aliasResult = aliasAnalysis->queryAlias(ptr, memsetPtr);
if (aliasResult != AliasType::NO_ALIAS) {
// Memset可能影响这个位置但我们继续查找是否有Store覆盖了memset
// 不立即设置mayBeModified = true让后续的Store有机会覆盖
if (DEBUG) {
std::cout << "SCCP: Found memset that may affect location, but continuing to check for overwriting stores" << std::endl;
}
}
}
}
if (DEBUG) {
std::cout << "SCCP: mayBeModified = " << (mayBeModified ? "true" : "false") << std::endl;
std::cout << "SCCP: hasFoundDefinitiveStore = " << (hasFoundDefinitiveStore ? "true" : "false") << std::endl;
}
if (!mayBeModified) {
if (hasFoundDefinitiveStore && foundConstantValue.state == LatticeVal::Constant) {
// 直接使用找到的常量值
if (DEBUG) {
std::cout << "SCCP: Using found constant value from store analysis: ";
if (foundConstantValue.constant_type == ValueType::Integer) {
std::cout << std::get<int>(foundConstantValue.constantVal);
} else {
std::cout << std::get<float>(foundConstantValue.constantVal);
}
std::cout << std::endl;
}
newState = foundConstantValue;
} else {
// 如果没有发现修改该位置的指令尝试用旧方法找到对应的Store值
SSAPValue constantValue = findStoredConstantValue(ptr, inst->getParent());
if (constantValue.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Found constant value for array load using fallback method: ";
if (constantValue.constant_type == ValueType::Integer) {
std::cout << std::get<int>(constantValue.constantVal);
} else {
std::cout << std::get<float>(constantValue.constantVal);
}
std::cout << std::endl;
}
newState = constantValue;
} else {
newState = SSAPValue(LatticeVal::Bottom);
}
}
} else {
newState = SSAPValue(LatticeVal::Bottom);
}
} else {
// 非局部数组或非常量访问,保守处理
newState = SSAPValue(LatticeVal::Bottom);
}
} else {
// 没有分析信息时保守处理
newState = SSAPValue(LatticeVal::Bottom);
}
if (DEBUG && aliasAnalysis && sideEffectAnalysis) {
std::cout << "SCCP: Load instruction analysis - "
<< (aliasAnalysis->isLocalArray(ptr) ? "local array" : "other")
<< ", static constant access: "
<< (aliasAnalysis->hasConstantAccess(ptr) ? "yes" : "no")
<< ", runtime constant access: "
<< (hasRuntimeConstantAccess(ptr) ? "yes" : "no") << std::endl;
}
break;
}
case Instruction::kStore:
// Store 指令不产生值,其 SSAPValue 不重要
newState = SSAPValue(); // 保持 Top
break;
case Instruction::kCall:
// 大多数 Call 指令都假定为 Bottom除非是纯函数且所有参数都是常量
newState = SSAPValue(LatticeVal::Bottom);
case Instruction::kCall: {
// 使用副作用分析改进Call指令处理
CallInst *callInst = static_cast<CallInst *>(inst);
if (sideEffectAnalysis) {
const auto &sideEffect = sideEffectAnalysis->getInstructionSideEffect(callInst);
// 检查是否为纯函数且所有参数都是常量
if (sideEffect.isPure && sideEffect.type == SideEffectType::NO_SIDE_EFFECT) {
// 对于纯函数,检查所有参数是否都是常量
bool allArgsConstant = true;
std::vector<SSAPValue> argValues;
for (unsigned i = 0; i < callInst->getNumOperands() - 1; ++i) { // 减1排除函数本身
SSAPValue argVal = GetValueState(callInst->getOperand(i));
argValues.push_back(argVal);
if (argVal.state != LatticeVal::Constant) {
allArgsConstant = false;
break;
}
}
if (allArgsConstant) {
// 对于参数全为常量的纯函数,可以尝试常量折叠
// 但由于实际执行函数比较复杂,这里先标记为可优化
// TODO: 实现具体的纯函数常量折叠
Function *calledFunc = callInst->getCallee();
if (calledFunc && isKnownPureFunction(calledFunc->getName())) {
// 对已知的纯函数进行常量计算
newState = computePureFunctionResult(callInst, argValues);
} else {
newState = SSAPValue(LatticeVal::Bottom);
}
} else {
// 参数不全是常量,但函数无副作用
newState = SSAPValue(LatticeVal::Bottom);
}
if (DEBUG) {
std::cout << "SCCP: Pure function call with "
<< (allArgsConstant ? "constant" : "non-constant") << " arguments" << std::endl;
}
} else {
// 有副作用的函数调用,保守处理
newState = SSAPValue(LatticeVal::Bottom);
if (DEBUG) {
std::cout << "SCCP: Function call with side effects" << std::endl;
}
}
} else {
// 没有副作用分析时保守处理所有Call
newState = SSAPValue(LatticeVal::Bottom);
}
break;
}
case Instruction::kGetElementPtr: {
// GEP 指令计算地址,通常其结果值(地址指向的内容)是 Bottom
// 除非所有索引和基指针都是常量,指向一个确定常量值的内存位置
@ -866,12 +1264,34 @@ bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) {
if (DEBUG) {
std::cout << "Running SCCP on function: " << F->getName() << std::endl;
}
SCCPContext context(builder);
// 获取别名分析结果
if (auto *aliasResult = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F)) {
context.setAliasAnalysis(aliasResult);
if (DEBUG) {
std::cout << "SCCP: Using alias analysis results" << std::endl;
}
}
// 获取副作用分析结果
if (auto *sideEffectResult = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>(F)) {
context.setSideEffectAnalysis(sideEffectResult);
if (DEBUG) {
std::cout << "SCCP: Using side effect analysis results" << std::endl;
}
}
context.run(F, AM);
return true;
}
void SCCP::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// 声明依赖别名分析和副作用分析
analysisDependencies.insert(&SysYAliasAnalysisPass::ID);
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
// analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析很可能失效