llvm:Data Flow Graph

Data Flow Graph

基本概念

Data Flow Graph又叫數據流程圖,表示在一個函數中的數據流動的方向。比如一個指令1定義了一個新變量%a,而另一個指令2用到了變量%a,此時就存在從指令1到指令2的邊。llvm IR的表示形式是SSA,簡單的來說SSA表示形式就是一個變量只能定義一次。

x = y + 1;
x = y + 2;
y = 3;

上面的形式就不是SSA的表示形式,因爲x被定義(賦值)了兩次,可以通過修改使其變成SSA的表示形式:

x1 = y + 1;
x2 = y + 2;
y = 3;

實驗過程

在具體的實驗中,我們遍歷函數中的每一個指令,判斷該指令是否爲load,store指令,把load和store指令與其他指令區別開來是因爲在IR中只有store和load指令直接與內存直接接觸。

                        case llvm::Instruction::Load:
                        {
                            LoadInst* linst = dyn_cast<LoadInst>(curII);
                            Value* loadValPtr = linst->getPointerOperand();
                            edges.push_back(edge(node(loadValPtr, getValueName(loadValPtr)), node(curII, getValueName(curII))));
                            break;
                        }
                        case llvm::Instruction::Store: {
                            StoreInst* sinst = dyn_cast<StoreInst>(curII);
                            Value* storeValPtr = sinst->getPointerOperand();
                            Value* storeVal = sinst->getValueOperand();
                            edges.push_back(edge(node(storeVal, getValueName(storeVal)), node(curII, getValueName(curII))));
                            edges.push_back(edge(node(curII, getValueName(curII)), node(storeValPtr, getValueName(storeValPtr))));
                            break;
                        }

對於其餘的指令,遍歷每一個指令的操作數,判斷其是不是一個指令,如果是指令的話,就添加相應的邊。

for (Instruction::op_iterator op = curII->op_begin(), opEnd = curII->op_end(); op != opEnd; ++op)
                            {
                                Instruction* tempIns;
                                if (dyn_cast<Instruction>(*op))
                                {
                                    edges.push_back(edge(node(op->get(), getValueName(op->get())), node(curII, getValueName(curII))));
                                }
                            }

具體代碼請參考我的github

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章