-
Notifications
You must be signed in to change notification settings - Fork 3
[Model] MinimumCodeGenerationParallelAssignments #903
Description
Motivation
MINIMUM CODE GENERATION FOR PARALLEL ASSIGNMENTS (P298) from Garey & Johnson, A11 PO6. Given a set of simultaneous variable assignments, find an execution ordering that minimizes the number of backward dependencies (cases where a variable is overwritten before a later assignment reads its old value). This models the problem of sequencing parallel assignment statements in compilers when all assignments should conceptually happen simultaneously.
Associated reduction rules:
- As target: R319 (FEEDBACK VERTEX SET →)
- Connections (beyond G&J):
- Closely related to MinimumFeedbackVertexSet: backward dependencies correspond to back-arcs in the dependency graph
- Applications: parallel assignment scheduling in compilers, register renaming, SSA destruction
Definition
Name: MinimumCodeGenerationParallelAssignments
Reference: Garey & Johnson, Computers and Intractability, A11 PO6
Mathematical definition:
INSTANCE: A set V of variables, a set of assignments A_1, A_2, ..., A_m where each A_i has the form "v_i ← op(B_i)" with v_i ∈ V and B_i ⊆ V being the set of variables read by the assignment.
OBJECTIVE: Find an ordering (permutation π) of the assignments that minimizes the number of backward dependencies. A backward dependency occurs when variable v_{π(i)} (written by the i-th executed assignment) appears in B_{π(j)} (read by the j-th executed assignment) for some j > i — i.e., the old value of v_{π(i)} is needed by a later assignment but has already been overwritten.
Variables
- Count: m (one variable per assignment, representing its position in the execution order)
- Per-variable domain: {0, 1, ..., m-1} (position in the permutation)
- Meaning: A permutation π of assignments. The cost is the number of pairs (i, j) with i < j such that v_{π(i)} ∈ B_{π(j)}.
Schema (data type)
Type name: MinimumCodeGenerationParallelAssignments
Variants: (none)
| Field | Type | Description |
|---|---|---|
num_variables |
usize |
Number of variables |
assignments |
Vec<(usize, Vec<usize>)> |
Each assignment (target_var, read_vars): v_i ← op(B_i) |
Complexity
- Decision complexity: NP-complete (Sethi, 1975; transformation from FEEDBACK VERTEX SET).
- Best known exact algorithm: O*(num_assignments! ) brute-force over all permutations, or equivalently O*(2^num_assignments) via dynamic programming.
- Restrictions: NP-complete even when |B_i| ≤ 2 for all assignments.
- References:
- R. Sethi (1975). "Complete Register Allocation Problems." SIAM Journal on Computing, 4(3), pp. 226–248.
Extra Remark
Full book text:
INSTANCE: Set V of variables, collection of assignments A_i: "v_i ← op(B_i)" where B_i ⊆ V, positive integer K.
QUESTION: Is there an ordering of the assignments such that the number of backward dependencies (where v_{π(i)} ∈ B_{π(j)} for some j > i) is at most K?
Reference: [Sethi, 1975]. Transformation from FEEDBACK VERTEX SET.
Comment: NP-complete even with |B_i| ≤ 2.
Note: The original G&J formulation is a decision problem with threshold K. We use the equivalent optimization formulation: minimize the number of backward dependencies.
How to solve
- It can be solved by (existing) bruteforce. (Enumerate all m! permutations of assignments and count backward dependencies for each; return the minimum.)
- It can be solved by reducing to integer programming.
- Other: Reduction to minimum feedback arc set in the dependency digraph.
Example Instance
Variables: V = {a, b, c, d} (indices 0, 1, 2, 3)
Assignments:
- A_0: a ← op(b, c) — writes a (index 0), reads {b, c} (indices {1, 2})
- A_1: b ← op(a) — writes b (index 1), reads {a} (index {0})
- A_2: c ← op(d) — writes c (index 2), reads {d} (index {3})
- A_3: d ← op(b, c) — writes d (index 3), reads {b, c} (indices {1, 2})
Dependency graph: An arc from A_i to A_j exists when v_i ∈ B_j (A_i's target variable is read by A_j):
- A_0 → A_1 (a written by A_0, read by A_1)
- A_1 → A_0 (b written by A_1, read by A_0)
- A_1 → A_3 (b written by A_1, read by A_3)
- A_2 → A_0 (c written by A_2, read by A_0)
- A_2 → A_3 (c written by A_2, read by A_3)
- A_3 → A_2 (d written by A_3, read by A_2)
Cycles: A_0 ↔ A_1 (mutual dependency on a and b), A_2 ↔ A_3 (mutual dependency on c and d).
Optimal ordering π = (A_0, A_2, A_3, A_1):
- Position 1: A_0 writes a → a ∈ B_{A_1} (position 4) → 1 backward dep
- Position 2: A_2 writes c → c ∈ B_{A_3} (position 3) → 1 backward dep
- Position 3: A_3 writes d → d ∉ B_{A_1} → 0
- Position 4: A_1 writes b → no later assignments → 0
- Total: 2 backward dependencies ✓
Why 1 backward dependency is impossible: The two cycles A_0 ↔ A_1 and A_2 ↔ A_3 are independent. Each cycle forces at least 1 backward dependency (in any ordering, one member of the cycle must come before the other). Since there are 2 independent cycles, the minimum is 2.
Suboptimal ordering π = (A_2, A_0, A_3, A_1):
- A_2 writes c, read by A_0 (pos 2) and A_3 (pos 3) → 2 backward deps
- A_0 writes a, read by A_1 (pos 4) → 1 backward dep
- Total: 3 backward dependencies
Expected Outcome
Optimal value: Min(2) — the minimum number of backward dependencies is 2. Out of 24 permutations: 6 achieve 2 deps, 12 have 3 deps, and 6 have 4 deps, giving 3 distinct objective values.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status