compiler: Own SSA cache storage during initialization

e0736f02d493de9e2dd9b0ab1280e582f6ab23e372fb067d73b70c74e6235432
Alexis Sellier committed ago 1 parent c3a1a901
lib/std/lang/lower.rad +4 -2
2171 2171
/// be switched to via [`switchToBlock`] before instructions can be emitted.
2172 2172
unsafe fn createBlock 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, labelBase: *[u8]) -> BlockId throws (LowerError) where 'arena: 'phase, 'phase: 'function {
2173 2173
    let label = try nextLabel(self, labelBase);
2174 2174
    let id = BlockId(self.blockData.len);
2175 2175
    let varCount = self.localCount;
2176 -
    let vars = try! alloc::allocRawSlice(self.arena, @sizeOf(?il::Val), @alignOf(?il::Val), varCount) as *unsafe mut [?il::Val];
2176 +
    let vars = try! alloc::allocSlice(
2177 +
        self.arena, @sizeOf(?il::Val), @alignOf(?il::Val), varCount
2178 +
    ) as *mut [?il::Val];
2177 2179
2178 2180
    for i in 0..varCount {
2179 2181
        set vars[i] = nil;
2180 2182
    }
2181 2183
    self.blockData.append(BlockData {
2183 2185
        params: &mut [],
2184 2186
        paramVars: &mut [],
2185 2187
        instrs: &mut [],
2186 2188
        locs: &mut [],
2187 2189
        preds: &mut [],
2188 -
        vars,
2190 +
        vars: (&mut vars[..]) as *unsafe mut [?il::Val],
2189 2191
        sealState: Sealed::No,
2190 2192
        loopDepth: self.loopDepth,
2191 2193
    }, alloc::arenaAllocator(self.arena));
2192 2194
2193 2195
    return id;
test/tests/ssa.block.locals.rad added +52 -0
1 +
//! returns: 0
2 +
3 +
/// Select different local bindings while retaining outer and loop values.
4 +
fn run(limit: u32, selected: bool) -> u32 {
5 +
    let outer: u32 = 11;
6 +
    let mut result: u32 = 0;
7 +
    for index in 0..limit {
8 +
        let current = outer + index;
9 +
        if selected {
10 +
            let outer = current * 2;
11 +
            let extra = outer + 3;
12 +
            set result += extra;
13 +
        } else {
14 +
            let outer = current * 3;
15 +
            let extra = outer + 5;
16 +
            set result += extra;
17 +
        }
18 +
        assert outer == 11;
19 +
        assert current == 11 + index;
20 +
        match index % 3 {
21 +
            case 0 => {
22 +
                let local = current + 1;
23 +
                set result += local;
24 +
            }
25 +
            case 1 => {
26 +
                let local = current + 2;
27 +
                set result += local;
28 +
            }
29 +
            else => {
30 +
                let local = current + 3;
31 +
                set result += local;
32 +
            }
33 +
        }
34 +
    }
35 +
    return result;
36 +
}
37 +
38 +
/// Compare both branches with a direct arithmetic accumulation.
39 +
@default fn main() -> u32 {
40 +
    for limit in 0..12 {
41 +
        let mut first: u32 = 0;
42 +
        let mut second: u32 = 0;
43 +
        for index in 0..limit {
44 +
            set first += (11 + index) * 3 + 4 + index % 3;
45 +
            set second += (11 + index) * 4 + 6 + index % 3;
46 +
        }
47 +
        assert run(limit, true) == first;
48 +
        assert run(limit, false) == second;
49 +
        assert run(limit, true) == first;
50 +
    }
51 +
    return 0;
52 +
}