我发现很难理解LLVM的IR流程。这项工作背后的动机是将给定的c / c ++程序转换为它的SSA表示。 我发现https://releases.llvm.org/3.4.2/docs/tutorial/LangImpl7.html,我们可以通过使用-mem2reg传递从LLVM的IR获得SSA。 作为一个初学者,我发现很难理解IR的流程,虽然我无法理解至少使用的一些不同类型的指令,如load,store,icmp.fcmp,br label,br i1等。 但是,块发生的顺序让我很困惑。如果有任何材料可以帮助我理解流程会有所帮助。
我看到llvm还使用opt选项" -view-cfg"提供了一个可视化表示的界面。并使用" dot -Tpdf cfg_file.dot -o cfg.pdf"。虽然它有很多帮助,但有流量连接,我无法理解它。
现在我的主要问题是我无法理解最后五个街区。这些(最后五个)块的顺序和控制流程是什么?目标是使用LLVM的IR表示创建程序的SSA(单个静态分配)。 请在下面找到IR和C程序的源代码。还可以找到指向我的Google驱动器CFG文件的链接。
LLVM的IR
call void @llvm.dbg.value(metadata %struct.INPUT_VAL* %input, metadata !31, metadata !DIExpression()), !dbg !42
call void @llvm.dbg.value(metadata %struct.RETURN_VAL* %ret_val, metadata !32, metadata !DIExpression()), !dbg !43
call void @llvm.dbg.value(metadata i32 2, metadata !33, metadata !DIExpression()), !dbg !44
call void @llvm.dbg.value(metadata double 7.000000e+01, metadata !36, metadata !DIExpression()), !dbg !45
call void @llvm.dbg.value(metadata double 6.600000e+01, metadata !37, metadata !DIExpression()), !dbg !46
%temperature = getelementptr inbounds %struct.INPUT_VAL, %struct.INPUT_VAL* %input, i64 0, i32 0, !dbg !47
%tmp = load double, double* %temperature, align 8, !dbg !47, !tbaa !48
call void @llvm.dbg.value(metadata double %tmp, metadata !35, metadata !DIExpression()), !dbg !53
%cmp = fcmp oge double %tmp, 6.600000e+01, !dbg !54
%cmp1 = fcmp olt double %tmp, 7.000000e+01, !dbg !56
%or.cond49 = and i1 %cmp, %cmp1, !dbg !57
br i1 %or.cond49, label %if.end9, label %if.else, !dbg !57
%cmp2 = fcmp ult double %tmp, 7.000000e+01, !dbg !58
br i1 %cmp2, label %if.else4, label %if.end9, !dbg !60
%cmp5 = fcmp olt double %tmp, 6.600000e+01, !dbg !61
%. = zext i1 %cmp5 to i32, !dbg !63
br label %if.end9, !dbg !63
%.pr52 = phi i32 [ 2, %entry ], [ 0, %if.else ], [ %., %if.else4 ]
%tmp1 = load i32, i32* @thermostat.off_counter, align 4, !dbg !64, !tbaa !66
%cmp10 = icmp sgt i32 %tmp1, 4, !dbg !68
%tmp2 = load i32, i32* @thermostat.on_counter, align 4, !dbg !69
%cmp11 = icmp sgt i32 %tmp2, 4, !dbg !70
%or.cond = or i1 %cmp10, %cmp11, !dbg !71
br i1 %or.cond, label %if.then12, label %if.end9.if.end13_crit_edge, !dbg !71
%.pr.pre = load i32, i32* @thermostat.chatter_detect, align 4, !dbg !72, !tbaa !66
br label %if.end13, !dbg !71
store i32 0, i32* @thermostat.chatter_detect, align 4, !dbg !74, !tbaa !66
br label %if.end13, !dbg !75
%.pr = phi i32 [ %.pr.pre, %if.end9.if.end13_crit_edge ], [ 0, %if.then12 ], !dbg !72
%cmp14 = icmp eq i32 %.pr52, 0, !dbg !76
br i1 %cmp14, label %if.end16, label %if.then15, !dbg !77
%inc = add nsw i32 %.pr, 1, !dbg !78
store i32 %inc, i32* @thermostat.chatter_detect, align 4, !dbg !78, !tbaa !66
br label %if.end16, !dbg !79
%tmp3 = phi i32 [ %inc, %if.then15 ], [ %.pr, %if.end13 ], !dbg !80
%cmp17 = icmp sgt i32 %tmp3, 2, !dbg !82
%brmerge = or i1 %cmp17, %cmp14, !dbg !83
br i1 %brmerge, label %if.end25.thread, label %if.end25, !dbg !83
store i32 0, i32* @thermostat.on_counter, align 4, !dbg !84, !tbaa !66
%inc22 = add nsw i32 %tmp1, 1, !dbg !87
store i32 %inc22, i32* @thermostat.off_counter, align 4, !dbg !88, !tbaa !66
br label %.thread, !dbg !89
%inc24 = add nsw i32 %tmp2, 1, !dbg !90
store i32 %inc24, i32* @thermostat.on_counter, align 4, !dbg !90, !tbaa !66
store i32 0, i32* @thermostat.off_counter, align 4, !dbg !88, !tbaa !66
%switch.selectcmp = icmp eq i32 %.pr52, 1, !dbg !89
br i1 %switch.selectcmp, label %.thread, label %bb, !dbg !89
%.ph56 = phi double [ 2.000000e+01, %if.end25.thread ], [ 1.000000e+02, %if.end25 ]
br label %bb, !dbg !89
%tmp4 = phi double [ %.ph56, %.thread ], [ 7.000000e+01, %if.end25 ]
call void @llvm.dbg.value(metadata double %tmp4, metadata !34, metadata !DIExpression()), !dbg !92
%u37 = getelementptr inbounds %struct.RETURN_VAL, %struct.RETURN_VAL* %ret_val, i64 0, i32 0, !dbg !93
store double %tmp4, double* %u37, align 8, !dbg !94, !tbaa !48
ret %struct.RETURN_VAL* %ret_val, !dbg !95
C计划
#include "thermostat.h" //contains structure information
#ifdef DEBUG
#include<stdio.h>
#endif
RETURN_VAL* thermostat(INPUT_VAL* input, RETURN_VAL* ret_val)
{
static int chatter_detect;
static int previous_command_to_heater;
static int on_counter, off_counter;
static int command_to_heater;
int chatter_limit=2;
double u, room_temp;
double MAX_TEMP=70.0, MED_TEMP=66.0;
// int NO_HEAT=0, NORMAL_HEAT = 2, FAST_HEAT = 1;
room_temp = input->temperature;
if(room_temp >= MED_TEMP && room_temp < MAX_TEMP)
command_to_heater = 2;
else if(room_temp >= MAX_TEMP)
command_to_heater = 0;
else if(room_temp < MED_TEMP)
command_to_heater = 1;
else
command_to_heater = previous_command_to_heater;
if(off_counter >= 5 || on_counter >= 5)
chatter_detect = 0;
if(command_to_heater != previous_command_to_heater)
chatter_detect++;
if(chatter_detect > chatter_limit)
command_to_heater = previous_command_to_heater;
if(command_to_heater == 0) {
on_counter = 0;
off_counter++;
} else {
on_counter++;
off_counter = 0;
}
if (command_to_heater==0)
u = 20;
else if (command_to_heater==1)
u = 100;
else if (command_to_heater==2)
u = 70;
ret_val->u = u;
return ret_val;
}
指向此IR https://drive.google.com/open?id=1wIvXR5PosWWViM4fo_jEaLpXkCbhYGSE
生成的CFG文件的链接这方面的任何帮助或指针都会很棒。 谢谢,抱歉让问题变得复杂而冗长。如果有任何遗漏信息,请随时澄清。