Browse Source

Fixed broken debug info for "out" and "inout" args. (#2914)

Adam Yang 5 năm trước cách đây
mục cha
commit
0c3cab299f

+ 1 - 0
include/llvm/InitializePasses.h

@@ -270,6 +270,7 @@ void initializeDxilInsertPreservesPass(PassRegistry&);
 void initializeDxilFinalizePreservesPass(PassRegistry&);
 void initializeDxilPreserveToSelectPass(PassRegistry&);
 void initializeDxilRemoveDeadBlocksPass(PassRegistry&);
+void initializeDxilRewriteOutputArgDebugInfoPass(PassRegistry&);
 // HLSL Change Ends
 void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&);
 void initializeScalarEvolutionPass(PassRegistry&);

+ 3 - 0
include/llvm/Transforms/Scalar.h

@@ -158,6 +158,9 @@ void initializeDxilPreserveToSelectPass(PassRegistry&);
 Pass *createDxilRemoveDeadBlocksPass();
 void initializeDxilRemoveDeadBlocksPass(PassRegistry&);
 
+void initializeDxilRewriteOutputArgDebugInfoPass(PassRegistry&);
+Pass *createDxilRewriteOutputArgDebugInfoPass();
+
 //===----------------------------------------------------------------------===//
 //
 // LowerStaticGlobalIntoAlloca. Replace static globals with alloca if only used

+ 6 - 0
include/llvm/Transforms/Utils/Local.h

@@ -271,6 +271,12 @@ bool LowerDbgDeclare(Function &F);
 /// an alloca, if any.
 DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
 
+// HLSL Change - Begin
+/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic corresponding to
+/// an alloca, if any.
+void FindAllocaDbgDeclare(Value *V, SmallVectorImpl<DbgDeclareInst *> &Declares);
+// HLSL Change - End
+
 /// \brief Replaces llvm.dbg.declare instruction when an alloca is replaced with
 /// a new value.  If Deref is true, tan additional DW_OP_deref is prepended to
 /// the expression.

+ 1 - 0
lib/HLSL/DxcOptimizer.cpp

