[midend-GVN]重构GVN的值编号系统

This commit is contained in:
rain2133
2025-08-17 16:33:15 +08:00
parent 969a78a088
commit 8ca64610eb
2 changed files with 291 additions and 573 deletions

View File

@ -19,8 +19,11 @@ public:
void run(Function* func, AnalysisManager* AM, bool& changed);
private:
// 值编号的哈希表Value -> 代表值
std::unordered_map<Value*, Value*> hashtable;
// 新的值编号系统
std::unordered_map<Value*, unsigned> valueToNumber; // Value -> 值编号
std::unordered_map<unsigned, Value*> numberToValue; // 值编号 -> 代表值
std::unordered_map<std::string, unsigned> expressionToNumber; // 表达式 -> 值编号
unsigned nextValueNumber = 1;
// 已访问的基本块集合
std::unordered_set<BasicBlock*> visited;
@ -39,31 +42,27 @@ private:
void computeRPO(Function* func);
void dfs(BasicBlock* bb);
// 检查哈希表并获取值编号
Value* checkHashtable(Value* value);
// 新的值编号方法
unsigned getValueNumber(Value* value);
unsigned assignValueNumber(Value* value);
// 为不同类型的指令获取值编号
Value* getValueNumber(Instruction* inst);
Value* getValueNumber(BinaryInst* inst);
Value* getValueNumber(UnaryInst* inst);
Value* getValueNumber(GetElementPtrInst* inst);
Value* getValueNumber(LoadInst* inst);
Value* getValueNumber(CallInst* inst);
// 基本块处理
void processBasicBlock(BasicBlock* bb, bool& changed);
// 访问指令并进行GVN优化
void visitInstruction(Instruction* inst);
// 指令处理
bool processInstruction(Instruction* inst);
// 检查是否可以安全地用一个值替换另一个值
bool canReplace(Instruction* original, Value* replacement);
// 表达式构建和查找
std::string buildExpressionKey(Instruction* inst);
Value* findExistingValue(const std::string& exprKey, Instruction* inst);
// 检查两个load指令之间是否有store指令修改了相同的内存位置
bool hasInterveningStore(LoadInst* earlierLoad, LoadInst* laterLoad, Value* ptr);
// 支配关系和安全性检查
bool dominates(Instruction* a, Instruction* b);
bool isMemorySafe(LoadInst* earlierLoad, LoadInst* laterLoad);
// 使受store指令影响的load指令失效
void invalidateLoadsAffectedByStore(StoreInst* storeInst);
// 生成表达式的标准化字符串
std::string getCanonicalExpression(Instruction* inst);
// 清理方法
void eliminateRedundantInstructions(bool& changed);
void invalidateMemoryValues(StoreInst* store);
};
// GVN优化遍类

View File

