فهرست منبع

Support nested struct in IsTypeMatchForMemcpy (#2346)

* Add TypeAnnotation for static global and support nested struct in IsTypeMatchForMemcpy.
Xiang Li 6 سال پیش
والد
کامیت
9b2139f762
2فایلهای تغییر یافته به همراه59 افزوده شده و 5 حذف شده
  1. 30 5
      tools/clang/lib/CodeGen/CGHLSLMS.cpp
  2. 29 0
      tools/clang/test/CodeGenHLSL/batch/declarations/globals/array_cast.hlsl

+ 30 - 5
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -2402,6 +2402,10 @@ void CGMSHLSLRuntime::addResource(Decl *D) {
           staticConstGlobalInitMap[InitExp] = GV;
           staticConstGlobalInitMap[InitExp] = GV;
         }
         }
       }
       }
+      // Add type annotation for static global variable.
+      DxilTypeSystem &typeSys = m_pHLModule->GetTypeSystem();
+      unsigned arrayEltSize = 0;
+      AddTypeAnnotation(VD->getType(), typeSys, arrayEltSize);
       return;
       return;
     }
     }
 
 
@@ -7067,6 +7071,30 @@ void CGMSHLSLRuntime::EmitHLSLAggregateCopy(CodeGenFunction &CGF, llvm::Value *S
     SmallVector<Value *, 4> idxList;
     SmallVector<Value *, 4> idxList;
     EmitHLSLAggregateCopy(CGF, SrcPtr, DestPtr, idxList, Ty, Ty, SrcPtr->getType());
     EmitHLSLAggregateCopy(CGF, SrcPtr, DestPtr, idxList, Ty, Ty, SrcPtr->getType());
 }
 }
+
+// Make sure all element type of struct is same type.
+static bool IsStructWithSameElementType(llvm::StructType *ST, llvm::Type *Ty) {
+  for (llvm::Type *EltTy : ST->elements()) {
+    if (StructType *EltSt = dyn_cast<StructType>(EltTy)) {
+      if (!IsStructWithSameElementType(EltSt, Ty))
+        return false;
+    } else if (llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(EltTy)) {
+      llvm::Type *ArrayEltTy = dxilutil::GetArrayEltTy(AT);
+      if (ArrayEltTy == Ty) {
+        continue;
+      } else if (StructType *EltSt = dyn_cast<StructType>(EltTy)) {
+        if (!IsStructWithSameElementType(EltSt, Ty))
+          return false;
+      } else {
+        return false;
+      }
+
+    } else if (EltTy != Ty)
+      return false;
+  }
+  return true;
+}
+
 // To memcpy, need element type match.
 // To memcpy, need element type match.
 // For struct type, the layout should match in cbuffer layout.
 // For struct type, the layout should match in cbuffer layout.
 // struct { float2 x; float3 y; } will not match struct { float3 x; float2 y; }.
 // struct { float2 x; float3 y; } will not match struct { float3 x; float2 y; }.
@@ -7097,11 +7125,8 @@ static bool IsTypeMatchForMemcpy(llvm::Type *SrcTy, llvm::Type *DestTy) {
       return false;
       return false;
     if (Ty->getVectorNumElements() != 4)
     if (Ty->getVectorNumElements() != 4)
       return false;
       return false;
-    for (llvm::Type *EltTy : ST->elements()) {
-      if (EltTy != Ty)
-        return false;
-    }
-    return true;
+
+    return IsStructWithSameElementType(ST, Ty);
   }
   }
 }
 }
 
 

+ 29 - 0
tools/clang/test/CodeGenHLSL/batch/declarations/globals/array_cast.hlsl

@@ -0,0 +1,29 @@
+// RUN: %dxc -E main -T ps_6_0 > %s | FileCheck %s
+
+// Make sure cast to nest struct works.
+
+// Test that no variable initializers are emitted, especially for cbuffers globals.
+// CHECK-NOT: {{.*}} = constant
+// Check the offset calculate.
+// CHECK: mul i32 {{.+}}, 5
+// CHECK: add i32 {{.+}}, 2
+
+float4 cb[5*4];
+
+struct N {
+  float4 b;
+  float4 c;
+};
+
+struct A {
+  float4 a;
+  N      n;
+  float4 d[2];
+};
+
+static const A a[4] = cb;
+
+
+float4 main(int i:I) : SV_Target {
+  return a[i].n.c + cb[i] + a[i+1].d[i%2];
+}