Code generation regression for inline while

Hello,

While going through the Ziglings, I reached exercise 72 and I got curious about the generated assembly. So, I went ahead and changed the code a bit to check it:

export fn magic() u32 {
    const ops = "+1 +2 +3";

    comptime var value: u32 = 0;
    comptime var i = 0;

    inline while (i < ops.len) : (i += 3) {
        const digit = ops[i + 1] - '0';

        switch (ops[i]) {
            '+' => value += digit,
            else => unreachable,
        }
    }

    return value;
}

To my surprise, in a recent development version, the assembly contained the ops string and a bunch of unnecessary instructions (0.12.0-dev.1768+39a966b0a - Compiler Explorer).
So I checked an older version and indeed the code is as I would expect (0.10.0 - Compiler Explorer).
Can this be a regression?

4 Likes

Yes. Both versions have the answer harcoded (mov eax, 6), but it seems that the newer version forgot to remove the unused movs after it had already computed the answer. I don’t know if the fault is on zig or llvm.

A good next step would be to open an issue on github: Issues · ziglang/zig · GitHub

4 Likes

Until this is fixed you can work around the problem by encapsulating all code in a comptime block:

    return comptime blk: {
        ...
        break :blk value;
    };
3 Likes

Opened https://github.com/ziglang/zig/issues/18186

The link doesn’t seem to work for me.

for me too, how that was possible?

Weird, my account seems to be having a problem. Can someone open it for me please?
Issue text:

(originally reported at Code generation regression for inline while)

Zig Version

0.12.0-dev.1768+39a966b0a

Steps to Reproduce and Observed Behavior

While going through the Ziglings, I reached exercise 72 and I got curious about the generated assembly. So, I went ahead and changed the code a bit to check it:

export fn magic() u32 {
    const ops = "+1 +2 +3";

    comptime var value: u32 = 0;
    comptime var i = 0;

    inline while (i < ops.len) : (i += 3) {
        const digit = ops[i + 1] - '0';

        switch (ops[i]) {
            '+' => value += digit,
            else => unreachable,
        }
    }

    return value;
}

To my surprise, in a recent development version (0.12.0-dev.1768+39a966b0a), the generated assembly contained the ops string and a bunch of unnecessary instructions (Compiler Explorer)

Expected Behavior

I expected the generated code to be similar to version 0.10.0 (Compiler Explorer)

1 Like

I opened it for you here: Code generation regression for inline while · Issue #18187 · ziglang/zig · GitHub

What is your github handle so I can mention you as the original author?

2 Likes

Thank you. It is https://github.com/rewot70545, but I can’t see it if not logged in :sweat_smile:
Already contacted support

1 Like

Cool - since that link is broken right now, I just have you mentioned by username in the first comment on the issue. When you get your account back up, you may want to track that issue so you can reply to questions they may have.

2 Likes