[midend-Alias]应用别名分析结果,sccp现在能简单传播数组元素了
This commit is contained in:
@ -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); // 活跃性分析很可能失效
|
||||
|
||||
Reference in New Issue
Block a user