一、理論基礎
別名分析是許多編譯最佳化得以順利進行的一個前提,也是剖析器特徵的一個基礎手段。通常而言,別名分析有以下幾類:
(1)按是否與控制流程相關可分為:flow-sensitive vs flow-insensitive
(2)按是否與上下文相關可分為:context-sensitive vs context-insensitive
(3)按是否與特定領域相關可分為:field-sensitive vs field-insensitive
(4)按實現方式可分為:unification-based vs subset-based
在進行別名分析時,區分別名資料型別:Must,May,No是十分重要的。由於判定任意變數在運行時是否真的相關的問題,是一個不可判定問題,它等價於圖靈機停機問題,所以編譯人員無論是對程式進行靜態還是動態別名分析,總是存在無法確定的情況。當我們肯定兩個變數或者指標的別名是一定存在的則別名資料型別為Must,若肯定他們是不存在的則別名資料型別是No,否則只能是May。對May類型的別名關係,我們必須承認它但不能依靠它;而對Must和No類型的別名關係,我們可以充分信任。
關於別名關係的詳細理論和更深層次的討論可以參考Muchnick的《進階編譯器設計與實現》和Andersen的博士論文《Program Analysis and Specialization for the C Programming Language》。
二、LLVM介面類AliasAnalysis
LLVM針對別名關係提出了統一的抽象類別AliasAnalysis,該類定義了各種別名分析需要實現的介面。該類定義了表示別名關係的公用枚舉類型:AliasResult
and ModRefResult,其定義如下:
enum AliasResult { NoAlias = 0, MayAlias = 1, MustAlias = 2 };
enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 };
其中定義的介面有:
(1)virtual AliasResult alias(const Value *V1, unsigned V1Size,const Value *V2, unsigned V2Size);
判斷兩個變數是否存在別名關係;
(2)virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2);
判斷兩個函數調用之間的別名關係;
(3)virtual void getMustAliases(Value *P, std::vector<Value*> &RetVals);
獲得一定與指標P存在別名關係的變數列表;
(4)virtual bool pointsToConstantMemory(const Value *P);
判斷指標是否僅僅指向常數記憶體
(5)bool doesNotAccessMemory(CallSite CS);
bool onlyReadsMemory(CallSite CS);
判斷訪問類型。
三、向LLVM中添加一遍新的別名分析最佳化
1、首先需要確定該遍最佳化的類型:
- If you require interprocedural analysis, it should be a
Pass.
- If you are a function-local analysis, subclass FunctionPass.
- If you don't need to look at the program at all, subclass
ImmutablePass.
2、初始化getAnalysisUsage並調用InitializeAliasAnalysis,如:
void getAnalysisUsage(AnalysisUsage &AU) const {
AliasAnalysis::getAnalysisUsage(AU);
// declare your dependencies here.
}
bool run(Module &M) {
InitializeAliasAnalysis(this);
// Perform analysis here...
return false;
}
3、注意AliasAnalysis chaining和Updating analysis results相關的內容
4、詳細可以參考http://www.llvm.org/docs/AliasAnalysis.html