new rm_struct pass’s process FunctionList

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。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值