@ -4,6 +4,8 @@
#include <algorithm>
#include <cassert>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
extern int DEBUG;
@ -62,9 +64,33 @@ void GVN::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void
}
// ======================================================================
// GVNContext 类的实现
// GVNContext 类的实现 - 重构版本
// ======================================================================
// 简单的表达式哈希结构
struct ExpressionKey {
enum Type { BINARY, UNARY, LOAD, GEP, CALL } type;
int opcode;
std::vector<Value*> operands;
Type* resultType;
bool operator==(const ExpressionKey& other) const {
return type == other.type && opcode == other.opcode &&
operands == other.operands && resultType == other.resultType;
}
};
struct ExpressionKeyHash {
size_t operator()(const ExpressionKey& key) const {
size_t hash = std::hash<int>()(static_cast<int>(key.type)) ^
std::hash<int>()(key.opcode);
for (auto op : key.operands) {
hash ^= std::hash<Value*>()(op) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
void GVNContext::run(Function *func, AnalysisManager *AM, bool &changed) {
if (DEBUG) {
std::cout << " Starting GVN analysis for function: " << func->getName() << std::endl;
@ -90,7 +116,10 @@ void GVNContext::run(Function *func, AnalysisManager *AM, bool &changed) {
}
// 清空状态
hashtable.clear();
valueToNumber.clear();
numberToValue.clear();
expressionToNumber.clear();
nextValueNumber = 1;
visited.clear();
rpoBlocks.clear();
needRemove.clear();
@ -110,14 +139,7 @@ void GVNContext::run(Function *func, AnalysisManager *AM, bool &changed) {
<< ": " << bb->getName() << std::endl;
}
int instCount = 0;
for (auto &instPtr : bb->getInstructions()) {
if (DEBUG) {
std::cout << " Processing instruction " << ++instCount
<< ": " << instPtr->getName() << std::endl;
}
visitInstruction(instPtr.get());
}
processBasicBlock(bb, changed);
}
if (DEBUG) {
@ -125,24 +147,11 @@ void GVNContext::run(Function *func, AnalysisManager *AM, bool &changed) {
}
// 删除冗余指令
int removeCount = 0;
for (auto inst : needRemove) {
auto bb = inst->getParent();
if (DEBUG) {
std::cout << " Removing redundant instruction " << ++removeCount
<< "/" << needRemove.size() << ": " << inst->getName() << std::endl;
}
// 删除指令前先断开所有使用关系
inst->replaceAllUsesWith(nullptr);
// 使用基本块的删除方法
// bb->removeInst(inst);
SysYIROptUtils::usedelete(inst);
changed = true;
}
eliminateRedundantInstructions(changed);
if (DEBUG) {
std::cout << " GVN analysis completed for function: " << func->getName() << std::endl;
std::cout << " Total instructions analyzed: " << hashtable.size() << std::endl;
std::cout << " Total values numbered: " << valueToNumber.size() << std::endl;
std::cout << " Instructions eliminated: " << needRemove.size() << std::endl;
}
}
@ -175,599 +184,309 @@ void GVNContext::dfs(BasicBlock *bb) {
rpoBlocks.push_back(bb);
}
Value *GVNContext::checkHashtable(Value *value) {
// 避免无限递归:如果已经在哈希表中,直接返回映射的值
if (auto it = hashtable.find(value); it != hashtable.end()) {
if (DEBUG >= 2) {
std::cout << " Found " << value->getName() << " in hashtable, mapped to "
<< it->second->getName() << std::endl;
}
unsigned GVNContext::getValueNumber(Value* value) {
// 如果已经有值编号,直接返回
auto it = valueToNumber.find(value);
if (it != valueToNumber.end()) {
return it->second;
}
// 为新值分配编号
return assignValueNumber(value);
}
// 如果是指令,尝试获取其值编号
if (auto inst = dynamic_cast<Instruction *>(value)) {
if (auto valueNumber = getValueNumber(inst)) {
// 如果找到了等价的值,建立映射关系
if (valueNumber != inst) {
hashtable[value] = valueNumber;
if (DEBUG >= 2) {
std::cout << " Mapping " << value->getName() << " to equivalent value "
<< valueNumber->getName() << std::endl;
}
return valueNumber;
}
}
}
// 没有找到等价值,将自己映射到自己
hashtable[value] = value;
unsigned GVNContext::assignValueNumber(Value* value) {
unsigned number = nextValueNumber++;
valueToNumber[value] = number;
numberToValue[number] = value;
if (DEBUG >= 2) {
std::cout << " Mapping " << value->getName() << " to itself (unique)" << std::endl;
std::cout << " Assigned value number " << number
<< " to " << value->getName() << std::endl;
}
return value;
return number;
}
Value *GVNContext::getValueNumber(Instruction *inst) {
if (auto binary = dynamic_cast<BinaryInst *>(inst)) {
return getValueNumber(binary);
} else if (auto unary = dynamic_cast<UnaryInst *>(inst)) {
return getValueNumber(unary);
} else if (auto gep = dynamic_cast<GetElementPtrInst *>(inst)) {
return getValueNumber(gep);
} else if (auto load = dynamic_cast<LoadInst *>(inst)) {
return getValueNumber(load);
} else if (auto call = dynamic_cast<CallInst *>(inst)) {
// 只为无副作用的函数调用进行GVN
if (sideEffectAnalysis && sideEffectAnalysis->isPureFunction(call->getCallee())) {
return getValueNumber(call);
}
return nullptr;
}
return nullptr;
}
Value *GVNContext::getValueNumber(BinaryInst *inst) {
auto lhs = checkHashtable(inst->getLhs());
auto rhs = checkHashtable(inst->getRhs());
if (DEBUG) {
std::cout << " Checking binary instruction: " << inst->getName()
<< " (kind: " << static_cast<int>(inst->getKind()) << ")" << std::endl;
}
for (auto [key, value] : hashtable) {
if (auto binary = dynamic_cast<BinaryInst *>(key)) {
auto binLhs = checkHashtable(binary->getLhs());
auto binRhs = checkHashtable(binary->getRhs());
if (binary->getKind() == inst->getKind()) {
// 检查操作数是否匹配
bool operandsMatch = false;
if (lhs == binLhs && rhs == binRhs) {
operandsMatch = true;
} else if (inst->isCommutative() && lhs == binRhs && rhs == binLhs) {
operandsMatch = true;
}
if (operandsMatch) {
// 检查支配关系,确保替换是安全的
if (canReplace(inst, binary)) {
// 对于涉及load指令的情况需要特别检查
bool hasLoadOperands = (dynamic_cast<LoadInst*>(lhs) != nullptr) ||
(dynamic_cast<LoadInst*>(rhs) != nullptr);
if (hasLoadOperands) {
// 检查是否有任何load操作数之间有intervening store
bool hasIntervening = false;
auto loadLhs = dynamic_cast<LoadInst*>(lhs);
auto loadRhs = dynamic_cast<LoadInst*>(rhs);
auto binLoadLhs = dynamic_cast<LoadInst*>(binLhs);
auto binLoadRhs = dynamic_cast<LoadInst*>(binRhs);
if (loadLhs && binLoadLhs) {
if (hasInterveningStore(binLoadLhs, loadLhs, checkHashtable(loadLhs->getPointer()))) {
hasIntervening = true;
}
}
if (!hasIntervening && loadRhs && binLoadRhs) {
if (hasInterveningStore(binLoadRhs, loadRhs, checkHashtable(loadRhs->getPointer()))) {
hasIntervening = true;
}
}
// 对于交换操作数的情况,也需要检查
if (!hasIntervening && inst->isCommutative()) {
if (loadLhs && binLoadRhs) {
if (hasInterveningStore(binLoadRhs, loadLhs, checkHashtable(loadLhs->getPointer()))) {
hasIntervening = true;
}
}
if (!hasIntervening && loadRhs && binLoadLhs) {
if (hasInterveningStore(binLoadLhs, loadRhs, checkHashtable(loadRhs->getPointer()))) {
hasIntervening = true;
}
}
}
if (hasIntervening) {
if (DEBUG) {
std::cout << " Found equivalent binary but load operands have intervening store, skipping" << std::endl;
}
continue;
}
}
if (DEBUG) {
std::cout << " Found equivalent binary instruction: " << binary->getName() << std::endl;
}
return value;
} else {
if (DEBUG) {
std::cout << " Found equivalent binary but dominance check failed: " << binary->getName() << std::endl;
}
}
}
}
}
}
if (DEBUG) {
std::cout << " No equivalent binary instruction found" << std::endl;
}
return inst;
}
Value *GVNContext::getValueNumber(UnaryInst *inst) {
auto operand = checkHashtable(inst->getOperand());
for (auto [key, value] : hashtable) {
if (auto unary = dynamic_cast<UnaryInst *>(key)) {
auto unOperand = checkHashtable(unary->getOperand());
if (unary->getKind() == inst->getKind() && operand == unOperand) {
return value;
}
}
}
return inst;
}
Value *GVNContext::getValueNumber(GetElementPtrInst *inst) {
auto ptr = checkHashtable(inst->getBasePointer());
std::vector<Value *> indices;
// 使用正确的索引访问方法
for (unsigned i = 0; i < inst->getNumIndices(); ++i) {
indices.push_back(checkHashtable(inst->getIndex(i)));
}
for (auto [key, value] : hashtable) {
if (auto gep = dynamic_cast<GetElementPtrInst *>(key)) {
auto gepPtr = checkHashtable(gep->getBasePointer());
if (ptr == gepPtr && gep->getNumIndices() == inst->getNumIndices()) {
bool indicesMatch = true;
for (unsigned i = 0; i < inst->getNumIndices(); ++i) {
if (checkHashtable(gep->getIndex(i)) != indices[i]) {
indicesMatch = false;
break;
}
}
if (indicesMatch && inst->getType() == gep->getType()) {
return value;
}
}
}
}
return inst;
}
Value *GVNContext::getValueNumber(LoadInst *inst) {
auto ptr = checkHashtable(inst->getPointer());
if (DEBUG) {
std::cout << " Checking load instruction: " << inst->getName()
<< " from address: " << ptr->getName() << std::endl;
}
for (auto [key, value] : hashtable) {
if (auto load = dynamic_cast<LoadInst *>(key)) {
auto loadPtr = checkHashtable(load->getPointer());
if (ptr == loadPtr && inst->getType() == load->getType()) {
if (DEBUG) {
std::cout << " Found potential equivalent load: " << load->getName() << std::endl;
}
// 检查支配关系load 必须支配 inst
if (!canReplace(inst, load)) {
if (DEBUG) {
std::cout << " Equivalent load does not dominate current load, skipping" << std::endl;
}
continue;
}
// 检查是否有中间的store指令影响
if (hasInterveningStore(load, inst, ptr)) {
if (DEBUG) {
std::cout << " Found intervening store, cannot reuse load value" << std::endl;
}
continue; // 如果有store指令不能复用之前的load
}
if (DEBUG) {
std::cout << " Can safely reuse load value from: " << load->getName() << std::endl;
}
return value;
}
}
}
if (DEBUG) {
std::cout << " No equivalent load found" << std::endl;
}
return inst;
}
Value *GVNContext::getValueNumber(CallInst *inst) {
// 此时已经确认是无副作用的函数调用可以安全进行GVN
for (auto [key, value] : hashtable) {
if (auto call = dynamic_cast<CallInst *>(key)) {
if (call->getCallee() == inst->getCallee() && call->getNumOperands() == inst->getNumOperands()) {
bool argsMatch = true;
// 跳过第一个操作数(函数指针),从参数开始比较
for (size_t i = 1; i < inst->getNumOperands(); ++i) {
if (checkHashtable(inst->getOperand(i)) != checkHashtable(call->getOperand(i))) {
argsMatch = false;
break;
}
}
if (argsMatch) {
return value;
}
}
}
}
return inst;
}
void GVNContext::visitInstruction(Instruction *inst) {
// 跳过分支指令
if (inst->isBranch()) {
void GVNContext::processBasicBlock(BasicBlock* bb, bool& changed) {
int instCount = 0;
for (auto &instPtr : bb->getInstructions()) {
if (DEBUG) {
std::cout << " Skipping branch instruction: " << inst->getName() << std::endl;
std::cout << " Processing instruction " << ++instCount
<< ": " << instPtr->getName() << std::endl;
}
if (processInstruction(instPtr.get())) {
changed = true;
}
return;
}
}
// 如果是store指令需要清理hashtable中可能被影响的load指令
if (auto storeInst = dynamic_cast<StoreInst*>(inst)) {
invalidateLoadsAffectedByStore(storeInst);
bool GVNContext::processInstruction(Instruction* inst) {
// 跳过分支指令和其他不可优化的指令
if (inst->isBranch() || dynamic_cast<ReturnInst*>(inst) ||
dynamic_cast<AllocaInst*>(inst) || dynamic_cast<StoreInst*>(inst)) {
// 如果是store指令需要使相关的内存值失效
if (auto store = dynamic_cast<StoreInst*>(inst)) {
invalidateMemoryValues(store);
}
// 为这些指令分配值编号但不尝试优化
getValueNumber(inst);
return false;
}
if (DEBUG) {
std::cout << " Visiting instruction: " << inst->getName()
std::cout << " Processing optimizable instruction: " << inst->getName()
<< " (kind: " << static_cast<int>(inst->getKind()) << ")" << std::endl;
}
auto value = checkHashtable(inst);
if (inst != value) {
if (auto instValue = dynamic_cast<Instruction *>(value)) {
if (canReplace(inst, instValue)) {
inst->replaceAllUsesWith(instValue);
needRemove.insert(inst);
// 构建表达式键
std::string exprKey = buildExpressionKey(inst);
if (exprKey.empty()) {
// 不可优化的指令,只分配值编号
getValueNumber(inst);
return false;
}
if (DEBUG >= 2) {
std::cout << " Expression key: " << exprKey << std::endl;
}
// 查找已存在的等价值
Value* existing = findExistingValue(exprKey, inst);
if (existing && existing != inst) {
// 检查支配关系
if (auto existingInst = dynamic_cast<Instruction*>(existing)) {
if (dominates(existingInst, inst)) {
if (DEBUG) {
std::cout << " GVN: Replacing redundant instruction " << inst->getName()
<< " with existing instruction " << instValue->getName() << std::endl;
std::cout << " GVN: Replacing " << inst->getName()
<< " with existing " << existing->getName() << std::endl;
}
// 用已存在的值替换当前指令
inst->replaceAllUsesWith(existing);
needRemove.insert(inst);
// 将当前指令的值编号指向已存在的值
unsigned existingNumber = getValueNumber(existing);
valueToNumber[inst] = existingNumber;
return true;
} else {
if (DEBUG) {
std::cout << " Cannot replace instruction " << inst->getName()
<< " with " << instValue->getName() << " (dominance check failed)" << std::endl;
std::cout << " Found equivalent but dominance check failed" << std::endl;
}
}
}
} else {
if (DEBUG) {
std::cout << " Instruction " << inst->getName() << " is unique" << std::endl;
}
}
}
bool GVNContext::canReplace(Instruction *original, Value *replacement) {
auto replInst = dynamic_cast<Instruction *>(replacement);
if (!replInst) {
return true; // 替换为常量总是安全的
// 没有找到等价值,为这个表达式分配新的值编号
unsigned number = assignValueNumber(inst);
expressionToNumber[exprKey] = number;
if (DEBUG) {
std::cout << " Instruction " << inst->getName() << " is unique" << std::endl;
}
auto originalBB = original->getParent();
auto replBB = replInst->getParent();
// 如果replacement是Call指令需要特殊处理
if (auto callInst = dynamic_cast<CallInst *>(replInst)) {
if (sideEffectAnalysis && !sideEffectAnalysis->isPureFunction(callInst->getCallee())) {
// 对于有副作用的函数,只有在同一个基本块且相邻时才能替换
if (originalBB != replBB) {
return false;
}
// 检查指令顺序
auto &insts = originalBB->getInstructions();
auto origIt =
std::find_if(insts.begin(), insts.end(), [original](const auto &ptr) { return ptr.get() == original; });
auto replIt =
std::find_if(insts.begin(), insts.end(), [replInst](const auto &ptr) { return ptr.get() == replInst; });
if (origIt == insts.end() || replIt == insts.end()) {
return false;
}
return std::abs(std::distance(origIt, replIt)) == 1;
}
}
// 简单的支配关系检查:如果在同一个基本块,检查指令顺序
if (originalBB == replBB) {
auto &insts = originalBB->getInstructions();
auto origIt =
std::find_if(insts.begin(), insts.end(), [original](const auto &ptr) { return ptr.get() == original; });
auto replIt =
std::find_if(insts.begin(), insts.end(), [replInst](const auto &ptr) { return ptr.get() == replInst; });
if (origIt == insts.end() || replIt == insts.end()) {
if (DEBUG) {
std::cout << " Cannot find instructions in basic block for dominance check" << std::endl;
}
return false;
}
// 替换指令必须在原指令之前(支配原指令)
bool canRepl = std::distance(insts.begin(), replIt) < std::distance(insts.begin(), origIt);
if (DEBUG) {
std::cout << " Same block dominance check: " << (canRepl ? "PASS" : "FAIL")
<< " (repl at " << std::distance(insts.begin(), replIt)
<< ", orig at " << std::distance(insts.begin(), origIt) << ")" << std::endl;
}
return canRepl;
}
// 使用支配关系检查(如果支配树分析可用)
if (domTree) {
auto dominators = domTree->getDominators(originalBB);
if (dominators && dominators->count(replBB)) {
return true;
}
}
return false;
}
bool GVNContext::hasInterveningStore(LoadInst* earlierLoad, LoadInst* laterLoad, Value* ptr) {
// 如果两个load在不同的基本块需要更复杂的分析
std::string GVNContext::buildExpressionKey(Instruction* inst) {
std::ostringstream oss;
if (auto binary = dynamic_cast<BinaryInst*>(inst)) {
oss << "binary_" << static_cast<int>(binary->getKind()) << "_";
oss << getValueNumber(binary->getLhs()) << "_" << getValueNumber(binary->getRhs());
// 对于可交换操作,确保操作数顺序一致
if (binary->isCommutative()) {
unsigned lhsNum = getValueNumber(binary->getLhs());
unsigned rhsNum = getValueNumber(binary->getRhs());
if (lhsNum > rhsNum) {
oss.str("");
oss << "binary_" << static_cast<int>(binary->getKind()) << "_";
oss << rhsNum << "_" << lhsNum;
}
}
} else if (auto unary = dynamic_cast<UnaryInst*>(inst)) {
oss << "unary_" << static_cast<int>(unary->getKind()) << "_";
oss << getValueNumber(unary->getOperand());
} else if (auto gep = dynamic_cast<GetElementPtrInst*>(inst)) {
oss << "gep_" << getValueNumber(gep->getBasePointer());
for (unsigned i = 0; i < gep->getNumIndices(); ++i) {
oss << "_" << getValueNumber(gep->getIndex(i));
}
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
oss << "load_" << getValueNumber(load->getPointer());
oss << "_" << reinterpret_cast<uintptr_t>(load->getType()); // 类型区分
} else if (auto call = dynamic_cast<CallInst*>(inst)) {
// 只为无副作用的函数调用建立表达式
if (sideEffectAnalysis && sideEffectAnalysis->isPureFunction(call->getCallee())) {
oss << "call_" << call->getCallee()->getName();
for (size_t i = 1; i < call->getNumOperands(); ++i) { // 跳过函数指针
oss << "_" << getValueNumber(call->getOperand(i));
}
} else {
return ""; // 有副作用的函数调用不可优化
}
} else {
return ""; // 不支持的指令类型
}
return oss.str();
}
Value* GVNContext::findExistingValue(const std::string& exprKey, Instruction* inst) {
auto it = expressionToNumber.find(exprKey);
if (it != expressionToNumber.end()) {
unsigned number = it->second;
auto valueIt = numberToValue.find(number);
if (valueIt != numberToValue.end()) {
Value* existing = valueIt->second;
// 对于load指令需要额外检查内存安全性
if (auto loadInst = dynamic_cast<LoadInst*>(inst)) {
if (auto existingLoad = dynamic_cast<LoadInst*>(existing)) {
if (!isMemorySafe(existingLoad, loadInst)) {
return nullptr;
}
}
}
return existing;
}
}
return nullptr;
}
bool GVNContext::dominates(Instruction* a, Instruction* b) {
auto aBB = a->getParent();
auto bBB = b->getParent();
// 同一基本块内的情况
if (aBB == bBB) {
auto &insts = aBB->getInstructions();
auto aIt = std::find_if(insts.begin(), insts.end(),
[a](const auto &ptr) { return ptr.get() == a; });
auto bIt = std::find_if(insts.begin(), insts.end(),
[b](const auto &ptr) { return ptr.get() == b; });
if (aIt == insts.end() || bIt == insts.end()) {
return false;
}
return std::distance(insts.begin(), aIt) < std::distance(insts.begin(), bIt);
}
// 不同基本块的情况,使用支配树
if (domTree) {
auto dominators = domTree->getDominators(bBB);
return dominators && dominators->count(aBB);
}
return false; // 保守做法
}
bool GVNContext::isMemorySafe(LoadInst* earlierLoad, LoadInst* laterLoad) {
// 检查两个load是否访问相同的内存位置
unsigned earlierPtr = getValueNumber(earlierLoad->getPointer());
unsigned laterPtr = getValueNumber(laterLoad->getPointer());
if (earlierPtr != laterPtr) {
return false; // 不同的内存位置
}
// 检查类型是否匹配
if (earlierLoad->getType() != laterLoad->getType()) {
return false;
}
// 简单情况如果在同一个基本块且没有中间的store则安全
auto earlierBB = earlierLoad->getParent();
auto laterBB = laterLoad->getParent();
if (earlierBB != laterBB) {
// 跨基本块的情况为了安全起见暂时认为有intervening store
// 这是保守的做法,可能会错过一些优化机会,但确保正确性
if (DEBUG) {
std::cout << " Cross-block load optimization: conservatively assuming intervening store" << std::endl;
}
return true;
// 跨基本块的情况需要更复杂的分析,暂时保守处理
return false;
}
// 同一基本块内的情况:检查指令序列
// 同一基本块内检查是否有中间的store
auto &insts = earlierBB->getInstructions();
// 找到两个load指令的位置
auto earlierIt = std::find_if(insts.begin(), insts.end(),
auto earlierIt = std::find_if(insts.begin(), insts.end(),
[earlierLoad](const auto &ptr) { return ptr.get() == earlierLoad; });
auto laterIt = std::find_if(insts.begin(), insts.end(),
[laterLoad](const auto &ptr) { return ptr.get() == laterLoad; });
if (earlierIt == insts.end() || laterIt == insts.end()) {
if (DEBUG) {
std::cout << " Could not find load instructions in basic block" << std::endl;
}
return true; // 找不到指令保守返回true
return false;
}
// 确定实际的执行顺序哪个load在前哪个在后
auto firstIt = earlierIt;
auto secondIt = laterIt;
if (std::distance(insts.begin(), earlierIt) > std::distance(insts.begin(), laterIt)) {
// 如果"earlier"实际上在"later"之后,交换它们
firstIt = laterIt;
secondIt = earlierIt;
if (DEBUG) {
std::cout << " Swapped load order: " << laterLoad->getName()
<< " actually comes before " << earlierLoad->getName() << std::endl;
}
// 确保earlierLoad真的在laterLoad之前
if (std::distance(insts.begin(), earlierIt) >= std::distance(insts.begin(), laterIt)) {
return false;
}
// 检查两个load之间的所有指令
for (auto it = std::next(firstIt); it != secondIt; ++it) {
auto inst = it->get();
// 检查是否是store指令
if (auto storeInst = dynamic_cast<StoreInst*>(inst)) {
auto storePtr = checkHashtable(storeInst->getPointer());
// 如果store的目标地址与load的地址相同说明内存被修改了
if (storePtr == ptr) {
if (DEBUG) {
std::cout << " Found intervening store to same address: " << storeInst->getName() << std::endl;
}
return true;
// 检查中间是否有store指令修改了相同的内存位置
for (auto it = std::next(earlierIt); it != laterIt; ++it) {
if (auto store = dynamic_cast<StoreInst*>(it->get())) {
unsigned storePtr = getValueNumber(store->getPointer());
if (storePtr == earlierPtr) {
return false; // 找到中间的store
}
// TODO: 这里还应该检查别名分析看store是否可能影响load的地址
// 为了简化,现在只检查精确匹配
}
// 检查函数调用是否可能修改内存
if (auto callInst = dynamic_cast<CallInst*>(inst)) {
if (sideEffectAnalysis && !sideEffectAnalysis->isPureFunction(callInst->getCallee())) {
// 如果是有副作用的函数调用且load的是全局变量可能修改
if (auto globalPtr = dynamic_cast<GlobalValue*>(ptr)) {
if (DEBUG) {
std::cout << " Found function call that may modify global variable: " << callInst->getName() << std::endl;
}
return true;
}
// TODO: 这里还应该检查函数是否可能修改通过指针参数传递的内存
if (auto call = dynamic_cast<CallInst*>(it->get())) {
if (sideEffectAnalysis && !sideEffectAnalysis->isPureFunction(call->getCallee())) {
// 保守处理:有副作用的函数可能修改内存
return false;
}
}
}
if (DEBUG) {
std::cout << " No intervening store found between loads" << std::endl;
}
return false; // 没有找到会修改内存的指令
return true; // 安全
}
void GVNContext::invalidateLoadsAffectedByStore(StoreInst* storeInst) {
auto storePtr = checkHashtable(storeInst->getPointer());
void GVNContext::invalidateMemoryValues(StoreInst* store) {
unsigned storePtr = getValueNumber(store->getPointer());
if (DEBUG) {
std::cout << " Invalidating loads affected by store to address" << std::endl;
std::cout << " Invalidating memory values affected by store" << std::endl;
}
// 查找hashtable中所有可能被这个store影响的指令
std::vector<Value*> toRemove;
std::set<Value*> invalidatedLoads;
// 找到所有可能被这个store影响的load表达式
std::vector<std::string> toRemove;
// 第一步找到所有被直接影响的load指令
for (auto& [key, value] : hashtable) {
if (auto loadInst = dynamic_cast<LoadInst*>(key)) {
auto loadPtr = checkHashtable(loadInst->getPointer());
// 如果load的地址与store的地址相同则需要从hashtable中移除
if (loadPtr == storePtr) {
toRemove.push_back(key);
invalidatedLoads.insert(loadInst);
if (DEBUG) {
std::cout << " Invalidating load from same address: " << loadInst->getName() << std::endl;
}
for (auto& [exprKey, number] : expressionToNumber) {
if (exprKey.find("load_" + std::to_string(storePtr)) == 0) {
toRemove.push_back(exprKey);
if (DEBUG) {
std::cout << " Invalidating expression: " << exprKey << std::endl;
}
}
}
// 第二步找到所有依赖被失效load的指令如binary指令
bool foundMore = true;
while (foundMore) {
foundMore = false;
std::vector<Value*> additionalToRemove;
for (auto& [key, value] : hashtable) {
// 跳过已经标记要删除的指令
if (std::find(toRemove.begin(), toRemove.end(), key) != toRemove.end()) {
continue;
}
bool shouldInvalidate = false;
// 检查binary指令的操作数
if (auto binaryInst = dynamic_cast<BinaryInst*>(key)) {
auto lhs = checkHashtable(binaryInst->getLhs());
auto rhs = checkHashtable(binaryInst->getRhs());
if (invalidatedLoads.count(lhs) || invalidatedLoads.count(rhs)) {
shouldInvalidate = true;
if (DEBUG) {
std::cout << " Invalidating binary instruction due to invalidated operand: "
<< binaryInst->getName() << std::endl;
}
}
}
// 检查unary指令的操作数
else if (auto unaryInst = dynamic_cast<UnaryInst*>(key)) {
auto operand = checkHashtable(unaryInst->getOperand());
if (invalidatedLoads.count(operand)) {
shouldInvalidate = true;
if (DEBUG) {
std::cout << " Invalidating unary instruction due to invalidated operand: "
<< unaryInst->getName() << std::endl;
}
}
}
// 检查GEP指令的操作数
else if (auto gepInst = dynamic_cast<GetElementPtrInst*>(key)) {
auto basePtr = checkHashtable(gepInst->getBasePointer());
if (invalidatedLoads.count(basePtr)) {
shouldInvalidate = true;
} else {
// 检查索引操作数
for (unsigned i = 0; i < gepInst->getNumIndices(); ++i) {
if (invalidatedLoads.count(checkHashtable(gepInst->getIndex(i)))) {
shouldInvalidate = true;
break;
}
}
}
if (shouldInvalidate && DEBUG) {
std::cout << " Invalidating GEP instruction due to invalidated operand: "
<< gepInst->getName() << std::endl;
}
}
if (shouldInvalidate) {
additionalToRemove.push_back(key);
if (auto inst = dynamic_cast<Instruction*>(key)) {
invalidatedLoads.insert(inst);
}
foundMore = true;
}
}
// 将新找到的失效指令加入移除列表
toRemove.insert(toRemove.end(), additionalToRemove.begin(), additionalToRemove.end());
}
// 从hashtable中移除所有被影响的指令
for (auto key : toRemove) {
hashtable.erase(key);
}
if (DEBUG && toRemove.size() > invalidatedLoads.size()) {
std::cout << " Total invalidated instructions: " << toRemove.size()
<< " (including " << (toRemove.size() - invalidatedLoads.size()) << " dependent instructions)" << std::endl;
// 移除失效的表达式
for (const auto& key : toRemove) {
expressionToNumber.erase(key);
}
}
std::string GVNContext::getCanonicalExpression(Instruction *inst) {
std::ostringstream oss;
if (auto binary = dynamic_cast<BinaryInst *>(inst)) {
oss << "binary_" << static_cast<int>(binary->getKind()) << "_";
oss << checkHashtable(binary->getLhs()) << "_";
oss << checkHashtable(binary->getRhs());
} else if (auto unary = dynamic_cast<UnaryInst *>(inst)) {
oss << "unary_" << static_cast<int>(unary->getKind()) << "_";
oss << checkHashtable(unary->getOperand());
} else if (auto gep = dynamic_cast<GetElementPtrInst *>(inst)) {
oss << "gep_" << checkHashtable(gep->getBasePointer());
for (unsigned i = 0; i < gep->getNumIndices(); ++i) {
oss << "_" << checkHashtable(gep->getIndex(i));
void GVNContext::eliminateRedundantInstructions(bool& changed) {
int removeCount = 0;
for (auto inst : needRemove) {
if (DEBUG) {
std::cout << " Removing redundant instruction " << ++removeCount
<< "/" << needRemove.size() << ": " << inst->getName() << std::endl;
}
// 删除指令前先断开所有使用关系
// inst->replaceAllUsesWith 已在 processInstruction 中调用
SysYIROptUtils::usedelete(inst);
changed = true;
}
return oss.str();
}
} // namespace sysy