Local Optimizations.

Slides:



Advertisements
Similar presentations
CSC 4181 Compiler Construction Code Generation & Optimization.
Advertisements

Synopsys University Courseware Copyright © 2012 Synopsys, Inc. All rights reserved. Compiler Optimization and Code Generation Lecture - 3 Developed By:
Intermediate Code Generation
Chapter 9 Code optimization Section 0 overview 1.Position of code optimizer 2.Purpose of code optimizer to get better efficiency –Run faster –Take less.
19 Classic Examples of Local and Global Code Optimizations Local Constant folding Constant combining Strength reduction.
1 Code generation Our book's target machine (appendix A): opcode source1, source2, destination add r1, r2, r3 addI r1, c, r2 loadI c, r2 load r1, r2 loadAI.
ECE 454 Computer Systems Programming Compiler and Optimization (I) Ding Yuan ECE Dept., University of Toronto
1 CS 201 Compiler Construction Machine Code Generation.
Intermediate Representation III. 2 PAs PA2 deadline is
8. Code Generation. Generate executable code for a target machine that is a faithful representation of the semantics of the source code Depends not only.
Control-Flow Graphs & Dataflow Analysis CS153: Compilers Greg Morrisett.
Chapter 10 Code Optimization. A main goal is to achieve a better performance Front End Code Gen Intermediate Code source Code target Code user Machine-
Code Generation Steve Johnson. May 23, 2005Copyright (c) Stephen C. Johnson The Problem Given an expression tree and a machine architecture, generate.
Optimization Compiler Baojian Hua
Representing programs Goals. Representing programs Primary goals –analysis is easy and effective just a few cases to handle directly link related things.
Improving code generation. Better code generation requires greater context Over expressions: optimal ordering of subtrees Over basic blocks: Common subexpression.
1 Intermediate representation Goals: –encode knowledge about the program –facilitate analysis –facilitate retargeting –facilitate optimization scanning.
Code Generation Simple Register Allocation Mooly Sagiv html:// Chapter
Prof. Bodik CS 164 Lecture 171 Register Allocation Lecture 19.
Arithmetic Expression Consider the expression arithmetic expression: (a – b) + ((c + d) + (e * f)) that can be represented as the following tree.
Register Allocation (via graph coloring)
U NIVERSITY OF M ASSACHUSETTS, A MHERST D EPARTMENT OF C OMPUTER S CIENCE Emery Berger University of Massachusetts, Amherst Advanced Compilers CMPSCI 710.
1 Copy Propagation What does it mean? – Given an assignment x = y, replace later uses of x with uses of y, provided there are no intervening assignments.
1 Lecture 7: Computer Arithmetic Today’s topics:  Chapter 2 wrap-up  Numerical representations  Addition and subtraction Reminder: Assignment 3 will.
Improving Code Generation Honors Compilers April 16 th 2002.
Improving code generation. Better code generation requires greater context Over expressions: optimal ordering of subtrees Over basic blocks: Common subexpression.
Compiler Construction A Compulsory Module for Students in Computer Science Department Faculty of IT / Al – Al Bayt University Second Semester 2008/2009.
What’s in an optimizing compiler?
Compiler course 1. Introduction. Outline Scope of the course Disciplines involved in it Abstract view for a compiler Front-end and back-end tasks Modules.
Chapter 7 Syntax-Directed Compilation (AST & Target Code) 1.
1 Code optimization “Code optimization refers to the techniques used by the compiler to improve the execution efficiency of the generated object code”
Compiler Principles Fall Compiler Principles Lecture 0: Local Optimizations Roman Manevich Ben-Gurion University.
Compiler Optimizations ECE 454 Computer Systems Programming Topics: The Role of the Compiler Common Compiler (Automatic) Code Optimizations Cristiana Amza.
More on Loop Optimization Data Flow Analysis CS 480.
Compiler Principles Fall Compiler Principles Lecture 8: Intermediate Representation Roman Manevich Ben-Gurion University.
CS 404Ahmed Ezzat 1 CS 404 Introduction to Compiler Design Lecture 10 Ahmed Ezzat.
Optimization Simone Campanoni
Dr. Hussien Sharaf Dr Emad Nabil. Dr. Hussien M. Sharaf 2 position := initial + rate * Lexical analyzer 2. Syntax analyzer id 1 := id 2 + id 3 *
©SoftMoore ConsultingSlide 1 Code Optimization. ©SoftMoore ConsultingSlide 2 Code Optimization Code generation techniques and transformations that result.
Credible Compilation With Pointers Martin Rinard and Darko Marinov Laboratory for Computer Science Massachusetts Institute of Technology.
Single Static Assignment Intermediate Representation (or SSA IR) Many examples and pictures taken from Wikipedia.
More Code Generation and Optimization Pat Morin COMP 3002.
Chapter 8 Code Generation
CS 404 Introduction to Compiler Design
Code Optimization Code produced by compilation algorithms can often be improved (ideally optimized) in terms of run-time speed and the amount of memory.
Code Optimization Overview and Examples
Compiler Design (40-414) Main Text Book:
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
Binary Search Tree (BST)
Optimization Code Optimization ©SoftMoore Consulting.
Register Allocation Noam Rinetzky Text book:
Basic Block Optimizations
Machine-Independent Optimization
Code Generation Part III
Unit IV Code Generation
1. Reaching Definitions Definition d of variable v: a statement d that assigns a value to v. Use of variable v: reference to value of v in an expression.
CS 201 Compiler Construction
Code Optimization Overview and Examples Control Flow Graph
Code Generation Part III
Programming Languages 2nd edition Tucker and Noonan
Data Flow Analysis Compiler Design
SYNTAX DIRECTED DEFINITION
8 Code Generation Topics A simple code generator algorithm
Intermediate Code Generation
Compiler Construction
COMPILERS Liveness Analysis
Live Variables – Basic Block
Basic Block Optimizations
Code Optimization.
CS 201 Compiler Construction
Presentation transcript:

