llvm memset memcpy 处理流程

code 框架:

ProcessMemIntrinsic(Module *m) {
//遍历module的function,寻找name为memset、memcpy的function。
ProcessMemset(memset_func);
ProcessMemcpy(memcpy_func);
}

ProcessMemset(memset_func) {
//遍历memset_func的user,对每条memset instruction进行replace
ReplaceMemsetInst(inst);
}

//; Function Attrs: argmemonly nounwind
//declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) 
//call void @llvm.memset.p0i8.i64(i8* nonnull %4, i8 0, i64 256, i32 16, i1 false)
ReplaceMemsetInst(Instruction *inst) {

}

memset分析

memset的定义

memset()函数原型是void *memset(void *buffer, int c, int count) :
buffer:为指针, c:是赋给buffer的值, count:是buffer的长度.
memset的pass中定义初始值必为integer 类型。

memset的pass处理流程

1、遍历module的Function,记录name 为memset、memcpy的Function。
2、遍历Function’s user : memset Instruction,进行替换处理。

如何替换:
1、解析memset的指令参数,memset(void *buffer, int c, int count) ,初始值必为integer 类型。

(2)当buffer指向单个变量:
%2 = alloca iN
%3 = bitcast iN* %2 to i8*
call void @memset(i8* nonnull %4, i8 0, i64 256, i32 16, i1 false)

%2 = alloca iN
Store iN value, iN* %2

(1)当buffer指向的是数组。

memset的一维数组处理

bc情况罗列:
1、全局变量,并且用getelementptr
@zculling.z_buffer = internal unnamed_addr global [256 x [256 x i8]] zeroinitializer
tail call void @llvm.memset.p0i8.i64(i8* getelementptr inbounds ([256 x [256 x i8]], [256 x [256 x i8]]* @zculling.z_buffer, i64 0, i64 0, i64 0), i8 -1, i64 65536, i32 16, i1 false)

2、函数参数 %5
%8 = getelementptr inbounds [256 x i8], [256 x i8]* %5, i64 0, i64 0
call void @llvm.memset.p0i8.i64(i8* %8, i8 0, i64 65536, i32 1, i1 false)

3、 局部变量
%2 = alloca [num x iN]
%4 = bitcast [num x iN]* %2 to i8*
call void @llvm.memset.p0i8.i64(i8* nonnull %4, i8 value, i64 N*num/8 , i32 alignment, i1 false)

Memset 处理:A为array : [num x iN]
数据A初始化:memset(A,value,length,alignment)
label 0: A
%2 = alloca [num x iN]
br label meminst

meminst:
%phi_inst = phi i32 [0, %0], [%add_inst, %meminst]
%add_inst = add i32 %phi_inst , 1
%sext_inst = sext i32 phi_inst to i64
%A.addr = getelementptr [num x iN], [num x iN]* A, i64 0, i64 %sext_inst
Store iN value, iN* A.addr
%icmp_inst = icmp eq i32 %phi_inst, num
br i1 %icmp_inst, label %2, label %meminst

在这里插入图片描述

memset的多维数组处理

C代码:
int bb[20][2];
memset(bb,1,sizeof(bb));

clang.bc:
%1 = alloca [20 x [2 x i32]], align 16
%2 = bitcast [20 x [2 x i32]]* %1 to i8*
call void @llvm.memset (i8* nonnull %2, i8 1, i64 160, i32 16, i1 false)

Vivado:针对多级array处理
a.g.1.bc:
在这里插入图片描述

利用memset对变量进行两次赋值:
在这里插入图片描述
生成的bc:
在这里插入图片描述

memcpy分析

自己写得小例子

int main()
{
    int bb[20][2][10];
	 memset(bb,1,sizeof(bb));

	 int result = 0;
	 for (int i = 0; i< 7;i++) {
	 bb[i][0][2]=bb[i][1][1]*bb[i][0][0]+i;
	 bb[i][1][2]=bb[i][0][1]*2;
    printf("bb: %d\n",bb[i][0][1]);
	 result += bb[i][1][0]+bb[i][0][0];
	 }
    int aa[20][2][10];
     memset(aa,2,sizeof(aa));
	 memcpy(aa,bb,200*sizeof(int));
	 for (int ii = 0; ii< 10;ii++) {
	 aa[ii][0][2]=aa[ii][1][1]*aa[ii][0][0]+ii;
	 aa[ii][1][2]=aa[ii][0][1]*2;
     printf("aa: %d\n",aa[ii][0][2]);
	 result += aa[ii][1][2]+aa[ii][0][0];
	 }
   return 0;
}
; Function Attrs: argmemonly nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1

clang O1生成的bc
在这里插入图片描述
vivado生成的bc:
在这里插入图片描述

memcpy one array

	 char aa[10];
	 memset(aa,'a',sizeof(aa));
	 for (int i = 0; i < 10; i++) {
	 	aa[i]=aa[i]+4;
		printf("aa = %c\n",aa[i]);
		aa[9-i]=aa[i];
	 }
	 char bb[10];
	 memcpy(&bb[0], &aa[0], sizeof(bb));
	 for (int i = 0; i < 10; i++) {
	 	bb[9-i]=bb[i];
		printf("bb[%d]=%c\n",i,bb[i]);
	 }

在这里插入图片描述

vivado a.g.1.bc

在这里插入图片描述

llvm-mc是一款基于LLVM框架的模拟器,用于将汇编代码翻译成机器码并进行相关操作。其工作流程可以简单概括为以下几步。 首先,llvm-mc会通过命令行参数或者脚本来指定输入的汇编代码文件。然后,它会将这些代码解析为一系列的指令对象。每个指令对象都包含了指令的类型、操作数以及其他属性。 接下来,llvm-mc会对指令对象进行表达式求解和一些优化操作。这些优化包括常量折叠、常量传播和复用等。这些优化可以提高代码的执行效率并减少生成的机器码的大小。 然后,llvm-mc会将优化后的指令对象转化为机器指令。这个过程涉及到指令选择、指令调度和机器寄存器分配等操作。在指令选择阶段,llvm-mc会根据目标架构的特性和约束选择最适合的指令形式。指令调度则是为了优化指令的执行顺序,提高并行度和数据访问效率。机器寄存器分配阶段是为了将虚拟寄存器映射到实际的物理寄存器。 最后,llvm-mc会生成目标机器码。生成的目标机器码可以保存到二进制文件中,也可以直接输出到标准输出。生成的机器码可以在目标架构上直接执行,实现对汇编代码的模拟执行。 综上所述,llvm-mc的工作流程包括汇编代码解析、表达式求解与优化、指令选择与调度以及机器码生成等步骤。通过这些步骤,llvm-mc可以将汇编代码转化为目标机器码并进行相关操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值