2015-10-08 2 views
6

Я немного новичок в LLVM и компиляторах.Каковы зависимости от клея и цепи в DAG LLVM?

Я решил сформировать группу DAG с помощью следующей команды

llc -view-sched-dags hello_world.ll 

Я получил очень большой график с различными типами зависимостей. «Начало работы с основными библиотеками LLVM» Книга разъяснена, что:

Черных стрелки означают зависимость потока данных
Красных стрелки означают клеевой зависимость
Синих пунктирные стрелки означают цепь зависимость

Я хорошо помню говоря о зависимости потока данных в моем классе компилятора в школе. Но я не помню, чтобы говорили о двух других. Может ли кто-нибудь объяснить смысл других зависимостей? Любая помощь приветствуется.

hello_world.cpp

#include <stdio.h> 
#include <assert.h> 

int sum(int a, int b) { 
    return a + b; 
} 

int main(int argc, char** argv) { 
    printf("Hello World! %d\n", sum(argc, 1)); 
    return 0; 
} 

hello_world.ll

; ModuleID = 'hello_world.cpp' 
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 
target triple = "x86_64-unknown-linux-gnu" 

@.str = private unnamed_addr constant [17 x i8] c"Hello World! %d\0A\00", align 1 

; Function Attrs: nounwind uwtable 
define i32 @_Z3sumii(i32 %a, i32 %b) #0 { 
entry: 
    %a.addr = alloca i32, align 4 
    %b.addr = alloca i32, align 4 
    store i32 %a, i32* %a.addr, align 4 
    store i32 %b, i32* %b.addr, align 4 
    %0 = load i32* %a.addr, align 4 
    %1 = load i32* %b.addr, align 4 
    %add = add nsw i32 %0, %1 
    ret i32 %add 
} 

; Function Attrs: uwtable 
define i32 @main(i32 %argc, i8** %argv) #1 { 
entry: 
    %retval = alloca i32, align 4 
    %argc.addr = alloca i32, align 4 
    %argv.addr = alloca i8**, align 8 
    store i32 0, i32* %retval 
    store i32 %argc, i32* %argc.addr, align 4 
    store i8** %argv, i8*** %argv.addr, align 8 
    %0 = load i32* %argc.addr, align 4 
    %call = call i32 @_Z3sumii(i32 %0, i32 1) 
    %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @.str, i32 0, i32 0), i32 %call) 
    ret i32 0 
} 

declare i32 @printf(i8*, ...) #2 

attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 
attributes #1 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 
attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 

!llvm.ident = !{!0} 

!0 = metadata !{metadata !"clang version 3.5.0 "} 

hello_world.main.jpg hello_world.main.jpg

HEL lo_world.sum.jpg hello_world.sum.jpg

ответ

7

зависимости цепи предотвратить узлы с побочными эффектами (в том числе операций с памятью и явными операциями регистров) из того планируется из порядка по отношению друг к другу.

Клей предотвращает разбиение двух узлов во время планирования. Это на самом деле более тонкое, чем это [1], но большую часть времени вам не нужно беспокоиться об этом. (Если вы реализуете свой собственный бэкэнд, который требует, чтобы две инструкции были смежными друг с другом, вы действительно хотите использовать псевдоинструкцию вместо этого и расширять это после планирования.)

[1]: см. Например, http://lists.llvm.org/pipermail/llvm-dev/2014-June/074046.html

Смежные вопросы