-
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
Adding EVEX encoding support for emitOutputRRR(). #75934
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsOverviewThis change adds the following
EVEX prefix
From the above the following bits are in inverted form : R, X, B, R', vvvv, V'. This results in the following initila EVEX prefix mask Since we are primarily interested in the RRR path, I have added the logic to set the following bits(some will need additional logic once we support zmm registers and/or additional vector registers) Added/Modified bit set logic
Bits not set anywhere - b and z Relevant DetailsHow it works now
How to TestThis feature is turned off by default. In order to turn it on, set the following environment variable on
|
b9e433d
to
63056c7
Compare
63056c7
to
764eb58
Compare
src/coreclr/jit/emitxarch.cpp
Outdated
#ifdef TARGET_AMD64 | ||
return emitter::code_t(code | 0x4800000000ULL); | ||
#else | ||
assert(!"UNREACHED"); | ||
return code; | ||
#endif | ||
} | ||
#ifdef TARGET_AMD64 | ||
return emitter::code_t(code | 0x4800000000ULL); | ||
#else | ||
assert(!"UNREACHED"); | ||
return code; | ||
#endif | ||
} |
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.
Do we know what changed as part of this diff? It looks identical to me, so maybe line endings or something else got changed by accident?
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 went over this and re-did the changes to make it cleaner but still looks weird. Not sure what's going on
|
||
#ifdef TARGET_AMD64 | ||
|
||
emitter::code_t emitter::AddRexRPrefix(instruction ins, code_t code) |
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.
Just noting that its unfortunate the diff is represented this way. It makes reviewing the changes around emitOutputSIMDPrefixIfNeeded
much harder.
This might be related to that place I called out above where the diff is reporting a change where visibly there is none.
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 tried to clean this up but could not find a way to do so. Might have to add the changes back manually as a last resort.
The changes generally LGTM. There are a few comments on possible naming changes and where we need to add "method headers" describing the functions. There's also a place where the diff seems to be particularly bad and makes it harder to review. No major changes needed from what I can tell, and it should be generally good to merge once we get the items raised above covered. CC. @dotnet/jit-contrib |
764eb58
to
b7bb8a9
Compare
nit: Formatting job is failing |
} | ||
} | ||
|
||
return IsAvx512OrPriorInstruction(ins); |
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 going to be dependent on AVX512VL
being supported for many instructions.
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.
Does the other change resolve this issue for now? As we add new instructions, the logic in TakesEvexPrefix should evolve to handle newer cases.
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 code still looks generally correct and works on my Intel Core i9-11900H (11th Gen Tiger Lake) and my AMD Ryzen 7950X (Zen4) CPU.
There is a concern around some of the EVEX checks and the new encoding stress switch in relation to
AVX512VL
.
@tannergooding Did the changes resolve all of your concerns or are there any other changes you're waiting on?
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 so, but I'll need to give it another pass when I'm back in office near the end of next week.
The code still looks generally correct and works on my Intel Core i9-11900H (11th Gen Tiger Lake) and my AMD Ryzen 7950X (Zen4) CPU. There is a concern around some of the EVEX checks and the new encoding stress switch in relation to |
40a34cf
to
9aae285
Compare
Adding flag to turn on EVEX encoding.
9aae285
to
028cdf5
Compare
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 left a few comments, but they are minor, so I won't ask for updates in this change, but would appreciate consideration of them for follow-up changes.
Sorry it took me so long to look at this.
// defined or used in a multireg context. | ||
CONFIG_INTEGER(EnableMultiRegLocals, W("EnableMultiRegLocals"), 1) // Enable the enregistration of locals that are | ||
// defined or used in a multireg context. | ||
CONFIG_INTEGER(JitStressEVEXEncoding, W("JitStressEVEXEncoding"), 0) // Enable EVEX encoding for SIMD instructions. |
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.
Do we need this switch to be available in Release builds? If not, put it in a "ifdef DEBUG" block (it's not currently in one AFAICT)
CONFIG_INTEGER(JitStressEVEXEncoding, W("JitStressEVEXEncoding"), 0) // Enable EVEX encoding for SIMD instructions. | |
#ifdef DEBUG | |
CONFIG_INTEGER(JitStressEVEXEncoding, W("JitStressEVEXEncoding"), 0) // Use EVEX encoding for SIMD instructions if possible. | |
#endif // DEBUG |
// canUseEvexEncoding - Answer the question: Is Evex encoding supported on this target. | ||
// | ||
// Returns: | ||
// TRUE if Evex encoding is supported, FALSE if not. |
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.
nit: for bool
returning functions, write the comment using true
and false
that match the casing of the C++ keywords, and not TRUE
and FALSE
. For some of us, TRUE
and FALSE
map to the Win32 concepts with BOOL
type. You can enclose them in single back-ticks like in GitHub markdown formatting if that helps distinguish them from other text, e.g.:
// `true` if Evex encoding is supported, `false` if not.
nit2: please include a blank //
line at the end of the header comment block before the function so the comment text doesn't "run into" the function declaration.
// Returns: | ||
// TRUE if ins is a SIMD instruction. | ||
// | ||
bool emitter::IsSimdInstruction(instruction ins) const |
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.
Seems like an odd name: aren't SSE2 instructions "SIMD"?
Maybe IsAvxOrNewerInstruction
?
return IsAvx512Instruction(ins) && !HasKMaskRegisterDest(ins); | ||
} | ||
|
||
// Add base EVEX prefix without setting W, R, X, or B bits |
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.
It would be useful to leave a reference here so people can find the definition of EVEX encoding. Something like:
// Intel AVX-512 encoding is defined in "Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2", Section 2.6.
Overview
This change adds the following
JitStressEVEXEncoding
emitOutputRRR()
as well as other encoding logic used fromemitOutputRRR()
to support EVEX encoding.EVEX prefix
From the above the following bits are in inverted form : R, X, B, R', vvvv, V'. This results in the following initila EVEX prefix mask
62 <11110000> <01111100> <00001000>
=0x62F07C0800000000ULL
Since we are primarily interested in the RRR path, I have added the logic to set the following bits(some will need additional logic once we support zmm registers and/or additional vector registers)
Added/Modified bit set logic
Vector Width
- This is done inAddEvexPrefix()
. Currently we are setting onlyL
since we support only xmm and ymm.To Do : once we have zmm enabled, need to set
L'L
EVEX.W
- Done inAddRexWPrefix()
. This is a legacy bit from VEX. Just needed to set the right bit in EVEXChoosing when to set
W
bit is a little more interesting since it can be an opcode extension. There are cases whereW
bit isWIG
for VEX but has to be set for EVEX. For now, this is handled inIsWEvexOpcodeExtension()
: returns TRUE if W=1EVEX.R - Done in
AddRexRPrefix
viainsEncodeReg345()
. Encodes target register.To Do : once we have zmm enabled, need to set
R'
This will requireRegEncoding()
to return 32 valuesEVEX.X - Done in
AddRexBPrefix
viainsEncodeReg012()
. Encodes 2nd src register.EVEX.vvvv
- Done ininsEncodeReg3456()
. Had to change offset to set the correct bit in EVEX prefix. Encodes 1st src register.To Do : once we have zmm enabled, need to set
V'
This will requireRegEncoding()
to return 32 valuespp
andmm
bits- used same logic as VEX but had to change offsetBits not set anywhere - b and z
Relevant Details
How it works now
IsAVX512OnlyInstruction()
- always returns false. We haven't added avx512 yet.IsAVX512Instruction()
- is not a strict superset of IsAVXInstruction and must be explicitly paired with an TakesEvexPrefix(ins) check. There are instructions which can be VEX encoded but not EVEX encoded. (For e.g., pmovmskb)Function with SIMD are used as a superset of VEX, AVX, and AVX512 now. They are equivalent to VEXOrAVXorAVX512.
Currently, since we do not support opcode masks(k mask), we cannot EVEX encode some instructions which requires kmask for its EVEX form. See
HasKMaskRegisterDest()
(e.g., pcmpgtb : The EVEX encoded form has k register as destination)TakesEvexPrefix(ins) will have to grow to actually check cases and will need the instruction descriptor.
codeEvexMigrationCheck()
is a temporary check. This is required since we are not adding EVEX support for all paths at the same time. This means that for common functions, we have to differentiate between cases where EVEX encoding is required vs VEX encoding.How to Test
This feature is turned off by default. In order to turn it on, set the following environment variable on
set COMPlus_JitStressEVEXEncoding=1