2017-12-22 22 views
1

루프의 유형이 다른 경우 이름으로 쉽게 식별 할 수 있지만 동일한 유형의 루프가 여러 개있는 경우 (예 : 5 while 루프) LLVM IR의 기본 블록이 어떤 루프에 해당하는지 식별 할 수 있습니까 소스 코드?함수 아래에있는 여러 개의 동일한 유형 루프를 LLVM IR의 생성 된 기본 블록에 매핑하는 방법은 무엇입니까?

우리는 코드와 LLVM IR을 순차적으로 방문하면서 손쉽게 식별 할 수 있지만 프로그래밍 방식으로 식별 할 수있는 방법을 찾고 있습니다.

; ModuleID = 'abc.c' 
source_filename = "abc.c" 
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" 
target triple = "x86_64-pc-windows-msvc19.0.23026" 

; Function Attrs: noinline nounwind uwtable 
define i32 @main() #0 { 
entry: 
    %retval = alloca i32, align 4 
    %count = alloca i32, align 4 
    store i32 0, i32* %retval, align 4 
    store i32 1, i32* %count, align 4 
    br label %while.cond 

while.cond:          ; preds = %while.body, %entry 
    %0 = load i32, i32* %count, align 4 
    %cmp = icmp sle i32 %0, 4 
    br i1 %cmp, label %while.body, label %while.end 

while.body:          ; preds = %while.cond 
    %1 = load i32, i32* %count, align 4 
    %inc = add nsw i32 %1, 1 
    store i32 %inc, i32* %count, align 4 
    br label %while.cond 

while.end:          ; preds = %while.cond 
    br label %while.cond1 

while.cond1:          ; preds = %while.body3, %while.end 
    %2 = load i32, i32* %count, align 4 
    %cmp2 = icmp sgt i32 %2, 4 
    br i1 %cmp2, label %while.body3, label %while.end4 

while.body3:          ; preds = %while.cond1 
    %3 = load i32, i32* %count, align 4 
    %dec = add nsw i32 %3, -1 
    store i32 %dec, i32* %count, align 4 
    br label %while.cond1 

while.end4:          ; preds = %while.cond1 
    ret i32 0 
} 

attributes #0 = { noinline nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } 

!llvm.module.flags = !{!0} 
!llvm.ident = !{!1} 

!0 = !{i32 1, !"PIC Level", i32 2} 
!1 = !{!"clang version 4.0.0 (tags/RELEASE_400/final)"} 

지금 두 가지가 있습니다 : 나는 fileName.ll은 아래의 내용으로 만들 수있어 COMAND clang -S -emit-llvm fileName.c을 실행할 때

int main() 
{ 
    int count=1; 
    while (count <= 4) 
    { 
     count++; 
    } 
    while (count > 4) 
    { 
     count--; 
    } 
    return 0; 
} 

:

예, 나는 C에서 아래의 소스 코드를 주어진 소스 파일에 대해 생성 된 기본 블록을 while.condwhile.cond1으로 만들면 소스 코드에서 어떤 기본 블록이 어떤 루프인지 식별 ​​할 수 있습니까?

답변

2

답을하기 전에 선택한 최적화 수준이나 수동으로 선택한 패스에 따라 opt과 함께 정보가 없거나 정확하지 않을 수 있음을 알려드립니다 (예 : 인라인, 복제 등으로 인해).).

저수준 표현과 소스 코드를 연결하는 방법은 디버깅 정보 (예 : DWARF 형식)를 사용하는 것입니다. 디버깅 정보를 생성하려면 컴파일하는 동안 -g 명령 줄 플래그를 사용해야합니다.

LLVM IR의 경우 Loop API를 보면 getStartLoc과 같은 관련 호출이 있습니다.

llvm::SmallVector<llvm::Loop *> workList; 
auto &LI = getAnalysis<llvm::LoopInfoWrapperPass>(CurFunc).getLoopInfo(); 

std::for_each(LI.begin(), LI.end(), [&workList](llvm::Loop *e) { workList.push_back(e); }); 

for(auto *e : workList) { 
    auto line = e->getStartLoc().getLine(); 
    auto *scope = llvm::dyn_cast<llvm::DIScope>(e->getStartLoc().getScope()); 
    auto filename = scope->getFilename(); 

    // do stuff here 
} 

또한, BasicBlock을 위해, 당신은 또한 Instruction에서 디버그 관련 방법을 사용할 수 있습니다 (예 : getDebugLoc)과 함께 결합 : 그래서 당신은 (A llvm::Function 패스의 runOn 방법 내부 예) 같은 것을 할 수

또한, 각 루프에 대한 내부의 고유 ID를 사용하는 getLoopID 방법이 있습니다 등과 같은 getHeader 다른 Loop의 방법에 대한 호출하지만 항상이없는 그것은 잠재적 elisions 대상의 I 처음에 언급했다. 어쨌든, 조작해야 할 경우 setLoopID 방법 (예 : lib/Transforms/Scalar/LoopRotation.cpp)에 따라 LLVM 소스에서 예제를 살펴보십시오.

+0

'getAnalysis()'메소드에 포함시킬 헤더 파일을 도와주십시오. –

+0

'getAnalysis' 메소드는 모든 패스 클래스에 상속되므로 쉽게 사용할 수 있습니다. 'LoopInfoWrapperPass'는'llvm/Analysis/LoopInfo.h'에서 구할 수 있습니다. 나는'grep'이나 LLVM 소스 트리에서 비슷한 도구를 사용하는 것이 많은 도움이된다고 생각합니다. – compor

+0

[this] (https://github.com/compor/AnnotateLoops) repo를 살펴볼 수도 있습니다. 루프에 숫자 ID를 주석으로 표시합니다. 그에 따라 적응할 수 있습니다. – compor