rm_strcut处理的重点:按照每一个Function进行处理instructions。
(1)processFunctionList遍历FunctionList,处理current Function。
void processFunctionList(list<Function*> &func_list, const unordered_set<StructType *> &uset)
(2)处理f内的所有含有uset内StructType的指令。
processFuncBody(Function *f, const unordered_set<StructType *> &uset)
所处理的指令类型为:
AllocaInst
case 30: **LoadInstProcess**(inst);
case 31: **StoreInstProcess**(inst);
case 32: **GetElementPtrInstProcess**(inst);
case 47: **BitCastInstProcess**(inst);
case 54: **CallInstProcess**(inst);
case 23: ShlInstProcess(inst);
case 24: LShrInstProcess(inst);
case 25: AShrInstProcess(inst);
case 26: AndInstProcess(inst);
case 27: OrInstProcess(inst);
case 28: XorInstProcess(inst);
case 36: TruncInstProcess(inst);
case 37: ZExtInstProcess(inst);
case 38: ZExtInstProcess(inst);
处理上述指令时,会将其放置于value_umap_与inst_list_中去。与current struct相关的inst都会放进inst_list_中,等待删除。《old_inst,new_insts》也都会放进value_umap中,等待替换处理。
AllocaInst会放置于value_umap_与delete_alloca中。删除由delete_alloca执行。
指令处理完毕,此时inst_list_为空,value_umap_只剩于globalvariable和argument的value信息。清空call_op_reslove_、则该Function就处理完毕了。
(3)处理每种类型的指令。
LoadInstProcess:
(0)load_src为AllocaInst的case:
需要将AllocaInst对应的每个sub_allocainst生成LoadInst指令。
(1)load_src为BitcastInst的case:
(1.1)当BitcastInst的struct的subvalue依旧是StructType类型且其MSB大于等于bitcast_width,则创建subvalue的BitcastInst代替old BitcastInst。
(1.2)otherwise,为BitcastInst和LoadInst建立MemoryTable,并将LoadInst加入inst_list_和value_umap中。
CreateBitcastMemoryTable(Instruction *bitcast_inst) {
CreateMemoryTabelElement(bitcast_inst, op_src, val_offset_list);
}
就是为了生成BitcastInst对应的MemoryTable,拿到op_src和val_offset_list后,根据bitcast_width,生成op_src的sub_value,并将其放入BitcastInst对应的MemoryTable中。
对LoadInst处理程序:inst_list_.push_back(inst); insertOneValue(inst, inst);
(2)当LoadInst的src是GetElementPtrInst时,且getelementptrInst最终结果是一个AllocaInst,则需对其子元素进行load,等待使用其指令继续处理。
StoreInstProcess:
除bitcast情况外,StoreInst都会加入inst_list_,然后生成相关指令insertBefore StoreInst。
分为三个区域:
if (hasToProcess(store_src) && hasToProcess(store_dest)) {
MemoryTable *mt_dest = StoreInstDestProcess(store_dest);
MemoryTable *mt_src = StoreInstSrcProcess(store_src);
if ((mt_dest != NULL) && (mt_src != NULL)) {
//两个都是来自于MemoryTable,直接copy
DestAndSrcWithMemoryTable(store_inst, mt_dest, mt_src);
} else if ((mt_dest != NULL) && (mt_src == NULL)) {
DestWithMemoryTable(store_inst, mt_dest);
} else if ((mt_dest == NULL) && (mt_src != NULL)) {
//dest来自于MemoryTable,src必然来自于Argument(因为不是指针,所以不会来自于globalvariable或者AllocaInst)
SrcWithMemoryTable(store_inst, mt_src);
} else {
outs() << "add a new case of storeInst!" << "\n";
assert(0);
}
inst_list_.push_back(store_inst);
} else if (hasToProcess(store_src)) {
if (isa<Argument>(store_src)) {
StoreSrcIsIntegerArgument(store_inst);
} else {
//src需要处理,将所有sub_value进行load,再concate给dest
ConcateSrcToDest(store_inst);
inst_list_.push_back(store_inst);
}
} else {
assert(hasToProcess(store_dest));
bool flag = false;
if (isa<BitCastInst>(store_dest)) {
BitCastInst *bitcast_inst = dyn_cast<BitCastInst>(store_dest);
flag = BitCastWithoutMemoryTable(bitcast_inst);
}
if (flag == false) {
SplitSrcToDest(store_inst);
inst_list_.push_back(store_inst);
}
}
StoreSrcIsIntegerArgument:
专门处理src是从Argument而来的,且其类型为Integer
(情况1)dest是一条AllocaInst指令,从getelementptr的map_vec而来。
//3d_rendering case
%6 = alloca { i64, i8 }, align 1
%7 = getelementptr inbounds { i64, i8 }, { i64, i8 }* %6, i32 0, i32 0
store i64 %0, i64* %7, align 1
(情况2)dest直接就是一个AllocaInst。
%12 = alloca i56, align 8
store i56 %0, i56* %12, align 8
需要将%12按照%0的sub_value类型将%12分解掉。
BitCastInstProcess:
如果bitcast的src的:hasToProcess(src)返回值为true,加入inst_list_,也将其与相关指令加入Value_umap。
等待其他指令使用情况对其进行处理。
GetElementPtrInstProcess:
如果getelementptrInst的src的:hasToProcess(src)返回值为true,加入inst_list_。
(1)src为isVariable(getelementptr_src),则将分解后的old与new_getelementptr加入value_umap中,否则,old与old加入value_umap,带以后解决。
(2)src为getelementptrInst,提取op_src为isVariable的getelementptrInst,为其生成new_getelementptrInst。
当getelementptrInst在Umap中对应全是替换指令时,用替换指令代替它。
当getelementptrInst在Umap中的map_vec存有自身和新建记录组合index的getelementptrInst,两者都会被删除,新建是先插入后删除。
%29 = getelementptr inbounds { i64, i32 }, { i64, i32 }* %4, i32 0, i32 0
当getelementptrInst在Umap中,get出来的元素仍旧要被分解,而且是一个AllocaInst指令,已经被插入进BasicBlock中,
所以遇到该指令,也是将自身和AllocaInst放入Umap,等待使用它的指令处理。
CallInstProcess:
memcpyInst(dest, src):
(1)当两种都是StructType时:
1.1:同为identify或者literal,MemcpySameType(inst);
1.2::两种为不同类型的StructType(一个为identify,另一个为literal),MemcpyDestIsLiteralAlloca(inst); MemcpySrcIsLiteralAlloca(inst);
无论何时,都是identify的粒度小于literal,所以都是循环遍历小粒度的identify。
MemcpyDestIsLiteralAlloca:此时dest是一个AllocaInst。
%4 = alloca { i64, i32 }, align 4
%21 = bitcast { i64, i32 }* %4 to i8*
%22 = bitcast %struct.TIME* %1 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %21, i8* %22, i64 12, i32 4, i1 false)
1、遍历src_type_table的sub_type。
2、依据src的sub_type的大小,生成与之一致的AllocaInst,并把它加入pushOneValue(dest_ptr, alloca_inst);
3、处理完毕时,memcpy的指令create完成,dest中的AllocaInst iN指令也生成对应的sub_AllocaInst。
MemcpySrcIsLiteralAlloca:此时src是一个AllocaInst。
define void @differenceBetweenTimePeriod(i64, i32, i64, i32, %struct.TIME*) #0 {
%6 = alloca %struct.TIME, align 4
%7 = alloca { i64, i32 }, align 4
%10 = getelementptr inbounds { i64, i32 }, { i64, i32 }* %7, i32 0, i32 0
store i64 %0, i64* %10, align 4
%11 = getelementptr inbounds { i64, i32 }, { i64, i32 }* %7, i32 0, i32 1
store i32 %1, i32* %11, align 4
%12 = bitcast %struct.TIME* %6 to i8*
%13 = bitcast { i64, i32 }* %7 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %12, i8* %13, i64 12, i32 4, i1 false)
1、由于此时的Src中AllocaInst已经被分解完毕,所以直接遍历src_type_table,并将子元素push进src_memcpy_list。
2、再遍历dest_type_table,目前认为dest_type_table的size和src_memcpy_list的size相等。然后两者进行create memcpyInst。
MemcpySrcIsIntegerAlloca:
%3 = alloca i56, align 8
store i56 %0, i56* %3, align 8
%4 = bitcast i56* %3 to i8*
%5 = bitcast %struct.Triangle_2D* %2 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* %4, i64 7, i32 1, i1 false)
此时的Src为IntegerAlloca,memcpy的src必然已经被分解过了,则可以直接遍历dest的element,将两个对应元素进行memcpy。
MemcpyDestIsIntegerAlloca:
define zeroext i1 @rasterization1(i56, i8* nocapture, i32* nocapture) #4 {
%4 = alloca %struct.Triangle_2D, align 1
%5 = alloca i56, align 8
%6 = alloca i56, align 8
%7 = alloca i56, align 8
store i56 %0, i56* %5, align 8
%8 = bitcast i56* %5 to i8*
%9 = bitcast %struct.Triangle_2D* %4 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %9, i8* %8, i64 7, i32 1, i1 false)
%10 = bitcast i56* %6 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %10, i8* %9, i64 7, i32 1, i1 false)
%10作为memcpy 的dest就是IntegerAlloca,src一定是有sub_value的,而首先确定dest是没有子变量的,然后遍历src的sub_value,生成同类型type的alloca作为dest的sub_value,然后memcpyInst。