compiler: Own block parameter tables

294a5bd7a2534bdbc98e7865aa292d52f0cd98defbce1bfadb18993e7911158c
Alexis Sellier committed ago 1 parent b82d80b2
lib/std/lang/lower.rad +10 -9
530 530
record BlockData {
531 531
    /// Block label for debugging and IL printing.
532 532
    label: *[u8],
533 533
    /// Block parameters for merging values at control flow joins. These
534 534
    /// receive values from predecessor edges when control flow merges.
535 -
    params: *unsafe mut [il::Param],
535 +
    params: *mut [il::Param],
536 536
    /// Variable ids in parameter order. Before sealing, these are the variables
537 537
    /// whose predecessor arguments must be resolved.
538 -
    paramVars: *unsafe mut [u32],
538 +
    paramVars: *mut [u32],
539 539
    /// Instructions accumulated so far. The last instruction should eventually
540 540
    /// be a terminator.
541 541
    instrs: *mut [il::Instr],
542 542
    /// Debug source locations, one per instruction. Only populated when
543 543
    /// debug info is enabled.
2087 2087
    return sym;
2088 2088
}
2089 2089
2090 2090
/// Remove the last block parameter and its associated variable.
2091 2091
/// Used when detecting a trivial phi that can be eliminated.
2092 -
unsafe fn removeLastBlockParam 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, block: BlockId) where 'arena: 'phase, 'phase: 'function {
2093 -
    let blk = getBlockMut(self, block);
2092 +
fn removeLastBlockParam 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, block: BlockId) where 'arena: 'phase, 'phase: 'function {
2093 +
    let blk = &mut self.blockData[*block];
2094 2094
    if blk.params.len > 0 {
2095 2095
        // TODO: Use `pop`?
2096 -
        set blk.params = @sliceOf(blk.params.ptr, blk.params.len - 1, blk.params.cap);
2096 +
        blk.params.delete(blk.params.len - 1);
2097 2097
    }
2098 2098
    if blk.paramVars.len > 0 {
2099 2099
        // TODO: Use `pop`?
2100 -
        set blk.paramVars = @sliceOf(blk.paramVars.ptr, blk.paramVars.len - 1, blk.paramVars.cap);
2100 +
        blk.paramVars.delete(blk.paramVars.len - 1);
2101 2101
    }
2102 2102
}
2103 2103
2104 2104
/// Rewrite cached SSA values for a variable across all blocks, and also
2105 2105
/// rewrite any terminator arguments that reference the provisional register.
2216 2216
unsafe fn sealBlock 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, block: BlockId) throws (LowerError) where 'arena: 'phase, 'phase: 'function {
2217 2217
    let blk = getBlockMut(self, block);
2218 2218
    let case Sealed::No = blk.sealState else {
2219 2219
        return; // Already sealed.
2220 2220
    };
2221 -
    // Keep the current parameter list. Resolution can add more parameters.
2222 -
    let paramVars = blk.paramVars;
2221 +
    // Keep the current parameter count. Resolution can add more parameters.
2222 +
    let paramCount = blk.paramVars.len;
2223 2223
    set blk.sealState = Sealed::Yes;
2224 2224
2225 2225
    // Complete each parameter that was created before sealing.
2226 -
    for varId, paramIdx in paramVars {
2226 +
    for paramIdx in 0..paramCount {
2227 +
        let varId = self.blockData[*block].paramVars[paramIdx];
2227 2228
        try resolveBlockArgs(self, block, Var(varId), paramIdx);
2228 2229
    }
2229 2230
}
2230 2231
2231 2232
/// Seal a block and switch to it.
test/tests/ssa.predecessor.storage.rad +17 -0
20 20
        }
21 21
    }
22 22
    return total + carry + stable;
23 23
}
24 24
25 +
/// Merge identical values beside a changing loop counter.
26 +
fn unchanged(limit: u32) -> u32 {
27 +
    let mut first: u32 = 7;
28 +
    let mut second: u32 = 11;
29 +
    let mut count: u32 = 0;
30 +
    for index in 0..limit {
31 +
        if index % 2 == 0 {
32 +
            set first = 7;
33 +
        } else {
34 +
            set second = 11;
35 +
        }
36 +
        set count += 1;
37 +
    }
38 +
    return first + second + count;
39 +
}
40 +
25 41
/// Compare both branch paths over empty and repeated loop iterations.
26 42
@default fn main() -> u32 {
27 43
    for limit in 0..32 {
44 +
        assert unchanged(limit) == 18 + limit;
28 45
        for choose in [false, true] {
29 46
            let mut total: u32 = 3;
30 47
            let mut carry: u32 = 5;
31 48
            for index in 0..limit {
32 49
                set carry += 7 if choose and index % 2 == 0 else 13;