소스 검색

Don't copy matrix arrays elementwise if orientations match.

Tristan Labelle 6 년 전
부모
커밋
5e4446344f

+ 17 - 1
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -6655,6 +6655,20 @@ void CGMSHLSLRuntime::ConvertAndStoreElements(CodeGenFunction &CGF,
   }
 }
 
+static bool AreMatrixArrayOrientationMatching(ASTContext& Context,
+  HLModule &Module, QualType LhsTy, QualType RhsTy) {
+  while (const clang::ArrayType *LhsArrayTy = Context.getAsArrayType(LhsTy)) {
+    LhsTy = LhsArrayTy->getElementType();
+    RhsTy = Context.getAsArrayType(RhsTy)->getElementType();
+  }
+
+  bool LhsRowMajor, RhsRowMajor;
+  LhsRowMajor = RhsRowMajor = Module.GetHLOptions().bDefaultRowMajor;
+  HasHLSLMatOrientation(LhsTy, &LhsRowMajor);
+  HasHLSLMatOrientation(RhsTy, &RhsRowMajor);
+  return LhsRowMajor == RhsRowMajor;
+}
+
 // Copy data from SrcPtr to DestPtr.
 // For matrix, use MatLoad/MatStore.
 // For matrix array, EmitHLSLAggregateCopy on each element.
@@ -6691,13 +6705,15 @@ void CGMSHLSLRuntime::EmitHLSLAggregateCopy(
     // Memcpy struct.
     CGF.Builder.CreateMemCpy(dstGEP, srcGEP, size, 1);
   } else if (llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Ty)) {
-    if (!HLMatrixType::isMatrixArray(Ty)) {
+    if (!HLMatrixType::isMatrixArray(Ty)
+      || AreMatrixArrayOrientationMatching(CGF.getContext(), *m_pHLModule, SrcType, DestType)) {
       Value *srcGEP = CGF.Builder.CreateInBoundsGEP(SrcPtr, idxList);
       Value *dstGEP = CGF.Builder.CreateInBoundsGEP(DestPtr, idxList);
       unsigned size = this->TheModule.getDataLayout().getTypeAllocSize(AT);
       // Memcpy non-matrix array.
       CGF.Builder.CreateMemCpy(dstGEP, srcGEP, size, 1);
     } else {
+      // Copy matrix arrays elementwise if orientation changes are needed.
       llvm::Type *ET = AT->getElementType();
       QualType EltDestType = CGF.getContext().getBaseElementType(DestType);
       QualType EltSrcType = CGF.getContext().getBaseElementType(SrcType);

+ 2 - 1
tools/clang/lib/Sema/SemaHLSL.cpp

@@ -3681,7 +3681,8 @@ public:
       type = RefType ? RefType->getPointeeType() : AttrType->getEquivalentType();
     }
 
-    return type->getCanonicalTypeUnqualified();
+    // Despite its name, getCanonicalTypeUnqualified will preserve const for array elements or something
+    return QualType(type->getCanonicalTypeUnqualified()->getTypePtr(), 0);
   }
 
   /// <summary>Given a Clang type, return the ArBasicKind classification for its contents.</summary>

+ 24 - 0
tools/clang/test/CodeGenHLSL/quick-test/matrix_array_arg_copy_optimized_away.hlsl

@@ -0,0 +1,24 @@
+// RUN: %dxc -E main -T vs_6_2 %s | FileCheck %s
+
+// Regression test for a bug where matrix array arguments would get expanded
+// into elementwise copies to respect pass-by-value semantics in case orientation
+// changes were needed, but the pattern would not be cleaned up by later optimization passes.
+
+const int1x1 cb_matrices[64];
+const row_major int1x1 cb_matrices_rm[64];
+const int cb_index;
+
+int get_cm(column_major int1x1 matrices[64]) { return matrices[cb_index]; }
+int get_rm(row_major int1x1 matrices[64]) { return matrices[cb_index]; }
+
+int2 main() : OUT
+{
+    // There should be no dynamic GEP of an array,
+    // we should be dynamically indexing the constant buffer directly
+    // CHECK-NOT: getelementptr
+    return int2(
+        // CHECK: call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %{{.*}}, i32 %{{.*}})
+        get_cm(cb_matrices), // Test implicit column major to explicit column major (no conversion needed)
+        // CHECK: call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %{{.*}}, i32 %{{.*}})
+        get_rm(cb_matrices_rm)); // Test explicit row major to explicit row major (no conversion needed)
+}