Skip to content

Ensure the other compilers consistently handle both get_IsHardwareAccelerated and get_IsSupported#128492

Draft
tannergooding wants to merge 5 commits into
dotnet:mainfrom
tannergooding:vector-shuffle
Draft

Ensure the other compilers consistently handle both get_IsHardwareAccelerated and get_IsSupported#128492
tannergooding wants to merge 5 commits into
dotnet:mainfrom
tannergooding:vector-shuffle

Conversation

@tannergooding
Copy link
Copy Markdown
Member

These checks frequently appear in generic and other code allowing early dead code elimination. They should be consistently handled to avoid pessimizing things.

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates multiple runtime backends (Mono mini JIT, Mono interpreter, and CoreCLR interpreter) to recognize and fold both get_IsHardwareAccelerated and get_IsSupported for vector APIs, and refactors CoreLib’s Vector*<T>.IsSupported implementations to delegate to Scalar<T>.IsSupported.

Changes:

  • Mono mini JIT: return a constant false for Vector256/Vector512.*.get_IsHardwareAccelerated instead of falling back to managed.
  • Mono interpreter + CoreCLR interpreter: add/extend intrinsic recognition to fold get_IsSupported (and keep folding get_IsHardwareAccelerated).
  • CoreLib: replace per-type typeof(T) == ... chains in Vector64/128/256/512<T>.IsSupported with Scalar<T>.IsSupported.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/mono/mono/mini/simd-intrinsics.c Adds constant-folding for get_IsHardwareAccelerated on unsupported vector sizes (256/512).
src/mono/mono/mini/interp/transform.c Extends interpreter intrinsic handling to fold get_IsSupported for relevant Vector APIs.
src/mono/mono/mini/interp/transform-simd.c Expands SIMD intrinsic handling across Vector sizes and adds get_IsSupported handling.
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs Refactors IsSupported to use Scalar<T>.IsSupported.
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs Refactors IsSupported to use Scalar<T>.IsSupported.
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs Refactors IsSupported to use Scalar<T>.IsSupported.
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs Refactors IsSupported to use Scalar<T>.IsSupported.
src/coreclr/interpreter/intrinsics.cpp Adds recognition for get_IsSupported on System.Runtime.Intrinsics.Vector* types.
src/coreclr/interpreter/compiler.cpp Implements NI_IsSupported_Type expansion to a constant based on the generic type argument.
Comments suppressed due to low confidence (1)

src/mono/mono/mini/interp/transform-simd.c:552

  • emit_sri_vector only identifies the vector type from a generic-inst return or first parameter. For explicit ISimdVector<...,T>.get_IsHardwareAccelerated (and other vector-less members), the signature has no MONO_TYPE_GENERICINST, so this returns FALSE and the interpreter won't constant-fold the check. If the intent is to fold these calls, consider also using cmethod->klass when it's a SIMD generic instance (or special-casing SN_get_IsHardwareAccelerated/SN_get_IsSupported before the vector_klass inference).
	gint16 simd_opcode = -1;
	gint16 simd_intrins = -1;

	if (csignature->ret->type == MONO_TYPE_GENERICINST) {
		vector_klass = mono_class_from_mono_type_internal (csignature->ret);
	} else if (csignature->param_count && csignature->params [0]->type == MONO_TYPE_GENERICINST) {
		vector_klass = mono_class_from_mono_type_internal (csignature->params [0]);
	} else {
		return FALSE;
	}

Comment thread src/mono/mono/mini/interp/transform-simd.c Outdated
Comment thread src/mono/mono/mini/interp/transform-simd.c Outdated
Comment thread src/mono/mono/mini/interp/transform-simd.c Outdated
Copilot AI review requested due to automatic review settings May 22, 2026 18:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comment thread src/mono/mono/mini/intrinsics.c Outdated
Comment thread src/mono/mono/mini/interp/transform.c
Copilot AI review requested due to automatic review settings May 22, 2026 18:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/mono/mono/mini/interp/transform-simd.c:552

  • emit_sri_vector() no longer successfully handles Vector64/Vector128/Vector256/Vector512.get_IsHardwareAccelerated: those APIs return bool and have no genericinst return/arg, so the current vector_klass discovery falls into the final return FALSE; (lines 546-552). As a result, the SIMD path won’t fold IsHardwareAccelerated to true when SIMD intrinsics are enabled (it will fall back to interp_handle_intrinsics, which folds it to false), and the later if (id == SN_get_IsHardwareAccelerated) { ... MINT_LDC_I4_1 ... } becomes effectively unreachable. Consider restoring an early special-case for SN_get_IsHardwareAccelerated (before requiring a genericinst) that bases the result on the declaring Vector* type/size (e.g., true for supported sizes, false for unsupported ones).
	const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name);

	int id = lookup_intrins (sri_vector_methods, sizeof (sri_vector_methods), cmethod_name);
	if (id == -1)
		return FALSE;

	MonoClass *vector_klass = NULL;
	int vector_size = 0;

	gint16 simd_opcode = -1;
	gint16 simd_intrins = -1;

	if (csignature->ret->type == MONO_TYPE_GENERICINST) {
		vector_klass = mono_class_from_mono_type_internal (csignature->ret);
	} else if (csignature->param_count && csignature->params [0]->type == MONO_TYPE_GENERICINST) {
		vector_klass = mono_class_from_mono_type_internal (csignature->params [0]);
	} else {
		return FALSE;
	}

Comment thread src/mono/mono/mini/interp/transform-simd.c
Comment thread src/coreclr/interpreter/intrinsics.cpp
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings May 23, 2026 02:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment on lines +2684 to +2692
g_assert (mono_class_is_ginst (target_method->klass));

// Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified
MonoType *etype = mono_class_get_context (target_method->klass)->class_inst->type_argv [0];

if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) {
*op = MINT_LDC_I4_1;
} else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) {
// Happens often in gshared code
Comment on lines +2734 to +2743
g_assert (mono_class_is_ginst (target_method->klass));

// Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified
MonoType *etype = mono_class_get_context (target_method->klass)->class_inst->type_argv [0];

if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) {
*op = MINT_LDC_I4_1;
} else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) {
// Happens often in gshared code
*op = MINT_LDC_I4_0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants