PointerArgProcess 函数指针参数处理算法

PointerArgProcess 函数指针参数处理算法

在这里插入图片描述
2020-10-19
New PointerAnalysis算法步骤详细说明(修改后的PointerArgProcess)

1、每次以Function为处理单位,从Top Function(默认main)开始,依次处理IR中与Top Function相关所有Function。

2、 OptGetElementPtrInst(func):对Function中两个连续getelementptr做合并操作。

3、getTargetedCallInst(func, call_list):遍历Function中CallInst,并用call_list记录CallInst。

4、processTargetedCallInst(call_list):依次遍历处理call_list中的每一条CallInst指令。并用new_callInst替换old_callInst。

(函数参数替换与创建指令)
5、SplitInstPointerArg(call_inst):目标是将函数的PointerArg分解Globalvariable、AllcaInst、Argument和非PointerType的变量。

5.1、AnalysisPointerArg(call_inst):分析CallInst的PointerArg,以及 GetelementptrInst、SelectInst、PHINode等指令,并记录memory和offset。

5.2、CreateMidFunction(call_inst):
先利用func_arg_vec_创建MidF,此时MidF函数参数和 body都需要修改。
其次为MidFunction AddNewInst,遍历process_inst_list_处理, 将相关的GetelementptrInst、SelectInst、PHINode等指令添加进MidFunction中。

5.3、getReplacedArg(call_inst, del_arg_index):记录CallInst中PointerArg为Inst的参数,准备删除。

5.4、DelFunctionArg(MidF, del_arg_index):删除MidF中useless pointer_argument by del_arg_index。生成NewFunction。

5.5、创建New_CallInst,并代替Old_CallInst,删除Old_CallInst,删除MidFunction。

5.6、MarkGlobalVariable(call_new, NewF):record the characteristic of global in function

5.7、addFuncUmap(OldF, NewF):unordered_map<Function*, list<Function*> > func_umap_,如果OldF对应list为空,NewF加入list,否则NewF与list中Function逐个比较FunctionType。(如果Type一致,再比较Function添加的全局变量是否一致。)当确定NewF在list已经存在,将其删除。

(目的:Global变量不允许出现在函数参数,将其转至函数内部)
6、delGlobalArg(call_inst): 当函数参数存在全局变量指针,利用delGlobalArg函数进行替换删除处理。

(函数参数独立性分析processNonUniquePointer)
7、processNonUniquePointer(call_inst):为保证函数参数直接相互独立,需要对不独立的参数进行替换删除,并生成NewFunc。(replace all uses of repetitive arg in body,delete the repetitive arguments & create new function with new CallInst。)

8、processUselessFunc():利用del_list_,删除被new_Function替换且无调用的old_function。

9、PointerArgProcessMain()处理完毕。

2020-10-15:对算法设计细节流程:(仅供参考)

对select、phi指令进行添加,算法进行改进工作

(1)处理callInst指令中pointer参数:callInst(%a, %b, %c, %d, %e,……)

(2)%a往前搜索规则终止规则:Value为port、globalvariable、alloca。
搜索的指令为:getelementptr、bitcast、select、phi。

(3)举个栗子:
在这里插入图片描述

Orderset_argument: %M1, %I1, %I2, %M2

%1 : %M1, %I1
%2:%M1, %I2
%3:%M2, %I1
%x: %1, %2, %3
%y: %1, %x

Func_Mid(%x, %y ,%M1, %I1, %I2, %M2)

Func(%M1, %I1, %I2, %M2)

具体算法流程:

process_inst_set(Instruction*):需要copy指令集合。
List(Instruction*) copy指令处理顺序
func_arg_vec(Value*):原始参数所有value + 拆解的memory和offset。
arg_map(value*,int):记录NewFunc的是否存在该value,与value在NewFunc中的index。
其中value为AllocaInst、GlobalVariable、Argument、(Inst’s op->getType()->isPointerTy() == false)

callInst(%1,……)

首先判断callInst是否需要处理条件:含有不是port、globalvariable、alloca的指针。

当%1%为函数参数时,判断%1:port、globalvariable、alloca。

1.1当%1为port、globalvariable、alloca, arg_map记录%1在函数参数的index_num。

1.2当%1不为port、globalvariable、alloca的指针参数。并用del_num记录。
判断%1是否在process_inst_set中。
1.2.1 当%1存在于process_inst_set中,不用处理。
1.2.2 当%1不存在于process_inst_set中,process_inst_set添加%1。依次处理%1的operands。
当operand为port、globalvariable、alloca、非pointer Type:
当operand存在于arg_map中,不用处理。
当不存在arg_map中,将其添加进入arg_map和func_arg_vec。

else:
当operand存在于process_inst_set中,不用处理。
当operand不存在于process_inst_set中,operand添加进process_inst_set中,继而处理operand这条指令。

1.3 memory到callInst中pointer参数之间的指令全部标记处理完毕。利用process_inst_set、func_arg_vec(Value*)、arg_map(value*,int)创建MidFunc(原始参数+func_arg_vec中参数)
1.3.1 利用func_arg_vec(Value*)创建MidFunc FunctionType。生成MidFunc函数。
注意:进行OldF 的ArgAttr相关属性copy到 Mid的问题,

1.3.2 利用process_inst_list_,准备将Instruction重新create到MidFunc函数中。
1.3.3 依次遍历处理process_inst_list_中的Instruction。
inst_map(Instruction*, Instruction*):OldF 中inst与MidF 中inst的map。

举例子:
%1 = memory + offset
通过memory、offset的index找到对应MidFunc中的argument。从而create MidFunc中的%Mid_1。需要建立%1与%Mid_1的联系。inst_map[%1] = %Mid_1。

%3 = %1 + %2 + offset
通过offset的index找到对应MidFunc中的argument。再从inst_map中寻找%1、%2对应的%Mid_1、%Mid_2。从而生成inst_map[%3] = %Mid_3。

vec_temp中所有的Value在arg_map或者inst_map中都能找到时,对该Instruction进行create。

1.4 当所有指令都在MidFunc中create完毕后,删除callInst中del_num记录的指针参数。生成NewFunc,并重新创建NewFunc对应的callInst_new。

猜你喜欢

转载自blog.csdn.net/pc153262603/article/details/109154947