Skip to content

[SM6.10] Add LinAng Matrix attributes and two new attributed matrix types#8125

Open
hekota wants to merge 20 commits intomicrosoft:mainfrom
hekota:linalg-matrix-attributes-and-types
Open

[SM6.10] Add LinAng Matrix attributes and two new attributed matrix types#8125
hekota wants to merge 20 commits intomicrosoft:mainfrom
hekota:linalg-matrix-attributes-and-types

Conversation

@hekota
Copy link
Member

@hekota hekota commented Feb 2, 2026

Adds new type attribute __LinAlg_Matrix_Attributes that can be attached to __builtin_LinAlg_Matrix built-in matrix handle type to specify the matrix component type, dimensions, use and scope. Includes enabling C11++ -style attributes on types in DXC.

Adds two new AST types that are used to capture the information from the attribute:

  • AttributedLinAlgMatrixType type is used when the attribute specifies concrete matrix parameters
  • DependentAttributedLinAlgMatrixType is for cases where the type attributes arguments are dependent on template instantiation

The AttributedLinAlgMatrixType is linked to LinAlgMatrix type alias used in gen_intrin_main.txt for built-in function APIs.

This change also adds the outline of the LinAlg Matrix template class to dx/linalg.h, including the enumeration types used as arguments to the new attribute and as template parameters of Matrix.

Note that the ComponentType enum in dx/linalg.h is defined using values matching the existing internal ComponentType enum that was added in SM 6.9 for cooperative vectors. This is different from the current LinAlg spec. The issue to update the spec is microsoft/hlsl-specs#779.

Fixes #8122

@hekota hekota marked this pull request as ready for review February 2, 2026 18:14
@hekota hekota requested a review from llvm-beanz February 2, 2026 18:15
@hekota hekota changed the title Add LinAng Matrix attributes and two new attributed matrix types [SM6.10] Add LinAng Matrix attributes and two new attributed matrix types Feb 2, 2026
@hekota hekota linked an issue Feb 2, 2026 that may be closed by this pull request
__builtin_LinAlg_Matrix [[__LinAlg_Matrix_Attributes(ComponentType::I32, 4, 5, MatrixUse::B, MatrixScope::ThreadGroup)]] mat8;

// expected-error@+1 {{cannot initialize a variable of type '__builtin_LinAlg_Matrix' with an lvalue of type '__builtin_LinAlg_Matrix [[__LinAlg_Matrix_Attributes(ComponentType::I32, 4, 5, MatrixUse::B, MatrixScope::ThreadGroup)]]'}}
__builtin_LinAlg_Matrix naked_mat = mat8;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should it be illegal to declare this type without attributes? Is that the reason for TMP?

Copy link
Member Author

@hekota hekota Feb 3, 2026

Choose a reason for hiding this comment

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

We could make it illegal by intercepting every place where a type can be used and adding a special check and error if it is the __builtin_LinAlgMatrix without attributes. Or we can do nothing because the naked typed cannot be used for anything anyway. The __builtin prefix means users should not be using these directly.


// Check that the value is a valid range.
int64_t Value = APVal.getLimitedValue();
if (Value < 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we enforce any maximum?

Copy link
Collaborator

Choose a reason for hiding this comment

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

The spec has maximums for the K dimension but no specified maximum the M or N dimensions:

| Matrix Scope | Scalar element dimensions |
| ------------ | ------------------------- |
| Thread       | [4,128]                   |
| Wave         | [4,128]                   |
| ThreadGroup  | [1,1024]                  |

The "scalar element" refers to the dimensions being 4x that number if the data type is an 8-bit type represented in packed data types.

Copy link
Collaborator

@V-FEXrt V-FEXrt left a comment

Choose a reason for hiding this comment

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

LGTM but I did a very rush job on the review. Wanted to mark my general approval before being out the next couple days

@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@llvm-beanz llvm-beanz left a comment

Choose a reason for hiding this comment

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

There's a lot of boilerplate here, but it all looks pretty reasonable to me.

Comment on lines 206 to 210
#ifdef __hlsl_dx_compiler
#define SIZE_TYPE int
#else
#define SIZE_TYPE uint
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't expect that this header will be portable to clang, so for the purposes of DXC we can simplify this to just:

Suggested change
#ifdef __hlsl_dx_compiler
#define SIZE_TYPE int
#else
#define SIZE_TYPE uint
#endif
#define SIZE_TYPE int

We should probably file an issue to decide what to do about size types generally in HLSL. I don't love that DXC decided size types were signed 32-bit integers, but we may want Clang to match that for at least some language modes (cc @tex3d & @bogner for visibility about Clang and language spec issues).


// Check that the value is a valid range.
int64_t Value = APVal.getLimitedValue();
if (Value < 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

The spec has maximums for the K dimension but no specified maximum the M or N dimensions:

| Matrix Scope | Scalar element dimensions |
| ------------ | ------------------------- |
| Thread       | [4,128]                   |
| Wave         | [4,128]                   |
| ThreadGroup  | [1,1024]                  |

The "scalar element" refers to the dimensions being 4x that number if the data type is an 8-bit type represented in packed data types.

@hekota hekota changed the base branch from user/hekota/pr8090-matrix-builtin-handle-type to main February 5, 2026 01:09
Copy link
Collaborator

@pow2clk pow2clk left a comment

Choose a reason for hiding this comment

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

I just implemented almost this exact change, so I had many thoughts. Nothing is really blocking, but some things you may want to consider

void TypePrinter::printAttributedLinAlgMatrixBefore(
const AttributedLinAlgMatrixType *T, raw_ostream &OS) {
printBefore(T->getWrappedType(), OS);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Slightly confusing to put the before after after 😄

def err_hlsl_linalg_matrix_attribute_on_invalid_type
: Error<"matrix attributes can only be applied to %0">;
def err_hlsl_linalg_attributed_matrix_required
: Error<"argument type must be linear algebra matrix with attributes">;
Copy link
Collaborator

Choose a reason for hiding this comment

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

The attributes are required for the linalg matrix type aren't they? Infrequent as I think this will be produced, I think it might be clearer to just say "linear algebra matrix" or "linear algebra matrix type"

// indexer object used to implement .mips[1].
AR_TOBJ_STRING, // Represents a string
AR_TOBJ_DEPENDENT, // Dependent type for template.
AR_TOBJ_LINALG_MATRIX // LinAlg Matric type
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is the change I'm least sure about. It provides a way to enforce argument matching, but I was looking at this as just another TOBJ_OBJECT. As it stands, there are a few other switches that will need LINALG_MATRIX entries if this is to persist. Pretty much wherever TOBJ_OBJECT shows up, this will be needed too.

LICOMPTYPE_BUILTIN_TRIANGLE_POSITIONS = 54,
LICOMPTYPE_BUILTIN_TRIANGLE_POSITIONS = 55,

#ifdef ENABLE_SPIRV_CODEGEN
Copy link
Collaborator

Choose a reason for hiding this comment

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

At some point, I think it would be simpler to follow the example of #7231 and remove these ifdefs. I don't know if this is that moment though. Maybe should be done as a separate change, but as you shuffled around a few numbers above, maybe you have thoughts.

DEF_TRAVERSE_TYPELOC(EnumType, {})
// HLSL Change Start
DEF_TRAVERSE_TYPELOC(AttributedLinAlgMatrixType, {})
DEF_TRAVERSE_TYPELOC(DependentAttributedLinAlgMatrixType, {})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can these be empty? I traversed each of the expressions and types similar to how ExtVector and DependentExtVector above do.

hlsl::DXIL::MatrixUse getUse() const { return Use; }
hlsl::DXIL::MatrixScope getScope() const { return Scope; }

void appendMangledAttributes(llvm::raw_ostream &OS) const;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't see any other types with this implemented as part of the type class. They put this in the mangling file. It's not that important, but I'm curious why it was placed here. Is it because the enums are converted from integers when they are stored here? Since they come in as integers and even the mangling treats them as such, I just kept them as integers.

TYPE_ADJUSTED = 42
TYPE_ADJUSTED = 42,
/// \brief An AttributedLinAlgMatrixType record.
TYPE_ATTRIBUTED_LINALG_MATRIX = 43
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't see this being used anywhere. Is it necessary?

T->getComponentType())
<< ", " << T->getRows() << ", " << T->getCols() << ", "
<< hlsl::ConvertLinAlgMatrixUseToString(T->getUse()) << ", "
<< hlsl::ConvertLinAlgMatrixScopeToString(T->getScope()) << ")]]";
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this is ever to be read, representing use and scope as strings is going to make that trickier, requiring a header somehow to define the values

<< hlsl::ConvertLinAlgMatrixComponentTypeToString(T->getComponentType())
<< ", " << T->getRows() << ", " << T->getCols() << ", "
<< hlsl::ConvertLinAlgMatrixUseToString(T->getUse()) << ", "
<< hlsl::ConvertLinAlgMatrixScopeToString(T->getScope()) << ")]]";
Copy link
Collaborator

Choose a reason for hiding this comment

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

I again wonder if printing string names of enums that aren't externally available is going to make this less computer readable, though more human readable.

}

def HLSLLinAlgMatrixAttributes : TypeAttr {
let Spellings = [CXX11<"", "__LinAlgMatrix_Attributes", 2015>];
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you were to put hlsl in the now empty string, the attribute would require a "hlsl:" prefix, which seems in keeping with the langopt inclusion below as well as how resources were done in modern LLVM

Suggested change
let Spellings = [CXX11<"", "__LinAlgMatrix_Attributes", 2015>];
let Spellings = [CXX11<"hlsl", "__LinAlgMatrix_Attributes", 2015>];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

Implement attributed matrix handle in the AST

5 participants