Compilation and Optimizations

Intro to Compilers

Overview

Declaration vs Definition

void swap(int *a, int *b); // in .h file
void swap(int *a, int *b) { // in .c file
 int temp = *a;
 *a = *b;
 *b = temp;
}

Compilers Frontend

Compilers

β€’ Bare minimum for a functional compiler

β€’ Good compilers o Produce meaningful errors on incorrect programs o Produce fast, optimized code

Detailed Compilation Flow

The C pre-processor

#include <stdio.h>
#include "A.h"
#define NAME value
#define MAX(X,Y) (X>Y ? X : Y) // careful with macros!
#ifdef DEBUG
printf("Debugging message");
#endif

// $ gcc -DDEBUG
#include <stdio.h>
#include "A.h"

Anatomy of a Modern Compiler

Frontend (analysis)

β€’ Read source program β€’ Break it up into basic elements β€’ Check correctness, report errors β€’ Translate to generic intermediate representation (IR)

Back-end (synthesis)

β€’ Optimize IR β€’ Translate IR to ASM β€’ Optimize ASM

Frontend Stages

β€’ Lexical analysis (scanning): Source -> List of tokens β€’ Syntactic analysis (parsing): Tokens -> Syntax tree β€’ Semantic analysis (mainly, type checking)

Intermediate Representation

β€’ Internal compiler language that is: β—‹ Language-independent β—‹ Machine-independent β—‹ Easy to optimize β€’ Why yet another language? β—‹ Assembly does not have enough info to optimize it well β—‹ Enables modularity and reuse

Data flow graph (DFG)

Static Single Assignment (SSA)

DFG and Partial Orders

Optimizations

Control-Data Flow Graph (CDFG)

IR Optimization

Code Generation

Summary: Modern Compilers

Loop Transformations

#1: Loop Unrolling

#2: Loop Fusion

#3: Loop Distribution/Fission

#4: Loop Interchange

#5: Loop Tiling

Function Inlining and Register Allocation

Procedure/Function Inlining

Register Allocation

Register Allocation with Graph Coloring

Instruction Selection

Assembler and linker

Symbol Table

Object File

Linker

Dynamic Linking