Skip to content

Vector256<Integer>.AllBitsSet emits illegal instructions on a machine without AVX2 #48283

@SingleAccretion

Description

@SingleAccretion

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 
       ret

According 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:

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;

cc @tannergooding

Metadata

Metadata

Assignees

Labels

arch-x64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIbug

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions