Table of Contents
Fetching ...

Efficient Algorithms for Partial Constraint Satisfaction Problems over Control-flow Graphs

Xuran Cai, Amir Goharshady

TL;DR

This work targets Partial Constraint Satisfaction Problems on control-flow graphs arising in compiler optimization. It presents a general, SPL-decomposition-based dynamic programming framework that solves graph PCSPs in $O(|G|\cdot|D|^6)$ time, enabling linear scaling in graph size for fixed domains and unifying prior SPL-based tasks such as register allocation and LOSPRE. The approach applies broadly to CFG-based optimization problems, with a detailed treatment of bank selection as a case study, where it achieves substantial practical speedups over state-of-the-art treewidth-based methods and outperforms SAT/ILP solvers on benchmarks. The combination of a principled SPL representation and a bottom-up DP yields a simple yet powerful solver for graph PCSPs in structured programs, with clear implications for compiler analyses and code-generation optimizations.

Abstract

In this work, we focus on the Partial Constraint Satisfaction Problem (PCSP) over control-flow graphs (CFGs) of programs. PCSP serves as a generalization of the well-known Constraint Satisfaction Problem (CSP). In the CSP framework, we define a set of variables, a set of constraints, and a finite domain $D$ that encompasses all possible values for each variable. The objective is to assign a value to each variable in such a way that all constraints are satisfied. In the graph variant of CSP, an underlying graph is considered and we have one variable corresponding to each vertex of the graph and one or several constraints corresponding to each edge. In PCSPs, we allow for certain constraints to be violated at a specified cost, aiming to find a solution that minimizes the total cost. Numerous classical compiler optimization tasks can be framed as PCSPs over control-flow graphs. Examples include Register Allocation, Lifetime-optimal Speculative Partial Redundancy Elimination (LOSPRE), and Optimal Placement of Bank Selection Instructions. On the other hand, it is well-known that control-flow graphs of structured programs are sparse and decomposable in a variety of ways. In this work, we rely on the Series-Parallel-Loop (SPL) decompositions as introduced by~\cite{RegisterAllocation}. Our main contribution is a general algorithm for PCSPs over SPL graphs with a time complexity of \(O(|G| \cdot |D|^6)\), where \(|G|\) represents the size of the control-flow graph. Note that for any fixed domain $D,$ this yields a linear-time solution. Our algorithm can be seen as a generalization and unification of previous SPL-based approaches for register allocation and LOSPRE. In addition, we provide experimental results over another classical PCSP task, i.e. Optimal Bank Selection, achieving runtimes four times better than the previous state of the art.

Efficient Algorithms for Partial Constraint Satisfaction Problems over Control-flow Graphs

TL;DR

This work targets Partial Constraint Satisfaction Problems on control-flow graphs arising in compiler optimization. It presents a general, SPL-decomposition-based dynamic programming framework that solves graph PCSPs in time, enabling linear scaling in graph size for fixed domains and unifying prior SPL-based tasks such as register allocation and LOSPRE. The approach applies broadly to CFG-based optimization problems, with a detailed treatment of bank selection as a case study, where it achieves substantial practical speedups over state-of-the-art treewidth-based methods and outperforms SAT/ILP solvers on benchmarks. The combination of a principled SPL representation and a bottom-up DP yields a simple yet powerful solver for graph PCSPs in structured programs, with clear implications for compiler analyses and code-generation optimizations.

Abstract

In this work, we focus on the Partial Constraint Satisfaction Problem (PCSP) over control-flow graphs (CFGs) of programs. PCSP serves as a generalization of the well-known Constraint Satisfaction Problem (CSP). In the CSP framework, we define a set of variables, a set of constraints, and a finite domain that encompasses all possible values for each variable. The objective is to assign a value to each variable in such a way that all constraints are satisfied. In the graph variant of CSP, an underlying graph is considered and we have one variable corresponding to each vertex of the graph and one or several constraints corresponding to each edge. In PCSPs, we allow for certain constraints to be violated at a specified cost, aiming to find a solution that minimizes the total cost. Numerous classical compiler optimization tasks can be framed as PCSPs over control-flow graphs. Examples include Register Allocation, Lifetime-optimal Speculative Partial Redundancy Elimination (LOSPRE), and Optimal Placement of Bank Selection Instructions. On the other hand, it is well-known that control-flow graphs of structured programs are sparse and decomposable in a variety of ways. In this work, we rely on the Series-Parallel-Loop (SPL) decompositions as introduced by~\cite{RegisterAllocation}. Our main contribution is a general algorithm for PCSPs over SPL graphs with a time complexity of \(O(|G| \cdot |D|^6)\), where represents the size of the control-flow graph. Note that for any fixed domain this yields a linear-time solution. Our algorithm can be seen as a generalization and unification of previous SPL-based approaches for register allocation and LOSPRE. In addition, we provide experimental results over another classical PCSP task, i.e. Optimal Bank Selection, achieving runtimes four times better than the previous state of the art.
Paper Structure (36 sections, 14 equations, 9 figures)

This paper contains 36 sections, 14 equations, 9 figures.

Figures (9)

  • Figure 1: Atomic SPL graphs: $A_\epsilon$ (left), $A_{\texttt{break}}$ (middle), and $A_{\texttt{continue}}$ (right) RegisterAllocation.
  • Figure 2: Two examples of the series operation $\otimes$, taken from RegisterAllocation.
  • Figure 3: An example of the parallel operation $\oplus$RegisterAllocation.
  • Figure 4: An example of the loop operation $^\circledast$RegisterAllocation.
  • Figure 5: A program $P$ (top left), its parse tree (top right), the corresponding parse tree of $G = \textsf{cfg}(P)$ (bottom left) and the graph $G = \textsf{cfg}(P)$ (bottom right) RegisterAllocation. The edges of the graph are labeled according to the statements in the program.
  • ...and 4 more figures