Author: Farzon Lotfi
Date: 2026-08-27T09:53:13-04:00
New Revision: 8e1857b4aeb8dc440df1133af678f3b94d7ffd05

URL: 
https://github.com/llvm/llvm-project/commit/8e1857b4aeb8dc440df1133af678f3b94d7ffd05
DIFF: 
https://github.com/llvm/llvm-project/commit/8e1857b4aeb8dc440df1133af678f3b94d7ffd05.diff

LOG: [HLSL][Driver][SPIRV] Add -fspv-use-legacy-buffer-matrix-order flag 
(#214575)

fixes https://github.com/llvm/llvm-project/issues/136941

This flag, mirroring DXC, opts into assuming row-major buffer bytes
instead, for compatibility with legacy shaders.

Outside of the driver change the raw buffers carry no layout metadata,
so matrix values loaded/stored via ByteAddressBuffer::Load<T>/Store<T>
are ambiguous (native layout is column-major).

- New __builtin_hlsl_resource_load_typed/store_typed builtins for the
templated ByteAddressBuffer Load<T>/Store<T> overloads
- CodeGen transposes matrix values via llvm.matrix.transpose when the
flag is set and the target is SPIR-V
- Plumb flag from driver -> cc1 -> new LangOpts bit

Assisted by Claude Sonnet 5 via CoPilot

Added: 
    clang/test/CodeGenHLSL/resources/ByteAddressBuffers-matrix-legacy-order.hlsl
    clang/test/Driver/dxc_fspv_use_legacy_buffer_matrix_order.hlsl

Modified: 
    clang/include/clang/Basic/Builtins.td
    clang/include/clang/Basic/LangOptions.def
    clang/include/clang/Options/Options.td
    clang/lib/CodeGen/CGHLSLBuiltins.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/HLSL.cpp
    clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
    clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
    clang/lib/Sema/SemaHLSL.cpp
    clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 968ff8e870295..0aec57f201301 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5317,6 +5317,12 @@ def HLSLResourceGetPointerTyped : Builtin {
   let Prototype = "void(...)";
 }
 
+def HLSLMaybeTransposeMatrix : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_transpose_if_memory_is_row_major"];
+  let Attributes = [NoThrow, Const, CustomTypeChecking];
+  let Prototype = "void(...)";
+}
+
 def HLSLResourceLoadWithStatus : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_resource_load_with_status"];
   let Attributes = [NoThrow];

