-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
x86_64: Implement integer saturating left shifting codegen #22529
base: master
Are you sure you want to change the base?
Conversation
c87f153
to
ebace39
Compare
ebace39
to
ec2df79
Compare
What's the CI error. It seems that I didn't touch that region of code. |
Don't mind that failure -- it's an inconsistent issue which is being debugged as I type this. Once it's fixed, a rebase should solve that error. |
I don't like that this introduces a miscomp, I would rather the backend error on unsupported types rather than silently produce incorrect code. |
@jacobly0 which unsupported types? there is already a compiler error when unsupported type is hit. |
|
ec2df79
to
9494329
Compare
@jacobly0 ahh! Sorry for my mistake and thanks for your careful review! I forgot that negative values need the minimum value to saturate and it seems that the saturating_arithmetic.zig behavior test is not strong enough. The force-push above should solve the error and the check you have given is passing successfully. However, x86 does not have a saturating shifting instruction so we have to emit up to two shifting and two conditional branches, totally ~10 MIR instructions, I doubt if the shl_sat grammar and IR is useful, as it seems to be a pretty rare case. |
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.
Looks good enough to get in the next release, if I don't manage to finish the rewrite before then.
.signed => { | ||
// check the sign of lhs | ||
try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, lhs_mcv, try self.genTypedValue(try self.pt.intValue(lhs_ty, 0))); | ||
const sign_reloc_condbr = try self.genCondBrMir(lhs_ty, .{ .eflags = Condition.g }); |
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.
The ZF is not reliable after genBinOpMir(.{ ._, .cmp }, ..)
, please use a condition that does not depend on it instead.
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 am going to use one more SHR to get the sign bit and pass it directly as condition. Thank you for the catch (:
It seems that airCmp is also using genBinOpMir with cmp and returning eflags conditions. is this intended?
https://github.com/ziglang/zig/blob/5cfcb015033864c769235726975ab9919c217ef9/src/arch/x86_64/CodeGen.zig#L20662-L20663
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.
As you can see here, all conditions depending on ZF are not possible in that code path.
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.
eq
and neq
are also ZF conditions, am I understanding wrong? If they are okay to use, then the current code should be working (the gt
has been replaced by sign bit == 1
), or else the equal condition above this piece of code also needs to be replaced.
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.
Indeed, airShlWithOverflow
is also wrong.
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.
How about hacking genBinOpMir
to emit JCC after each asmRegisterRegister
?
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.
If only it were that simple... I'm sure there exists a jcc that would work for each desired condition, but we don't know the desired condition there.
Either extract the contents of airCmp
into a separate function, or fail if the int is > 64 bits.
9494329
to
0f90ddb
Compare
Simliarly to shl_with_overflow, we first SHL/SAL the integer, then SHR/SAR it back to compare if overflow happens. If overflow happened, set result to the upper limit to make it saturating. Bug: ziglang#17645
0f90ddb
to
0d040ec
Compare
Simliarly to shl_with_overflow, we first SHL/SAL the integer, then SHR/SAR it back to compare if overflow happens.
If overflow happened, set result to the upper limit to make it saturating.
Theoretically, if the left shifting instruction is lowered as a single SHL/SAL opcode, and the left operand fits into a register (so no truncation is needed), the CF flag can be used to check for overflow. However the optimization is not implemented right now (for my laziness).
Bug: #17645