-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
sat-arithmetic: add operator support #9679
Conversation
travisstaloch
commented
Sep 2, 2021
•
edited
Loading
edited
- implements accepted syntax from Saturating arithmetic #1284
- adds initial support for the operators +|, -|, *|, <<|, +|=, -|=, *|=, <<|=
- uses operators in addition to builtins in behavior test
- adds binOpExt() and assignBinOpExt() to AstGen.zig. these need to be audited
TODOS
I'm not sure what needs to be done yet for 3, 4, and 5. Any advice appreciated. |
Here's some advice to get you going-
You can add any functions you need to src/link/C/zig.h, and then in codegen/c.zig you can emit calls to them. This part is pretty fun! I recommend to play with godbolt to test out your saturating arithmetic implementations and see how optimizable they are (the goal would be that most C compilers would be able to optimize them into machine code instructions when available).
Double check your edits to tokenizer.zig. Perhaps try adding some test cases at the bottom of tokenizer.zig (there are a few examples already there you can look at). Something to keep in mind is that tokenizer.zig and tokenizer.cpp are intentionally nearly identical implementations, so your edits to each file should look almost the same.
Not needed for this PR to be merged :) |
bf14b88
to
1659b97
Compare
src/Sema.zig
Outdated
// TODO: audit - not sure if its a good idea to reuse this, adding `opt_extended` param | ||
// FIXME: somehow, rhs of <<| is required to be Log2T. this should accept T | ||
fn analyzeArithmetic( | ||
sema: *Sema, | ||
block: *Scope.Block, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm reusing analyzeArithmetic() by adding an opt_extended
param here. Is this a bad idea?
Also, I can't figure out where the check that rhs of <<|
is a Log2T happens (and how to disable it). It needs to accept T, but currently doesn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have expected this to be in zirShl
, but I did not find it either. You should be able to disable this in stage1, which ensures one does not use too big types for shifting left. I may be wrong, but bigint_shl
might be the function in stage1.
However this sounds to me inconsistent to the behavior of normal shift left and could hide a logical bug.
For prototyping using const/var shlcount = @intcast(Log2Int(@bitSizeOf(var1)), var2) (Log2Int is from math.zig) also does the job.
Why do you think requiring an @intcast for the left-shift is a bad idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, this is how the llvm intrinsics are defined
ee220a8
to
c98f767
Compare
I looked at them on godbolt with clang and gcc, both with -O1. They were all branchless using cmovs except for the gcc signed 64 bit operations have one jump instruction. I'm not super confident in the signed shl impl.
This worked well. I was updating the result instead of the state when in the Thank you for the guildance! Please let me know if you get a chance to look at this again. I've left some TODOs and FIXMEs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some tests and simplification with using maxInt from math.zig.
Changing the behavior to allowing types on right hand side that are not Log2(left hand side) sounds to me inconsistent to the other <<
operations and (from my perspective) can hide logical bugs without crashing/overflowing in tests if one is not cautious.
src/Sema.zig
Outdated
// TODO: audit - not sure if its a good idea to reuse this, adding `opt_extended` param | ||
// FIXME: somehow, rhs of <<| is required to be Log2T. this should accept T | ||
fn analyzeArithmetic( | ||
sema: *Sema, | ||
block: *Scope.Block, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have expected this to be in zirShl
, but I did not find it either. You should be able to disable this in stage1, which ensures one does not use too big types for shifting left. I may be wrong, but bigint_shl
might be the function in stage1.
However this sounds to me inconsistent to the behavior of normal shift left and could hide a logical bug.
For prototyping using const/var shlcount = @intcast(Log2Int(@bitSizeOf(var1)), var2) (Log2Int is from math.zig) also does the job.
Why do you think requiring an @intcast for the left-shift is a bad idea?
This is how @shlWithSaturation is defined:
|
4a8f2c5
to
c7c5487
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not fully looked at the review but I am about to go do something else so I wanted to give you something to work with in the meantime-
I'm confident this was just a glitch. Last few commits have passed CI |
1439d02
to
6785552
Compare
- adds initial support for the operators +|, -|, *|, <<|, +|=, -|=, *|=, <<|= - uses operators in addition to builtins in behavior test - adds binOpExt() and assignBinOpExt() to AstGen.zig. these need to be audited
- modify AstGen binOpExt()/assignBinOpExt() to accept generic extended payload T - rework Sema zirSatArithmetic() to use existing sema.analyzeArithmetic() by adding an `opt_extended` parameter. - add airSatOp() to codegen/c.zig - add saturating functions to src/link/C/zig.h
- set state rather than result.tag in tokenizer.zig - add test to tokenizer.zig for <<, <<|, <<|=
- similar to Sema.analyzeArithmetic but uses accepts Zir.Inst.Extended.InstData - missing support for Pointer types and comptime arithmetic
- not necessary as we are testing the operators
* Remove the builtins `@addWithSaturation`, `@subWithSaturation`, `@mulWithSaturation`, and `@shlWithSaturation` now that we have first-class syntax for saturating arithmetic. * langref: Clarify the behavior of `@shlExact`. * Ast: rename `bit_shift_left` to `shl` and `bit_shift_right` to `shr` for consistency. * Air: rename to include underscore separator with consistency with the rest of the ops. * Air: add shl_exact instruction * Use non-extended tags for saturating arithmetic, to keep it simple so that all the arithmetic operations can be done the same way. - Sema: unify analyzeArithmetic with analyzeSatArithmetic - implement comptime `+|`, `-|`, and `*|` - allow float operands to saturating arithmetic * `<<|` allows any integer type for the RHS. * C backend: fix rebase conflicts * LLVM backend: reduce the amount of branching for arithmetic ops * zig.h: fix magic number not matching actual size of C integer types
9761f93
to
5467582
Compare