-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Arm64/Sve: Remove unwanted insScalableOpts and instructions #103620
Conversation
@dotnet/arm64-contrib @TIHan @amanasifkhalid PTAL |
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
src/coreclr/jit/emitarm64.cpp
Outdated
@@ -4252,9 +4252,15 @@ void emitter::emitIns_Mov( | |||
{ | |||
if (isPredicateRegister(dstReg) && isPredicateRegister(srcReg)) | |||
{ | |||
assert(insOptsNone(opt)); | |||
if (insOptsNone(opt)) |
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 code is odd. This is because for predicates we always use INS_OPTS_SCALABLE_B for a mov, so the passed in opt
value doesn't matter ?
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.
Yes, so basically, this code operates just on INS_OPTS_SCALABLE_B
(and we added single test for that). For other places, if we have to pass INS_OPTS_SCALABLE_B
if register types are predicate feels like an overhead, so instead this code expects it to be NONE, in which case it will set the options to INS_OPTS_SCALABLE_B
.
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.
Would something like this work?
if (!insOptsNone(opt))
{
assert(opt == INS_OPTS_SCALABLE_B);
}
opt = INS_OPTS_SCALABLE_B;
I think that shape makes it clearer the if-statement is debug-only code, and ensures opt
is always INS_OPTS_SCALABLE_B
even if we don't have asserts on to catch improper handling.
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.
assert(opt == INS_OPTS_SCALABLE_B || insOptsNone(opt));
opt = INS_OPTS_SCALABLE_B;
?
@@ -1926,22 +1926,17 @@ void emitter::emitInsSve_R_R(instruction ins, | |||
assert(insOptsScalableStandard(opt)); | |||
return emitInsSve_R_R_I(INS_sve_pmov, attr, reg1, reg2, 0, opt, sopt); | |||
} | |||
if (sopt == INS_SCALABLE_OPTS_TO_PREDICATE) |
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.
Are there any functions we can remove sopt
completely?
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.
Not sure I understand. Can you please elaborate?
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 think Alan means are there any emitInsSve_*
methods that no longer need the sopt
parameter, because it's only checking that sopt
is INS_SCALABLE_OPTS_NONE
? emitInsSve_R_R
seems close to that, though we still check sopt
with insScalableOptsWithVectorLength
at the end of the method.
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.
Ah ok. Thanks @amanasifkhalid for clarifying. I didn't check, but can do it as a follow-up work.
src/coreclr/jit/gentree.cpp
Outdated
return true; | ||
// For some variants, the address is in vector. | ||
// Return false for such cases. | ||
return false; |
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 was returning true
here because I assumed we needed to track the fact there were addresses in Op2
. Is it safe to not track that?
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.
Re-reading, the OperIsMemoryLoad()
contract is to return true if this intrinsic may throw NullReferenceException
of address is "null". Now, for certain non-faulting intrinsics, it should return false
, but for Gather*
, this should return true
.
Fixed 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.
the OperIsMemoryLoad() contract is to return true if this intrinsic may throw NullReferenceException of address is "null".
That was the part I wasn't sure of.
Happy with the new version.
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, thanks!
/ba-g timeout issues |
Now that we have separate predicate and vector registers, remove all the unnecessary
insScalableOpts
entries and fix some unit tests. Also included a fix forGatherVector*
which currently AVs.They are all passing: https://gist.github.com/kunalspathak/797640e95a3f3edfd67ef107c19389ae
Also ran the unit tests and they are all working.
Fixes: #103606