[clang] Clang][HLSL] Emit constant matrix values in column-major order (PR #227356)

Farzon Lotfi via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 29 08:52:32 PDT 2026


https://github.com/farzonl created https://github.com/llvm/llvm-project/pull/227356

Emit matrix APValues in the canonical column-major register layout, independent of the selected matrix memory layout.

When a constant is used as a row-major memory initializer, reorder its elements at the register-to-memory boundary. This preserves the physical layout of global and static row-major matrices while ensuring constexpr matrix expressions produce canonical register values.

Assisted by Cop-pilot GPT 5.6-Sol

>From 2177db6988a358127da874a03580ffc9a82e5fc5 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 29 Sep 2026 11:48:59 -0400
Subject: [PATCH] Clang][HLSL] Emit constant matrix values in column-major
 order

Emit matrix APValues in the canonical column-major register layout,
independent of the selected matrix memory layout.

When a constant is used as a row-major memory initializer, reorder its
elements at the register-to-memory boundary. This preserves the physical
layout of global and static row-major matrices while ensuring constexpr
matrix expressions produce canonical register values.

Assisted by Cop-pilot GPT 5.6-Sol
---
 clang/lib/CodeGen/CGExprConstant.cpp              | 15 ++++++++++++---
 .../BasicFeatures/MatrixInitializerListOrder.hlsl | 11 +++++++++++
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 3d8fefb4988b7..917be246b7346 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -2087,6 +2087,17 @@ llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
     }
   }
 
+  if (destType->isConstantMatrixType() &&
+      isMatrixRowMajor(CGM.getLangOpts(), destType)) {
+    const auto *MT = destType->castAs<ConstantMatrixType>();
+    SmallVector<llvm::Constant *, 16> Inits(MT->getNumElementsFlattened());
+    for (unsigned Row = 0; Row != MT->getNumRows(); ++Row)
+      for (unsigned Col = 0; Col != MT->getNumColumns(); ++Col)
+        Inits[MT->getRowMajorFlattenedIndex(Row, Col)] =
+            C->getAggregateElement(MT->getColumnMajorFlattenedIndex(Row, Col));
+    return llvm::ConstantVector::get(Inits);
+  }
+
   return C;
 }
 
@@ -2667,12 +2678,10 @@ ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
     unsigned NumElts = NumRows * NumCols;
     SmallVector<llvm::Constant *, 16> Inits(NumElts);
 
-    bool IsRowMajor = isMatrixRowMajor(CGM.getLangOpts(), DestType);
-
     for (unsigned Row = 0; Row != NumRows; ++Row) {
       for (unsigned Col = 0; Col != NumCols; ++Col) {
         const APValue &Elt = Value.getMatrixElt(Row, Col);
-        unsigned Idx = MT->getFlattenedIndex(Row, Col, IsRowMajor);
+        unsigned Idx = MT->getColumnMajorFlattenedIndex(Row, Col);
         if (Elt.isInt())
           Inits[Idx] =
               llvm::ConstantInt::get(CGM.getLLVMContext(), Elt.getInt());
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/MatrixInitializerListOrder.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/MatrixInitializerListOrder.hlsl
index 97ebe1712e9c7..d5879d7cdd5b4 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/MatrixInitializerListOrder.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixInitializerListOrder.hlsl
@@ -11,6 +11,17 @@
 // The register value is reordered to col0=[1,4], col1=[2,5], col2=[3,6] =
 // <1,4,2,5,3,6>. Row-major memory layout transposes that value at the store.
 
+constexpr float2x3 make_matrix() {
+  return float2x3(1, 2, 3, 4, 5, 6);
+}
+
+export float2x3 return_constexpr_matrix() {
+// CHECK-LABEL: define {{.*}} <6 x float> @_Z23return_constexpr_matrixv
+// CHECK: ret <6 x float> <float 1.000000e+00, float 4.000000e+00, float 2.000000e+00, float 5.000000e+00, float 3.000000e+00, float 6.000000e+00>
+  constexpr float2x3 value = make_matrix();
+  return value;
+}
+
 export float test_row0_col2() {
 // CHECK-LABEL: define {{.*}} float @_Z14test_row0_col2v
 // COL-CHECK: store <6 x float> <float 1.000000e+00, float 4.000000e+00, float 2.000000e+00, float 5.000000e+00, float 3.000000e+00, float 6.000000e+00>



More information about the cfe-commits mailing list