@@ -0,0 +1,450 @@
# include "GVN.h"
# include "Dom.h"
# include "SysYIROptUtils.h"
# include <algorithm>
# include <cassert>
# include <iostream>
extern int DEBUG ;
namespace sysy {
// GVN 遍的静态 ID
void * GVN : : ID = ( void * ) & GVN : : ID ;
// ======================================================================
// GVN 类的实现
// ======================================================================
bool GVN : : runOnFunction ( Function * func , AnalysisManager & AM ) {
if ( func - > getBasicBlocks ( ) . empty ( ) ) {
return false ;
}
if ( DEBUG ) {
std : : cout < < " \n === Running GVN on function: " < < func - > getName ( ) < < " === " < < std : : endl ;
}
bool changed = false ;
GVNContext context ;
context . run ( func , & AM , changed ) ;
if ( DEBUG ) {
if ( changed ) {
std : : cout < < " GVN: Function " < < func - > getName ( ) < < " was modified " < < std : : endl ;
} else {
std : : cout < < " GVN: Function " < < func - > getName ( ) < < " was not modified " < < std : : endl ;
}
std : : cout < < " === GVN completed for function: " < < func - > getName ( ) < < " === " < < std : : endl ;
}
return changed ;
}
void GVN : : getAnalysisUsage ( std : : set < void * > & analysisDependencies , std : : set < void * > & analysisInvalidations ) const {
// GVN依赖以下分析:
// 1. 支配树分析 - 用于检查指令的支配关系,确保替换的安全性
analysisDependencies . insert ( & DominatorTreeAnalysisPass : : ID ) ;
// 2. 副作用分析 - 用于判断函数调用是否可以进行GVN
analysisDependencies . insert ( & SysYSideEffectAnalysisPass : : ID ) ;
// GVN不会使任何分析失效, 因为:
// - GVN只删除冗余计算, 不改变CFG结构
// - GVN不修改程序的语义, 只是消除重复计算
// - 支配关系保持不变
// - 副作用分析结果保持不变
// analysisInvalidations 保持为空
if ( DEBUG ) {
std : : cout < < " GVN: Declared analysis dependencies (DominatorTree, SideEffectAnalysis) " < < std : : endl ;
}
}
// ======================================================================
// GVNContext 类的实现
// ======================================================================
void GVNContext : : run ( Function * func , AnalysisManager * AM , bool & changed ) {
if ( DEBUG ) {
std : : cout < < " Starting GVN analysis for function: " < < func - > getName ( ) < < std : : endl ;
}
// 获取分析结果
if ( AM ) {
domTree = AM - > getAnalysisResult < DominatorTree , DominatorTreeAnalysisPass > ( func ) ;
sideEffectAnalysis = AM - > getAnalysisResult < SideEffectAnalysisResult , SysYSideEffectAnalysisPass > ( ) ;
if ( DEBUG ) {
if ( domTree ) {
std : : cout < < " GVN: Using dominator tree analysis " < < std : : endl ;
} else {
std : : cout < < " GVN: Warning - dominator tree analysis not available " < < std : : endl ;
}
if ( sideEffectAnalysis ) {
std : : cout < < " GVN: Using side effect analysis " < < std : : endl ;
} else {
std : : cout < < " GVN: Warning - side effect analysis not available " < < std : : endl ;
}
}
}
// 清空状态
hashtable . clear ( ) ;
visited . clear ( ) ;
rpoBlocks . clear ( ) ;
needRemove . clear ( ) ;
// 计算逆后序遍历
computeRPO ( func ) ;
if ( DEBUG ) {
std : : cout < < " Computed RPO with " < < rpoBlocks . size ( ) < < " blocks " < < std : : endl ;
}
// 按逆后序遍历基本块进行GVN
int blockCount = 0 ;
for ( auto bb : rpoBlocks ) {
if ( DEBUG ) {
std : : cout < < " Processing block " < < + + blockCount < < " / " < < rpoBlocks . size ( )
< < " : " < < 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 ( ) ) ;
}
}
if ( DEBUG ) {
std : : cout < < " Found " < < needRemove . size ( ) < < " redundant instructions to remove " < < std : : endl ;
}
// 删除冗余指令
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 ;
}
if ( DEBUG ) {
std : : cout < < " GVN analysis completed for function: " < < func - > getName ( ) < < std : : endl ;
std : : cout < < " Total instructions analyzed: " < < hashtable . size ( ) < < std : : endl ;
std : : cout < < " Instructions eliminated: " < < needRemove . size ( ) < < std : : endl ;
}
}
void GVNContext : : computeRPO ( Function * func ) {
rpoBlocks . clear ( ) ;
visited . clear ( ) ;
auto entry = func - > getEntryBlock ( ) ;
if ( entry ) {
dfs ( entry ) ;
std : : reverse ( rpoBlocks . begin ( ) , rpoBlocks . end ( ) ) ;
}
}
void GVNContext : : dfs ( BasicBlock * bb ) {
if ( ! bb | | visited . count ( bb ) ) {
return ;
}
visited . insert ( bb ) ;
// 访问所有后继基本块
for ( auto succ : bb - > getSuccessors ( ) ) {
if ( visited . find ( succ ) = = visited . end ( ) ) {
dfs ( succ ) ;
}
}
rpoBlocks . push_back ( bb ) ;
}
Value * GVNContext : : checkHashtable ( Value * value ) {
if ( auto it = hashtable . find ( value ) ; it ! = hashtable . end ( ) ) {
return it - > second ;
}
if ( auto inst = dynamic_cast < Instruction * > ( value ) ) {
if ( auto valueNumber = getValueNumber ( inst ) ) {
hashtable [ value ] = valueNumber ;
return valueNumber ;
}
}
hashtable [ value ] = value ;
return value ;
}
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 ) ) {
return getValueNumber ( call ) ;
}
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 ( ) ) {
// 检查操作数是否匹配
if ( ( lhs = = binLhs & & rhs = = binRhs ) | | ( inst - > isCommutative ( ) & & lhs = = binRhs & & rhs = = binLhs ) ) {
if ( DEBUG ) {
std : : cout < < " Found equivalent binary instruction: " < < binary - > getName ( ) < < std : : endl ;
}
return value ;
}
}
}
}
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 ( ) ) ;
for ( auto [ key , value ] : hashtable ) {
if ( auto load = dynamic_cast < LoadInst * > ( key ) ) {
auto loadPtr = checkHashtable ( load - > getPointer ( ) ) ;
if ( ptr = = loadPtr & & inst - > getType ( ) = = load - > getType ( ) ) {
return value ;
}
}
}
return inst ;
}
Value * GVNContext : : getValueNumber ( CallInst * inst ) {
// 只为无副作用的函数调用进行GVN
if ( sideEffectAnalysis & & ! sideEffectAnalysis - > isPureFunction ( inst - > getCallee ( ) ) ) {
return nullptr ;
}
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 ( ) ) {
if ( DEBUG ) {
std : : cout < < " Skipping branch instruction: " < < inst - > getName ( ) < < std : : endl ;
}
return ;
}
if ( DEBUG ) {
std : : cout < < " Visiting 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 ) ;
if ( DEBUG ) {
std : : cout < < " GVN: Replacing redundant instruction " < < inst - > getName ( )
< < " with existing instruction " < < instValue - > getName ( ) < < std : : endl ;
}
} else {
if ( DEBUG ) {
std : : cout < < " Cannot replace instruction " < < inst - > getName ( )
< < " with " < < instValue - > getName ( ) < < " (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 ; // 替换为常量总是安全的
}
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 ; } ) ;
// 替换指令必须在原指令之前
return std : : distance ( insts . begin ( ) , replIt ) < std : : distance ( insts . begin ( ) , origIt ) ;
}
// 使用支配关系检查(如果支配树分析可用)
if ( domTree ) {
auto dominators = domTree - > getDominators ( originalBB ) ;
if ( dominators & & dominators - > count ( replBB ) ) {
return true ;
}
}
return false ;
}
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 ) ) ;
}
}
return oss . str ( ) ;
}
} // namespace sysy