@@ -114,6 +114,7 @@ HRESULT SetupRegistryPassForHLSL() {
     initializeDxilPromoteLocalResourcesPass(Registry);
     initializeDxilPromoteStaticResourcesPass(Registry);
     initializeDxilRemoveDeadBlocksPass(Registry);
+    initializeDxilRewriteOutputArgDebugInfoPass(Registry);
     initializeDxilSimpleGVNHoistPass(Registry);
     initializeDxilTranslateRawBufferPass(Registry);
     initializeDxilValidateWaveSensitivityPass(Registry);

+ 72 - 0
lib/HLSL/DxilNoops.cpp

@@ -92,6 +92,8 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/IR/DIBuilder.h"
 #include "llvm/Support/raw_os_ostream.h"
 #include "dxc/DXIL/DxilMetadataHelper.h"
 #include "dxc/DXIL/DxilConstants.h"
@@ -481,6 +483,76 @@ Pass *llvm::createDxilPreserveToSelectPass() {
 INITIALIZE_PASS(DxilPreserveToSelect, "dxil-preserves-to-select", "Dxil Preserves To Select", false, false)
 
 
+//==========================================================
+// output Argument debug info rewrite
+//
+namespace {
+
+class DxilRewriteOutputArgDebugInfo : public ModulePass {
+public:
+  static char ID;
+
+  DxilRewriteOutputArgDebugInfo() : ModulePass(ID) {
+    initializeDxilRewriteOutputArgDebugInfoPass(*PassRegistry::getPassRegistry());
+  }
+
+  bool runOnModule(Module &M) override {
+    DITypeIdentifierMap EmptyMap;
+    DIBuilder DIB(M);
+
+    bool Changed = false;
+
+    for (Function &F : M) {
+      for (Argument &Arg : F.args()) {
+        if (!Arg.getType()->isPointerTy())
+          continue;
+
+        DbgDeclareInst *Declare = llvm::FindAllocaDbgDeclare(&Arg);
+        if (!Declare)
+          continue;
+
+        DILocalVariable *Var = Declare->getVariable();
+        DIType *Ty = Var->getType().resolve(EmptyMap);
+
+        DIExpression *Expr = Declare->getExpression();
+        if (Expr->getNumElements() == 1 && Expr->getElement(0) == dwarf::DW_OP_deref) {
+          while (Ty &&
+            Ty->getTag() == dwarf::DW_TAG_reference_type ||
+            Ty->getTag() == dwarf::DW_TAG_restrict_type)
+          {
+            Ty = cast<DIDerivedType>(Ty)->getBaseType().resolve(EmptyMap);
+          }
+
+          if (Ty) {
+            DILocalVariable *NewVar =
+              DIB.createLocalVariable(dwarf::DW_TAG_arg_variable,
+                Var->getScope(), Var->getName(), Var->getFile(),
+                Var->getLine(), Ty, false, 0, Var->getArg());
+            DIExpression *EmptyExpr = DIExpression::get(M.getContext(), {});
+            DIB.insertDeclare(&Arg, NewVar, EmptyExpr, Declare->getDebugLoc(), Declare);
+            Declare->eraseFromParent();
+
+            Changed = true;
+          }
+        }
+      }
+    }
+
+    return Changed;
+  }
+  const char *getPassName() const override { return "Dxil Rewrite Output Arg Debug Info"; }
+};
+
+char DxilRewriteOutputArgDebugInfo::ID;
+}
+
+Pass *llvm::createDxilRewriteOutputArgDebugInfoPass() {
+  return new DxilRewriteOutputArgDebugInfo();
+}
+
+INITIALIZE_PASS(DxilRewriteOutputArgDebugInfo, "dxil-rewrite-output-arg-debug-info", "Dxil Rewrite Output Arg Debug Info", false, false)
+
+
 //==========================================================
 // Finalize pass
 //

+ 4 - 0
lib/Transforms/IPO/PassManagerBuilder.cpp

@@ -327,6 +327,8 @@ void PassManagerBuilder::populateModulePassManager(
       MPM.add(createHLEnsureMetadataPass()); // HLSL Change - rehydrate metadata from high-level codegen
     }
 
+    MPM.add(createDxilRewriteOutputArgDebugInfoPass()); // Fix output argument types.
+
     if (!HLSLHighLevel)
       MPM.add(createDxilInsertPreservesPass(HLSLAllowPreserveValues)); // HLSL Change - insert preserve instructions
 
@@ -378,6 +380,8 @@ void PassManagerBuilder::populateModulePassManager(
 
   // HLSL Change Begins
 
+  MPM.add(createDxilRewriteOutputArgDebugInfoPass()); // Fix output argument types.
+
   MPM.add(createHLLegalizeParameter()); // legalize parameters before inline.
   MPM.add(createAlwaysInlinerPass(/*InsertLifeTime*/false));
   if (Inliner) {

+ 12 - 0
lib/Transforms/Utils/Local.cpp

@@ -1082,6 +1082,18 @@ DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {
   return nullptr;
 }
 
+// HLSL Change - Begin
+/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic corresponding to
+/// an alloca, if any.
+void llvm::FindAllocaDbgDeclare(Value *V, SmallVectorImpl<DbgDeclareInst *> &Declares) {
+  if (auto *L = LocalAsMetadata::getIfExists(V))
+    if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
+      for (User *U : MDV->users())
+        if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
+          Declares.push_back(DDI);
+}
+// HLSL Change - End
+
 bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
                                       DIBuilder &Builder, bool Deref) {
   DbgDeclareInst *DDI = FindAllocaDbgDeclare(AI);

+ 25 - 16
lib/Transforms/Utils/PromoteMemoryToRegister.cpp

@@ -102,7 +102,8 @@ struct AllocaInfo {
   bool OnlyUsedInOneBlock;
 
   Value *AllocaPointerVal;
-  DbgDeclareInst *DbgDeclare;
+  //DbgDeclareInst *DbgDeclare; // HLSL Change
+  SmallVector<DbgDeclareInst *, 4> DbgDeclareInsts; // HLSL Change
 
   void clear() {
     DefiningBlocks.clear();
@@ -111,7 +112,8 @@ struct AllocaInfo {
     OnlyBlock = nullptr;
     OnlyUsedInOneBlock = true;
     AllocaPointerVal = nullptr;
-    DbgDeclare = nullptr;
+    // DbgDeclare = nullptr; // HLSL Change
+    DbgDeclareInsts.clear(); // HLSL Change
   }
 
   /// Scan the uses of the specified alloca, filling in the AllocaInfo used
@@ -146,7 +148,8 @@ struct AllocaInfo {
       }
     }
 
-    DbgDeclare = FindAllocaDbgDeclare(AI);
+    // DbgDeclare = FindAllocaDbgDeclare(AI); // HLSL Change
+    FindAllocaDbgDeclare(AI, DbgDeclareInsts); // HLSL Change
   }
 };
 
@@ -255,7 +258,8 @@ struct PromoteMem2Reg {
   /// For each alloca, we keep track of the dbg.declare intrinsic that
   /// describes it, if any, so that we can convert it to a dbg.value
   /// intrinsic if the alloca gets promoted.
-  SmallVector<DbgDeclareInst *, 8> AllocaDbgDeclares;
+  // SmallVector<DbgDeclareInst *, 8> AllocaDbgDeclares; // HLSL Change
+  SmallVector<SmallVector<DbgDeclareInst *, 4>, 8> AllocaDbgDeclares; // HLSL Change
 
   /// The set of basic blocks the renamer has already visited.
   ///
@@ -401,7 +405,8 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
 
   // Record debuginfo for the store and remove the declaration's
   // debuginfo.
-  if (DbgDeclareInst *DDI = Info.DbgDeclare) {
+  // if (DbgDeclareInst *DDI = Info.DbgDeclare) { // HLSL Change
+  for (DbgDeclareInst *DDI : Info.DbgDeclareInsts) {
     DIBuilder DIB(*AI->getParent()->getParent()->getParent(),
                   /*AllowUnresolved*/ false);
     ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore, DIB);
@@ -495,7 +500,8 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
   while (!AI->use_empty()) {
     StoreInst *SI = cast<StoreInst>(AI->user_back());
     // Record debuginfo for the store before removing it.
-    if (DbgDeclareInst *DDI = Info.DbgDeclare) {
+    // if (DbgDeclareInst *DDI = Info.DbgDeclare) { // HLSL Change
+    for (DbgDeclareInst *DDI : Info.DbgDeclareInsts) { // HLSL Change
       DIBuilder DIB(*AI->getParent()->getParent()->getParent(),
                     /*AllowUnresolved*/ false);
       ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
@@ -510,7 +516,8 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
   LBI.deleteValue(AI);
 
   // The alloca's debuginfo can be removed as well.
-  if (DbgDeclareInst *DDI = Info.DbgDeclare) {
+  // if (DbgDeclareInst *DDI = Info.DbgDeclare) { // HLSL Change
+  for (DbgDeclareInst *DDI : Info.DbgDeclareInsts) { // HLSL Change
     DDI->eraseFromParent();
     LBI.deleteValue(DDI);
   }
@@ -589,8 +596,9 @@ void PromoteMem2Reg::run() {
       PointerAllocaValues[AllocaNum] = Info.AllocaPointerVal;
 
     // Remember the dbg.declare intrinsic describing this alloca, if any.
-    if (Info.DbgDeclare)
-      AllocaDbgDeclares[AllocaNum] = Info.DbgDeclare;
+    // if (Info.DbgDeclare)
+    if (Info.DbgDeclareInsts.size())
+      AllocaDbgDeclares[AllocaNum] = Info.DbgDeclareInsts;
 
     // Keep the reverse mapping of the 'Allocas' array for the rename pass.
     AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
@@ -779,16 +787,16 @@ void PromoteMem2Reg::run() {
        I != E; ++I) {
     PHINode *PN = I->second;
     unsigned AllocaNum = I->first.second;
-    DbgDeclareInst *DDI = AllocaDbgDeclares[AllocaNum];
-    if (!DDI) continue;
-
-    DIBuilder DIB(*PN->getModule());
-    DIB.insertDbgValueIntrinsic(PN, 0, DDI->getVariable(), DDI->getExpression(), DDI->getDebugLoc(), PN->getParent()->getFirstNonPHI());
+    ArrayRef<DbgDeclareInst *> DDIs = AllocaDbgDeclares[AllocaNum];
+    for (DbgDeclareInst *DDI : DDIs) {
+      DIBuilder DIB(*PN->getModule());
+      DIB.insertDbgValueIntrinsic(PN, 0, DDI->getVariable(), DDI->getExpression(), DDI->getDebugLoc(), PN->getParent()->getFirstNonPHI());
+    }
   }
 
   // Remove alloca's dbg.declare instrinsics from the function.
   for (unsigned i = 0, e = AllocaDbgDeclares.size(); i != e; ++i)
-    if (DbgDeclareInst *DDI = AllocaDbgDeclares[i])
+    for (DbgDeclareInst *DDI : AllocaDbgDeclares[i])
       DDI->eraseFromParent();
 // HLSL Change - End
 
@@ -984,7 +992,8 @@ NextIteration:
       // what value were we writing?
       IncomingVals[ai->second] = SI->getOperand(0);
       // Record debuginfo for the store before removing it.
-      if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second])
+      // if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second]) // HLSL Change
+      for (DbgDeclareInst *DDI : AllocaDbgDeclares[ai->second]) // HLSL Change
         ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
       BB->getInstList().erase(SI);
     }

+ 34 - 0
tools/clang/test/HLSLFileCheck/dxil/debug/out_args.hlsl

@@ -0,0 +1,34 @@
+// RUN: %dxc -E main -T ps_6_0 %s -Zi -O0 | FileCheck %s
+
+// CHECK-NOT: DW_OP_deref
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"arg0" !DIExpression(DW_OP_bit_piece, 0, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"arg0" !DIExpression(DW_OP_bit_piece, 32, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"arg0" !DIExpression(DW_OP_bit_piece, 64, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"arg1" !DIExpression(DW_OP_bit_piece, 0, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"arg1" !DIExpression(DW_OP_bit_piece, 32, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"arg1" !DIExpression(DW_OP_bit_piece, 64, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"output" !DIExpression(DW_OP_bit_piece, 0, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"output" !DIExpression(DW_OP_bit_piece, 32, 32)
+// CHECK-DAG: dbg.value(metadata float {{.+}}, i64 0, metadata !{{[0-9]+}}, metadata !{{[0-9]+}}), !dbg !{{[0-9]+}} ; var:"output" !DIExpression(DW_OP_bit_piece, 64, 32)
+
+void foo(out float3 arg0) {
+  arg0 = float3(1,2,3); // @BREAK
+  return;
+}
+
+void bar(inout float3 arg1) {
+  arg1 += float3(1,2,3);
+  return;
+}
+
+[RootSignature("")]
+float3 main() : SV_Target {
+  float3 output;
+  foo(output);
+  bar(output);
+  return output;
+}
+
+// Exclude quoted source file (see readme)
+// CHECK-LABEL: {{!"[^"]*\\0A[^"]*"}}
+

+ 1 - 0
utils/hct/hctdb.py

@@ -2014,6 +2014,7 @@ class db_dxil(object):
         add_pass('dxil-fix-array-init', 'DxilFixConstArrayInitializer', 'Dxil Fix Array Initializer', [])
         add_pass('hlsl-validate-wave-sensitivity', 'DxilValidateWaveSensitivity', 'HLSL DXIL wave sensitiveity validation', [])
         add_pass('dxil-elim-vector', 'DxilEliminateVector', 'Dxil Eliminate Vectors', [])
+        add_pass('dxil-rewrite-output-arg-debug-info', 'DxilRewriteOutputArgDebugInfo', 'Dxil Rewrite Output Arg Debug Info', [])
         add_pass('dxil-finalize-preserves', 'DxilFinalizePreserves', 'Dxil Finalize Preserves', [])
         add_pass('dxil-insert-preserves', 'DxilInsertPreserves', 'Dxil Insert Noops', [
                 {'n':'AllowPreserves', 't':'bool', 'c':1},