ソースを参照

Improve matrix and constant buffer debug info. (#2076)

- Hijack dwarf debug info to present matrices as having _11 to _44 fields, similar to vectors
- Better preservation of debug info for constant buffer loads
- Improve and rename resource loading tests
- Improve and reorganize vector members tests, adding matrix members test
Tristan Labelle 6 年 前
コミット
55b29a12c4

+ 2 - 0
lib/HLSL/HLOperationLower.cpp

@@ -5500,6 +5500,7 @@ void TranslateCBAddressUserLegacy(Instruction *user, Value *handle,
       Value *newLd = TranslateConstBufMatLdLegacy(
         MatTy, handle, legacyIdx, colMajor, hlslOP, /*memElemRepr*/false, DL, Builder);
       CI->replaceAllUsesWith(newLd);
+      dxilutil::ScatterDebugValueToVectorElements(newLd);
       CI->eraseFromParent();
     } else if (group == HLOpcodeGroup::HLSubscript) {
       HLSubscriptOpcode subOp = static_cast<HLSubscriptOpcode>(opcode);
@@ -5668,6 +5669,7 @@ void TranslateCBAddressUserLegacy(Instruction *user, Value *handle,
                                    hlslOP, Builder);
 
     ldInst->replaceAllUsesWith(newLd);
+    if (Ty->isVectorTy()) dxilutil::ScatterDebugValueToVectorElements(newLd);
     ldInst->eraseFromParent();
   } else if (BitCastInst *BCI = dyn_cast<BitCastInst>(user)) {
     for (auto it = BCI->user_begin(); it != BCI->user_end(); ) {

+ 24 - 0
tools/clang/lib/CodeGen/CGDebugInfo.cpp

@@ -1050,6 +1050,30 @@ bool CGDebugInfo::TryCollectHLSLRecordElements(const RecordType *Ty,
 
     return true;
   }
+  else if (hlsl::IsHLSLMatType(QualTy)) {
+    // The HLSL matrix type is defined as containing a field 'h' of
+    // array of extended vector type, but logically we want to represent
+    // it as per-element fields.
+    QualType ElemQualTy = hlsl::GetHLSLMatElementType(QualTy);
+    uint32_t NumRows, NumCols;
+    hlsl::GetHLSLMatRowColCount(QualTy, NumRows, NumCols);
+    unsigned ElemSizeInBits = CGM.getContext().getTypeSize(ElemQualTy);
+    for (unsigned RowIdx = 0; RowIdx < NumRows; ++RowIdx) {
+      for (unsigned ColIdx = 0; ColIdx < NumCols; ++ColIdx) {
+        char FieldName[] = "_11";
+        FieldName[1] += RowIdx;
+        FieldName[2] += ColIdx;
+        unsigned RowMajorIdx = RowIdx * NumCols + ColIdx;
+        unsigned OffsetInBits = ElemSizeInBits * RowMajorIdx;
+        llvm::DIType *FieldType = createFieldType(FieldName, ElemQualTy, 0,
+          SourceLocation(), AccessSpecifier::AS_public, OffsetInBits,
+          /* tunit */ nullptr, DITy, Ty->getDecl());
+        Elements.emplace_back(FieldType);
+      }
+    }
+
+    return true;
+  }
   else if (hlsl::IsHLSLResourceType(QualTy) || hlsl::IsHLSLStreamOutputType(QualTy)) {
     // Should appear as having no members rather than exposing our internal handles.
     return true;

+ 1 - 1
tools/clang/test/CodeGenHLSL/debug/_readme.txt

@@ -13,7 +13,7 @@ The current workaround is to include the following in your test to explicitly ma
 the quoted source file:
 
   // Exclude quoted source file (see readme)
-  // CHECK: {{!"[^"]*\\0A[^"]*"}}
+  // CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
 
 This will match a metadata string containing \0A (newline), which should only appear
 in the quoted source file. It will not match itself in the quoted source file because

+ 22 - 0
tools/clang/test/CodeGenHLSL/debug/locals/constantbuffer_loadlegacy_vector.hlsl

@@ -0,0 +1,22 @@
+// RUN: %dxc -E main -T vs_6_0 -Zi %s | FileCheck %s
+
+// Test that the debug information for the result of a texture load
+// is preserved after scalarization and optims.
+
+// CHECK: call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32
+// CHECK: extractvalue %dx.types.CBufRet.i32
+// CHECK-DAG: call void @llvm.dbg.value
+// CHECK-DAG: extractvalue %dx.types.CBufRet.i32
+// CHECK: call void @llvm.dbg.value
+// CHECK: call void @dx.op.storeOutput.i32
+// CHECK: call void @dx.op.storeOutput.i32
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+int2 cb;
+int2 main() : OUT
+{
+    int2 result = cb;
+    return result;
+}

+ 21 - 0
tools/clang/test/CodeGenHLSL/debug/locals/matrix_no_opt.hlsl

@@ -0,0 +1,21 @@
+// RUN: %dxc -E main -T vs_6_0 -Zi -Od %s | FileCheck %s
+
+// Test that local matrices preserve debug info without optimizations
+
+// CHECK: %[[mat:.*]] = alloca [4 x i32]
+// CHECK: call void @llvm.dbg.declare(metadata [4 x i32]* %[[mat]], metadata ![[divar:.*]], metadata ![[diexpr:.*]])
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+// CHECK-DAG: ![[divar]] = !DILocalVariable(tag: DW_TAG_auto_variable, name: "mat"
+// CHECK-DAG: ![[diexpr]] = !DIExpression()
+
+int2x2 cb_mat;
+int main() : OUT
+{
+  // Initialize from CB to ensure the variable is not optimized away
+  int2x2 mat = cb_mat;
+  // Consume all values but return a scalar to avoid another alloca [4 x i32]
+  return determinant(mat);
+}

+ 26 - 0
tools/clang/test/CodeGenHLSL/debug/locals/matrix_opt.hlsl

@@ -0,0 +1,26 @@
+// RUN: %dxc -E main -T vs_6_0 -Zi %s | FileCheck %s
+
+// Test that local matrices preserve debug info with optimizations
+
+// CHECK: call void @llvm.dbg.value
+// CHECK: call void @llvm.dbg.value
+// CHECK: call void @llvm.dbg.value
+// CHECK: call void @llvm.dbg.value
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+// CHECK-DAG: !DILocalVariable(tag: DW_TAG_auto_variable, name: "mat"
+// CHECK-DAG: !DIExpression(DW_OP_bit_piece, 0, 32)
+// CHECK-DAG: !DIExpression(DW_OP_bit_piece, 32, 32)
+// CHECK-DAG: !DIExpression(DW_OP_bit_piece, 64, 32)
+// CHECK-DAG: !DIExpression(DW_OP_bit_piece, 96, 32)
+
+int2x2 cb_mat;
+int main() : OUT
+{
+  // Initialize from CB to ensure the variable is not optimized away
+  int2x2 mat = cb_mat;
+  // Consume all values but return a scalar to avoid another alloca [4 x i32]
+  return determinant(mat);
+}

+ 4 - 4
tools/clang/test/CodeGenHLSL/debug/locals/structuredbuffer_load.hlsl → tools/clang/test/CodeGenHLSL/debug/locals/structuredbuffer_load_vector.hlsl

@@ -4,14 +4,14 @@
 // is preserved after scalarization and optims.
 
 // CHECK: call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32
-// CHECK: call void @llvm.dbg.value
-// CHECK: extractvalue %dx.types.ResRet.i32
-// CHECK: extractvalue %dx.types.ResRet.i32
+// CHECK-DAG: call void @llvm.dbg.value
+// CHECK-DAG: extractvalue %dx.types.ResRet.i32
+// CHECK-DAG: extractvalue %dx.types.ResRet.i32
 // CHECK: call void @dx.op.storeOutput.i32
 // CHECK: call void @dx.op.storeOutput.i32
 
 // Exclude quoted source file (see readme)
-// CHECK: {{!"[^"]*\\0A[^"]*"}}
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
 
 StructuredBuffer<int2> buf;
 int2 main() : OUT

+ 0 - 25
tools/clang/test/CodeGenHLSL/debug/locals/texture_load.hlsl

@@ -1,25 +0,0 @@
-// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
-
-// Test that the debug information for the result of a texture load
-// is preserved after scalarization and optims.
-
-// CHECK: call %dx.types.ResRet.f32 @dx.op.textureLoad.f32
-// CHECK: call void @llvm.dbg.value
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: call void @dx.op.storeOutput.f32
-// CHECK: call void @dx.op.storeOutput.f32
-// CHECK: call void @dx.op.storeOutput.f32
-// CHECK: call void @dx.op.storeOutput.f32
-
-// Exclude quoted source file (see readme)
-// CHECK: {{!"[^"]*\\0A[^"]*"}}
-
-Texture1D<float4> tex;
-float4 main() : SV_Target
-{
-    float4 texel = tex.Load(0);
-    return texel;
-}

+ 21 - 0
tools/clang/test/CodeGenHLSL/debug/locals/texture_load_vector.hlsl

@@ -0,0 +1,21 @@
+// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
+
+// Test that the debug information for the result of a texture load
+// is preserved after scalarization and optims.
+
+// CHECK: call %dx.types.ResRet.f32 @dx.op.textureLoad.f32
+// CHECK-DAG: call void @llvm.dbg.value
+// CHECK-DAG: extractvalue %dx.types.ResRet.f32
+// CHECK-DAG: extractvalue %dx.types.ResRet.f32
+// CHECK: call void @dx.op.storeOutput.f32
+// CHECK: call void @dx.op.storeOutput.f32
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+Texture1D<float2> tex;
+float2 main() : SV_Target
+{
+    float2 texel = tex.Load(0);
+    return texel;
+}

+ 0 - 26
tools/clang/test/CodeGenHLSL/debug/locals/texture_sample.hlsl

@@ -1,26 +0,0 @@
-// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
-
-// Test that the debug information for the result of a texture sample
-// is preserved after scalarization and optims.
-
-// CHECK: call %dx.types.ResRet.f32 @dx.op.sample.f32
-// CHECK: call void @llvm.dbg.value
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: extractvalue %dx.types.ResRet.f32
-// CHECK: call void @dx.op.storeOutput.f32
-// CHECK: call void @dx.op.storeOutput.f32
-// CHECK: call void @dx.op.storeOutput.f32
-// CHECK: call void @dx.op.storeOutput.f32
-
-// Exclude quoted source file (see readme)
-// CHECK: {{!"[^"]*\\0A[^"]*"}}
-
-sampler samp;
-Texture2D<float4> tex;
-float4 main() : SV_Target
-{
-    float4 texel = tex.Sample(samp, 0);
-    return texel;
-}

+ 22 - 0
tools/clang/test/CodeGenHLSL/debug/locals/texture_sample_vector.hlsl

@@ -0,0 +1,22 @@
+// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
+
+// Test that the debug information for the result of a texture sample
+// is preserved after scalarization and optims.
+
+// CHECK: call %dx.types.ResRet.f32 @dx.op.sample.f32
+// CHECK-DAG: call void @llvm.dbg.value
+// CHECK-DAG: extractvalue %dx.types.ResRet.f32
+// CHECK-DAG: extractvalue %dx.types.ResRet.f32
+// CHECK: call void @dx.op.storeOutput.f32
+// CHECK: call void @dx.op.storeOutput.f32
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+
+sampler samp;
+Texture2D<float2> tex;
+float2 main() : SV_Target
+{
+    float2 texel = tex.Sample(samp, 0);
+    return texel;
+}

+ 0 - 0
tools/clang/test/CodeGenHLSL/debug/locals/input_vector.hlsl → tools/clang/test/CodeGenHLSL/debug/shader_params/input_vector.hlsl


+ 0 - 0
tools/clang/test/CodeGenHLSL/debug/locals/input_vector_in_struct.hlsl → tools/clang/test/CodeGenHLSL/debug/shader_params/input_vector_in_struct.hlsl


+ 14 - 0
tools/clang/test/CodeGenHLSL/debug/types/matrix_members.hlsl

@@ -0,0 +1,14 @@
+// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
+
+// Test that the debug info for HLSL matrices exposes per-component fields.
+
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "int2x2"
+// CHECK-DAG: !DICompositeType(tag: DW_TAG_class_type, name: "matrix<int, 2, 2>", {{.*}}, size: 128, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_11", {{.*}}, size: 32, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_12", {{.*}}, size: 32, align: 32, offset: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_21", {{.*}}, size: 32, align: 32, offset: 64
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_22", {{.*}}, size: 32, align: 32, offset: 96
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+int2x2 main(int2x2 v : IN) : OUT { return v; }

+ 15 - 0
tools/clang/test/CodeGenHLSL/debug/types/matrix_members_bool.hlsl

@@ -0,0 +1,15 @@
+// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
+
+// Test that the debug info for HLSL bool matrices exposes per-component fields
+// in the memory representation of matrices (32-bits)
+
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "bool2x2"
+// CHECK-DAG: !DICompositeType(tag: DW_TAG_class_type, name: "matrix<bool, 2, 2>", {{.*}}, size: 128, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_11", {{.*}}, size: 32, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_12", {{.*}}, size: 32, align: 32, offset: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_21", {{.*}}, size: 32, align: 32, offset: 64
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_22", {{.*}}, size: 32, align: 32, offset: 96
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+bool2x2 main(bool2x2 v : IN) : OUT { return v; }

+ 12 - 0
tools/clang/test/CodeGenHLSL/debug/types/vector_members.hlsl

@@ -0,0 +1,12 @@
+// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
+
+// Test that the debug info for HLSL vectors exposes per-component fields.
+
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "int2"
+// CHECK-DAG: !DICompositeType(tag: DW_TAG_class_type, name: "vector<int, 2>", {{.*}}, size: 64, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 32, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "y", {{.*}}, size: 32, align: 32, offset: 32
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+int2 main(int2 v : IN) : OUT { return v; }

+ 13 - 0
tools/clang/test/CodeGenHLSL/debug/types/vector_members_bool.hlsl

@@ -0,0 +1,13 @@
+// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
+
+// Test that the debug info for HLSL bool vectors exposes per-component fields
+// in the memory representation of bools (32-bits)
+
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "bool2"
+// CHECK-DAG: !DICompositeType(tag: DW_TAG_class_type, name: "vector<bool, 2>", {{.*}}, size: 64, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 32, align: 32
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "y", {{.*}}, size: 32, align: 32, offset: 32
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+bool2 main(bool2 v : IN) : OUT { return v; }

+ 0 - 9
tools/clang/test/CodeGenHLSL/debug/vector_members.hlsl

@@ -1,9 +0,0 @@
-// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
-
-// Test that the debug info for HLSL vectors exposes per-component fields.
-
-// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "int2"
-// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "vector<int, 2>", {{.*}}, size: 64, align: 32
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 32, align: 32
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "y", {{.*}}, size: 32, align: 32, offset: 32
-int2 main(int2 v : IN) : OUT { return v; }

+ 0 - 10
tools/clang/test/CodeGenHLSL/debug/vector_members_bool.hlsl

@@ -1,10 +0,0 @@
-// RUN: %dxc -T vs_6_0 -E main -Od -Zi %s | FileCheck %s
-
-// Test that the debug info for HLSL bool vectors exposes per-component fields
-// in the memory representation of bools (32-bits)
-
-// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "bool2"
-// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "vector<bool, 2>", {{.*}}, size: 64, align: 32
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 32, align: 32
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "y", {{.*}}, size: 32, align: 32, offset: 32
-bool2 main(bool2 v : IN) : OUT { return v; }