Skip to content

Conversation

@shumway
Copy link
Collaborator

@shumway shumway commented Dec 4, 2025

We were getting ugly error messages when we tried to call describe<Instance> on an instance that is not a supported (forward XDL) kernel.

Changes in this PR:

  1. Add concepts to conv_traits.hpp to get better error message.
  2. Put the correct requires clauses in the right places to get descriptive error messages.
  3. General cleanup of functions in conv_traits.hpp to make functions easier to read.

When I asked for a description of operators that didn't have ConvTraits, I was getting very long confusing errors about ConvTraits not being defined. Now we get specific errors explaining which concepts are violated, making it easier to know which code to generalize or update.

We were getting ugly error messages when we tried to call `describe<Instance>` on an instance that is not a supported (forward XDL) kernel.
* Fix concepts and requires clauses to get much better error messages.
* Also clean up functions in conv_traits.hpp to make the more concise
  and readable.
@bartekxk bartekxk requested a review from Copilot December 4, 2025 22:46
Copilot finished reviewing on behalf of bartekxk December 4, 2025 22:49
Copy link
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 enhances error reporting and code readability in conv_traits.hpp by introducing C++20 concepts and refactoring several functions. The changes aim to provide clearer, more descriptive error messages when using unsupported kernel instances with the builder API.

Key changes:

  • Added six C++20 concepts (HasFwdConvLayouts, HasGemmSpec, HasDataTypes, HasElementwiseOps, HasTileParams, IsXdlFwdConv, and HasConvTraits) to validate kernel instance properties and provide better compiler diagnostics
  • Refactored multiple functions to use switch statements instead of if-constexpr chains for improved readability
  • Applied requires clauses to functions that need specific traits, constraining them at the correct level

Reviewed changes

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

File Description
experimental/builder/include/ck_tile/builder/reflect/conv_traits.hpp Added concepts for trait validation, refactored conversion and extraction functions to use switch statements, added requires clauses to constrain template functions
experimental/builder/include/ck_tile/builder/reflect/conv_description.hpp Updated to use the new HasConvTraits concept from conv namespace instead of local definition

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if constexpr(layouts_are<A, B, E, ctl::NGCDHW, ctl::GKCZYX, ctl::NGKDHW>)
return layouts(NGCDHW, GKCZYX, NGKDHW);
break;
}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The function may not return a value in all code paths. If none of the layout combinations match or if kSpatialDim is not 1, 2, or 3, the function will have undefined behavior. Consider adding a default return value or static_assert to ensure all cases are handled.

Suggested change
}
}
static_assert(always_false<Instance>, "Unsupported convolution layout or spatial dimension in conv_layout()");

Copilot uses AI. Check for mistakes.
case MNOPadding: return MNO_PADDING;
case MKOPadding: return MKO_PADDING;
case NKOPadding: return NKO_PADDING;
case MNKOPadding: return MNKO_PADDING;
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. If gemm_spec doesn't match any of the enumerated cases, the function will have undefined behavior. Consider adding a default case to handle unexpected values.

Suggested change
case MNKOPadding: return MNKO_PADDING;
case MNKOPadding: return MNKO_PADDING;
default:
static_assert([]{return false;}(), "Unhandled GemmSpecialization value in gemm_spec()");

Copilot uses AI. Check for mistakes.
if constexpr(detail::case_insensitive_equal(name, "PassThrough"))
return PASS_THROUGH;
if constexpr(detail::case_insensitive_equal(name, "ScaleAddScaleAddRelu"))
return SCALEADD_SCALEADD_RELU;
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The function may not return a value in all code paths. If none of the elementwise operation names match, the function will have undefined behavior. Consider adding a default return value or ensuring all cases are exhaustively handled.

Suggested change
return SCALEADD_SCALEADD_RELU;
return SCALEADD_SCALEADD_RELU;
return PASS_THROUGH; // Default fallback if no match found

Copilot uses AI. Check for mistakes.
case v2: return V2;
case v3: return V3;
case v4: return V4;
case v5: return V5;
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. If ck_ver doesn't match any of the enumerated cases (v1-v5), the function will have undefined behavior. Consider adding a default case or ensuring all enum values are covered.

Suggested change
case v5: return V5;
case v5: return V5;
default:
static_assert(ck_ver == v1 || ck_ver == v2 || ck_ver == v3 || ck_ver == v4 || ck_ver == v5,
"Unsupported ck::BlockGemmPipelineVersion in convert_pipeline_version");
// The following is just to satisfy the compiler; this line should never be reached.
return V1;

