-
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
JIT ARM64-SVE: Add BP_1A to BQ_2B, BU_2A #99245
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsPart of #94549. Adds the following encodings:
cstool output:
JitDisasm output:
cc @dotnet/arm64-contrib.
|
imm = emitGetInsSC(id); | ||
assert(insOptsScalableAtLeastHalf(id->idInsOpt())); | ||
assert(isVectorRegister(id->idReg1())); // ddddd | ||
assert(isValidSimm8(imm) || isValidUimm8(imm)); // iiiiiiii |
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 is validating the encoded imm
which is interesting. It does strike me as odd that it's checking if imm
is either simm8
or uimm8
- but maybe that is actually fine?
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.
Yeah, I don't love the way this looks. Since this runs in Debug builds only, maybe we should actually try decoding the immediate here to see if it works, instead of taking the easy way out. I'll update this.
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.
Looks good Aman!
fpImm.immFPIVal = (unsigned)imm; | ||
assert(insOptsScalableAtLeastHalf(id->idInsOpt())); | ||
assert(isVectorRegister(id->idReg1())); // ddddd | ||
assert(isValidSimm8((ssize_t)emitDecodeFloatImm8(fpImm))); // iiiiiiii |
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 line looks wrong. emitDecodeFloatImm8 should be here?
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 result of emitDecodeFloatImm8 is being passed to isValidSimm8
src/coreclr/jit/emitarm64.cpp
Outdated
@@ -24398,6 +24512,7 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id) | |||
// Immediate and pattern to general purpose. | |||
case IF_SVE_BL_1A: // ............iiii ......pppppddddd -- SVE element count | |||
case IF_SVE_BM_1A: // ............iiii ......pppppddddd -- SVE inc/dec register by element count | |||
case IF_SVE_BO_1A: // ...........Xiiii ......pppppddddd -- SVE saturating inc/dec register by element count |
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.
how are we taking care of 64-bit encoding, where sf
field at bit 20 needs to be 1?
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.
Thanks for pointing that out; fixed.
assert(insOptsNone(opt)); | ||
assert(isGeneralRegister(reg1)); // ddddd | ||
assert(isValidUimm4From1(imm)); // iiii | ||
assert(size == EA_4BYTE); |
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.
what about EA_8BYTE
?
@@ -5912,6 +5912,100 @@ void CodeGen::genArm64EmitterUnitTestsSve() | |||
theEmitter->emitIns_R_PATTERN_I(INS_sve_incw, EA_SCALABLE, REG_V5, SVE_PATTERN_VL6, 16, | |||
INS_OPTS_SCALABLE_S); // INCW <Zdn>.S{, <pattern>{, MUL #<imm>}} | |||
|
|||
// IF_SVE_BO_1A | |||
theEmitter->emitIns_R_PATTERN_I(INS_sve_sqdecb, EA_4BYTE, REG_R0, SVE_PATTERN_POW2, |
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.
Here are below, the comment says Xdn
, so this should be 8 bytes.
theEmitter->emitIns_R_PATTERN_I(INS_sve_sqdecb, EA_4BYTE, REG_R0, SVE_PATTERN_POW2, | |
theEmitter->emitIns_R_PATTERN_I(INS_sve_sqdecb, EA_8BYTE, REG_R0, SVE_PATTERN_POW2, |
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 that's the 32-bit pattern, right? The docs say the 64-bit pattern is <Xdn>{, <pattern>{, MUL #<imm>}}
.
src/coreclr/jit/codegenarm64test.cpp
Outdated
// IF_SVE_BO_1A | ||
theEmitter->emitIns_R_PATTERN_I(INS_sve_sqdecb, EA_4BYTE, REG_R0, SVE_PATTERN_POW2, | ||
1); // SQDECB <Xdn>, <Wdn>{, <pattern>{, MUL #<imm>}} | ||
theEmitter->emitIns_R_PATTERN_I(INS_sve_sqdecd, EA_4BYTE, REG_R1, SVE_PATTERN_VL1, |
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.
as mentioned elsewhere, I don't see the test for SQDECB <Xdn>{, <pattern>{, MUL #<imm>}}
src/coreclr/jit/codegenarm64test.cpp
Outdated
12); // UQDECW <Wdn>{, <pattern>{, MUL #<imm>}} | ||
theEmitter->emitIns_R_PATTERN_I(INS_sve_uqincb, EA_4BYTE, REG_R12, SVE_PATTERN_VL128, | ||
13); // UQINCB <Wdn>{, <pattern>{, MUL #<imm>}} | ||
theEmitter->emitIns_R_PATTERN_I(INS_sve_uqincd, EA_4BYTE, REG_R13, SVE_PATTERN_VL256, |
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.
likewise, don't see test for UQDECB <Xdn>{, <pattern>{, MUL #<imm>}}
the 64-bit variant.
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.
Can you double check about 64-bit variants of some of the instructions I pointed out.
case IF_SVE_BQ_2A: // ...........iiiii ...iiinnnnnddddd -- SVE extract vector (immediate offset, destructive) | ||
case IF_SVE_BQ_2B: // ...........iiiii ...iiimmmmmddddd -- SVE extract vector (immediate offset, destructive) | ||
assert(id->idInsOpt() == INS_OPTS_SCALABLE_B); | ||
assert(isVectorRegister(id->idReg1())); // ddddd |
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.
can we double check what is the requirement for {Zn1, Zn2} like should Zn1 is an odd or even register and what happens if it is Z31, do we have to round 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.
According to the docs, there doesn't seem to be any extra requirements for Zn1
. Zn2
is calculated by just adding 1 to Zn1
, MOD 32, so if Zn1
is 31, Zn2
wraps around to 0. I added a unit test for this that demonstrates the correct behavior -- emitDispVectorRegList
seems to already handle this correctly.
@kunalspathak thanks for the review, I added the 64-bit version of |
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!
Widespread CI failures are #99320. |
Part of #94549. Adds the following encodings:
cstool output:
JitDisasm output:
cc @dotnet/arm64-contrib.