-
Notifications
You must be signed in to change notification settings - Fork 4.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
imul instruction size misprediction #57179
Conversation
@dotnet/jit-contrib |
Can someone take a look so we can get this in before next week? @echesakov or @tannergooding |
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.
Changes LGTM for a quick fix.
We should log an issue to track fixing this properly (likely by centralizing the size computation logic so we don't risk duplicating checks, etc).
Sure, I have created #57368 and included links to multiple issues that talks about it. |
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 reviewed it and it looks OK
(and better than before)
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.
LGTM
no asmdiff in benchmarks/libraries. Minor improvements in coreclr_tests:
|
During emitting
imul
, we wrongly predict the size of instruction as16 bytes
whereas it should be just15 bytes
(which is debatable, see below) comprising of 1 byteREX prefix
+ 1 byteopcode
+ 1 bytemodR/M
+ 4 bytesRIP-relative displacement
+ 4 bytes ofimmediate
. Last row in https://www.felixcloutier.com/x86/imul table.Now as per Intel docs:
which means the RIP immediate above should be just 4-bytes and the instruction size should be just
11 bytes
. But inemitInsSizeCV()
we have it calculated asvalSize == 8
.When calculating the size, it seems that we double calculate the
REX prefix size
, once inruntime/src/coreclr/jit/emitxarch.cpp
Line 2612 in 53a1ddc
and then further in
emitInsSize() -> emitGetPrefixSize()
inruntime/src/coreclr/jit/emitxarch.cpp
Lines 1188 to 1191 in 53a1ddc
Because of above conditions, we end up with size of
16 bytes
but when we save the size ininstrDesc
, we cap it to15 bytes
because of #12840.runtime/src/coreclr/jit/emit.h
Lines 887 to 896 in d20606c
Further, we account the wrong size of instruction
16 bytes
instead of the one we have inid->CodeSize()
of15 bytes
.runtime/src/coreclr/jit/emitxarch.cpp
Lines 5596 to 5601 in 53a1ddc
Due to this, the
emitCurIGSize
and henceig->igOffs
becomes off by 1 byte and during emitting, we think that we just over-estimated the instruction by 4 bytes = 15 (id->CodeSize()
) - 11 (actual encoding size
) but the offsets were calculated assuming the instruction size of16 bytes
. That difference of 1 byte leads to an assert in #57041.To summarize, there are 3 problems:
This is fixed by tracking if we have already counted REX prefix size and if yes, do not include it in
emitGetPrefixSize()
.valSize > 4
for RIP-immediate . I have added an assert in this draft PR to see if there are any instructions other thanmov
for which we getvalSize > 4
other wise, we should just update this code to capvalSize
to 4 bytes.This is fixed by making sure we cap
valSize
to 4 bytes for all instructions exceptmov
.This problem should never arise because I have removed the code that caps
sz
to 15 bytes and added an assert forsz <= 15
. With that, it will be safe to useemitCurIGsize += sz
.Thanks @tannergooding for pointing me to manuals.
Fixes: #12840, #57041