diff  --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index f945b60b6966d..ad993ce7e5d95 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -250,6 +250,7 @@ ENUM_LANGOPT(HLSLVersion, HLSLLangStd, 16, HLSL_Unset, 
NotCompatible, "HLSL Vers
 LANGOPT(HLSLStrictAvailability, 1, 0, NotCompatible,
         "Strict availability diagnostic mode for HLSL built-in functions.")
 LANGOPT(HLSLSpvUseUnknownImageFormat, 1, 0, NotCompatible, "For storage images 
and texel buffers, sets the default format to 'Unknown' when not specified via 
the `vk::image_format` attribute. If this option is not used, the format is 
inferred from the resource's data type.")
+LANGOPT(HLSLSpvUseLegacyBufferMatrixOrder, 1, 0, NotCompatible, "Assume the 
legacy matrix order (row major) when accessing raw buffers (e.g. 
ByteAddressBuffer). Defaults to column major.")
 LANGOPT(HLSLSpvEnableMaximalReconvergence, 1, 0, NotCompatible, "Enables the 
MaximallyReconvergesKHR execution mode for this module. This ensures that 
control flow reconverges at well-defined merge points as defined by the Vulkan 
spec.")
 LANGOPT(HLSLSpvPreserveInterface, 1, 0, NotCompatible, "Preserve entry-point 
interface variables from dead-code elimination.")
 LANGOPT(EmitLogicalPointer, 1, 0, NotCompatible, "Allow emitting structured 
GEP/alloca intrinsics instead of normal GEP/alloca instructions.")

diff  --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index f5cd81279b343..d1d33e9bb6a95 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -10038,6 +10038,15 @@ def fhlsl_spv_use_unknown_image_format
                "from the resource's data type.">,
       MarshallingInfoFlag<LangOpts<"HLSLSpvUseUnknownImageFormat">>;
 
+def fhlsl_spv_use_legacy_buffer_matrix_order
+    : Flag<["-"], "fspv-use-legacy-buffer-matrix-order">,
+      Group<dxc_Group>,
+      Visibility<[CC1Option, DXCOption]>,
+      HelpText<"Assume the legacy matrix order (row major) when accessing "
+               "raw buffers (e.g. ByteAddressBuffer). Defaults to column "
+               "major.">,
+      MarshallingInfoFlag<LangOpts<"HLSLSpvUseLegacyBufferMatrixOrder">>;
+
 def fhlsl_spv_enable_maximal_reconvergence
     : Flag<["-"], "fspv-enable-maximal-reconvergence">,
       Group<dxc_Group>,

diff  --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp 
b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index b1b875bdb78df..8d74e7652ff49 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -665,6 +665,27 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
     CI->setCallingConv(IntrFn->getCallingConv());
     return CI;
   }
+  case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
+    const Expr *ValueExpr = E->getArg(0);
+    if (hasAggregateEvaluationKind(ValueExpr->getType())) {
+      EmitAnyExprToMem(ValueExpr, ReturnValue.getAddress(),
+                       ValueExpr->getType().getQualifiers(), /*IsInit=*/true);
+      return ReturnValue.getAddress().getBasePointer();
+    }
+
+    Value *ValueOp = EmitScalarExpr(ValueExpr);
+    const auto *MatTy = ValueExpr->getType()->getAs<ConstantMatrixType>();
+    if (!MatTy || !getLangOpts().HLSLSpvUseLegacyBufferMatrixOrder)
+      return ValueOp;
+
+    bool IsLoad =
+        E->getArg(1)->EvaluateKnownConstInt(getContext()).getBoolValue();
+    unsigned Rows = MatTy->getNumRows();
+    unsigned Columns = MatTy->getNumColumns();
+    llvm::MatrixBuilder MB(Builder);
+    return IsLoad ? MB.CreateMatrixTranspose(ValueOp, Columns, Rows)
+                  : MB.CreateMatrixTranspose(ValueOp, Rows, Columns);
+  }
   case Builtin::BI__builtin_hlsl_resource_sample: {
     Value *HandleOp = EmitScalarExpr(E->getArg(0));
     Value *SamplerOp = EmitScalarExpr(E->getArg(1));

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index b081265412752..b86f15918a554 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3972,6 +3972,7 @@ static void RenderHLSLOptions(const Driver &D, const 
ArgList &Args,
       options::OPT_fdx_rootsignature_define,
       options::OPT_fdx_rootsignature_version,
       options::OPT_fhlsl_spv_use_unknown_image_format,
+      options::OPT_fhlsl_spv_use_legacy_buffer_matrix_order,
       options::OPT_fhlsl_spv_enable_maximal_reconvergence,
       options::OPT_fhlsl_spv_preserve_interface};
   if (!types::isHLSL(InputType))

diff  --git a/clang/lib/Driver/ToolChains/HLSL.cpp 
b/clang/lib/Driver/ToolChains/HLSL.cpp
index 558408cc969f0..9e7005b8798f2 100644
--- a/clang/lib/Driver/ToolChains/HLSL.cpp
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -533,6 +533,15 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, 
BoundArch BA,
       continue;
     }
 
+    if (A->getOption().getID() ==
+            options::OPT_fhlsl_spv_use_legacy_buffer_matrix_order &&
+        getArch() != llvm::Triple::spirv) {
+      getDriver().Diag(diag::err_drv_argument_only_allowed_with)
+          << A->getAsString(Args) << "-spirv";
+      A->claim();
+      continue;
+    }
+
     if (A->getOption().getID() == options::OPT_enable_16bit_types) {
       // Translate -enable-16bit-types into -fnative-half-type and
       // -fnative-int16-type

diff  --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 744edd8713291..35caa0a740235 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1671,13 +1671,14 @@ 
BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
 
   ASTContext &AST = SemaRef.getASTContext();
 
-  auto AddLoads = [&](StringRef MethodName, QualType ReturnType) {
+  auto AddLoads = [&](StringRef MethodName, QualType ReturnType,
+                      bool TransposeResult = false) {
     IdentifierInfo &II = AST.Idents.get(MethodName, 
tok::TokenKind::identifier);
     DeclarationName Load(&II);
 
     addHandleAccessFunction(Load,
                             /*IsConstReturn=*/false, /*IsRef=*/false,
-                            AST.UnsignedIntTy, ReturnType);
+                            AST.UnsignedIntTy, ReturnType, TransposeResult);
     addLoadWithStatusFunction(Load, ReturnType);
   };
 
@@ -1685,7 +1686,10 @@ 
BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
   AddLoads("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
   AddLoads("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
   AddLoads("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
-  AddLoads("Load", AST.DependentTy); // Templated version
+
+  // Templated Load<T>() needs buffer-order-aware handling for matrix T.
+  AddLoads("Load", AST.DependentTy, /*TransposeResult=*/true);
+
   return *this;
 }
 
@@ -1695,18 +1699,21 @@ 
BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
 
   ASTContext &AST = SemaRef.getASTContext();
 
-  auto AddStore = [&](StringRef MethodName, QualType ValueType) {
+  auto AddStore = [&](StringRef MethodName, QualType ValueType,
+                      bool TransposeArg = false) {
     IdentifierInfo &II = AST.Idents.get(MethodName, 
tok::TokenKind::identifier);
     DeclarationName Store(&II);
 
-    addStoreFunction(Store, /*IsConst=*/false, ValueType);
+    addStoreFunction(Store, /*IsConst=*/false, ValueType, TransposeArg);
   };
 
   AddStore("Store", AST.UnsignedIntTy);
   AddStore("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
   AddStore("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
   AddStore("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
-  AddStore("Store", AST.DependentTy); // Templated version
+
+  // Templated Store<T>(); see addByteAddressBufferLoadMethods() above.
+  AddStore("Store", AST.DependentTy, /*TransposeArg=*/true);
 
   return *this;
 }
@@ -2453,7 +2460,7 @@ 
BuiltinTypeDeclBuilder::addLoadWithStatusFunction(DeclarationName &Name,
 
 BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleAccessFunction(
     DeclarationName &Name, bool IsConstReturn, bool IsRef, QualType IndexTy,
-    QualType ElemTy) {
+    QualType ElemTy, bool TransposeResult) {
   assert(!Record->isCompleteDefinition() && "record is already complete");
   ASTContext &AST = SemaRef.getASTContext();
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
@@ -2493,12 +2500,16 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeDeclBuilder::addHandleAccessFunction(
     MMB.callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, 
PH::Handle,
                     PH::_0);
 
-  return MMB.dereference(PH::LastStmt).finalize();
+  MMB.dereference(PH::LastStmt);
+  if (TransposeResult)
+    MMB.callBuiltin("__builtin_hlsl_transpose_if_memory_is_row_major", ElemTy,
+                    PH::LastStmt, getConstantIntExpr(1));
+  return MMB.finalize();
 }
 
 BuiltinTypeDeclBuilder &
 BuiltinTypeDeclBuilder::addStoreFunction(DeclarationName &Name, bool IsConst,
-                                         QualType ValueTy) {
+                                         QualType ValueTy, bool TransposeArg) {
   assert(!Record->isCompleteDefinition() && "record is already complete");
   ASTContext &AST = SemaRef.getASTContext();
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
@@ -2511,13 +2522,15 @@ 
BuiltinTypeDeclBuilder::addStoreFunction(DeclarationName &Name, bool IsConst,
       AST.getAddrSpaceQualType(ValueTy, LangAS::hlsl_device);
   QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
 
-  return MMB.addParam("Index", AST.UnsignedIntTy)
-      .addParam("Value", ValueTy)
-      .callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
-                   PH::Handle, PH::_0, ValueTy)
+  MMB.addParam("Index", AST.UnsignedIntTy).addParam("Value", ValueTy);
+  if (TransposeArg)
+    MMB.callBuiltin("__builtin_hlsl_transpose_if_memory_is_row_major", ValueTy,
+                    PH::_1, getConstantIntExpr(0));
+  MMB.callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
+                  PH::Handle, PH::_0, ValueTy)
       .dereference(PH::LastStmt)
-      .assign(PH::LastStmt, PH::_1)
-      .finalize();
+      .assign(PH::LastStmt, TransposeArg ? PH::LastStmt : PH::_1);
+  return MMB.finalize();
 }
 
 BuiltinTypeDeclBuilder &

diff  --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 48c0bb514759c..c9bc92b7d0f15 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -137,12 +137,14 @@ class BuiltinTypeDeclBuilder {
   BuiltinTypeDeclBuilder &addHandleAccessFunction(DeclarationName &Name,
                                                   bool IsConstReturn,
                                                   bool IsRef, QualType IndexTy,
-                                                  QualType ElemTy = 
QualType());
+                                                  QualType ElemTy = QualType(),
+                                                  bool TransposeResult = 
false);
   BuiltinTypeDeclBuilder &
   addLoadWithStatusFunction(DeclarationName &Name,
                             QualType ReturnTy = QualType());
   BuiltinTypeDeclBuilder &addStoreFunction(DeclarationName &Name, bool IsConst,
-                                           QualType ValueType);
+                                           QualType ValueType,
+                                           bool TransposeArg = false);
   BuiltinTypeDeclBuilder &
   addByteAddressBufferInterlockedMethod(StringRef MethodName, QualType ValueTy,
                                         StringRef BuiltinName);

diff  --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index af94416aa835d..99c2191ec3787 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4287,6 +4287,16 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned 
BuiltinID, CallExpr *TheCall) {
 
     break;
   }
+  case Builtin::BI__builtin_hlsl_transpose_if_memory_is_row_major: {
+    if (SemaRef.checkArgCount(TheCall, 2) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
+                            SemaRef.getASTContext().IntTy))
+      return true;
+
+    TheCall->setType(TheCall->getArg(0)->getType());
+
+    break;
+  }
   case Builtin::BI__builtin_hlsl_resource_load_with_status: {
     if (SemaRef.checkArgCount(TheCall, 3) ||
         CheckResourceHandle(&SemaRef, TheCall, 0) ||

diff  --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl 
b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 55db9a936ae15..d6d2aa0819e7b 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -298,6 +298,9 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-LOAD-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_transpose_if_memory_is_row_major' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue 
prefix '*' cannot overflow
 // CHECK-LOAD-NEXT: CStyleCastExpr {{.*}} 'hlsl_device element_type *' 
<Dependent>
 // CHECK-LOAD-NEXT: CallExpr {{.*}} '<dependent type>'
@@ -306,6 +309,7 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue 
implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 
'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'element_type *'
+// CHECK-LOAD-NEXT: IntegerLiteral {{.*}} 'int' 1
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out 
unsigned int)
@@ -410,7 +414,11 @@ RESOURCE Buffer;
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit 
this
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 
'Index' 'unsigned int'
 // CHECK-STORE-NEXT: CXXScalarValueInitExpr {{.*}} 'element_type *'
+// CHECK-STORE-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent>
+// CHECK-STORE-NEXT: CallExpr {{.*}} '<dependent type>'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_transpose_if_memory_is_row_major' 'void (...) noexcept'
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'element_type' lvalue ParmVar {{.*}} 
'Value' 'element_type'
+// CHECK-STORE-NEXT: IntegerLiteral {{.*}} 'int' 0
 // CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // GetDimensions method

diff  --git 
a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-matrix-legacy-order.hlsl 
b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-matrix-legacy-order.hlsl
new file mode 100644
index 0000000000000..e1ee18a697373
--- /dev/null
+++ 
b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-matrix-legacy-order.hlsl
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan-library 
-finclude-default-header \
+// RUN:   -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,DEFAULT
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan-library 
-finclude-default-header \
+// RUN:   -fspv-use-legacy-buffer-matrix-order -emit-llvm -disable-llvm-passes 
-o - %s \
+// RUN:   | FileCheck %s --check-prefixes=CHECK,LEGACY
+
+// Raw buffers carry no layout information. By default, a matrix read from or
+// written to a raw buffer is assumed to be stored in column-major order,
+// matching the native in-register representation, so no reordering is
+// needed. -fspv-use-legacy-buffer-matrix-order assumes the raw bytes are
+// stored in row-major order instead, which requires transposing the loaded
+// (or, before storing, the to-be-stored) value.
+
+ByteAddressBuffer Buf : register(t0);
+RWByteAddressBuffer RWBuf : register(u0);
+
+export float2x3 TestLoad() {
+  return Buf.Load<float2x3>(0);
+}
+
+// CHECK-LABEL: define {{.*}} <6 x float> 
@{{.*}}ByteAddressBuffer4LoadIu11matrix_typeILj2ELj3EfEEET_j
+// CHECK: [[LOADED:%.*]] = load <6 x float>, ptr addrspace(11) %{{.*}}
+// DEFAULT-NOT: call {{.*}} @llvm.matrix.transpose
+// DEFAULT: ret <6 x float> [[LOADED]]
+// LEGACY: [[TRANSPOSED:%.*]] = call {{.*}} <6 x float> 
@llvm.matrix.transpose.v6f32(<6 x float> [[LOADED]], i32 3, i32 2)
+// LEGACY: ret <6 x float> [[TRANSPOSED]]
+
+export void TestStore(float2x3 M) {
+  RWBuf.Store<float2x3>(0, M);
+}
+
+// CHECK-LABEL: define {{.*}} void 
@{{.*}}RWByteAddressBuffer5StoreIu11matrix_typeILj2ELj3EfEEEvjT_
+// CHECK: [[VALUE:%.*]] = load <6 x float>, ptr %Value.addr
+// DEFAULT-NOT: call {{.*}} @llvm.matrix.transpose
+// DEFAULT: store <6 x float> [[VALUE]], ptr addrspace(11) %{{.*}}
+// LEGACY: [[TRANSPOSED:%.*]] = call {{.*}} <6 x float> 
@llvm.matrix.transpose.v6f32(<6 x float> [[VALUE]], i32 2, i32 3)
+// LEGACY: store <6 x float> [[TRANSPOSED]], ptr addrspace(11) %{{.*}}

diff  --git a/clang/test/Driver/dxc_fspv_use_legacy_buffer_matrix_order.hlsl 
b/clang/test/Driver/dxc_fspv_use_legacy_buffer_matrix_order.hlsl
new file mode 100644
index 0000000000000..f63985c7745a6
--- /dev/null
+++ b/clang/test/Driver/dxc_fspv_use_legacy_buffer_matrix_order.hlsl
@@ -0,0 +1,17 @@
+// Verify that -fspv-use-legacy-buffer-matrix-order is accepted by the driver
+// and forwarded to cc1 as -fspv-use-legacy-buffer-matrix-order.
+// RUN: %clang_dxc -spirv -Tlib_6_7 -fspv-use-legacy-buffer-matrix-order -### 
%s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-LEGACY
+// CHECK-LEGACY: "-fspv-use-legacy-buffer-matrix-order"
+
+// Without the flag, -fspv-use-legacy-buffer-matrix-order must not appear in
+// cc1 args.
+// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-NO-LEGACY
+// CHECK-NO-LEGACY-NOT: "-fspv-use-legacy-buffer-matrix-order"
+
+// The flag requires -spirv.
+// RUN: not %clang_dxc -Tlib_6_7 -fspv-use-legacy-buffer-matrix-order -### %s 
2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-NO-SPIRV
+// CHECK-NO-SPIRV: error: invalid argument 
'-fspv-use-legacy-buffer-matrix-order' only allowed with '-spirv'
+


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to