afonso360 opened PR #3056 from aarch64-fix-overflow-imm
to main
:
When encoding constants as immediates into an RSE Imm12 instruction we need to take special care to check if the value that we are trying to input does not overflow its type when viewed as a signed value. (i.e. iconst.i8 200)
We cannot both put an immediate and sign extend it, so we need to lower it into a separate reg, and emit the sign extend into the instruction.
For more details see the cg_clif bug report.
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
bjorn3 submitted PR review.
bjorn3 created PR review comment:
On CI:
thread 'worker #1' panicked at 'attempt to subtract with overflow', cranelift/codegen/src/isa/aarch64/lower.rs:450:42
afonso360 updated PR #3056 from aarch64-fix-overflow-imm
to main
.
afonso360 submitted PR review.
afonso360 created PR review comment:
Oops, should be fixed.
cfallin submitted PR review.
cfallin submitted PR review.
cfallin created PR review comment:
This feels somehow like the wrong place to be handling this. IMHO,
iconst.i8 200
should be rejected by the CLIF validator, because the given constant value is out-of-range for thei8
type. Instead we're saying here that we should implement a wrapping behavior, but then we're only doing it in one backend (so then really we should address it in all backends instead).I'm curious what others think, but to me this seems like a weird corner of IR semantics that is safer to define as "disallowed"...
cfallin created PR review comment:
Can we just do this as:
let is_negative = i.bits & (1 << (out_ty_bits - 1)) != 0
(i.e., check the MSB / sign bit)?
cfallin submitted PR review.
cfallin created PR review comment:
(Nevermind this, resolving comment.)
cfallin submitted PR review.
cfallin submitted PR review.
bjorn3 submitted PR review.
bjorn3 created PR review comment:
iconst.i8 0xff00
should result in the non-negative value 0. There is no guarantee that the immediate is either zero or sign extended. Only the n least significant bits should be considered for an n bit big type.
cfallin submitted PR review.
cfallin created PR review comment:
For clarity, @bjorn3, are you referring to the original or the suggested change? I think that checking the MSB only (
1 << 7
in thei8
case) will correctly indicate thaticonst.i8 0xff00
is non-negative when masked to the proper width; whereas thebits > ty_signed_max
logic will indicate it is negative.
bjorn3 submitted PR review.
bjorn3 created PR review comment:
With your version it is ok, though I think you misplaced a paren. (
- 1))
instead kf) -1)
)
bjorn3 edited PR review comment.
bjorn3 edited PR review comment.
afonso360 updated PR #3056 from aarch64-fix-overflow-imm
to main
.
afonso360 submitted PR review.
afonso360 created PR review comment:
Can we just do this as: let is_negative = i.bits & (1 << (out_ty_bits - 1)) != 0 (i.e., check the MSB / sign bit)?
Had to change it slightly because it was underflowing in
out_ty_bits
.
iconst.i8 0xff00
should result in the non-negative value 0This one I feel like we should forbid? It feels like malformed input.
cfallin submitted PR review.
cfallin created PR review comment:
iconst.i8 0xff00 should result in the non-negative value 0
This one I feel like we should forbid? It feels like malformed input.
Hmm, this is actually interesting: in the absence of signedness (until use), there are two possible ranges (-128..127 or 0..255 in the
i8
case). If we allow the union of these, we have a 1.5*2^N-sized range, which is a little weird, but makes some sense. And, while it shouldn't be authoritative for our case, I was curious and just checked whatwat2wasm
does: it accepts exactly that range in the analogous case (I testedi32.const
with -2^31..2^32-1), but roundtrips the values as signed unconditionally.So, this feels like a reasonable behavior to me: we should validate in the CLIF validator that const values are in either signed or unsigned range for the type.
This can be a followup fix, though; no need to solve it here.
With your version it is ok, though I think you misplaced a paren. (- 1)) instead of ) -1))
It's actually inside the paren correctly, I think: we want the next-lower power of two (bit 7 for an i8), not an all-ones mask. I think @afonso360's latest commit got this right fwiw.
afonso360 updated PR #3056 from aarch64-fix-overflow-imm
to main
.
afonso360 created PR review comment:
This can be a followup fix, though; no need to solve it here.
Let me create an issue for this
afonso360 submitted PR review.
cfallin created PR review comment:
Thanks!
cfallin submitted PR review.
cfallin merged PR #3056.
Last updated: Dec 23 2024 at 12:05 UTC