Conditional Elimination through Code Duplication

Similar documents
Topic 9: Control Flow

Data Flow Analysis. Agenda CS738: Advanced Compiler Optimizations. 3-address Code Format. Assumptions

Compiler Construction 2010/2011 Loop Optimizations

A Bad Name. CS 2210: Optimization. Register Allocation. Optimization. Reaching Definitions. Dataflow Analyses 4/10/2013

Data Flow Analysis. Program Analysis

Introduction to Machine-Independent Optimizations - 6

Compiler Construction 2016/2017 Loop Optimizations

CS553 Lecture Profile-Guided Optimizations 3

Dataflow Analysis. Xiaokang Qiu Purdue University. October 17, 2018 ECE 468

CFG (Control flow graph)

The Static Single Assignment Form:

Compiler Design. Fall Control-Flow Analysis. Prof. Pedro C. Diniz

Compiler Construction 2009/2010 SSA Static Single Assignment Form

Lecture Notes on Liveness Analysis

Compiler Optimizations. Chapter 8, Section 8.5 Chapter 9, Section 9.1.7

Search Algorithms. IE 496 Lecture 17

Compiler Optimizations. Chapter 8, Section 8.5 Chapter 9, Section 9.1.7

Data Flow Analysis. CSCE Lecture 9-02/15/2018

Languages and Compiler Design II IR Code Optimization

COMPILER DESIGN - CODE OPTIMIZATION

Compiler Optimization Techniques

Goals of Program Optimization (1 of 2)

Optimizations. Optimization Safety. Optimization Safety CS412/CS413. Introduction to Compilers Tim Teitelbaum

A Propagation Engine for GCC

CSE P 501 Compilers. SSA Hal Perkins Spring UW CSE P 501 Spring 2018 V-1

Compiler Design Prof. Y. N. Srikant Department of Computer Science and Automation Indian Institute of Science, Bangalore

Partial Redundancy Analysis

EECS 583 Class 2 Control Flow Analysis LLVM Introduction

Backtracking and Branch-and-Bound

The Encoding Complexity of Network Coding

3 No-Wait Job Shops with Variable Processing Times

Live Variable Analysis. Work List Iterative Algorithm Rehashed

Solution to Problem 1 of HW 2. Finding the L1 and L2 edges of the graph used in the UD problem, using a suffix array instead of a suffix tree.

CS 426 Fall Machine Problem 4. Machine Problem 4. CS 426 Compiler Construction Fall Semester 2017

Combining Analyses, Combining Optimizations - Summary

7. Optimization! Prof. O. Nierstrasz! Lecture notes by Marcus Denker!

Example. Example. Constant Propagation in SSA

Intermediate representation

Middle End. Code Improvement (or Optimization) Analyzes IR and rewrites (or transforms) IR Primary goal is to reduce running time of the compiled code

Compiler Passes. Optimization. The Role of the Optimizer. Optimizations. The Optimizer (or Middle End) Traditional Three-pass Compiler

Lecture 21 CIS 341: COMPILERS

On the Max Coloring Problem

Final Exam in Algorithms and Data Structures 1 (1DL210)

Branch-and-bound: an example

STA 4273H: Statistical Machine Learning

Intermediate representations IR #1: CPS/L 3. Code example. Advanced Compiler Construction Michel Schinz

V Advanced Data Structures

Constraint Satisfaction Problems

Theorem 2.9: nearest addition algorithm

CS 406/534 Compiler Construction Putting It All Together

Loop Optimizations. Outline. Loop Invariant Code Motion. Induction Variables. Loop Invariant Code Motion. Loop Invariant Code Motion

Dual-Based Approximation Algorithms for Cut-Based Network Connectivity Problems

Analyze the obvious algorithm, 5 points Here is the most obvious algorithm for this problem: (LastLargerElement[A[1..n]:

LECTURES 3 and 4: Flows and Matchings

Machine-Independent Optimizations

Topic I (d): Static Single Assignment Form (SSA)

Paths, Flowers and Vertex Cover

Reduced branching-factor algorithms for constraint satisfaction problems

Unit-II Programming and Problem Solving (BE1/4 CSE-2)

V Advanced Data Structures

IR Optimization. May 15th, Tuesday, May 14, 13

Constraint Satisfaction Problems

Boolean Representations and Combinatorial Equivalence

Bi-Objective Optimization for Scheduling in Heterogeneous Computing Systems

Lecture Notes on Static Single Assignment Form

Lecture Notes on Common Subexpression Elimination

Department of Computer Sciences CS502. Purdue University is an Equal Opportunity/Equal Access institution.

Register Allocation & Liveness Analysis

Compiler Optimization and Code Generation

Compiler Design Spring 2017

Lecture Notes on Loop Optimizations

Lecture Compiler Backend

Horn Formulae. CS124 Course Notes 8 Spring 2018

Topic 14: Scheduling COS 320. Compiling Techniques. Princeton University Spring Lennart Beringer

Class 6. Review; questions Assign (see Schedule for links) Slicing overview (cont d) Problem Set 3: due 9/8/09. Program Slicing

Treewidth and graph minors

Design and Analysis of Algorithms Prof. Madhavan Mukund Chennai Mathematical Institute. Week 02 Module 06 Lecture - 14 Merge Sort: Analysis

Flow-sensitive rewritings and Inliner improvements for the Graal JIT compiler

Lecture Compiler Middle-End

Data structures are often needed to provide organization for large sets of data.

February 19, Integer programming. Outline. Problem formulation. Branch-andbound

Dominance Constraints and Dominance Graphs

26 The closest pair problem

Byzantine Consensus in Directed Graphs

Lecture 5: Suffix Trees

CSC D70: Compiler Optimization Register Allocation

The Running Time of Programs

Control-Flow Analysis

Global Optimization. Lecture Outline. Global flow analysis. Global constant propagation. Liveness analysis. Local Optimization. Global Optimization

Lecture 1 Contracts : Principles of Imperative Computation (Fall 2018) Frank Pfenning

Compiler Optimisation

Dataflow analysis (ctd.)

Lecture Outline. Intermediate code Intermediate Code & Local Optimizations. Local optimizations. Lecture 14. Next time: global optimizations

Joint Entity Resolution

A Toolbox for Counter-Example Analysis and Optimization

Propagating separable equalities in an MDD store

Solutions to the Second Midterm Exam

γ 2 γ 3 γ 1 R 2 (b) a bounded Yin set (a) an unbounded Yin set

Instruction Scheduling Beyond Basic Blocks Extended Basic Blocks, Superblock Cloning, & Traces, with a quick introduction to Dominators.

B-Trees. Disk Storage. What is a multiway tree? What is a B-tree? Why B-trees? Insertion in a B-tree. Deletion in a B-tree

Transcription:

Conditional Elimination through Code Duplication Joachim Breitner May 27, 2011 We propose an optimizing transformation which reduces program runtime at the expense of program size by eliminating conditional jumps. 1 Preface 1.1 Motivation In a variety of cases, code is written in a way that in one execution, a conditional execution is evaluated several time. Situations where this may be happening include the following: Repeated use of the ternary operator (? : ) with a common conditional expression. An if-then-else statement inside a loop, where the condition is loop invariant. Use of macros or inlined functions provided by a library that include conditional expression. Conditional jumps implicitly inserted by the compiler due to short-circuit logic. Naive code mechanically generated from another source via tools such as parser generators, or compilers of higher languages that compile to C and then invoke a C compiler. Conditionals introduced by earlier compilation passes, such as the Partial Dead Code pass conceived by Bodík and Gupta [BG97] are likely to make other conditionals redundant. In fact, the PDE paper recommends a branch elimination step without giving the details of this. CECD can serve as an implementation of this step. e-mail: mail@joachim-breitner.de 1

In some of these cases the programmer might be able to eliminate the redundant conditional expression by himself, but often at the cost of less readable code or repetition, such as two instances of the loop mentioned in the second bullet. In other cases, such as the library-provided macros or the generated code, it is not feasible to expect the source code to be free of redundant conditionals. Therefore it is desirable that an optimizing compiler can perform this transformation. Furthermore, this transformation not only reduces execution time but can enabled further optimizations: If the conditional expression is of the form v == c for a variable v and a constant c, a constant propagation pass can replace v by c in the then-branch, which has been enlarged by our optimization. Also, modern computer architectures, due to long pipelines, perform better if fewer conditional jumps occur in the code. 1.2 Outline In the next section, we explain when a given region to duplicate is valid and how to perform the conditional elimination. Aiming for a very clear, simple and homogeneous presentation, we describe the algorithm in a very general setting. This will possibly introduce dead code. An implementation would either run a dead code elimination pass afterwards or refine the given algorithm as required. The transformation is demonstrated by example. Section 3 discusses which properties the region should satisfy for the optimization to actually have a positive effect, and how to avoid useless code duplication. To decide whether to perform the optimization, we give a simple heuristic that selects a region to be duplicated and decides whether the optimization should be performed, weighting the (runtime) benefits weighted against the (code size) cost in subsection 3.2. We also show that a slight more sophisticated approach, which takes profiling information into account, becomes N P-hard. Data flow equations for the properties discussed in the preceding two sections are given in 4. 1.3 Acknowledgements This paper was written for the group project of the CS614 Advanced Compiler course at IIT Bombay under Prof. D. M. Dhamdhere. I have had fruitful discussions with him and my fellow group members, Anup Agarwal, Yogesh Bagul and Anup Naik, who subsequently implemented parts of this using the LLVM compiler suite. 2

2 Conditional elimination Let e be an expression, which should occur as the condition for a conditional branch in the control flow graph (CFG) of a program, and let v 1, v 2,... be the operands of the expression. Let D be a region of the control flow graph, i.e. D BB where BB is the set of basic blocks in the control flow graph. The region D is valid if and only if no basic block body in D contains an assignment to any of the operands v 1, v 2,... of e. The parameters of the optimization are the conditional expression e and any valid set D. The transformation is performed in three steps, where the first step is generic code duplication which does not yet consider the conditional expression, the second step rewires some edges to make the other copies reachable and the last step removes the redundant conditionals. Each step preserves the meaning of the program. 1. (Code duplication) For every basic block bb i D, create three copies 1 : the true copy bb t i, the false copy bbf i and the unknown copy bb u i. The edges of the graph are modified as follows: An edge between bb i / D and bb j / D is left unchanged. An edge between bb i D and bb j D is reproduced by the three edges bb t i to bb t j, bbf i to bb f j and bbu i to bb u j. An edge between bb i D and bb j / D is reproduced by the three edges bb t i to bb j, bb f i to bb j to bb u i to bb j. An edge between bb i / D and bb j D is changed to an edge from bb i to bb u j. 2. (Conditional evaluation) For every conditional edge from bb i to bb j depending on e being true (false) at the end of bb i, where bb j is a copy of a node in D, replace it by an edge bb i to bb t j (bbf j ). 3. (Conditional elimination) For every basic block bb i D which has a conditional branch depending on e being true (false), remove the condition in bb t i (bbf i ), unconditionally follow the true (false) case and remove the other edge. This algorithm is correct and safe. For correctness, consider an execution path. If the path does not pass any node in D, it is not altered by the above algorithm. If the path passes through D, but only through unknown copies, it is also not altered. If the path eventually reaches a true (false) copy of a node, it must be because of an edge altered in step 2. At that point of execution, the value of e is known to be true (false), and because D is valid, it remains so until the execution path leaves the region D. Any conditional 1 Technically, this is triplication, not duplication. 3

bb 1 bb 2 bb 3 bb 6 e :=... bb 4 bb 5 useful bb 7 valid bb 11 bb 8 bb 9 bb 10 Figure 2: Example control flow graph before CECD jump skipped because of step 3 is therefore behaving exactly as in the original execution path.. Safeness follows from the fact that we only copy nodes and remove the evaluation of conditionals, so along no path new instructions are added. Example Consider the code fragment in Figure 1 (leaving out any unrelated assignments or expressions). The corresponding control flow graph is given in figure 2. The largest valid region is marked, as well as the largest region if useful nodes. Applying the algorithm with D set to the region of useful nodes, after step 1 we obtain the graph shown in figure 3 on the following page. At this point, the true and false copies are not reachable yet. Steps 2 and 3 modify the edges related to conditional on e, and we reach figure 4 on the next page. This contains a lot of dead code. Removing this in a standard dead code removal pass, we reach the final state 5 if... then if e then... else... else e := end while... do if e then... else... end... Figure 1: Example code on page 6. It can clearly be seen that on every path from entry to exit, the conditional e is evaluated at most once. Also the issue of a while-loop occurrence (in contrast to the optimizer-friendly do-while-loop) is gracefully taken care of. 4

bb 1 bb 2 bb 3 e :=... bb 6 bb t 4 bb t 5 bb f 4 bb f 5 bb u 4 bb u 5 bb t 7 bb f 7 bb u 7 bb t 8 bb f 8 bb u 8 bb t 9 bb t 10 bb f 9 bb f 10 bb u 9 bb u 10 bb 11 Figure 3: Example control flow graph after code duplication of useful nodes bb 2 bb 1 bb 3 e :=... bb 6 bb t 4 bb t 5 bb f 4 bb f 5 bb u 4 bb u 5 bb t 7 bb f 7 bb u 7 bb u 8 bb t 9 bb f 10 bb u 9 bb u 10 bb 11 Figure 4: Example control flow graph after conditional evaluation and elimination 5

bb 1 bb 2 bb 3 e :=... bb 6 bb u 7 bb t 4 bb f 5 bb u 8 bb t 7 bb f 7 bb t 9 bb f 10 bb 11 Figure 5: Example control flow graph after conditional evaluation and elimination and dead code elimination 6

3 The region of duplication The above algorithm works for any valid region, and validity is a simple local property that is easily checked. But not all valid regions are useful. For example, entry nodes bb i of the region where no incoming edge depends on e would be duplicated, but only bb u i would be reachable. Similarly, exit nodes of the region that do not have a conditional evaluation of e would be copied for no gain. 3.1 Usefulness Therefore, we can define that a node bb i in a valid region D to be useless if on all paths leading to bb i, there is no conditional evaluation of e followed only by nodes in D or no path originating from bb i reaches an conditional evaluation of e before it leaves the region D. A node bb i D that is not useless is useful. Uselessness is, in contrast to validity, not a property of the basic block alone but defined with respect to the chosen region D. A basic block may be useless in D but not so in a different region D. But the property is monotonous: If D D and D is useful in D, then it is also useful in D. 3.2 Evaluation of a region For a given conditional expression, there are many possible regions of duplication, and even if we only consider fully useful regions, their number might be exponential in the size of the graph. Therefore we need an heuristic that selects a sensible region or decides that no region is good enough to perform CECD. We split this decision into two independent steps: Region Selection, where the the best region for a particular conditional, for some meaning of best is chosen, and Region Evaluation, where it is decided whether CECD should be performed for the selected region. These decisions have to depend on the intended use of the code. Code for an embedded system might have very tight size requirements and large regions of duplication would be unsuitable, whereas code written for massive numerical calculations may be allowed to grow quite a bit if it removes instructions from the inner loops. At this point, we suggest a very simple heuristic for Region Selection: To cover as many executions paths as possible, we just pick the largest valid region consisting of useful nodes. The heuristic for Region Evaluation expects one parameter k, which is the number of additional expressions that the program is allowed to grow for one conditional to be removed. Together, this amounts to the following steps being taken: 7

1. Let D be the largest valid region consisting only of useful nodes. 2. Let R t, R f resp. R u the set of those basic blocks in D, whose true, false resp unknown copy will be reachable after CECD. 3. Let n be the number of basic blocks in D that contain a conditional evaluation of e, i.e. the number of redundant conditionals. 4. If bb i R t S(bb i ) + bb i R f S(bb i ) + bb i R u S(bb i ) bb i D S(bb i ) n k, where k is a user-defined parameter and S(bb i ) is the number of instructions in the basic block bb i, perform CECD on D, otherwise do not perform CECD for this conditional expression. A number of improvements to this scheme come to mind: The selection heuristic should consider subsets of the largest valid and useful regions as well. It should give different weights to conditionals that are completely removed and conditionals that are only partially removed. Removal of conditionals in inner loops should allow for a larger increase of code size. Given sufficiently detailed execution traces, a more exact heuristic can be implemented. In the next section we see that this easily leads to a N P-hard problem. 3.3 N P-hardness of a profiling based Region Selection heuristic A straight forward extension of the above Region Selection heuristic that takes profiling data in the form of execution traces into account, would maximize the sum bb i E f(bb i), where E is the set of of basic blocks containing an eliminated conditional and f(bb i ) is the number of paths in the execution traces where the conditional in bb i would be eliminated due to CECD. For simplicity, we assume that an occurrence of a conditional expression does not contribute to the size S(bb i ) of a basic block. If we have an algorithm that selects the optimal region, we can solve the 0-1 knapsack problem, which is N P-complete. The specification of this problem is as follows: Given n items with weight w i N and value v i N, i = 1,..., n and a bound W N, find a selection of items X {1,..., n} that maximizes the sum i X v i under the constraint i X w i W. Given such a problem, we construct a control flow graph and profiling data as follows: 8

The entry node is bb s, which contains a conditional expression e. Both conditional branches point to the node bb r. There is one exit node bb e with a conditional expression e. The node bb r is the root of a binary tree of basic blocks. The inner nodes contain no instructions but conditional jumps with conditional expressions that are pairwise distinct and distinct from e. The tree contains n leaf nodes bb i l, i = 1,..., n. The node bbi l contains w i instructions, i.e. S(bb i l ) = w i and the profiling data gives a frequency of v i for the execution path passing through bb i l. The parameter k is chosen to be W. A valid and useful region of duplication D in this CFG corresponds to a subset of X 1,.., n and, if non-empty, includes bb e, bb i l for i X and the nodes connecting bb r with those leaf nodes. Because bb s dominates all nodes in D, no unknown copies will be generated, and both true and false copies are reachable. The inner nodes of the binary tree and bb e only contain conditional expressions and thus do not contribute to the size of the duplicated region. Only one redundant conditional occurs, hence n = 1. The number of executions of bb e where the conditional is eliminated is exactly the number of execution paths that pass through one of the leaf nodes in D. Therefore, the constraint imposed by the Region Evaluation heuristic becomes S(bb i ) + S(bb i ) + S(bb i ) S(bb i ) n k bb i R t bb i R f bb i R u bb i D S(bb i l ) 1 k S(bb i l ) + S(bb i l ) + 0 i X i X i X w i W and the term to be optimized can be transformed as follows: v i. bb i E f(bb i ) = i X f(bb i l ) = i X This concludes the proof of N P-hardness of this profiling-based heuristic for CECD. The assumption that conditional expressions do not contribute to the size of a node is not critical: If they do contribute, then this result can still be obtained by a technical modification: Increase k by one and then scale k and the number of instructions in the nodes bb i l by a factor larger than the number of all conditional expressions occurring. i X 9

4 Data Flow equations Three properties of basic blocks have been defined so far: Validness, usefulness and, for the heuristics, which copies of the block will be present after dead code removal. The first one is a purely local property, while the others can be obtained by standard data flow analyses. The defining equations are given in this section. succ(i) is the set of successor nodes of bb i in the control flow graph, pred(i) the set of predecessors. We assume that nodes with a conditional jump have exactly two successors, one for true and one for false. Local properties: Valid i : Basic block bb i does not contain an assignment to an operator of e. TrueEdge ij : An edge bb i bb j exists and depends on e being true. FalseEdge ij : An edge bb i bb j exists and depends on e being false. Expr i = j succ(i) TrueEdge ij + FalseEdge ij : e is a conditional expression in bb i Determining the largest valid region D of useful nodes: Live i = Valid i j pred(i) Expr j + Live j Antic i = Valid i (Expr i + j succ(i) Antic j) D i = Live i Antic i Given a valid region D (which may or may not be obtained using our suggested simple heuristic), determining which copies of the nodes therein are reachable: R u i = D i j pred(i) Expr j ( D j + R u j ) R t i = D i j pred(i) Rt j + TrueEdge ji R f i = D i j pred(i) Rf j + FalseEdge ji All given data flow equations are any-path equations and therefore, the values can be initialized to false before solving the equations using a standard iterative round-robin or worklist approach. 10

5 Future work and conclusions While the how of CECD is fully understood, the question of where and when, i.e. coming up with good heuristics for the selection of the conditional and region of duplication, needs much further investigation. Also, experiments with real code have yet to be conducted to quantify the benefit and suggest good values for the heuristics parameters. Another possible improvement would be to not only consider syntactically equal conditions, but also take algebraic identities into account. The simplicity of the CECD transformation and the fact that it can easily handle complex control flow indicate that it could be an optimization of general interest. References [BG97] Bodík, Rastislav ; Gupta, Rajiv: Partial dead code elimination using slicing transformations. In: SIGPLAN Not. 32 (1997), May, S. 159 170. http:// dx.doi.org/10.1145/258916.258930. DOI 10.1145/258916.258930. ISSN 0362 1340 11