compiler: Grow initialized SSA argument storage

c3a1a901e5072c1d6b9e0fe6686c3e55e1b39279b883c3c31e2305f2b7b8e027
Alexis Sellier committed ago 1 parent 05d04410
lib/std/lang/lower.rad +5 -7
3198 3198
/// Grow an args array to hold at least the given capacity.
3199 3199
unsafe fn growArgs 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, args: *unsafe mut [il::Val], capacity: u32) -> *unsafe mut [il::Val] where 'arena: 'phase, 'phase: 'function {
3200 3200
    if args.len >= capacity {
3201 3201
        return args;
3202 3202
    }
3203 -
    let newArgs = try! alloc::allocRawSlice(
3204 -
        self.arena, @sizeOf(il::Val), @alignOf(il::Val), capacity
3205 -
    ) as *unsafe mut [il::Val];
3203 +
    let mut newArgs: *mut [il::Val] = &mut [];
3206 3204
3207 -
    for arg, i in args {
3208 -
        set newArgs[i] = arg;
3205 +
    for arg in args {
3206 +
        newArgs.append(arg, alloc::arenaAllocator(self.arena));
3209 3207
    }
3210 3208
    for i in args.len..capacity {
3211 -
        set newArgs[i] = il::Val::Undef;
3209 +
        newArgs.append(il::Val::Undef, alloc::arenaAllocator(self.arena));
3212 3210
    }
3213 -
    return newArgs;
3211 +
    return (&mut newArgs[..]) as *unsafe mut [il::Val];
3214 3212
}
3215 3213
3216 3214
/// Extract the parameter name from an [`FnParam`] AST node value.
3217 3215
fn paramName(value: *ast::NodeValue) -> *[u8] throws (LowerError) {
3218 3216
    let case ast::NodeValue::FnParam(param) = *value else {
test/tests/ssa.argument.growth.rad added +51 -0
1 +
//! returns: 0
2 +
3 +
/// Keep eight distinct values live across branch and loop edges.
4 +
fn run(limit: u32) -> u32 {
5 +
    let mut a: u32 = 1;
6 +
    let mut b: u32 = 2;
7 +
    let mut c: u32 = 3;
8 +
    let mut d: u32 = 4;
9 +
    let mut e: u32 = 5;
10 +
    let mut f: u32 = 6;
11 +
    let mut g: u32 = 7;
12 +
    let mut h: u32 = 8;
13 +
    for index in 0..limit {
14 +
        let mut step: u32 = 0;
15 +
        match index % 3 {
16 +
            case 0 => set step = 1,
17 +
            case 1 => set step = 3,
18 +
            else => set step = 5,
19 +
        }
20 +
        if index % 2 == 0 {
21 +
            set a += step;
22 +
            set c += step * 3;
23 +
            set e += step * 5;
24 +
            set g += step * 7;
25 +
        } else {
26 +
            set b += step * 2;
27 +
            set d += step * 4;
28 +
            set f += step * 6;
29 +
            set h += step * 8;
30 +
        }
31 +
    }
32 +
    return a + 2*b + 3*c + 4*d + 5*e + 6*f + 7*g + 8*h;
33 +
}
34 +
35 +
/// Compute the weighted sum without carrying the eight separate values.
36 +
fn expected(limit: u32) -> u32 {
37 +
    let mut result: u32 = 204;
38 +
    for index in 0..limit {
39 +
        let step = 1 + (index % 3) * 2;
40 +
        set result += step * (84 if index % 2 == 0 else 120);
41 +
    }
42 +
    return result;
43 +
}
44 +
45 +
/// Check empty, single-iteration, and repeatedly merged control flow.
46 +
@default fn main() -> u32 {
47 +
    for limit in 0..20 {
48 +
        assert run(limit) == expected(limit);
49 +
    }
50 +
    return 0;
51 +
}