Development Tip

정확히 PHI 명령어의 기능과 LLVM에서 사용하는 방법

yourdevel 2020. 10. 19. 12:56
반응형

정확히 PHI 명령어의 기능과 LLVM에서 사용하는 방법


LLVM에는 매우 이상한 설명 이 포함 된 파이 명령어가 있습니다.

'phi'명령어는 함수를 나타내는 SSA 그래프에서 φ 노드를 구현하는 데 사용됩니다.

일반적으로 분기를 구현하는 데 사용됩니다. 올바르게 이해했다면 종속성 분석을 가능하게하는 것이 필요하며 경우에 따라 불필요한로드를 피하는 데 도움이 될 수 있습니다. 그러나 정확히 무엇을하는지 이해하기는 여전히 어렵습니다.

Kaleidoscope 예제사례에 대해 꽤 잘 설명합니다 if. 그러나 같은 논리 연산을 구현하는 방법이 명확하지 않다 &&||. 온라인 llvm 컴파일러에 다음을 입력하면 :

void main1(bool r, bool y) {
    bool l = y || r;
}

마지막 몇 줄은 완전히 혼란 스럽습니다.

; <label>:10                                      ; preds = %7, %0
%11 = phi i1 [ true, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8

파이 노드가 사용할 수있는 결과를 생성하는 것처럼 보입니다. 그리고 나는 파이 노드가 값이 오는 경로를 정의한다는 인상을 받았습니다.

누군가 Phi 노드가 무엇이며 어떻게 구현하는지 설명 할 ||수 있습니까?


파이 노드는 현재 블록의 선행자에 따라 값을 선택하는 데 사용되는 명령어입니다 ( 전체 계층 구조를 보려면 여기 를 참조하십시오. 상속되는 클래스 중 하나 인 값으로도 사용됨).

LLVM 코드의 SSA (정적 단일 할당) 스타일의 구조로 인해 Phi 노드가 필요합니다 (예 : 다음 C ++ 함수).

void m(bool r, bool y){
    bool l = y || r ;
}

다음 IR로 변환됩니다 : (통해 생성 clang -c -emit-llvm file.c -o out.bc- 다음을 통해 볼 llvm-dis)

define void @_Z1mbb(i1 zeroext %r, i1 zeroext %y) nounwind {
entry:
  %r.addr = alloca i8, align 1
  %y.addr = alloca i8, align 1
  %l = alloca i8, align 1
  %frombool = zext i1 %r to i8
  store i8 %frombool, i8* %r.addr, align 1
  %frombool1 = zext i1 %y to i8
  store i8 %frombool1, i8* %y.addr, align 1
  %0 = load i8* %y.addr, align 1
  %tobool = trunc i8 %0 to i1
  br i1 %tobool, label %lor.end, label %lor.rhs

lor.rhs:                                          ; preds = %entry
  %1 = load i8* %r.addr, align 1
  %tobool2 = trunc i8 %1 to i1
  br label %lor.end

lor.end:                                          ; preds = %lor.rhs, %entry
  %2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]
  %frombool3 = zext i1 %2 to i8
  store i8 %frombool3, i8* %l, align 1
  ret void
}

그래서 여기서 무슨 일이 일어나나요? 변수 bool l가 0 또는 1 일 수 있는 C ++ 코드와 달리 LLVM IR에서는 한 번 정의해야합니다 . 그래서 우리 %tobool는 참 인지 확인한 다음 lor.end또는로 이동 lor.rhs합니다.

에서 lor.end우리는 마지막의 값이 || 운영자. 진입 블록에서 도착했다면 사실입니다. 그렇지 않으면 %tobool2- 의 값과 같 으며 다음 IR 라인에서 얻은 결과입니다.

%2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]

파이를 전혀 사용할 필요가 없습니다. 임시 변수를 많이 만드십시오. LLVM 최적화 패스는 임시 변수 최적화를 처리하고 자동으로 phi 노드를 사용합니다.

예를 들어 이렇게하려면 다음을 수행하십시오.

x = 4;
if (something) x = x + 2;
print(x);

이를 위해 (의사 코드에서) phi 노드를 사용할 수 있습니다.

  1. x1에 4를 할당
  2. if (! something) 분기가 4
  3. calculate x2 from x1 by adding 2
  4. assign x3 phi from x1 and x2
  5. call print with x3

But you can do without phi node (in pseudocode):

  1. allocate local variable on stack called x
  2. load into temp x1 value 4
  3. store x1 to x
  4. if (!something) branch to 8
  5. load x to temp x2
  6. add x2 with 4 to temp x3
  7. store x3 to x
  8. load x to temp x4
  9. call print with x4

By running optimization passes with llvm this second code will get optimized to first code.

참고URL : https://stackoverflow.com/questions/11485531/what-exactly-phi-instruction-does-and-how-to-use-it-in-llvm

반응형