Skip to content

fix: resolve phi swap cycles in parallel copy lowering #140#145

Open
BibhabenduMukherjee wants to merge 2 commits into
rux-lang:devfrom
BibhabenduMukherjee:fix-140
Open

fix: resolve phi swap cycles in parallel copy lowering #140#145
BibhabenduMukherjee wants to merge 2 commits into
rux-lang:devfrom
BibhabenduMukherjee:fix-140

Conversation

@BibhabenduMukherjee

Copy link
Copy Markdown

Introduce a topological sort and cycle-breaking algorithm for phi move lowerings in both the textual assembly (Asm) and binary machine code (Rcu) generators. This resolves silent value corruption when two or more phi nodes form a circular swap dependency. Cycle-breaking is achieved by pushing the cycle-start value onto the machine stack and restoring it after walking the copy cycle.

Example of Failure

Consider a block transition that requires a register/stack slot swap between two variables a (located at [rbp - 8]) and b (located at [rbp - 16]):

Move 1: a = b (src: b, dst: a)
Move 2: b = a (src: a, dst: b)

Because the previous implementation of EmitPhiMoves iterated sequentially, it generated the following instructions:

; --- Move 1: a = b ---
mov rax, qword [rbp - 16]   ; Load b's value into rax
mov qword [rbp - 8], rax    ; Store rax into a's slot
                            ; [rbp - 8] (a) is now overwritten with b's value. 
                            ; The original value of a is permanently lost!

; --- Move 2: b = a ---
mov rax, qword [rbp - 8]    ; Load a's value (which is now b's value!) into rax
mov qword [rbp - 16], rax   ; Store rax into b's slot

Tests & Verification

We registered a new regression test package, Tests/PhiSwap, containing a loop-based Fibonacci accumulator swap which naturally generates parallel-copy cycles during lowering.

Test Source (Tests/PhiSwap/Src/Main.rux):

func FibLoop(n: int) -> int {
    var a: int = 0;
    var b: int = 1;
    var i: int = 0;
    while i < n {
        let t: int = a + b;
        a = b;   // triggers parallel-copy swap
        b = t;
        i = i + 1;
    }
    return a;
}

func Main() -> int {
    if FibLoop(0) != 0   { return 1; }
    if FibLoop(1) != 1   { return 2; }
    if FibLoop(5) != 5   { return 3; }
    if FibLoop(10) != 55  { return 4; }
    if FibLoop(15) != 610 { return 5; }
    return 0;
}

Verification Results:

CTest Suite: The new test was successfully registered under CMake and ran as part of CTest:

Start 10: PhiSwap
10/14 Test #10: PhiSwap ..........................   Passed    2.73 sec

Executable Exit Code: Running the compiled debug binary directly exits with status code 0, confirming that the Fibonacci numbers computed correctly without any variable corruption:

Introduce a topological sort and cycle-breaking algorithm for phi move lowerings in both the textual assembly (Asm) and binary machine code (Rcu) generators. This resolves silent value corruption when two or more phi nodes form a circular swap dependency. Cycle-breaking is achieved by pushing the cycle-start value onto the machine stack and restoring it after walking the copy cycle.

Added a new regression test package (Tests/PhiSwap) verifying correctness.
@spatulari spatulari requested a review from pascalecu June 13, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant