Repository navigation
Vector256<Integer>.AllBitsSet emits illegal instructions on a machine without AVX2 #48283
Description
Description
On a machine without AVX2 but with AVX (Sandy Bridge / Ivy Bridge), Vector256<IntegralType>.AllBitsSet will emit illegal instructions and cause the program to crash.
In particular, this method:
public static Vector256<byte> Problem() => Vector256<byte>.AllBitsSet;Will emit the following:
vzeroupper
G_M65241_IG02:
vpcmpeqd ymm0, ymm0, ymm0
vmovupd ymmword ptr[rcx], ymm0
mov rax, rcx
G_M65241_IG03:
vzeroupper
retAccording to https://www.felixcloutier.com/x86/pcmpeqb:pcmpeqw:pcmpeqd, vpcmpeqd with ymm operands is only available when AVX2 is.
This is also a problem for Vector256.Create(-1).
Configuration
This applies to .NET 5 and .NET 6, tested on an Ivy Bridge machine running Windows 10 x64.
Regression?
This is not a regression in case of AllBitsSet (the API was introduced in .NET 5), but it is a regression from .NET Core 3.1 for the Create(-1) call (lowering now folds it to the same get_AllBitsSet node, see also #47385).
Other information
During importation, Vector256<byte>.AllBitsSet depends on the Vector256 ISA, presumably because it is declared like so:
HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmppd}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
This ISA is available when AVX is available, and the intrinsic is recognized:
Named Intrinsic System.Runtime.Intrinsics.Vector256`1.get_AllBitsSet: Notify VM instruction set (Vector256) must be supported.
And the node is later emitted as vpcmpeqd:
runtime/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
Lines 1254 to 1269 in 7e681c1
| case NI_Vector128_get_AllBitsSet: | |
| case NI_Vector256_get_AllBitsSet: | |
| { | |
| assert(op1 == nullptr); | |
| if (varTypeIsFloating(baseType) && compiler->compOpportunisticallyDependsOn(InstructionSet_AVX)) | |
| { | |
| // The immediate 8 means Equal (unordered, non-signaling) | |
| // This is not available without VEX prefix. | |
| emit->emitIns_SIMD_R_R_R_I(ins, attr, targetReg, targetReg, targetReg, 8); | |
| } | |
| else | |
| { | |
| assert(varTypeIsIntegral(baseType) || !compiler->compIsaSupportedDebugOnly(InstructionSet_AVX)); | |
| emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, targetReg, targetReg, targetReg); | |
| } | |
| break; |
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
EgorBo commentedon Feb 15, 2021
As far as I remember that optimization (
Create(-1)toget_AllBitsSet) was introduced in .NET 5.0SingleAccretion commentedon Feb 15, 2021
Indeed, that is my understanding as well and why I pointed it out as a regression.
I. e. this application works fine when targeting
netcoreapp3.1and but throwsSEHExceptionwhen targetingnet5.0:JulieLeeMSFT commentedon Feb 16, 2021
CC @echesakovMSFT
echesakov commentedon Feb 16, 2021
I will take a look
echesakov commentedon Feb 17, 2021
Setting 6.0 milestone for now
echesakov commentedon Feb 19, 2021
Reopened to track 5.0 backporting
SingleAccretion commentedon Mar 11, 2021
Backported in #48630.