귀하의 질문에 대답하기위한 가장 좋은 책은 아마도 Cooper와 Torczon, "컴파일러 엔지니어링"2003 일 것입니다. 대학 도서관에 액세스 할 수 있다면 사본을 빌릴 수 있어야합니다.
llvm 또는 gcc와 같은 프로덕션 컴파일러에서 설계자는 모든 알고리즘을 미만으로 유지하기 위해 모든 노력을 기울입니다. 여기서 은 입력 크기입니다. "최적화"단계에 대한 일부 분석의 경우 이는 실제로 최적의 코드를 생성하는 대신 휴리스틱을 사용해야한다는 것을 의미합니다.O(n2)n
렉서는 유한 상태 기계이므로, (문자) 입력의 크기 및 스트림 생성 파서로 전달되는 토큰.O(n)O(n)
많은 언어의 많은 컴파일러에서 파서는 LALR (1)이므로 입력 토큰 수 에서 시간 에 토큰 스트림을 처리합니다 . 구문 분석 중에는 일반적으로 기호 테이블을 추적해야하지만 많은 언어의 경우 해시 테이블 스택 ( "사전")으로 처리 할 수 있습니다. 각 사전 액세스는 이지만 때로는 기호를 찾기 위해 스택을 걸어야 할 수도 있습니다. 스택의 깊이는 이며 여기서 는 범위의 중첩 깊이입니다. (따라서 C와 같은 언어에서는 몇 개의 중괄호 레이어가 들어 있습니까?)O(n)O(1)O(s)s
그런 다음 구문 분석 트리는 일반적으로 제어 플로우 그래프로 "평 평화"됩니다. 제어 흐름 그래프의 노드는 3 주소 명령 (RISC 어셈블리 언어와 유사) 일 수 있으며 제어 흐름 그래프의 크기는 일반적으로 구문 분석 트리의 크기에 선형입니다.
그런 다음 일련의 중복 제거 단계가 일반적으로 적용됩니다 (공통 하위 표현 제거, 루프 불변 코드 모션, 상수 전파 등). 결과에 대해 최적의 결과는 거의 없지만 실제로는 "최적화"라고합니다. 실제 목표는 컴파일러에서 설정 한 시간 및 공간 제약 내에서 가능한 한 많이 코드를 개선하는 것입니다. 각 중복 제거 단계는 일반적으로 제어 흐름 그래프에 대한 몇 가지 사실에 대한 증거가 필요합니다. 이러한 증명은 일반적으로 데이터 흐름 분석을 사용하여 수행됩니다 . 대부분의 데이터 흐름 분석은 가 루프 중첩 깊이이고 흐름 그래프를 통과하는 데 시간 가 걸리는 흐름 그래프 를 통해 패스로 수렴되도록 설계되었습니다.O(d)dO(n)여기서 은 3- 주소 명령의 수입니다.n
보다 정교한 최적화를 위해보다 정교한 분석을 수행 할 수 있습니다. 이 시점에서 트레이드 오프가 시작됩니다. 분석 알고리즘이 보다 훨씬 적게 걸리기를 원합니다.O(n2)전체 프로그램의 흐름 그래프의 크기에 시간이 걸리지 만 이는 증명하기에 비용이 많이 드는 정보 (및 변환을 개선하는 프로그램)없이 수행해야 함을 의미합니다. 이에 대한 전형적인 예는 별칭 분석입니다. 여기서 일부 메모리 쓰기 쌍의 경우 두 쓰기가 동일한 메모리 위치를 대상으로 할 수 없음을 증명하려고합니다. (한 명령을 다른 명령 위로 이동할 수 있는지 확인하기 위해 별칭 분석을 수행 할 수 있습니다.) 별칭에 대한 정확한 정보를 얻으려면 프로그램을 통해 가능한 모든 제어 경로를 분석해야 할 수 있습니다. 이는 분기 수의 지수입니다 프로그램에서 (따라서 제어 흐름 그래프의 노드 수에 지수 적으로)
다음으로 레지스터 할당에 들어갑니다. 레지스터 할당은 그래프 색 문제 로 표현 될 수 있으며 , 최소한의 색으로 그래프를 채색하는 것은 NP-Hard로 알려져 있습니다. 따라서 대부분의 컴파일러는 합리적인 시간 범위 내에서 가능한 한 최대한 레지스터 유출 수를 줄이기 위해 레지스터 유출과 결합 된 탐욕적 휴리스틱을 사용합니다.
마지막으로 코드 생성에 들어갑니다. 코드 생성은 일반적으로 기본 블록 이 단일 입력 및 단일 종료를 갖는 선형 연결된 제어 흐름 그래프 노드 세트 인 시점에서 최대 기본 블록으로 수행됩니다 . 이것은 당신이 다루려고하는 그래프가 기본 블록에있는 3- 어드레스 명령어 세트의 의존성 그래프이고 사용 가능한 기계를 나타내는 그래프 세트로 다루려고하는 경우 문제를 다루는 그래프로 재구성 될 수 있습니다. 명령. 이 문제는 가장 큰 기본 블록의 크기 (원칙적으로 전체 프로그램의 크기와 동일한 순서 일 수 있음)의 크기에 기하 급수적이므로 가능한 커버링의 작은 하위 집합 만있는 휴리스틱으로 다시 수행됩니다. 검사했다.