Понимание ИК потока - PullRequest
       97

Понимание ИК потока

0 голосов
/ 31 мая 2018

Я испытываю затруднения в понимании потока IR LLVM.Мотивом этой работы является преобразование данной программы на языке c / c ++ в ее представление SSA.Я обнаружил, что https://releases.llvm.org/3.4.2/docs/tutorial/LangImpl7.html, мы можем получить SSA из IR LLVM с помощью прохода -mem2reg.Как новичку, мне трудно понять поток IR, хотя я не мог понять, по крайней мере, некоторые из различных типов используемых инструкций, таких как load, store, icmp.fcmp, br label, br i1 и т. Д. ОднакоПоследовательность, в которой возникают блоки, сбивает меня с толку.Если есть какой-либо материал, который поможет мне понять поток, было бы полезно.

Я вижу, что llvm также предоставляет интерфейс для визуального представления с использованием опции opt "-view-cfg" и использованием "dot -Tpdf"cfg_file.dot -o cfg.pdf ".Хотя это очень помогло, но есть потоковые соединения, которые я не могу понять из этого.

Теперь моя главная проблема - я не могу понять последние пять блоков.Какова последовательность и последовательность управления этими (последними пятью) блоками?Цель состоит в том, чтобы создать SSA (одиночное статическое назначение) программы, используя это IR-представление LLVM.Пожалуйста, найдите ниже IR и исходный код программы на C.Также найдите ссылку на мой диск Google с файлом CFG.

IR LLVM

    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;
    }

Ссылка на файл CFG, сгенерированный из этого IR https://drive.google.com/open?id=1wIvXR5PosWWViM4fo_jEaLpXkCbhYGSE

Любая помощь или указатель в этом направлении будут хороши.Спасибо и извините за сложность и длительность вопроса.Пожалуйста, не стесняйтесь уточнить, есть ли недостающая информация.

...