Pass 인프라 — 변환·최적화의 기본 구조

Pass 인프라 — 변환·최적화의 기본 구조

MLIR에서 변환과 최적화의 기본 단위는 pass예요. 이 페이지는 pass manager의 구조와 pass를 올바르게 작성하는 규칙을 설명하는 문서예요.

출처: https://mlir.llvm.org/docs/PassManagement/

모든 pass는 OperationPass에서 파생되고, pass manager는 중첩된 연산 레벨 각각에 대해 pass를 실행해요. 멀티스레드 환경을 염두에 두고 다음 제약을 지켜야 해요:

  • 현재 연산의 형제(sibling) 연산 상태를 검사하지 말 것. 병렬로 수정될 수 있어요. 조상/부모 연산 검사는 허용돼요.
  • 현재 연산 아래 중첩된 연산 외에는 수정하지 말 것. 예외적으로 현재 연산의 속성(attribute)은 자유롭게 바꿀 수 있어요.
  • runOnOperation 호출 사이에 가변 pass 상태를 유지하지 말 것. 실행 순서가 보장되지 않아요.
  • 전역 가변 상태(파일 내 static 변수)를 두지 말 것.
  • copy-constructible 일 것. 병렬 처리를 위해 여러 인스턴스가 만들어질 수 있어요.

Op-agnostic pass 는 pass manager가 다루는 연산 타입에 무관하게 동작해요. 예를 들어 Canonicalization나 CSE(공통 부분식 제거)가 그렇고, CRTP 기반 PassWrapperrunOnOperation() 오버라이드를 이용해 작성해요.

필터링을 걸면 실행 대상을 제한할 수 있어요. 특정 연산 타입(예: func::FuncOp)에만 돌게 하거나, 특정 인터페이스(예: FunctionOpInterface)를 구현한 연산에만 돌게 하는 InterfacePass가 있어요. 정적 필터가 걸린 pass를 op-agnostic manager에 넣으면 그 manager 전체가 같은 제약을 물려받는다는 점을 기억해야 해요.

분석(analysis)은 변환 pass와 달리 연산을 수정하지 않고 정보만 계산해요. lazy 하게 필요할 때 계산되고 캐시돼요. 디버깅에는 -mlir-timing 으로 pass별 소요 시간을 보거나, -mlir-print-ir-before / -mlir-print-ir-after 같은 플래그로 각 단계의 IR을 덤프할 수 있어요.

더 알아보기