Local Optimizations

Code generation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b);

Code generation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = a + b ; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Common Subexpression Elimination If we have two variable assignments v1 = a op b … v2 = a op b and the values of v1, a, and b have not changed between the assignments, rewrite the code as v2 = v1 Eliminates useless recalculation. Paves the way for later optimizations.

Common Subexpression Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = a + b ; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Common Subexpression Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Common Subexpression Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Common Subexpression Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Common Subexpression Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Common Subexpression Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Common Subexpression Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation If we have a variable assignment v1 = v2 then as long as v1 and v2 are not reassigned, we can rewrite expressions of the form a = … v1 … as a = … v2 … provided that such a rewrite is legal. This will help immensely later on, as you'll see.

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(x) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam x ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(_tmp1 ) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = a + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(_tmp1 ) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(_tmp1 ) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(_tmp1 ) ; _tmp7 = *(_tmp6) ; PushParam _tmp5 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(_tmp1 ) ; _tmp7 = *(_tmp6) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = *(_tmp1) ; _tmp7 = *(_tmp6) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp6) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp6) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp3 ; _tmp4 = _tmp3 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp0 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = _tmp0 ; a = _tmp0 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = c; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam c; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Copy Propagation Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination An assignment to a variable v is called dead if the value of that assignment is never read anywhere. Dead code elimination removes dead assignments from IR. Determining whether an assignment is dead depends on what variable is being assigned to and when it's being assigned.

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; x = _tmp1 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp3 = 4 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; a = 4 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp4 = _tmp0 + b ; c = _tmp4 ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp4 = _tmp0 + b ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp4 = _tmp0 + b ; _tmp5 = _tmp4 ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp4 = _tmp0 + b ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp4 = _tmp0 + b ; _tmp6 = _tmp2 ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Dead Code Elimination Object x; int a; int b; int c; x = new Object; a = 4; c = a + b; x.fn(a + b); _tmp0 = 4 ; PushParam _tmp0 ; _tmp1 = LCall _Alloc ; PopParams 4 ; _tmp2 = Object ; *(_tmp1) = _tmp2 ; _tmp4 = _tmp0 + b ; _tmp7 = *(_tmp2 ) ; PushParam _tmp4 ; PushParam _tmp1 ; ACall _tmp7 ; PopParams 8 ;

Register allocation When generating code for arithmetic expressions, the compiler has to decide which is the best way to translate the expression in terms of number of instructions used as well as number of registers needed to evaluate a certain subtree. Especially in the case that free registers are scarce, the order of evaluation can be important to the length of the generated code, because different orderings may lead to larger or smaller numbers of intermediate values being spilled to memory and then restored.

Simple Sethi–Ullman algorithm Traverse the abstract syntax tree in pre- or postorder: For every non-constant leaf node, assign a 1 (i.e. 1 register is needed to hold the variable/field/etc.). For every constant leaf node (RHS of an operation – literals, values), assign a 0. For every non-leaf node n, assign the number of registers needed to evaluate the respective subtrees of n. If the number of registers needed in the left subtree (l) are not equal to the number of registers needed in the right subtree (r), the number of registers needed for the current node n is max(l, r). If l == r, then the number of registers needed for the current node is l + 1.

Simple Sethi–Ullman algorithm

Simple Sethi–Ullman algorithm

Simple Sethi–Ullman algorithm Code emission: If the number of registers needed to compute the left subtree of node n is bigger than the number of registers for the right subtree, then the left subtree is evaluated first (since it may be possible that the one more register needed by the right subtree to save the result makes the left subtree spill). If the right subtree needs more registers than the left subtree, the right subtree is evaluated first accordingly. If both subtrees need equal as much registers, then the order of evaluation is irrelevant.

Simple Sethi–Ullman algorithm * + + + * d 3 b c f g

Simple Sethi–Ullman algorithm ∗ 2 + 2 + 1 + 1 ∗ 1 𝑑 1 3 0 𝑏 1 𝑐 0 𝑓 1 𝑔 0