Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapping negation of unsigned integers is allowed at runtime but not at comptime #7951

Closed
SpexGuy opened this issue Feb 5, 2021 · 4 comments · Fixed by #8599
Closed

Wrapping negation of unsigned integers is allowed at runtime but not at comptime #7951

SpexGuy opened this issue Feb 5, 2021 · 4 comments · Fixed by #8599
Labels
bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend.
Milestone

Comments

@SpexGuy
Copy link
Contributor

SpexGuy commented Feb 5, 2021

Wrapping negation of unsigned integers is occasionally useful, especially in branchless code. It converts 0 to 0, and 1 to 0xFFFF... . This is perfect for construct masks from booleans. Unfortunately, it doesn't work at comptime. The workarounds here are pretty ugly, here's the simplest one I can come up with that doesn't depend on whether the mask type is signed:

    if (@typeInfo(@TypeOf(.{value})).Struct.fields[0].is_comptime) {
        // Since it's comptime, we don't need this to generate nice code.
        return if (value) ~@as(MaskInt, 0) else 0;
    }

    return -%@intCast(MaskInt, @boolToInt(value));

Wrapping negation should be allowed for sized unsigned integers both at runtime and comptime.

@LemonBoy
Copy link
Contributor

LemonBoy commented Feb 5, 2021

The fix for this is literally shorter than the whole ticket, check out ir_eval_negation_scalar.

@RogierBrussee
Copy link

It does not work at compile time because a comptime_int has infinite precision, so how could it "wrap", or do modular arithmetic.

Of course if it is explicitly sized it can. But then one should be forced to use -% (or if it is about using bool's as masks,

n*@boolToInt(b)

)

This is just one more example of the confusion that arising from treating integers at the same time as integers, modular integers and bitfields. (see #7512)

(speaking of which, MaskInt seems to be a comptime version of b8, b16,..)

@SpexGuy
Copy link
Contributor Author

SpexGuy commented Feb 5, 2021

I'm specifically talking about comptime known tyoed integers, not comptime_int. I think unary minus is already a compile error for unsigned values, but -% should be allowed. No need to use multiplication for a mask, negation works fine and is faster. MaskInt here is any integer type which you want to fill with ones or zeroes, so in a sense it does match your bXX type.

@RogierBrussee
Copy link

I completely agree that for known sized integers a unary -% makes just as much sense as binary -% including for comptime known ones.

The compiler should be able to translate n*@boolToInt(b) to n&(-%@boolToInt(b)) itself and depending on whether you want to to think of the int as an integer or as a bit vector one or the other makes more or less sense.

@SpexGuy SpexGuy added bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend. labels Mar 16, 2021
@Vexu Vexu added this to the 0.9.0 milestone Mar 19, 2021
LemonBoy added a commit to LemonBoy/zig that referenced this issue Apr 23, 2021
@andrewrk andrewrk modified the milestones: 0.9.0, 0.8.0 Apr 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants