[clang] [Matrix][HLSL] Add codegen support for Matrix Layout keywords (PR #198887)
github-actions[bot] wrote: # :penguin: Linux x64 Test Results * 88173 tests passed * 1641 tests skipped * 2 tests failed ## Failed Tests (click on a test name to see its output) ### Clang Clang.Driver/hip-toolchain-no-rdc.hip ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 1 rm -rf /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/test/Driver/Output/hip-toolchain-no-rdc.hip.tmp && mkdir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/test/Driver/Output/hip-toolchain-no-rdc.hip.tmp # executed command: rm -rf /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/test/Driver/Output/hip-toolchain-no-rdc.hip.tmp # note: command had no output on stdout or stderr # executed command: mkdir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/test/Driver/Output/hip-toolchain-no-rdc.hip.tmp # note: command had no output on stdout or stderr # RUN: at line 2 /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -### --target=x86_64-linux-gnu -fno-gpu-rdc-x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900--hip-device-lib=lib1.bc --hip-device-lib=lib2.bc --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib1 --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib2 -fuse-ld=lld -B/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/lld -nogpuinc --no-offload-new-driver /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/a.cu /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/b.hip 2>&1 | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=CHECK,LINK,OLD /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/hip-toolchain-no-rdc.hip # executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang '-###' --target=x86_64-linux-gnu -fno-gpu-rdc -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 --hip-device-lib=lib1.bc --hip-device-lib=lib2.bc --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib1 --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib2 -fuse-ld=lld -B/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/lld -nogpuinc --no-offload-new-driver /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/a.cu /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/b.hip # note: command had no output on stdout or stderr # executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=CHECK,LINK,OLD /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/hip-toolchain-no-rdc.hip # note: command had no output on stdout or stderr # RUN: at line 12 /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -### --target=x86_64-linux-gnu -fno-gpu-rdc-x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900--hip-device-lib=lib1.bc --hip-device-lib=lib2.bc --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib1 --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib2 -fuse-ld=lld -B/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/lld -nogpuinc -c --no-offload-new-driver /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/a.cu /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/b.hip 2>&1 | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck -check-prefixes=CHECK,OLD /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/hip-toolchain-no-rdc.hip # executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang '-###' --target=x86_64-linux-gnu -fno-gpu-rdc -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 --hip-device-lib=lib1.bc --hip-device-lib=lib2.bc --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib1 --hip-device-lib-path=/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/hip_multiple_inputs/lib2 -fuse-ld=lld -B/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Driver/Inputs/lld -nogpuinc -c --no-offload-new-driver /h
[clang] [Matrix][HLSL] Add codegen support for Matrix Layout keywords (PR #198887)
https://github.com/farzonl auto_merge_enabled https://github.com/llvm/llvm-project/pull/198887 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Matrix][HLSL] Add codegen support for Matrix Layout keywords (PR #198887)
farzonl wrote: test failures are unrelated: ``` Failed Tests (2): Clang :: Driver/hip-toolchain-no-rdc.hip Clang :: Driver/hipspv-toolchain.hip ``` https://github.com/llvm/llvm-project/pull/198887 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Matrix][HLSL] Add codegen support for Matrix Layout keywords (PR #198887)
https://github.com/farzonl updated
https://github.com/llvm/llvm-project/pull/198887
>From 656f637d6da026c6fc0491ef0bcfc2b3c644a5fb Mon Sep 17 00:00:00 2001
From: Farzon Lotfi
Date: Mon, 4 May 2026 12:10:08 -0400
Subject: [PATCH 01/10] [Matrix][HLSL] Add codgen support for Matrix Layout
keywords
fixes #192262
- Wrap Matrix Type in HLSLMatrixLayoutArrr
- Add Helper to know which Matrix Layout to apply in codegen or check for in
Sema
---
clang/include/clang/AST/MatrixUtils.h | 71 +++
clang/include/clang/Basic/Attr.td | 16 ++
clang/lib/AST/TypePrinter.cpp | 20 ++
clang/lib/CodeGen/CGExpr.cpp | 17 +-
clang/lib/CodeGen/CGExprConstant.cpp | 4 +-
clang/lib/CodeGen/CGExprScalar.cpp| 22 ++-
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 9 +-
clang/lib/CodeGen/CodeGenTypes.cpp| 5 +-
clang/lib/Sema/SemaHLSL.cpp | 79
clang/test/AST/HLSL/matrix_layout_attr.hlsl | 11 ++
.../matrix-layout-attr-overrides-default.hlsl | 175 ++
11 files changed, 400 insertions(+), 29 deletions(-)
create mode 100644 clang/include/clang/AST/MatrixUtils.h
create mode 100644
clang/test/CodeGenHLSL/matrix-layout-attr-overrides-default.hlsl
diff --git a/clang/include/clang/AST/MatrixUtils.h
b/clang/include/clang/AST/MatrixUtils.h
new file mode 100644
index 0..d1b351bf4b07b
--- /dev/null
+++ b/clang/include/clang/AST/MatrixUtils.h
@@ -0,0 +1,71 @@
+//===- MatrixUtils.h - Matrix AST utilities -*- C++
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+/// \file
+/// Defines AST-level helper utilities for matrix types.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_AST_MATRIXUTILS_H
+#define LLVM_CLANG_AST_MATRIXUTILS_H
+
+#include "clang/AST/Type.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/LangOptions.h"
+
+namespace clang {
+/// Returns true if matrices of \p T should be laid out in row-major order.
+///
+/// In HLSL mode, an `HLSLRowMajor` / `HLSLColumnMajor` AttributedType anywhere
+/// in the sugar chain of \p T (imprinted by Sema when a source decl carries
+/// `[[hlsl::row_major]]` / `[[hlsl::column_major]]`) takes precedence over the
+/// `-fmatrix-memory-layout=` default carried in \p LangOpts. Otherwise the
+/// LangOptions default is used.
+inline bool isMatrixRowMajor(const LangOptions &LangOpts, QualType T) {
+ if (LangOpts.HLSL && !T.isNull()) {
+QualType Cur = T;
+while (const auto *AT = Cur->getAs()) {
+ switch (AT->getAttrKind()) {
+ case attr::HLSLRowMajor:
+return true;
+ case attr::HLSLColumnMajor:
+return false;
+ default:
+break;
+ }
+ Cur = AT->getModifiedType();
+}
+ }
+ return LangOpts.getDefaultMatrixMemoryLayout() ==
+ LangOptions::MatrixMemoryLayout::MatrixRowMajor;
+}
+
+/// Returns true if matrices of \p T should be laid out in column-major order.
+/// Mirrors `isMatrixRowMajor`; per-decl HLSL attributes win over the
+/// `-fmatrix-memory-layout=` default.
+inline bool isMatrixColumnMajor(const LangOptions &LangOpts, QualType T) {
+ if (LangOpts.HLSL && !T.isNull()) {
+QualType Cur = T;
+while (const auto *AT = Cur->getAs()) {
+ switch (AT->getAttrKind()) {
+ case attr::HLSLColumnMajor:
+return true;
+ case attr::HLSLRowMajor:
+return false;
+ default:
+break;
+ }
+ Cur = AT->getModifiedType();
+}
+ }
+ return LangOpts.getDefaultMatrixMemoryLayout() ==
+ LangOptions::MatrixMemoryLayout::MatrixColMajor;
+}
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATRIXUTILS_H
diff --git a/clang/include/clang/Basic/Attr.td
b/clang/include/clang/Basic/Attr.td
index 32f72e8da960e..accb3ca3c4ce7 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -5299,6 +5299,22 @@ def HLSLMatrixLayout : InheritableAttr {
let Documentation = [HLSLMatrixLayoutDocs];
}
+// Internal type-attribute markers attached to matrix QualTypes by Sema when
+// a decl carries `[[hlsl::row_major]]` / `[[hlsl::column_major]]`. They let
+// CodeGen / const-eval recover the layout from any matrix-typed expression
+// without re-walking back to the source decl.
+def HLSLRowMajor : TypeAttr {
+ let Spellings = [];
+ let LangOpts = [HLSL];
+ let Documentation = [InternalOnly];
+}
+
+def HLSLColumnMajor : TypeAttr {
+ let Spellings = [];
+ let LangOpts = [HLSL];
+ let Documentation = [InternalOnly];
+}
+
def RandomizeLayout : InheritableAttr {
let Spellings = [GCC<"randomize_layout">];
let Subjects = SubjectList<[Record]>;
diff -
[clang] [Matrix][HLSL] Add codegen support for Matrix Layout keywords (PR #198887)
@@ -2704,60 +2704,76 @@ static bool isMatrixOrArrayOfMatrix(const ASTContext
&Ctx, QualType QT) {
return Ty->isDependentType() || Ty->isConstantMatrixType();
}
-static bool diagnoseMatrixLayoutOnNonMatrix(Sema &SemaRef, Decl *D,
-SourceLocation Loc,
-const IdentifierInfo *AttrName) {
- QualType Ty;
- if (auto *VD = dyn_cast(D))
-Ty = VD->getType();
- else if (auto *TD = dyn_cast(D))
-Ty = TD->getUnderlyingType();
-
- if (Ty.isNull() || Ty->isDependentType())
-return false;
-
- // For functions, the qualifier can apply to the return type or any
parameter.
- if (const auto *FPT = Ty->getAs()) {
-if (isMatrixOrArrayOfMatrix(SemaRef.getASTContext(), FPT->getReturnType()))
- return false;
-SemaRef.Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << AttrName;
-return true;
+/// Walks the existing AttributedType sugar of \p T looking for a previously
+/// applied HLSLRowMajor/HLSLColumnMajor marker. If one is found, populates
+/// \p ExistingKind with its attr::Kind and returns true.
+static bool findExistingMatrixLayoutMarker(QualType T,
+ attr::Kind &ExistingKind) {
+ QualType Cur = T;
+ while (const auto *AT = Cur->getAs()) {
+attr::Kind K = AT->getAttrKind();
+if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
+ ExistingKind = K;
+ return true;
+}
+Cur = AT->getModifiedType();
}
+ return false;
+}
- if (isMatrixOrArrayOfMatrix(SemaRef.getASTContext(), Ty))
-return false;
+Attr *SemaHLSL::buildMatrixLayoutTypeAttr(QualType T, const ParsedAttr &AL) {
+ ASTContext &Ctx = getASTContext();
+ attr::Kind AttrK = AL.getKind() == ParsedAttr::AT_HLSLRowMajor
+ ? attr::HLSLRowMajor
+ : attr::HLSLColumnMajor;
- SemaRef.Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << AttrName;
- return true;
-}
+ if (T.isNull())
+return nullptr;
-void SemaHLSL::handleMatrixLayoutAttr(Decl *D, const ParsedAttr &AL) {
- // row_major and column_major are only valid on matrix types.
- if (diagnoseMatrixLayoutOnNonMatrix(SemaRef, D, AL.getLoc(),
- AL.getAttrName()))
-return;
+ // For non-dependent types, the operand must be a matrix (or array of
+ // matrices).
+ if (!T->isDependentType() && !isMatrixOrArrayOfMatrix(Ctx, T)) {
+Diag(AL.getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
+<< AL.getAttrName();
+AL.setInvalid();
+return nullptr;
+ }
- // Check for conflicting or duplicate matrix layout attributes.
- if (const auto *Existing = D->getAttr()) {
-if (Existing->getSemanticSpelling() != AL.getSemanticSpelling()) {
- Diag(AL.getLoc(), diag::err_hlsl_matrix_layout_conflict)
- << AL.getAttrName() << Existing->getAttrName();
- Diag(Existing->getLoc(), diag::note_conflicting_attribute);
-} else {
+ // Conflict / duplicate detection by walking existing sugar.
+ attr::Kind ExistingKind;
+ if (findExistingMatrixLayoutMarker(T, ExistingKind)) {
+if (ExistingKind == AttrK) {
Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact)
<< AL.getAttrName();
- Diag(Existing->getLoc(), diag::note_previous_attribute);
+ Diag(AL.getLoc(), diag::note_previous_attribute);
+ return nullptr;
}
-return;
+IdentifierInfo *ExistingII = &Ctx.Idents.get(
+ExistingKind == attr::HLSLRowMajor ? "row_major" : "column_major");
+Diag(AL.getLoc(), diag::err_hlsl_matrix_layout_conflict)
+<< AL.getAttrName() << ExistingII;
+Diag(AL.getLoc(), diag::note_conflicting_attribute);
+AL.setInvalid();
+return nullptr;
}
- D->addAttr(::new (getASTContext()) HLSLMatrixLayoutAttr(getASTContext(),
AL));
+ if (AttrK == attr::HLSLRowMajor)
+return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
+ return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
}
-bool SemaHLSL::diagnoseInstantiatedMatrixLayoutAttr(
-Decl *D, const HLSLMatrixLayoutAttr *Attr) {
- return diagnoseMatrixLayoutOnNonMatrix(SemaRef, D, Attr->getLoc(),
- Attr->getAttrName());
+bool SemaHLSL::diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T,
+ SourceLocation Loc) {
farzonl wrote:
actually just fed in my comment to claude and it thinks this is better
```
// Re-validates an HLSL `row_major` / `column_major` attribute after template
// substitution. The parse-time check in `buildMatrixLayoutTypeAttr` is skipped
// for dependent types; `TransformAttributedType` calls this once the type is
// concrete. Returns `true` (and emits a diagnostic) if the substituted type is
// not a matrix or array of matrices, signaling the caller to abort the
// transform.
```
https://github.com/llvm/llvm-project/pull/198887
_
[clang] [Matrix][HLSL] Add codegen support for Matrix Layout keywords (PR #198887)
@@ -2704,60 +2704,76 @@ static bool isMatrixOrArrayOfMatrix(const ASTContext
&Ctx, QualType QT) {
return Ty->isDependentType() || Ty->isConstantMatrixType();
}
-static bool diagnoseMatrixLayoutOnNonMatrix(Sema &SemaRef, Decl *D,
-SourceLocation Loc,
-const IdentifierInfo *AttrName) {
- QualType Ty;
- if (auto *VD = dyn_cast(D))
-Ty = VD->getType();
- else if (auto *TD = dyn_cast(D))
-Ty = TD->getUnderlyingType();
-
- if (Ty.isNull() || Ty->isDependentType())
-return false;
-
- // For functions, the qualifier can apply to the return type or any
parameter.
- if (const auto *FPT = Ty->getAs()) {
-if (isMatrixOrArrayOfMatrix(SemaRef.getASTContext(), FPT->getReturnType()))
- return false;
-SemaRef.Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << AttrName;
-return true;
+/// Walks the existing AttributedType sugar of \p T looking for a previously
+/// applied HLSLRowMajor/HLSLColumnMajor marker. If one is found, populates
+/// \p ExistingKind with its attr::Kind and returns true.
+static bool findExistingMatrixLayoutMarker(QualType T,
+ attr::Kind &ExistingKind) {
+ QualType Cur = T;
+ while (const auto *AT = Cur->getAs()) {
+attr::Kind K = AT->getAttrKind();
+if (K == attr::HLSLRowMajor || K == attr::HLSLColumnMajor) {
+ ExistingKind = K;
+ return true;
+}
+Cur = AT->getModifiedType();
}
+ return false;
+}
- if (isMatrixOrArrayOfMatrix(SemaRef.getASTContext(), Ty))
-return false;
+Attr *SemaHLSL::buildMatrixLayoutTypeAttr(QualType T, const ParsedAttr &AL) {
+ ASTContext &Ctx = getASTContext();
+ attr::Kind AttrK = AL.getKind() == ParsedAttr::AT_HLSLRowMajor
+ ? attr::HLSLRowMajor
+ : attr::HLSLColumnMajor;
- SemaRef.Diag(Loc, diag::err_hlsl_matrix_layout_non_matrix) << AttrName;
- return true;
-}
+ if (T.isNull())
+return nullptr;
-void SemaHLSL::handleMatrixLayoutAttr(Decl *D, const ParsedAttr &AL) {
- // row_major and column_major are only valid on matrix types.
- if (diagnoseMatrixLayoutOnNonMatrix(SemaRef, D, AL.getLoc(),
- AL.getAttrName()))
-return;
+ // For non-dependent types, the operand must be a matrix (or array of
+ // matrices).
+ if (!T->isDependentType() && !isMatrixOrArrayOfMatrix(Ctx, T)) {
+Diag(AL.getLoc(), diag::err_hlsl_matrix_layout_non_matrix)
+<< AL.getAttrName();
+AL.setInvalid();
+return nullptr;
+ }
- // Check for conflicting or duplicate matrix layout attributes.
- if (const auto *Existing = D->getAttr()) {
-if (Existing->getSemanticSpelling() != AL.getSemanticSpelling()) {
- Diag(AL.getLoc(), diag::err_hlsl_matrix_layout_conflict)
- << AL.getAttrName() << Existing->getAttrName();
- Diag(Existing->getLoc(), diag::note_conflicting_attribute);
-} else {
+ // Conflict / duplicate detection by walking existing sugar.
+ attr::Kind ExistingKind;
+ if (findExistingMatrixLayoutMarker(T, ExistingKind)) {
+if (ExistingKind == AttrK) {
Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact)
<< AL.getAttrName();
- Diag(Existing->getLoc(), diag::note_previous_attribute);
+ Diag(AL.getLoc(), diag::note_previous_attribute);
+ return nullptr;
}
-return;
+IdentifierInfo *ExistingII = &Ctx.Idents.get(
+ExistingKind == attr::HLSLRowMajor ? "row_major" : "column_major");
+Diag(AL.getLoc(), diag::err_hlsl_matrix_layout_conflict)
+<< AL.getAttrName() << ExistingII;
+Diag(AL.getLoc(), diag::note_conflicting_attribute);
+AL.setInvalid();
+return nullptr;
}
- D->addAttr(::new (getASTContext()) HLSLMatrixLayoutAttr(getASTContext(),
AL));
+ if (AttrK == attr::HLSLRowMajor)
+return ::new (Ctx) HLSLRowMajorAttr(Ctx, AL);
+ return ::new (Ctx) HLSLColumnMajorAttr(Ctx, AL);
}
-bool SemaHLSL::diagnoseInstantiatedMatrixLayoutAttr(
-Decl *D, const HLSLMatrixLayoutAttr *Attr) {
- return diagnoseMatrixLayoutOnNonMatrix(SemaRef, D, Attr->getLoc(),
- Attr->getAttrName());
+bool SemaHLSL::diagnoseMatrixLayoutInstantiation(attr::Kind K, QualType T,
+ SourceLocation Loc) {
farzonl wrote:
Something like this:
```
// At parse time, row_major/column_major are validated to apply to a matrix.
// But in a template the attribute is attached to a dependent type. This helper
// catches the matrix layout at instantiation time.
```
https://github.com/llvm/llvm-project/pull/198887
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
