rethinking code generation in compilers/rethinking co… · • example: instruction scheduling...

60
Rethinking Code Generation in Compilers Christian Schulte SCALE KTH Royal Institute of Technology & SICS (Swedish Institute of Computer Science) joint work with: Mats Carlsson SICS Roberto Castañeda Lozano SICS + KTH Frej Drejhammar SICS Gabriel Hjort Blindell KTH funded by: Ericsson, Vetenskapsrådet

Upload: others

Post on 16-Aug-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Rethinking Code Generation in Compilers

Christian Schulte SCALE

KTH Royal Institute of Technology & SICS (Swedish Institute of Computer Science)

joint work with: Mats Carlsson SICS

Roberto Castañeda Lozano SICS + KTH

Frej Drejhammar SICS

Gabriel Hjort Blindell KTH

funded by: Ericsson, Vetenskapsrådet

Page 2: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Compilation

• Front-end: depends on source programming language • changes infrequently

• Optimizer: independent optimizations • changes infrequently

• Back-end: depends on processor architecture • changes often: new architectures, new features, …

2

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

front-end optimizer back-end (code generator)

source program

assembly program

Page 3: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Building a Compiler

• Infrequent changes: front-end & optimizer • reuse state-of-the-art: LLVM, for example

3

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

front-end optimizer back-end (code generator)

source program

assembly program

LLVM

Page 4: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Building a Compiler

• Infrequent changes: front-end & optimizer • reuse state-of-the-art: LLVM, for example

• Frequent changes: back-end • use flexible approach: Unison (project this talk is based on) 4

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

front-end optimizer back-end (code generator)

source program

assembly program

Unison

Page 5: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • instruction selection,

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

5

instruction selection

x = y + z; add r0 r1 r2 mv $a6f0 r0

Page 6: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • instruction selection, register allocation,

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

6

register allocation

x = y + z; x register r0 y memory (spill to stack) …

Page 7: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • instruction selection, register allocation, instruction scheduling

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

7

instruction scheduling

x = y + z; … u = v – w;

u = v – w; … x = y + z;

Page 8: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • stages are interdependent: no optimal order possible

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

8

instruction selection

register allocation

instruction scheduling

Page 9: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • stages are interdependent: no optimal order possible

• Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

registers used over longer time-spans

more registers needed

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

9

instruction selection

instruction scheduling

register allocation

Page 10: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • stages are interdependent: no optimal order possible

• Example: instruction scheduling register allocation • put variables into fewer registers

more dependencies among instructions

less opportunity for reordering instructions

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

10

instruction selection

register allocation

instruction scheduling

Page 11: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • stages are interdependent: no optimal order possible

• Stages use heuristic algorithms • for hard combinatorial problems (NP hard)

• assumption: optimal solutions not possible anyway

• difficult to take advantage of processor features

• error-prone when adapting to change

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

11

instruction selection

instruction scheduling

register allocation

Page 12: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

State-of-the-art

• Code generation organized into stages • stages are interdependent: no optimal order possible

• Stages use heuristic algorithms • for hard combinatorial problems (NP hard)

• assumption: optimal solutions not possible anyway

• difficult to take advantage of processor features

• error-prone when adapting to change

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

12

instruction selection

instruction scheduling

register allocation

preclude optimal code, make development

complex

Page 13: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Rethinking: Unison Idea

• No more staging and heuristic algorithms! • many assumptions are decades old...

• Use state-of-the-art technology for solving combinatorial optimization problems: constraint programming

• tremendous progress in last two decades...

• Generate and solve single model • captures all code generation tasks in unison

• high-level of abstraction: based on processor description

• flexible: ideally, just change processor description

• potentially optimal: tradeoff between decisions accurately reflected

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

13

Page 14: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Unison Approach

• Generate constraint model • based on input program and processor description

• constraints for all code generation tasks

• generate but not solve: simpler and more expressive

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

14

instruction selection

instruction scheduling

register allocation

input program

processor description

constraint model

constraints

constraints

constraints

Page 15: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Unison Approach

• Off-the-shelf constraint solver solves constraint model • solution is assembly program

• optimization takes inter-dependencies into account

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

15

instruction selection

instruction scheduling

register allocation

input program

processor description

constraint model

constraints

constraints

constraints

off-the-shelf constraint

solver

assembly program

Page 16: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Overview

• Constraint programming in a nutshell

• Approach

• Results

• Discussion

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

16

Page 17: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

CONSTRAINT PROGRAMMING IN A NUTSHELL

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

17

Page 18: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Constraint Programming

• Model and solve combinatorial (optimization) problems

• Modeling • variables

• constraints

• branching heuristics

• (cost function)

• Solving • constraint propagation

• heuristic search

• Of course simplified… • array of modeling techniques

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

18

Page 19: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Problem: Send More Money

• Find distinct digits for letters such that

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

19

SEND

+ MORE

= MONEY

Page 20: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Constraint Model

• Variables:

S,E,N,D,M,O,R,Y {0,…,9}

• Constraints: distinct(S,E,N,D,M,O,R,Y)

1000×S+100×E+10×N+D + 1000×M+100×O+10×R+E = 10000×M+1000×O+100×N+10×E+Y

S0 M0

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

20

Page 21: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Constraints

• State relations between variables • legal combinations of values for variables

• Examples • all variables pair wise distinct: distinct(x1, …, xn)

• arithmetic constraints: x + 2×y = z

• domain-specific: cumulative(t1, …, tn)

nooverlap(r1, …, rn)

• Success story: global constraints • modeling: capture recurring problem structures

• solving: enable strong reasoning

constraint-specific methods

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

21

Page 22: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Solving: Variables and Values

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

22

• Record possible values for variables • solution: single value left

• failure: no values left

x{1,2,3,4} y{1,2,3,4} z{1,2,3,4}

Page 23: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Constraint Propagation

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

23

• Prune values that are in conflict with constraint

x{1,2,3,4} y{1,2,3,4} z{1,2,3,4}

distinct(x, y, z) x + y = 3

Page 24: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Constraint Propagation

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

24

• Prune values that are in conflict with constraint

x{1,2} y{1,2} z{1,2,3,4}

distinct(x, y, z) x + y = 3

Page 25: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Constraint Propagation

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

25

• Prune values that are in conflict with constraint • propagation is often smart if not perfect!

• captured by so-called global constraints

x{1,2} y{1,2} z{3,4}

distinct(x, y, z) x + y = 3

Page 26: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Heuristic Search

• Propagation alone not sufficient • decompose into simpler sub-problems

• search needed

• Create subproblems with additional constraints • enables further propagation

• defines search tree

• uses problem specific heuristic

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

26

x{1,2} y{1,2} z{3,4}

distinct(x, y, z) x + y = 3

x{1} y{2} z{3,4}

distinct(x, y, z) x + y = 3

x{2} y{1} z{3,4}

distinct(x, y, z) x + y = 3

x=1 x≠1

Page 27: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

What Makes It Work?

• Essential: avoid search...

...as it always suffers from combinatorial explosion

• Constraint propagation drastically reduces search space

• Efficient and powerful methods for propagation available

• When using search, use a clever heuristic

• Array of modeling techniques available that reduce search

• adding redundant constraints for more propagation, symmetry breaking, ...

• Hybrid methods (together with LP, SAT, stochastic, ...)

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

27

Page 28: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Approach

Page 29: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Source Material

• Survey on Combinatorial Register Allocation and Instruction Scheduling

• Roberto Castañeda Lozano, Christian Schulte. CoRR entry, 2014.

• Combinatorial Spill Code Optimization and Ultimate Coalescing

• Roberto Castañeda Lozano, Mats Carlsson, Gabriel Hjort Blindell, Christian Schulte. Languages, Compilers, Tools and Theory for Embedded Systems, 2014.

• Constraint-based Register Allocation and Instruction Scheduling

• Roberto Castañeda Lozano, Mats Carlsson, Frej Drejhammar, Christian Schulte. Eighteenth International Conference on Principles and Practice of Constraint Programming, 2012.

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

29

Page 30: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Getting Started…

• Function is unit of compilation • generate code for one function at a time

• Instruction selection has already been performed • some instructions might depend on register allocation [later]

• Use control flow graph (CFG) and turn it into LSSA form • edges = control flow

• nodes = basic blocks (no control flow)

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

30

int fac(int n) { int f = 1; while (n > 0) { f = f * n; n--; } return f; }

t3li t4slti t2 bne t3

jr t10

t8mul t7,t6 t9subiu t6 bgtz t9

Page 31: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Register Allocation

• Assign registers to program temporaries (variables) • infinite number of temporaries

• finite number of registers

• Naive strategy: each temporary assigned a different register • will never work, way too few registers!

• Assign the same register to several temporaries • when is this safe? interference

• what if there are not enough registers? spilling

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

31

t2 mul t1, 2 t3 sub t1, 2 t4 add t2, t3 return t4

r2 mul r1, 2 r3 sub r1, 2 r4 add r2, r3 return r4

r2 mul r1, 2 r1 sub r1, 2 r1 add r2, r1 return r1

Page 32: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Static Single Assignment (SSA)

• SSA: each temporary is defined (t ...) once

• SSA simplifies many optimizations

• Instead of using -functions we use -congruences and LSSA • -functions disambiguate definitions of temporaries

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

32

t3li t4slti t2 bne t3

jr t10

t8mul t7,t6 t9subiu t6 bgtz t9

Page 33: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Liveness and Interference

• Temporary is live when it might be still used • live range of a temporary from its definition to use

• Temporaries interfere if they are live simultaneously • this definition is naive [more later]

• Non-interfering temporaries can be assigned to same register

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

33

t0add ...

... ...

jr t0

Page 34: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Linear SSA (LSSA)

• Linear live range of a temporary cannot span block boundaries

• Liveness across blocks defined by temporary congruence

t t’ represent same original temporary

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

34

t3li t4slti t2 bne t4

jr t10

t8mul t7,t6 t9subiu t6 bgtz t9

t1t5

t2t6

t3t7

t1t10

t3t11

t5t10

t8t11

t6t9

t7t8

Page 35: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Linear SSA (LSSA)

• Linear live range of a temporary cannot span block boundaries

• Liveness across blocks defined by temporary congruence

t t’ represent same original temporary

• Example: t3, t7, t8, t11 are congruent • correspond to the program variable f (factorial result)

• not discussed: t1 return address, t2 first argument, t11 return value

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

35

t3li t4slti t2 bne t4

jr t10

t8mul t7,t6 t9subiu t6 bgtz t9

t1t5

t2t6

t3t7

t1t10

t3t11

t5t10

t8t11

t6t9

t7t8

Page 36: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Linear SSA (LSSA)

• Linear live range of a temporary cannot span block boundaries

• Liveness across blocks defined by temporary congruence

t t’ represent same original temporary

• Advantage • simple modeling for linear live ranges

• enables problem decomposition for solving

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

36

t3li t4slti t2 bne t4

jr t10

t8mul t7,t6 t9subiu t6 bgtz t9

t1t5

t2t6

t3t7

t1t10

t3t11

t5t10

t8t11

t6t9

t7t8

Page 37: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Spilling

• If not enough registers available: spill

• Spilling moves temporary to memory (stack) • store in memory after defined

• load from memory before used

• memory access typically considerably more expensive

• decision on spilling crucial for performance

• Architectures might have more than one register file • some instructions only capable of addressing a particular file

• “spilling” from one register bank to another

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

37

Page 38: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Coalescing

• Temporaries d (“destination”) and s (“source”) are move-related if

d s

• d and s should be coalesced (assigned to same register)

• coalescing saves move instructions and registers

• Coalescing is important • due to how registers are managed (calling convention, callee-save)

• due to using LSSA for our model (congruence)

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

38

Page 39: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Copy Operations

• Copy operations replicate a temporary t to a temporary t’

t’ {i1, i2, …, in} t • copy is implemented by one of the alternative instructions i1, i2, …, in

• instruction depends on where t and t’ are stored

similar to [Appel & George, 2001]

• Example MIPS32

t’ {move, sw, nop} t • t’ memory and t register: sw spill

• t’ register and t register: move move-related

• t’ and t same register: nop coalescing

• MIPS32: instructions can only be performed on registers

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

39

Page 40: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Alternative Temporaries

• Program representation uses operands and alternative temporaries

• enable substitution of temporaries that hold the same value

• Alternative temporaries realize ultimate coalescing • all temporaries which are copy-related can be coalesced

• opposed to naïve coalescing: temporaries which are not live at the same time can be coalesced

• Alternative temporaries enable spill code optimization • possibly reuse spilled temporary defined by load instruction

• Significant impact on code quality

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

40

Page 41: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Register Allocation Approach

• Local register allocation • perform register allocation per basic block

• possible as temporaries are not shared among basic blocks

• Local register assignment as geometrical packing problem • take width of temporaries into account

• also known as “register packing”

• Global register allocation • force temporaries into same registers across blocks

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

41

Page 42: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Unified Register Array

• Unified register array • limited number of registers for each register file

• memory is just another “register” file

• unlimited number of memory “registers”

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

42

unified register array

r0 r1 rn-1

registers memory registers

m0 m1

Page 43: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Geometrical Interpretation

• Temporary t is rectangle • width is 1 (occupies one register)

• top = issue cycle of defining instruction (t …)

• bottom = last issue cycle of using instructions ( … t)

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

43

unified register array

r0 r1 rn-1

registers memory registers

m0 m1

clock cycle

temporary t

Page 44: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Register Assignment

• Register assignment = geometric packing problem • find horizontal coordinates for all temporaries

• such that no two rectangles for temporaries overlap

• corresponds to global constraint (no-overlap)

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

44

unified register array

r0 r1 rn-1

registers memory registers

m0 m1

clock cycle

temporary t

Page 45: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Register Packing

• Temporaries might have different width width(t) • many processors support access to register parts

• still modeled as geometrical packing problem [Pereira & Palsberg, 2008]

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

45

Page 46: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Register Packing

• Temporaries might have different width width(t) • many processors support access to register parts

• still modeled as geometrical packing problem [Pereira & Palsberg, 2008]

• Example: Intel x86 • assign two 8 bit temporaries (width = 1) to 16 bit register (width = 2)

• register parts: AH, AL, BH, BL, CH, CL

• possible for 8 bit: AH, AL, BH, BL, CH, CL

• possible for 16 bit: AH, BH, CH

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

46

AH AL BH BL CH CL AX BX CX

clock cycle

width(t1)=1

width(t3)=2

width(t3)=1

width(t4)=2

Page 47: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Register Packing

• Temporaries might have different width width(t) • many processors support access to register parts

• still modeled as geometrical packing problem [Pereira & Palsberg, 2008]

• Example: Intel x86 • assign two 8 bit temporaries (width = 1) to 16 bit register (width = 2)

• register parts: AH, AL, BH, BL, CH, CL

• possible for 8 bit: AH, AL, BH, BL, CH, CL

• possible for 16 bit: AH, BH, CH

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

47

AH AL BH BL CH CL AX BX CX

clock cycle

t3

t1

t4

t2

start(t1)=0

start(t2)=0

start(t3)=0

start(t4)=1

end(t1)=1

end(t2)=2

end(t3)=1

end(t4)=2

width(t1)=1

width(t3)=2

width(t3)=1

width(t4)=2

Page 48: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Register Packing

• Temporaries might have different width width(t) • many processors support access to register parts

• still modeled as geometrical packing problem [Pereira & Palsberg, 2008]

• Example: Intel x86 • assign two 8 bit temporaries (width = 1) to 16 bit register (width = 2)

• register parts: AH, AL, BH, BL, CH, CL

• possible for 8 bit: AH, AL, BH, BL, CH, CL

• possible for 16 bit: AH, BH, CH

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

48

AH AL BH BL CH CL AX BX CX

clock cycle

t3 t1

t4 t2

start(t1)=0

start(t2)=0

start(t3)=0

start(t4)=1

end(t1)=1

end(t2)=2

end(t3)=1

end(t4)=2

width(t1)=1

width(t3)=2

width(t3)=1

width(t4)=2

Page 49: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Global Register Allocation

• Enforce that congruent temporaries are assigned to same register

• If register pressure is low… • copy instructions might disappear (nop)

= coalescing

• If register pressure is high… • copy instructions might be implemented by a move (move)

= no coalescing

• copy instructions might be implemented by a load/store (lw , sw)

= spill

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

49

Page 50: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Local Instruction Scheduling

• Data and control dependencies • data, control, artificial (for making in and out first/last)

• again ignored: t1 return address, t2 first argument

• If instruction i depends on j

issue distance of operation for i

must be at least latency of operation for j

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

50

t3li t4slti t2 bne t4

in

li

out

bne

slti

1 (t2)

1 (t4)

1 (t3)

1 (t2)

1 (t1)

1 (t2) 1

1

2

Page 51: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Limited Processor Resources

• Processor resources • functional units

• data buses

• Classical cumulative scheduling problem functional

units • processor resource has capacity #units

• instructions occupy parts of resource 1 unit

• resource consumption can never exceed capacity

• Also modeled as resources • instruction bundle width for VLIW processor

• how many instructions can be issued simultaneously

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

51

Page 52: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

RESULTS

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

52

Page 53: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Code Quality

• Compared to LLVM 3.3 for Qualcomm’s Hexagon V4

• 7% mean improvement

• Provably optimal () for 29% of functions

• model limitation: no re-materialization

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

53

Page 54: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Scalability

• Quadratic average complexity up to 1000 instructions

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

54

Page 55: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Optimizing for Size

• Code size improvement over LLVM 3.3

• 1% mean improvement

• Important: straightforward replacement of optimization criterion

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

55

Page 56: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Impact Alternative Temporaries

• 62% of functions become faster, none slower

• 2% mean improvement

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

56

Page 57: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

DISCUSSION

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

57

Page 58: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Related Approaches

• Idea and motivation in Unison for combinatorial optimization is absolutely not new!

• starting in the early 1990s

[Castañeda Lozano & Schulte, Survey on Combinatorial Register

Allocation and Instruction Scheduling, CoRR, 2014]

• Common to pretty much all approaches: compilation unit is basic block

• Approaches differ • which code generation tasks covered

• which technology used (ILP, CLP, SAT, Stochastic Optimization, ...)

• Common challenge: robustness and scalability

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

58

Page 59: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Unique to Unison Approach

• First global approach (function as compilation unit)

• Constraint programming using global constraints • sweet spot: cumulative and nooverlap are state-of-the-art!

• Full register allocation with ultimate coalescing, packing, spilling, and spill code optimization

• spilling is internalized

• Robust at the expense of optimality • problem decomposition

• But: instruction selection not yet there!

Oct

1, 2

01

4

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

59

Page 60: Rethinking Code Generation in Compilers/Rethinking Co… · • Example: instruction scheduling register allocation • increased delay between instructions can increase throughput

Project Context

• Goal • deliver a deployable product to Ericsson

• possibly open source software to LLVM

• Project funded by • Ericsson 2010-2015 13.3 MSEK

2015-2017 5.8 MSEK

• Vetenskapsrådet 2012-2014 2.4 MSEK

• Connected project: several tools generated from processor description

• code generator just one tool

• other tools: assembler, linker, ...

Sep

5, 2

01

3

Ret

hin

kin

g C

od

e G

ener

atio

n

Sch

ult

e, S

CA

LE

60