-
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: Incorrect codegen for f32x4.abs v128.not #3327
Comments
This is another module which I believe is broken: (module
(func (;0;) (result i32)
v128.const i32x4 0xffffffff 0x80bfffff 0x80bf0a0a 0x80bf0a0a
f64x2.promote_low_f32x4
v128.not
v128.not
v128.not
v128.not
v128.not
v128.not
v128.not
v128.const i32x4 0 0 0 0
f64x2.gt
v128.not
i64x2.bitmask)
(export "" (func 0))) It still has |
cc @jlb6740, could you take a look? |
Another one cropped up today which I'm lumping in with this one, but recording to ensure we can test the fix: (module
(type (;0;) (func (param i32) (result i32)))
(func (;0;) (type 0) (param i32) (result i32)
local.get 0
i32x4.splat
f64x2.abs
v128.not
i64x2.bitmask)
(memory (;0;) 1 1)
(export "" (func 0))
(export "1" (func 0))) |
My goal was to poke around at bytecodealliance#3327 and see if translation to ISLE would fix the bug. The answer turned out to be yes! The underlying bug in the original lowering code was the implementation of `Bnot` where in an attempt to create an all-ones value register floating point types input to `v128.not` were not handled correctly. It turns out that wtihin `f32x4.abs` there was already code for creating an all-ones value and this same logic which specially handled floats just wasn't accidentally also part of the `v128.not` implementation. By unifying these two (and translating to ISLE at the same time) the original bug is fixed. Closes bytecodealliance#3327
I've got a fix for this when ISLE lands |
@alexcrichton I think I see the issue here. The abs lowering:
leaves xmm1 with:
takes a register (in this case xmm1) and then tries to make it have the float value 1. It does this in order to then do an xorps to flip the bits. The problem is that the abs sequence has left the register xmm1 with an invalid float so cmpeqps doesn't return as expected. If we do this on another register that happens to have a valid float value then this sequence would work, but in our case it doesn't. The fix seems to be to do a logical xor on the float register before doing the cmpeqps. This logical xor correctly zeros the register allowing the cmpeqps to return as desired. Maybe a another instruction sequence exist but will push this lowering for not:
to resolve this bug. |
@alexcrichton btw .. just read your comment on alexcrichton@f7ccaf2 and indeed the fabs/fneg lowering implements this correctly. The bnot implementation apparently didn't foresee this issue. I created a jist here that may be useful for debugging similar bugs: https://gist.github.com/jlb6740/33e77c7f32beb99bdc392ff456fbc864 |
Fixed in #3517 |
This was my first attempt at transitioning code to ISLE to originally fix bytecodealliance#3327 but that fix has since landed on `main`, so this is instead now just porting a few operations to ISLE. Closes bytecodealliance#3336
Found via fuzzing this module:
yields:
when it should print
u128::MAX
.The disassembly of this function is:
I don't for sure know what's going on here with each individual instruction, but this sort of looks like a register allocator issue? I'm not sure what the second
xorps
is doing there with those registers. If this is a register allocator thing it may or may not be related to #3216The text was updated successfully, but these errors were encountered: