컴파일러

[컴파일러] 4. LLVM을 이용한 IR 레벨에서 명령어 삭제 및 생성

용성군 2021. 7. 28. 09:51
728x90
반응형

이번 글은 제목처럼 IR(intermediate representation) 레벨에서 프로그램 내의 명령어를 삭제 또는 생성을 해보려한다.

 

LLVM IR은 계층 구조로 프로그램을 관리하므로 반복문을 통해 특정 종류의 명령어에 접근 할 수 있다(ADD, SUB, DIV 등에 접근할 수 있으며 모르겠다면 이전 글 컴파일러 3을 참조 ). 이를 통해 instruction을 생성하도록 하겠다.


명령어 생성

LLVM에서 명령어를 생성하는 방법은 Create 함수를 이용하는 것이다. 

LLVM은 아래와 같이 수행할 명령어의 Operand들을(Value *s1, Value *s2) Create 함수의 매개변수로 요구한다. Operand에는 Value, Type 등의 형태가 될 수 있다.

static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, 
				const Twine &Name = Twine(), 
				Instruction *InsertBefore = nullptr)

 

또한 결과 값을 가지는 명령어 (binary operator, non-void return function call ) 또한 Instruction 객체를 다른 InstructionOperand로 사용함으로써 그 결과 값을 다른 명령어의 Operand로 사용할 수 있습니다. (llvm::Instruction은 llvm::Value 클래스의 자식 클래스이기 때문)

 

추가적으로 Create 함수를 사용하기 위해서 IRBuilder.h 를 include해야한다.

 

다음은 두개의 Human Readable Assembly(.ll 파일) 파일을 인자로 받아 새로운 파일에 add 1,1을 추가하는 코드의 일부분이다. 

작성한 프로그램을 컴파일 하고 Test.c를 .ll파일로 컴파일하여 vimdiff 명령어를 통해 두개의 .ll 파일을 비교해 본다.

다음 그림은 add i32 1,1이 add instruction 앞에 추가된 것을 알 수 있다.

두개의 인자 중 왼쪽은 우리가 .ll파일로 컴파일 한것이고 오른쪽은 위의 코드로 만든 파일이다.  


명령어 추가 및 삭제

특정 명령어를 삭제하기 위해서는, 당연히 해당 명령어의 결과 값을 사용하는 명령어들의 종속 관계를 해결해 주어야 한다. 어떤 명령어의 결과 값을 다른 명령어가 사용하는 것을 고려하지 않고 삭제한다면 오류가 발생할 것이다.

 

따라서 add instruction을 sub instruction으로 바꿀 때,

(1) add instruction과 같은 operand로 sub instruction을 생성

(2) add instruction의 결과 값이 사용되는 곳을 sub instruction의 결과를 사용하도록 변경

(3)  add instruction을 삭제하는 과정으로 진행한다.

 

IR 레벨의 소스에서 생기는 문제는 주로 Human-readable IR로 현재의 Module을 출력한 이후, llvm-as를 통해 bitcode로 포맷을 변환하면 확인 할 수 있습니다.

 

 

(1) 원래 add instruction과 같은 operand, sub가 수행되도록 코드를 변경합니다.

 

(2) 생성한 add instruction의 결과값이 사용되는 곳을 sub instruction으로 대체해버리는 코드를 작성한다.(AddInst->replaceAllUsesWith(SubInst) 부분)

만약 dependency 문제를 해결하지 않는다면 오른쪽 부분의 <badref>라는 문구처럼 bad reference가 발생하게 된다.

(3) ADD 명령어를 삭제한다. , 현재 BBIter가 삭제할 명령어를 가리키고 있기 때문에, loop 밖에서 삭제해야 한다.

각각 컴파일하고, 만들어진 Human Readable Assembly 파일을 비교하면 add가 sub로 바뀐것을 확인할 수 있다.

위의 IR 레벨의 파일을 바너리로 컴파일하여 실행하면 결과가 덧셈이 아닌 뺄셈으로 바뀌어서 결과가 출력된다.(4-5-3 = -4)

 

이를 응용하면 A * B - C도 만들 수 있다.

 

728x90
반응형