-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
x64: Mask shift amounts for small types #4752
Conversation
Subscribe to Label Action
This issue or pull request has been labeled: "cranelift", "cranelift:area:x64", "isle"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
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.
This looks great to me!
I think this is also going to invalidate all the fuzzer issues that were reported today, since it changes the input format for the fuzzer, not sure how good OSS-Fuzz is with these situations. |
ab87ae9
to
94bd34b
Compare
You're right, Afonso. Could you remove the function-generator changes from this PR for now while we sort out all those issues? |
They are fixed. But we had a bunch of fuzzgen issues come in, and we don't want to accidentaly mark them as fixed
The rustfmt CI failure looks like a transient network issue. Let's re-run it after the rest of the jobs complete. |
if let Some(c) = inputs.constant { | ||
let mask = 1_u64.checked_shl(ty.bits()).map_or(u64::MAX, |x| x - 1); | ||
return Imm8Gpr::new(Imm8Reg::Imm8 { | ||
imm: (c & mask) as u8, | ||
}) | ||
.unwrap(); | ||
} | ||
|
||
Imm8Gpr::new(Imm8Reg::Reg { | ||
reg: self.put_in_regs(val).regs()[0], | ||
}) | ||
.unwrap() |
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 want to see if I understand why this PR fixes this issue. Could you confirm or correct my interpretation?
It looks like there are two bugs in put_masked_in_imm8_gpr
, and I gather that these bugs aren't present in the similar-looking ISLE rules.
If the shift amount is not defined by an iconst
instruction, then this function doesn't mask it at all...? The only thing it does is, if the shift amount needs two registers because it's an i128, then it only takes the lower 64-bit register.
If it is a constant, then it's masked by (1 << ty.bits()) - 1
. So for an 8-bit LHS, the shift amount is used modulo 256, but it's actually supposed to be modulo 8. For a 64-bit LHS the shift amount is effectively not masked at all. By contrast, the shift_mask
function just returns ty.lane_bits() - 1
so it gets this right. (And also handles vector types correctly, I guess?)
I guess the reason these bugs weren't obvious sooner is that wasm only uses i32 and i64 types, and x86 already masks 32-bit and 64-bit shift amounts to 5 and 6 bits, respectively. But narrower 8-bit and 16-bit shifts are also masked to 5 bits on x86, so those were wrong.
Now that I think I understand this, I'm wondering how hard it is in ISLE to avoid emitting the and
instruction when the type is i32 or i64.
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 the shift amount is not defined by an iconst instruction, then this function doesn't mask it at all...?
Yes, the source of the issue I was trying to fix was exactly this.
It looks like there are two bugs in put_masked_in_imm8_gpr, and I gather that these bugs aren't present in the similar-looking ISLE rules.
Wow! I was just trying to fix the unmasked non const one, didn't actually realize that the const case didn't do the right thing either!
We should probably add some shift_imm
test cases as well.
Now that I think I understand this, I'm wondering how hard it is in ISLE to avoid emitting the and instruction when the type is i32 or i64.
I think that's a good improvement, i'll push it soon.
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.
And it turns out the const case was also wrong. Great Catch!
Now that `put_masked_in_imm8_gpr` works properly we can simplify rotl/rotr
We now use the general case that is using These were the only uses of |
Very nice work! Good catch on noticing that |
This was reported by @bjorn3 in https://github.com/bjorn3/rustc_codegen_cranelift/pull/1268#issuecomment-1223916783 when we tried to remove the explicit shift amount masking done by
cg_clif
.As a consequence of this fix, #4699 is also fixed, which is nice!
This PR also does some other housekeeping:
i128
shifts in the fuzzeri128-shifts-small-types.clif
runtests and moves them toi128-shifts.clif
i128
one)ishl
/sshr
/ushr
Fixes: #4699
cc: @elliottt