Copilot uses AI. Check for mistakes.
case v1: return V1;
case v2: return V2;
case v4: return V4;
case weight_only: return WEIGHT_ONLY;
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. If ck_ver doesn't match any of the enumerated cases (v1, v2, v4, weight_only), the function will have undefined behavior. Consider adding a default case or ensuring all enum values are covered.

Suggested change
case weight_only: return WEIGHT_ONLY;
case weight_only: return WEIGHT_ONLY;
default:
static_assert(ck_ver == v1 || ck_ver == v2 || ck_ver == v4 || ck_ver == weight_only,
"Unsupported ck::PipelineVersion value in convert_pipeline_version.");
// To satisfy all code paths, return a dummy value (will never be used due to static_assert)
return V1;

Copilot uses AI. Check for mistakes.
switch(ck_sched)
{
case Intrawave: return INTRAWAVE;
case Interwave: return INTERWAVE;
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. If ck_sched doesn't match any of the enumerated cases (Intrawave, Interwave), the function will have undefined behavior. Consider adding a default case or ensuring all enum values are covered.

Suggested change
case Interwave: return INTERWAVE;
case Interwave: return INTERWAVE;
default:
static_assert(
ck_sched == Intrawave || ck_sched == Interwave,
"Unsupported ck::BlockGemmPipelineScheduler value in convert_pipeline_scheduler"
);
// The following is unreachable, but required to satisfy all code paths.
return INTRAWAVE;

Copilot uses AI. Check for mistakes.
Comment on lines +293 to 299
switch(InstTraits::kConvForwardSpecialization)
{
return builder::ConvFwdSpecialization::FILTER_3x3;
case Default: return DEFAULT;
case Filter1x1Pad0: return FILTER_1X1_PAD0;
case Filter1x1Stride1Pad0: return FILTER_1X1_STRIDE1_PAD0;
case Filter3x3: return FILTER_3x3;
}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. When the specialization doesn't match any case, the function will have undefined behavior. Consider adding a default case to handle unexpected values.

Copilot uses AI. Check for mistakes.
switch(ck_sched)
{
case Default: return DEFAULT;
case Interwave: return INTERWAVE;
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. If ck_sched doesn't match any of the enumerated cases (Default, Interwave), the function will have undefined behavior. Consider adding a default case or ensuring all enum values are covered.

Suggested change
case Interwave: return INTERWAVE;
case Interwave: return INTERWAVE;
default:
static_assert(ck_sched == Default || ck_sched == Interwave,
"Unsupported ck::LoopScheduler value in convert_pipeline_scheduler");
// To satisfy all code paths, return a value (will never be reached)
return DEFAULT;

Copilot uses AI. Check for mistakes.
Comment on lines +306 to 310
switch(InstTraits::kConvBwdDataSpecialization)
{
return builder::ConvBwdDataSpecialization::DEFAULT;
}
else if constexpr(InstTraits::kConvBwdDataSpecialization == Filter1x1Stride1Pad0)
{
return builder::ConvBwdDataSpecialization::FILTER_1X1_STRIDE1_PAD0;
case Default: return DEFAULT;
case Filter1x1Stride1Pad0: return FILTER_1X1_STRIDE1_PAD0;
}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. When the specialization doesn't match any case, the function will have undefined behavior. Consider adding a default case to handle unexpected values.

Copilot uses AI. Check for mistakes.
Comment on lines +317 to 323
switch(InstTraits::kConvBwdWeightSpecialization)
{
return builder::ConvBwdWeightSpecialization::DEFAULT;
}
else if constexpr(InstTraits::kConvBwdWeightSpecialization == Filter1x1Stride1Pad0)
{
return builder::ConvBwdWeightSpecialization::FILTER_1X1_STRIDE1_PAD0;
}
else if constexpr(InstTraits::kConvBwdWeightSpecialization == Filter1x1Pad0)
{
return builder::ConvBwdWeightSpecialization::FILTER_1X1_PAD0;
}
else if constexpr(InstTraits::kConvBwdWeightSpecialization == OddC)
{
return builder::ConvBwdWeightSpecialization::ODD_C;
case Default: return DEFAULT;
case Filter1x1Stride1Pad0: return FILTER_1X1_STRIDE1_PAD0;
case Filter1x1Pad0: return FILTER_1X1_PAD0;
case OddC: return ODD_C;
}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

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

The switch statement lacks a default case and may not return a value in all code paths. When the specialization doesn't match any case, the function will have undefined behavior. Consider adding a default case to handle unexpected values.

Copilot uses AI. Check for mistakes.
@shumway shumway merged commit 13f6d63 into develop Dec 5, 2025
31 checks passed
@shumway shumway deleted the jshumway/conv-traits branch December 5, 2025 03:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants