#fix remainder loop of simd program

1 messages · Page 1 of 1 (latest)

buoyant karma
#

essentially i want to express the program below, but in zig

void foo(unsigned *);

int square(unsigned num, unsigned *d) {
    switch (num % 8) {
        case 7: foo(d++);
        case 6: foo(d++);
        case 5: foo(d++);
        case 4: foo(d++);
        case 3: foo(d++);
        case 2: foo(d++);
        case 1: foo(d++);
        case 0:;
    }
}
```https://godbolt.org/z/qfbMv6s39 with codegen similar to this (obv foo would be something else)
broken ridge
#

because i would be incredibly surprised if it is

#

it's a cleanup loop, it's specifically designed to be the slow bit

#

a few extra jumps isn't going to make much difference

median night
buoyant karma
#

thanks!

buoyant karma
#

doesnt "actually" matter

buoyant karma
broken ridge
#

that's fair, but i doubt this is actually even noticeable

#

there's a reason duff's device has mostly died out ^^'

buoyant karma
#

although i guess i can just use extern C

#

right?

#

at least a lot better than using inline asm

broken ridge
#

you could yeah, but honestly i would just use a loop

#

you won't even be able to see the difference

buoyant karma
#

i expect it not to make a difference

#

i just want to see it with my own eyes

broken ridge
#

it's entirely possible the loop version will actually be slightly faster due to smaller code size, but like it'll probably be overshadowed by sampling noise either way

median night
#

Here's an attempt to trick it by using 2 inline loops and a comptime function. I managed to get fallthrough code generated, but it also does some extra operations due to the inline function.
https://godbolt.org/z/8chn5MKna

#

Guess the extra ops aren't due to the inline function but the inline for loops as inlining the 2 inlines together also produces the same extra mov operations. :(
https://godbolt.org/z/7Y5ozTfTd

buoyant karma
#

i think i got it to work!

#
extern fn foo(a: [*]u8) void;

fn make_func(comptime T: type, comptime N: comptime_int) type {
    @setEvalBranchQuota(1 << 20);
    return struct {
        fn call(a: [*]T) void {
            if (N > 0) {
                foo(a);
                @call(.never_inline, make_func(T, N - 1).call, .{a + 1});
            }
        }
    };
}


export fn bar(a: [*]u8, n: usize) void {
    @setEvalBranchQuota(1 << 20);
    inline for (0..8) |i| {
        if (i == n) {
            make_func(u8, i).call(a);
        }
    }
}
```its not pretty
#

and it doesnt work at comptime

#

but it basically does what i want

#

unfortunately theres still pushes and pops and jumps

#

but oh well

#

nvm cant get rid of those can you

median night
#

Doesn't it do jump?

median night
#

It does fall through though.

buoyant karma
#

and it doesnt have the fallthrough which sucks

#

but no obvious up front overhead

#

ill just have to measure