OSDN Git Service

Revert r313825: "[IR] Add llvm.dbg.addr, a control-dependent version of llvm.dbg...
authorDaniel Jasper <djasper@google.com>
Thu, 21 Sep 2017 12:07:33 +0000 (12:07 +0000)
committerDaniel Jasper <djasper@google.com>
Thu, 21 Sep 2017 12:07:33 +0000 (12:07 +0000)
.. as well as the two subsequent changes r313826 and r313875.

This leads to segfaults in combination with ASAN. Will forward repro
instructions to the original author (rnk).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313876 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
docs/SourceLevelDebugging.rst
include/llvm/IR/IntrinsicInst.h
include/llvm/IR/Intrinsics.td
include/llvm/Transforms/Utils/Local.h
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/IR/DIBuilder.cpp
lib/IR/Verifier.cpp
lib/Transforms/InstCombine/InstructionCombining.cpp
lib/Transforms/Scalar/SROA.cpp
lib/Transforms/Utils/Local.cpp
lib/Transforms/Utils/PromoteMemoryToRegister.cpp
test/DebugInfo/X86/dbg-addr-dse.ll [deleted file]
test/DebugInfo/X86/dbg-addr.ll [deleted file]
test/DebugInfo/X86/sroasplit-5.ll
test/DebugInfo/X86/sroasplit-dbg-declare.ll [deleted file]
test/Transforms/Mem2Reg/dbg-addr-inline-dse.ll [deleted file]
test/Transforms/Mem2Reg/dbg-addr.ll [deleted file]
test/Transforms/SROA/dbg-addr-diamond.ll [deleted file]

index c46b51c..ee4c5ce 100644 (file)
@@ -171,64 +171,35 @@ Debugger intrinsic functions
 ----------------------------
 
 LLVM uses several intrinsic functions (name prefixed with "``llvm.dbg``") to
-track source local variables through optimization and code generation.
+provide debug information at various points in generated code.
 
-``llvm.dbg.addr``
+``llvm.dbg.declare``
 ^^^^^^^^^^^^^^^^^^^^
 
 .. code-block:: llvm
 
-  void @llvm.dbg.addr(metadata, metadata, metadata)
+  void @llvm.dbg.declare(metadata, metadata, metadata)
 
-This intrinsic provides information about a local element (e.g., variable).
-The first argument is metadata holding the address of variable, typically a
-static alloca in the function entry block.  The second argument is a
-`local variable <LangRef.html#dilocalvariable>`_ containing a description of
-the variable.  The third argument is a `complex expression
-<LangRef.html#diexpression>`_.  An `llvm.dbg.addr` intrinsic describes the
-*address* of a source variable.
+This intrinsic provides information about a local element (e.g., variable).  The
+first argument is metadata holding the alloca for the variable.  The second
+argument is a `local variable <LangRef.html#dilocalvariable>`_ containing a
+description of the variable.  The third argument is a `complex expression
+<LangRef.html#diexpression>`_.  An `llvm.dbg.declare` instrinsic describes the
+*location* of a source variable.
 
 .. code-block:: llvm
 
     %i.addr = alloca i32, align 4
-    call void @llvm.dbg.addr(metadata i32* %i.addr, metadata !1,
-                             metadata !DIExpression()), !dbg !2
+    call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !1, metadata !2), !dbg !3
     !1 = !DILocalVariable(name: "i", ...) ; int i
-    !2 = !DILocation(...)
+    !2 = !DIExpression()
+    !3 = !DILocation(...)
     ...
     %buffer = alloca [256 x i8], align 8
     ; The address of i is buffer+64.
-    call void @llvm.dbg.addr(metadata [256 x i8]* %buffer, metadata !3,
-                             metadata !DIExpression(DW_OP_plus, 64)), !dbg !4
-    !3 = !DILocalVariable(name: "i", ...) ; int i
-    !4 = !DILocation(...)
-
-A frontend should generate exactly one call to ``llvm.dbg.addr`` at the point
-of declaration of a source variable. Optimization passes that fully promote the
-variable from memory to SSA values will replace this call with possibly
-multiple calls to `llvm.dbg.value`. Passes that delete stores are effectively
-partial promotion, and they will insert a mix of calls to ``llvm.dbg.value``
-and ``llvm.dbg.addr`` to track the source variable value when it is available.
-After optimization, there may be multiple calls to ``llvm.dbg.addr`` describing
-the program points where the variables lives in memory. All calls for the same
-concrete source variable must agree on the memory location.
-
-
-``llvm.dbg.declare``
-^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: llvm
-
-  void @llvm.dbg.declare(metadata, metadata, metadata)
-
-This intrinsic is identical to `llvm.dbg.addr`, except that there can only be
-one call to `llvm.dbg.declare` for a given concrete `local variable
-<LangRef.html#dilocalvariable>`_. It is not control-dependent, meaning that if
-a call to `llvm.dbg.declare` exists and has a valid location argument, that
-address is considered to be the true home of the variable across its entire
-lifetime. This makes it hard for optimizations to preserve accurate debug info
-in the presence of ``llvm.dbg.declare``, so we are transitioning away from it,
-and we plan to deprecate it in future LLVM releases.
+    call void @llvm.dbg.declare(metadata [256 x i8]* %buffer, metadata !1, metadata !2)
+    !1 = !DILocalVariable(name: "i", ...) ; int i
+    !2 = !DIExpression(DW_OP_plus, 64)
 
 
 ``llvm.dbg.value``
@@ -271,9 +242,6 @@ following C fragment, for example:
   8.    X = Y;
   9.  }
 
-.. FIXME: Update the following example to use llvm.dbg.addr once that is the
-   default in clang.
-
 Compiled to LLVM, this function would be represented like this:
 
 .. code-block:: text
index b8d6e23..eccb408 100644 (file)
@@ -71,12 +71,6 @@ namespace llvm {
     /// variable's value or its address.
     Value *getVariableLocation(bool AllowNullOp = true) const;
 
-    /// Does this describe the address of a local variable. True for dbg.addr
-    /// and dbg.declare, but not dbg.value, which describes its value.
-    bool isAddressOfVariable() const {
-      return getIntrinsicID() != Intrinsic::dbg_value;
-    }
-
     DILocalVariable *getVariable() const {
       return cast<DILocalVariable>(getRawVariable());
     }
@@ -93,13 +87,11 @@ namespace llvm {
       return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
     }
 
-    /// \name Casting methods
-    /// @{
+    // Methods for support type inquiry through isa, cast, and dyn_cast:
     static bool classof(const IntrinsicInst *I) {
       switch (I->getIntrinsicID()) {
       case Intrinsic::dbg_declare:
       case Intrinsic::dbg_value:
-      case Intrinsic::dbg_addr:
         return true;
       default: return false;
       }
@@ -107,7 +99,6 @@ namespace llvm {
     static bool classof(const Value *V) {
       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
     }
-    /// @}
   };
 
   /// This represents the llvm.dbg.declare instruction.
@@ -115,30 +106,13 @@ namespace llvm {
   public:
     Value *getAddress() const { return getVariableLocation(); }
 
-    /// \name Casting methods
-    /// @{
+    // Methods for support type inquiry through isa, cast, and dyn_cast:
     static bool classof(const IntrinsicInst *I) {
       return I->getIntrinsicID() == Intrinsic::dbg_declare;
     }
     static bool classof(const Value *V) {
       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
     }
-    /// @}
-  };
-
-  /// This represents the llvm.dbg.addr instruction.
-  class DbgAddrIntrinsic : public DbgInfoIntrinsic {
-  public:
-    Value *getAddress() const { return getVariableLocation(); }
-
-    /// \name Casting methods
-    /// @{
-    static bool classof(const IntrinsicInst *I) {
-      return I->getIntrinsicID() == Intrinsic::dbg_addr;
-    }
-    static bool classof(const Value *V) {
-      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
-    }
   };
 
   /// This represents the llvm.dbg.value instruction.
@@ -148,15 +122,13 @@ namespace llvm {
       return getVariableLocation(/* AllowNullOp = */ false);
     }
 
-    /// \name Casting methods
-    /// @{
+    // Methods for support type inquiry through isa, cast, and dyn_cast:
     static bool classof(const IntrinsicInst *I) {
       return I->getIntrinsicID() == Intrinsic::dbg_value;
     }
     static bool classof(const Value *V) {
       return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
     }
-    /// @}
   };
 
   /// This is the common base class for constrained floating point intrinsics.
index cb16c3d..6ced600 100644 (file)
@@ -583,16 +583,12 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
 let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
   def int_dbg_declare      : Intrinsic<[],
                                        [llvm_metadata_ty,
-                                        llvm_metadata_ty,
-                                        llvm_metadata_ty]>;
+                                       llvm_metadata_ty,
+                                       llvm_metadata_ty]>;
   def int_dbg_value        : Intrinsic<[],
                                        [llvm_metadata_ty,
                                         llvm_metadata_ty,
                                         llvm_metadata_ty]>;
-  def int_dbg_addr         : Intrinsic<[],
-                                       [llvm_metadata_ty,
-                                        llvm_metadata_ty,
-                                        llvm_metadata_ty]>;
 }
 
 //===------------------ Exception Handling Intrinsics----------------------===//
index 9816e7f..42c2ec8 100644 (file)
@@ -16,7 +16,6 @@
 #define LLVM_TRANSFORMS_UTILS_LOCAL_H
 
 #include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/Dominators.h"
@@ -33,7 +32,6 @@ class BranchInst;
 class Instruction;
 class CallInst;
 class DbgDeclareInst;
-class DbgInfoIntrinsic;
 class DbgValueInst;
 class StoreInst;
 class LoadInst;
@@ -264,28 +262,26 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP,
 ///
 
 /// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
                                      StoreInst *SI, DIBuilder &Builder);
 
 /// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
                                      LoadInst *LI, DIBuilder &Builder);
 
-/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated
-/// llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// Inserts a llvm.dbg.value intrinsic after a phi of an alloca'd value
+/// that has an associated llvm.dbg.decl intrinsic.
+void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
                                      PHINode *LI, DIBuilder &Builder);
 
 /// Lowers llvm.dbg.declare intrinsics into appropriate set of
 /// llvm.dbg.value intrinsics.
 bool LowerDbgDeclare(Function &F);
 
-/// Finds all intrinsics declaring local variables as living in the memory that
-/// 'V' points to. This may include a mix of dbg.declare and
-/// dbg.addr intrinsics.
-TinyPtrVector<DbgInfoIntrinsic *> FindDbgAddrUses(Value *V);
+/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca, if any.
+DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
 
 /// Finds the llvm.dbg.value intrinsics describing a value.
 void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V);
index a98be56..fb32487 100644 (file)
@@ -5109,48 +5109,37 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
     DAG.setRoot(CallResult.second);
     return nullptr;
   }
-  case Intrinsic::dbg_addr:
   case Intrinsic::dbg_declare: {
-    const DbgInfoIntrinsic &DI = cast<DbgInfoIntrinsic>(I);
+    const DbgDeclareInst &DI = cast<DbgDeclareInst>(I);
     DILocalVariable *Variable = DI.getVariable();
     DIExpression *Expression = DI.getExpression();
+    const Value *Address = DI.getAddress();
     assert(Variable && "Missing variable");
+    if (!Address) {
+      DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
+      return nullptr;
+    }
 
     // Check if address has undef value.
-    const Value *Address = DI.getVariableLocation();
-    if (!Address || isa<UndefValue>(Address) ||
+    if (isa<UndefValue>(Address) ||
         (Address->use_empty() && !isa<Argument>(Address))) {
       DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
       return nullptr;
     }
 
-    bool isParameter = Variable->isParameter() || isa<Argument>(Address);
-
-    // Check if this variable can be described by a frame index, typically
-    // either as a static alloca or a byval parameter.
-    int FI = INT_MAX;
+    // Static allocas are handled more efficiently in the variable frame index
+    // side table.
     if (const auto *AI =
-            dyn_cast<AllocaInst>(Address->stripInBoundsConstantOffsets())) {
-      if (AI->isStaticAlloca()) {
-        auto I = FuncInfo.StaticAllocaMap.find(AI);
-        if (I != FuncInfo.StaticAllocaMap.end())
-          FI = I->second;
-      }
-    } else if (const auto *Arg = dyn_cast<Argument>(
-                   Address->stripInBoundsConstantOffsets())) {
-      FI = FuncInfo.getArgumentFrameIndex(Arg);
-    }
+            dyn_cast<AllocaInst>(Address->stripInBoundsConstantOffsets()))
+      if (AI->isStaticAlloca() && FuncInfo.StaticAllocaMap.count(AI))
+        return nullptr;
 
-    // llvm.dbg.addr is control dependent and always generates indirect
-    // DBG_VALUE instructions. llvm.dbg.declare is handled as a frame index in
-    // the MachineFunction variable table.
-    if (FI != INT_MAX) {
-      if (Intrinsic == Intrinsic::dbg_addr)
-        DAG.AddDbgValue(DAG.getFrameIndexDbgValue(Variable, Expression, FI, dl,
-                                                  SDNodeOrder),
-                        getRoot().getNode(), isParameter);
-      return nullptr;
-    }
+    // Byval arguments with frame indices were already handled after argument
+    // lowering and before isel.
+    if (const auto *Arg =
+            dyn_cast<Argument>(Address->stripInBoundsConstantOffsets()))
+      if (FuncInfo.getArgumentFrameIndex(Arg) != INT_MAX)
+        return nullptr;
 
     SDValue &N = NodeMap[Address];
     if (!N.getNode() && isa<Argument>(Address))
@@ -5161,6 +5150,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
       if (const BitCastInst *BCI = dyn_cast<BitCastInst>(Address))
         Address = BCI->getOperand(0);
       // Parameters are handled specially.
+      bool isParameter = Variable->isParameter() || isa<Argument>(Address);
       auto FINode = dyn_cast<FrameIndexSDNode>(N.getNode());
       if (isParameter && FINode) {
         // Byval parameter. We have a frame index at this point.
index 88f5b36..1a40d5c 100644 (file)
 using namespace llvm;
 using namespace llvm::dwarf;
 
-cl::opt<bool>
-    UseDbgAddr("use-dbg-addr",
-                llvm::cl::desc("Use llvm.dbg.addr for all local variables"),
-                cl::init(false));
-
 DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)
   : M(m), VMContext(M.getContext()), CUNode(nullptr),
       DeclareFn(nullptr), ValueFn(nullptr),
@@ -781,11 +776,6 @@ static Instruction *withDebugLoc(Instruction *I, const DILocation *DL) {
   return I;
 }
 
-static Function *getDeclareIntrin(Module &M) {
-  return Intrinsic::getDeclaration(&M, UseDbgAddr ? Intrinsic::dbg_addr
-                                                  : Intrinsic::dbg_declare);
-}
-
 Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
                                       DIExpression *Expr, const DILocation *DL,
                                       Instruction *InsertBefore) {
@@ -795,7 +785,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
              VarInfo->getScope()->getSubprogram() &&
          "Expected matching subprograms");
   if (!DeclareFn)
-    DeclareFn = getDeclareIntrin(M);
+    DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
 
   trackIfUnresolved(VarInfo);
   trackIfUnresolved(Expr);
@@ -814,7 +804,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
              VarInfo->getScope()->getSubprogram() &&
          "Expected matching subprograms");
   if (!DeclareFn)
-    DeclareFn = getDeclareIntrin(M);
+    DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
 
   trackIfUnresolved(VarInfo);
   trackIfUnresolved(Expr);
index 9f671e4..c875e30 100644 (file)
@@ -4001,8 +4001,6 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
            "invalid llvm.dbg.declare intrinsic call 1", CS);
     visitDbgIntrinsic("declare", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
     break;
-  case Intrinsic::dbg_addr: // llvm.dbg.addr
-    visitDbgIntrinsic("addr", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
   case Intrinsic::dbg_value: // llvm.dbg.value
     visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
     break;
index 60db2dd..f51b838 100644 (file)
@@ -2106,10 +2106,10 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
 
   // If we are removing an alloca with a dbg.declare, insert dbg.value calls
   // before each store.
-  TinyPtrVector<DbgInfoIntrinsic *> DIIs;
+  DbgDeclareInst *DDI = nullptr;
   std::unique_ptr<DIBuilder> DIB;
   if (isa<AllocaInst>(MI)) {
-    DIIs = FindDbgAddrUses(&MI);
+    DDI = FindAllocaDbgDeclare(&MI);
     DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false));
   }
 
@@ -2145,9 +2145,8 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
       } else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I) ||
                  isa<AddrSpaceCastInst>(I)) {
         replaceInstUsesWith(*I, UndefValue::get(I->getType()));
-      } else if (auto *SI = dyn_cast<StoreInst>(I)) {
-        for (auto *DII : DIIs)
-          ConvertDebugDeclareToDebugValue(DII, SI, *DIB);
+      } else if (DDI && isa<StoreInst>(I)) {
+        ConvertDebugDeclareToDebugValue(DDI, cast<StoreInst>(I), *DIB);
       }
       eraseInstFromFunction(*I);
     }
@@ -2160,8 +2159,8 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
                          None, "", II->getParent());
     }
 
-    for (auto *DII : DIIs)
-      eraseInstFromFunction(*DII);
+    if (DDI)
+      eraseInstFromFunction(*DDI);
 
     return eraseInstFromFunction(MI);
   }
index b968cb8..c96606a 100644 (file)
@@ -4102,10 +4102,9 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
 
   // Migrate debug information from the old alloca to the new alloca(s)
   // and the individual partitions.
-  TinyPtrVector<DbgInfoIntrinsic *> DbgDeclares = FindDbgAddrUses(&AI);
-  if (!DbgDeclares.empty()) {
-    auto *Var = DbgDeclares.front()->getVariable();
-    auto *Expr = DbgDeclares.front()->getExpression();
+  if (DbgDeclareInst *DbgDecl = FindAllocaDbgDeclare(&AI)) {
+    auto *Var = DbgDecl->getVariable();
+    auto *Expr = DbgDecl->getExpression();
     DIBuilder DIB(*AI.getModule(), /*AllowUnresolved*/ false);
     uint64_t AllocaSize = DL.getTypeSizeInBits(AI.getAllocatedType());
     for (auto Fragment : Fragments) {
@@ -4137,12 +4136,12 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
             DIExpression::createFragmentExpression(Expr, Start, Size);
       }
 
-      // Remove any existing intrinsics describing the same alloca.
-      for (DbgInfoIntrinsic *OldDII : FindDbgAddrUses(Fragment.Alloca))
-        OldDII->eraseFromParent();
+      // Remove any existing dbg.declare intrinsic describing the same alloca.
+      if (DbgDeclareInst *OldDDI = FindAllocaDbgDeclare(Fragment.Alloca))
+        OldDDI->eraseFromParent();
 
       DIB.insertDeclare(Fragment.Alloca, Var, FragmentExpr,
-                        DbgDeclares.front()->getDebugLoc(), &AI);
+                        DbgDecl->getDebugLoc(), &AI);
     }
   }
   return Changed;
@@ -4247,15 +4246,6 @@ void SROA::deleteDeadInstructions(
     Instruction *I = DeadInsts.pop_back_val();
     DEBUG(dbgs() << "Deleting dead instruction: " << *I << "\n");
 
-    // If the instruction is an alloca, find the possible dbg.declare connected
-    // to it, and remove it too. We must do this before calling RAUW or we will
-    // not be able to find it.
-    if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
-      DeletedAllocas.insert(AI);
-      for (DbgInfoIntrinsic *OldDII : FindDbgAddrUses(AI))
-        OldDII->eraseFromParent();
-    }
-
     I->replaceAllUsesWith(UndefValue::get(I->getType()));
 
     for (Use &Operand : I->operands())
@@ -4266,6 +4256,12 @@ void SROA::deleteDeadInstructions(
           DeadInsts.insert(U);
       }
 
+    if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
+      DeletedAllocas.insert(AI);
+      if (DbgDeclareInst *DbgDecl = FindAllocaDbgDeclare(AI))
+        DbgDecl->eraseFromParent();
+    }
+
     ++NumDeleted;
     I->eraseFromParent();
   }
index 43b0755..c3251e2 100644 (file)
@@ -1098,13 +1098,12 @@ static bool PhiHasDebugValue(DILocalVariable *DIVar,
 }
 
 /// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
                                            StoreInst *SI, DIBuilder &Builder) {
-  assert(DII->isAddressOfVariable());
-  auto *DIVar = DII->getVariable();
+  auto *DIVar = DDI->getVariable();
   assert(DIVar && "Missing variable");
-  auto *DIExpr = DII->getExpression();
+  auto *DIExpr = DDI->getExpression();
   Value *DV = SI->getOperand(0);
 
   // If an argument is zero extended then use argument directly. The ZExt
@@ -1115,7 +1114,7 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
   if (SExtInst *SExt = dyn_cast<SExtInst>(SI->getOperand(0)))
     ExtendedArg = dyn_cast<Argument>(SExt->getOperand(0));
   if (ExtendedArg) {
-    // If this DII was already describing only a fragment of a variable, ensure
+    // If this DDI was already describing only a fragment of a variable, ensure
     // that fragment is appropriately narrowed here.
     // But if a fragment wasn't used, describe the value as the original
     // argument (rather than the zext or sext) so that it remains described even
@@ -1128,23 +1127,23 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
                                    DIExpr->elements_end() - 3);
       Ops.push_back(dwarf::DW_OP_LLVM_fragment);
       Ops.push_back(FragmentOffset);
-      const DataLayout &DL = DII->getModule()->getDataLayout();
+      const DataLayout &DL = DDI->getModule()->getDataLayout();
       Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType()));
       DIExpr = Builder.createExpression(Ops);
     }
     DV = ExtendedArg;
   }
   if (!LdStHasDebugValue(DIVar, DIExpr, SI))
-    Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DII->getDebugLoc(),
+    Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DDI->getDebugLoc(),
                                     SI);
 }
 
 /// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
                                            LoadInst *LI, DIBuilder &Builder) {
-  auto *DIVar = DII->getVariable();
-  auto *DIExpr = DII->getExpression();
+  auto *DIVar = DDI->getVariable();
+  auto *DIExpr = DDI->getExpression();
   assert(DIVar && "Missing variable");
 
   if (LdStHasDebugValue(DIVar, DIExpr, LI))
@@ -1155,16 +1154,16 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
   // preferable to keep tracking both the loaded value and the original
   // address in case the alloca can not be elided.
   Instruction *DbgValue = Builder.insertDbgValueIntrinsic(
-      LI, DIVar, DIExpr, DII->getDebugLoc(), (Instruction *)nullptr);
+      LI, DIVar, DIExpr, DDI->getDebugLoc(), (Instruction *)nullptr);
   DbgValue->insertAfter(LI);
 }
 
-/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated
-/// llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// Inserts a llvm.dbg.value intrinsic after a phi
+/// that has an associated llvm.dbg.decl intrinsic.
+void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
                                            PHINode *APN, DIBuilder &Builder) {
-  auto *DIVar = DII->getVariable();
-  auto *DIExpr = DII->getExpression();
+  auto *DIVar = DDI->getVariable();
+  auto *DIExpr = DDI->getExpression();
   assert(DIVar && "Missing variable");
 
   if (PhiHasDebugValue(DIVar, DIExpr, APN))
@@ -1177,7 +1176,7 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
   // insertion point.
   // FIXME: Insert dbg.value markers in the successors when appropriate.
   if (InsertionPt != BB->end())
-    Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, DII->getDebugLoc(),
+    Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, DDI->getDebugLoc(),
                                     &*InsertionPt);
 }
 
@@ -1232,25 +1231,16 @@ bool llvm::LowerDbgDeclare(Function &F) {
   return true;
 }
 
-/// Finds all intrinsics declaring local variables as living in the memory that
-/// 'V' points to. This may include a mix of dbg.declare and
-/// dbg.addr intrinsics.
-TinyPtrVector<DbgInfoIntrinsic *> llvm::FindDbgAddrUses(Value *V) {
-  auto *L = LocalAsMetadata::getIfExists(V);
-  if (!L)
-    return {};
-  auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L);
-  if (!MDV)
-    return {};
-
-  TinyPtrVector<DbgInfoIntrinsic *> Declares;
-  for (User *U : MDV->users()) {
-    if (auto *DII = dyn_cast<DbgInfoIntrinsic>(U))
-      if (DII->isAddressOfVariable())
-        Declares.push_back(DII);
-  }
+/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
+/// alloca 'V', if any.
+DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {
+  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))
+          return DDI;
 
-  return Declares;
+  return nullptr;
 }
 
 void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
@@ -1261,22 +1251,23 @@ void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
           DbgValues.push_back(DVI);
 }
 
+
 bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
                              Instruction *InsertBefore, DIBuilder &Builder,
                              bool Deref, int Offset) {
-  auto DbgAddrs = FindDbgAddrUses(Address);
-  for (DbgInfoIntrinsic *DII : DbgAddrs) {
-    DebugLoc Loc = DII->getDebugLoc();
-    auto *DIVar = DII->getVariable();
-    auto *DIExpr = DII->getExpression();
-    assert(DIVar && "Missing variable");
-    DIExpr = DIExpression::prepend(DIExpr, Deref, Offset);
-    // Insert llvm.dbg.declare immediately after the original alloca, and remove
-    // old llvm.dbg.declare.
-    Builder.insertDeclare(NewAddress, DIVar, DIExpr, Loc, InsertBefore);
-    DII->eraseFromParent();
-  }
-  return !DbgAddrs.empty();
+  DbgDeclareInst *DDI = FindAllocaDbgDeclare(Address);
+  if (!DDI)
+    return false;
+  DebugLoc Loc = DDI->getDebugLoc();
+  auto *DIVar = DDI->getVariable();
+  auto *DIExpr = DDI->getExpression();
+  assert(DIVar && "Missing variable");
+  DIExpr = DIExpression::prepend(DIExpr, Deref, Offset);
+  // Insert llvm.dbg.declare immediately after the original alloca, and remove
+  // old llvm.dbg.declare.
+  Builder.insertDeclare(NewAddress, DIVar, DIExpr, Loc, InsertBefore);
+  DDI->eraseFromParent();
+  return true;
 }
 
 bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
index e2ba5c4..ac28f59 100644 (file)
@@ -103,7 +103,7 @@ struct AllocaInfo {
   bool OnlyUsedInOneBlock;
 
   Value *AllocaPointerVal;
-  TinyPtrVector<DbgInfoIntrinsic*> DbgDeclares;
+  DbgDeclareInst *DbgDeclare;
 
   void clear() {
     DefiningBlocks.clear();
@@ -112,7 +112,7 @@ struct AllocaInfo {
     OnlyBlock = nullptr;
     OnlyUsedInOneBlock = true;
     AllocaPointerVal = nullptr;
-    DbgDeclares.clear();
+    DbgDeclare = nullptr;
   }
 
   /// Scan the uses of the specified alloca, filling in the AllocaInfo used
@@ -147,7 +147,7 @@ struct AllocaInfo {
       }
     }
 
-    DbgDeclares = FindDbgAddrUses(AI);
+    DbgDeclare = FindAllocaDbgDeclare(AI);
   }
 };
 
@@ -245,7 +245,7 @@ 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<TinyPtrVector<DbgInfoIntrinsic *>, 8> AllocaDbgDeclares;
+  SmallVector<DbgDeclareInst *, 8> AllocaDbgDeclares;
 
   /// The set of basic blocks the renamer has already visited.
   ///
@@ -409,11 +409,11 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
 
   // Record debuginfo for the store and remove the declaration's
   // debuginfo.
-  for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
+  if (DbgDeclareInst *DDI = Info.DbgDeclare) {
     DIBuilder DIB(*AI->getModule(), /*AllowUnresolved*/ false);
-    ConvertDebugDeclareToDebugValue(DII, Info.OnlyStore, DIB);
-    DII->eraseFromParent();
-    LBI.deleteValue(DII);
+    ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore, DIB);
+    DDI->eraseFromParent();
+    LBI.deleteValue(DDI);
   }
   // Remove the (now dead) store and alloca.
   Info.OnlyStore->eraseFromParent();
@@ -505,9 +505,9 @@ 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.
-    for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
+    if (DbgDeclareInst *DDI = Info.DbgDeclare) {
       DIBuilder DIB(*AI->getModule(), /*AllowUnresolved*/ false);
-      ConvertDebugDeclareToDebugValue(DII, SI, DIB);
+      ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
     }
     SI->eraseFromParent();
     LBI.deleteValue(SI);
@@ -517,9 +517,9 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
   LBI.deleteValue(AI);
 
   // The alloca's debuginfo can be removed as well.
-  for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
-    DII->eraseFromParent();
-    LBI.deleteValue(DII);
+  if (DbgDeclareInst *DDI = Info.DbgDeclare) {
+    DDI->eraseFromParent();
+    LBI.deleteValue(DDI);
   }
 
   ++NumLocalPromoted;
@@ -587,8 +587,8 @@ void PromoteMem2Reg::run() {
     }
 
     // Remember the dbg.declare intrinsic describing this alloca, if any.
-    if (!Info.DbgDeclares.empty())
-      AllocaDbgDeclares[AllocaNum] = Info.DbgDeclares;
+    if (Info.DbgDeclare)
+      AllocaDbgDeclares[AllocaNum] = Info.DbgDeclare;
 
     // Keep the reverse mapping of the 'Allocas' array for the rename pass.
     AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
@@ -666,9 +666,9 @@ void PromoteMem2Reg::run() {
   }
 
   // Remove alloca's dbg.declare instrinsics from the function.
-  for (auto &Declares : AllocaDbgDeclares)
-    for (auto *DII : Declares)
-      DII->eraseFromParent();
+  for (DbgDeclareInst *DDI : AllocaDbgDeclares)
+    if (DDI)
+      DDI->eraseFromParent();
 
   // Loop over all of the PHI nodes and see if there are any that we can get
   // rid of because they merge all of the same incoming values.  This can
@@ -895,8 +895,8 @@ NextIteration:
 
         // The currently active variable for this block is now the PHI.
         IncomingVals[AllocaNo] = APN;
-        for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[AllocaNo])
-          ConvertDebugDeclareToDebugValue(DII, APN, DIB);
+        if (DbgDeclareInst *DDI = AllocaDbgDeclares[AllocaNo])
+          ConvertDebugDeclareToDebugValue(DDI, APN, DIB);
 
         // Get the next phi node.
         ++PNI;
@@ -952,8 +952,8 @@ NextIteration:
       // what value were we writing?
       IncomingVals[ai->second] = SI->getOperand(0);
       // Record debuginfo for the store before removing it.
-      for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[ai->second])
-        ConvertDebugDeclareToDebugValue(DII, SI, DIB);
+      if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second])
+        ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
       BB->getInstList().erase(SI);
     }
   }
diff --git a/test/DebugInfo/X86/dbg-addr-dse.ll b/test/DebugInfo/X86/dbg-addr-dse.ll
deleted file mode 100644 (file)
index b438982..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-; RUN: llc %s -o %t.s
-; RUN: llvm-mc %t.s -filetype=obj -triple=x86_64-windows-msvc -o %t.o
-; RUN: FileCheck %s < %t.s --check-prefix=ASM
-; RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=DWARF
-
-; In this example, the variable lives mostly in memory, but at the point of the
-; assignment to global, it lives nowhere, and is described as the constant
-; value 1.
-
-; C source:
-;
-; void escape(int *);
-; extern int global;
-; void f(int x) {
-;   escape(&x);
-;   x = 1; // DSE should delete and insert dbg.value(i32 1)
-;   global = x;
-;   x = 2; // DSE should insert dbg.addr
-;   escape(&x);
-; }
-
-; ModuleID = 'dse.c'
-source_filename = "dse.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-declare void @llvm.dbg.addr(metadata, metadata, metadata) #2
-declare void @llvm.dbg.value(metadata, metadata, metadata) #2
-declare void @escape(i32*)
-
-@global = external global i32, align 4
-
-; Function Attrs: nounwind uwtable
-define void @f(i32 %x) #0 !dbg !8 {
-entry:
-  %x.addr = alloca i32, align 4
-  store i32 %x, i32* %x.addr, align 4
-  call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !18
-  call void @escape(i32* %x.addr), !dbg !19
-  call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression()), !dbg !20
-  store i32 1, i32* @global, align 4, !dbg !22
-  call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !23
-  store i32 2, i32* %x.addr, align 4, !dbg !23
-  call void @escape(i32* %x.addr), !dbg !24
-  ret void, !dbg !25
-}
-
-; ASM-LABEL: f: # @f
-; ASM: movl    %ecx, [[OFF_X:[0-9]+]](%rsp)
-; ASM: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [%RSP+0]
-; ASM: callq   escape
-; ASM: #DEBUG_VALUE: f:x <- 1
-; ASM: movl    $1, global(%rip)
-; FIXME: Needs a fix to LiveDebugVariables
-; ASMX: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [%RSP+0]
-; ASM: movl    $2, [[OFF_X]](%rsp)
-; ASM: callq   escape
-; ASM: retq
-
-; DWARF:      DW_TAG_formal_parameter
-; DWARF-NEXT:   DW_AT_location        (0x00000000
-; DWARF-NEXT:      {{[^:]*}}: DW_OP_breg7 RSP+{{[0-9]+}}
-; DWARF-NEXT:      {{[^:]*}}: DW_OP_consts +1, DW_OP_stack_value
-; FIXME: Needs a fix to LiveDebugVariables
-; DWARFX-NEXT:      {{[^:]*}}: DW_OP_breg7 RSP+{{[0-9]+}})
-; DWARF-NEXT:   DW_AT_name    ("x")
-
-attributes #0 = { nounwind uwtable }
-attributes #2 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
-!9 = !DISubroutineType(types: !10)
-!10 = !{null, !11}
-!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!12 = !{!13}
-!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type: !11)
-!14 = !{!15, !15, i64 0}
-!15 = !{!"int", !16, i64 0}
-!16 = !{!"omnipotent char", !17, i64 0}
-!17 = !{!"Simple C/C++ TBAA"}
-!18 = !DILocation(line: 3, column: 12, scope: !8)
-!19 = !DILocation(line: 4, column: 3, scope: !8)
-!20 = !DILocation(line: 5, column: 5, scope: !8)
-!21 = !DILocation(line: 6, column: 12, scope: !8)
-!22 = !DILocation(line: 6, column: 10, scope: !8)
-!23 = !DILocation(line: 7, column: 5, scope: !8)
-!24 = !DILocation(line: 8, column: 3, scope: !8)
-!25 = !DILocation(line: 9, column: 1, scope: !8)
diff --git a/test/DebugInfo/X86/dbg-addr.ll b/test/DebugInfo/X86/dbg-addr.ll
deleted file mode 100644 (file)
index ffd0f77..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-; RUN: llc %s -o %t.s
-; RUN: llvm-mc -triple x86_64--linux %t.s -filetype=obj -o %t.o
-; RUN: FileCheck < %t.s %s
-; RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=DWARF
-
-; Unlike dbg.declare, dbg.addr should be lowered to DBG_VALUE instructions. It
-; is control-dependent.
-
-; CHECK-LABEL: use_dbg_addr:
-; CHECK: #DEBUG_VALUE: use_dbg_addr:o <- [%RSP+0]
-
-; FIXME: Avoid the use of a single-location location list and use
-; DW_AT_start_offset instead.
-
-; DWARF: DW_TAG_variable
-; DWARF-NEXT:              DW_AT_location (0x00000000
-; DWARF-NEXT:                          0x{{.*}} - 0x{{.*}}: DW_OP_breg7 RSP+0)
-; DWARF-NEXT:              DW_AT_name ("o")
-
-
-; ModuleID = 't.c'
-source_filename = "t.c"
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64--linux"
-
-%struct.Foo = type { i32 }
-
-; Function Attrs: noinline nounwind uwtable
-define void @use_dbg_addr() #0 !dbg !7 {
-entry:
-  %o = alloca %struct.Foo, align 4
-  call void @llvm.dbg.addr(metadata %struct.Foo* %o, metadata !10, metadata !15), !dbg !16
-  call void @escape_foo(%struct.Foo* %o), !dbg !17
-  ret void, !dbg !18
-}
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.addr(metadata, metadata, metadata) #1
-
-declare void @escape_foo(%struct.Foo*)
-
-attributes #0 = { noinline nounwind uwtable }
-attributes #1 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5}
-!llvm.ident = !{!6}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 4}
-!6 = !{!"clang version 6.0.0 "}
-!7 = distinct !DISubprogram(name: "use_dbg_addr", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
-!8 = !DISubroutineType(types: !9)
-!9 = !{null}
-!10 = !DILocalVariable(name: "o", scope: !7, file: !1, line: 4, type: !11)
-!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 32, elements: !12)
-!12 = !{!13}
-!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32)
-!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!15 = !DIExpression()
-!16 = !DILocation(line: 4, column: 14, scope: !7)
-!17 = !DILocation(line: 5, column: 3, scope: !7)
-!18 = !DILocation(line: 6, column: 1, scope: !7)
index 78f5ca9..dbd3b49 100644 (file)
@@ -20,10 +20,10 @@ target triple = "x86_64-unknown-linux-gnu"
 ;
 ; There should be no debug info for the padding.
 ; CHECK-NOT: DW_OP_LLVM_fragment, 56
-; CHECK: DIExpression(DW_OP_LLVM_fragment, 0, 32)
-; CHECK-NOT: DW_OP_LLVM_fragment, 56
 ; CHECK: DIExpression(DW_OP_LLVM_fragment, 32, 24)
 ; CHECK-NOT: DW_OP_LLVM_fragment, 56
+; CHECK: DIExpression(DW_OP_LLVM_fragment, 0, 32)
+; CHECK-NOT: DW_OP_LLVM_fragment, 56
 %struct.prog_src_register = type { i32, i24 }
 
 ; Function Attrs: nounwind
diff --git a/test/DebugInfo/X86/sroasplit-dbg-declare.ll b/test/DebugInfo/X86/sroasplit-dbg-declare.ll
deleted file mode 100644 (file)
index 0a1a41b..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-; RUN: opt -S -sroa -o - %s | FileCheck %s
-
-; SROA should split the alloca in two new ones, each with its own dbg.declare.
-; The original alloca and dbg.declare should be removed.
-
-define void @f1() {
-entry:
-  %0 = alloca [9 x i32]
-  call void @llvm.dbg.declare(metadata [9 x i32]* %0, metadata !11, metadata !DIExpression()), !dbg !17
-  %1 = bitcast [9 x i32]* %0 to i8*
-  call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 36, i32 16, i1 true)
-  %2 = getelementptr [9 x i32], [9 x i32]* %0, i32 0, i32 0
-  store volatile i32 1, i32* %2
-  ret void
-}
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
-
-; Function Attrs: argmemonly nounwind
-declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #0
-
-attributes #0 = { argmemonly nounwind }
-attributes #1 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5}
-!llvm.ident = !{!6}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "foo.c", directory: "/bar")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 4}
-!6 = !{!"clang version 6.0.0"}
-!7 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !10)
-!8 = !DISubroutineType(types: !9)
-!9 = !{null}
-!10 = !{!11}
-!11 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !12)
-!12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 288, elements: !15)
-!13 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !14)
-!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!15 = !{!16}
-!16 = !DISubrange(count: 9)
-!17 = !DILocation(line: 3, column: 18, scope: !7)
-
-; CHECK-NOT:  = alloca [9 x i32]
-; CHECK-NOT:  call void @llvm.dbg.declare(metadata [9 x i32]*
-
-; CHECK:      %[[VAR1:.*]] = alloca i32
-; CHECK-NEXT: %[[VAR2:.*]] = alloca [8 x i32]
-; CHECK-NEXT: call void @llvm.dbg.declare(metadata i32* %[[VAR1]]
-; CHECK-NEXT: call void @llvm.dbg.declare(metadata [8 x i32]* %[[VAR2]]
-
-; CHECK-NOT:  = alloca [9 x i32]
-; CHECK-NOT:  call void @llvm.dbg.declare(metadata [9 x i32]*
-
diff --git a/test/Transforms/Mem2Reg/dbg-addr-inline-dse.ll b/test/Transforms/Mem2Reg/dbg-addr-inline-dse.ll
deleted file mode 100644 (file)
index 8fe2e0a..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-; RUN: opt -mem2reg -S < %s | FileCheck %s -implicit-check-not="call void @llvm.dbg.addr"
-
-; This example is intended to simulate this pass pipeline, which may not exist
-; in practice:
-; 1. DSE f from the original C source
-; 2. Inline escape
-; 3. mem2reg
-; This exercises the corner case of multiple llvm.dbg.addr intrinsics.
-
-; C source:
-;
-; void escape(int *px) { ++*px; }
-; extern int global;
-; void f(int x) {
-;   escape(&x);
-;   x = 1; // DSE should delete and insert dbg.value(i32 1)
-;   global = x;
-;   x = 2; // DSE should insert dbg.addr
-;   escape(&x);
-; }
-
-; ModuleID = 'dse.c'
-source_filename = "dse.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-declare void @llvm.dbg.addr(metadata, metadata, metadata) #2
-declare void @llvm.dbg.value(metadata, metadata, metadata) #2
-
-@global = external global i32, align 4
-
-; Function Attrs: nounwind uwtable
-define void @f(i32 %x) #0 !dbg !8 {
-entry:
-  %x.addr = alloca i32, align 4
-  store i32 %x, i32* %x.addr, align 4
-  call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !18
-  %ld.1 = load i32, i32* %x.addr, align 4, !dbg !19
-  %inc.1 = add nsw i32 %ld.1, 1, !dbg !19
-  store i32 %inc.1, i32* %x.addr, align 4, !dbg !19
-  call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression()), !dbg !20
-  store i32 1, i32* @global, align 4, !dbg !22
-  call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !23
-  store i32 2, i32* %x.addr, align 4, !dbg !23
-  %ld.2 = load i32, i32* %x.addr, align 4, !dbg !19
-  %inc.2 = add nsw i32 %ld.2, 1, !dbg !19
-  store i32 %inc.2, i32* %x.addr, align 4, !dbg !19
-  ret void, !dbg !25
-}
-
-; CHECK-LABEL: define void @f(i32 %x)
-; CHECK: call void @llvm.dbg.value(metadata i32 %x, metadata !13, metadata !DIExpression())
-; CHECK: %inc.1 = add nsw i32 %x, 1
-; CHECK: call void @llvm.dbg.value(metadata i32 %inc.1, metadata !13, metadata !DIExpression())
-; CHECK: call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression())
-; CHECK: store i32 1, i32* @global, align 4
-; CHECK: call void @llvm.dbg.value(metadata i32 2, metadata !13, metadata !DIExpression())
-; CHECK: %inc.2 = add nsw i32 2, 1
-; CHECK: call void @llvm.dbg.value(metadata i32 %inc.2, metadata !13, metadata !DIExpression())
-; CHECK: ret void
-
-attributes #0 = { nounwind uwtable }
-attributes #2 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
-!9 = !DISubroutineType(types: !10)
-!10 = !{null, !11}
-!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!12 = !{!13}
-!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type: !11)
-!14 = !{!15, !15, i64 0}
-!15 = !{!"int", !16, i64 0}
-!16 = !{!"omnipotent char", !17, i64 0}
-!17 = !{!"Simple C/C++ TBAA"}
-!18 = !DILocation(line: 3, column: 12, scope: !8)
-!19 = !DILocation(line: 4, column: 3, scope: !8)
-!20 = !DILocation(line: 5, column: 5, scope: !8)
-!21 = !DILocation(line: 6, column: 12, scope: !8)
-!22 = !DILocation(line: 6, column: 10, scope: !8)
-!23 = !DILocation(line: 7, column: 5, scope: !8)
-!24 = !DILocation(line: 8, column: 3, scope: !8)
-!25 = !DILocation(line: 9, column: 1, scope: !8)
diff --git a/test/Transforms/Mem2Reg/dbg-addr.ll b/test/Transforms/Mem2Reg/dbg-addr.ll
deleted file mode 100644 (file)
index 8c97f79..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-; RUN: opt -mem2reg -S < %s | FileCheck %s
-
-; ModuleID = 'newvars.c'
-source_filename = "newvars.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-; Function Attrs: nounwind uwtable
-define i32 @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
-entry:
-  %x = alloca i32, align 4
-  call void @llvm.dbg.addr(metadata i32* %x, metadata !16, metadata !DIExpression()), !dbg !26
-  store i32 %a, i32* %x, align 4, !dbg !26, !tbaa !17
-  %tobool = icmp ne i32 %cond, 0, !dbg !28
-  br i1 %tobool, label %if.then, label %if.else, !dbg !30
-
-if.then:                                          ; preds = %entry
-  store i32 0, i32* %x, align 4, !dbg !31, !tbaa !17
-  br label %if.end, !dbg !33
-
-if.else:                                          ; preds = %entry
-  store i32 %b, i32* %x, align 4, !dbg !36, !tbaa !17
-  br label %if.end
-
-if.end:                                           ; preds = %if.else, %if.then
-  %rv = load i32, i32* %x, align 4, !dbg !37, !tbaa !17
-  ret i32 %rv, !dbg !39
-}
-
-; CHECK-LABEL: define i32 @if_else({{.*}})
-; CHECK: entry:
-; CHECK-NOT:   alloca i32
-; CHECK:   call void @llvm.dbg.value(metadata i32 %a, metadata ![[X_LOCAL:[0-9]+]], metadata !DIExpression())
-; CHECK: if.then:                                          ; preds = %entry
-; CHECK:   call void @llvm.dbg.value(metadata i32 0, metadata ![[X_LOCAL]], metadata !DIExpression())
-; CHECK: if.else:                                          ; preds = %entry
-; CHECK:   call void @llvm.dbg.value(metadata i32 %b, metadata ![[X_LOCAL]], metadata !DIExpression())
-; CHECK: if.end:                                           ; preds = %if.else, %if.then
-; CHECK:   %[[PHI:[^ ]*]] = phi i32 [ 0, %if.then ], [ %b, %if.else ]
-; CHECK:   call void @llvm.dbg.value(metadata i32 %[[PHI]], metadata ![[X_LOCAL]], metadata !DIExpression())
-; CHECK:   ret i32
-
-; CHECK: ![[X_LOCAL]] = !DILocalVariable(name: "x", {{.*}})
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.declare(metadata, metadata, metadata)
-declare void @llvm.dbg.addr(metadata, metadata, metadata)
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
-!9 = !DISubroutineType(types: !10)
-!10 = !{!11, !11, !11, !11}
-!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!12 = !{!13, !14, !15, !16}
-!13 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 1, type: !11)
-!14 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 1, type: !11)
-!15 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 1, type: !11)
-!16 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !11)
-!17 = !{!18, !18, i64 0}
-!18 = !{!"int", !19, i64 0}
-!19 = !{!"omnipotent char", !20, i64 0}
-!20 = !{!"Simple C/C++ TBAA"}
-!22 = !DILocation(line: 1, column: 34, scope: !8)
-!23 = !DILocation(line: 1, column: 27, scope: !8)
-!24 = !DILocation(line: 1, column: 17, scope: !8)
-!25 = !DILocation(line: 2, column: 3, scope: !8)
-!26 = !DILocation(line: 2, column: 7, scope: !8)
-!27 = !DILocation(line: 2, column: 11, scope: !8)
-!28 = !DILocation(line: 3, column: 7, scope: !29)
-!29 = distinct !DILexicalBlock(scope: !8, file: !1, line: 3, column: 7)
-!30 = !DILocation(line: 3, column: 7, scope: !8)
-!31 = !DILocation(line: 4, column: 7, scope: !32)
-!32 = distinct !DILexicalBlock(scope: !29, file: !1, line: 3, column: 13)
-!33 = !DILocation(line: 5, column: 3, scope: !32)
-!34 = !DILocation(line: 6, column: 9, scope: !35)
-!35 = distinct !DILexicalBlock(scope: !29, file: !1, line: 5, column: 10)
-!36 = !DILocation(line: 6, column: 7, scope: !35)
-!37 = !DILocation(line: 8, column: 10, scope: !8)
-!38 = !DILocation(line: 9, column: 1, scope: !8)
-!39 = !DILocation(line: 8, column: 3, scope: !8)
diff --git a/test/Transforms/SROA/dbg-addr-diamond.ll b/test/Transforms/SROA/dbg-addr-diamond.ll
deleted file mode 100644 (file)
index 132da99..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-; RUN: opt -use-dbg-addr -sroa -S < %s | FileCheck %s
-
-; ModuleID = '<stdin>'
-source_filename = "newvars.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-%struct.Pair = type { i32, i32 }
-
-@pair = internal global %struct.Pair zeroinitializer
-
-; Function Attrs: nounwind uwtable
-define void @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
-entry:
-  %p = alloca %struct.Pair, align 4
-  %0 = bitcast %struct.Pair* %p to i8*, !dbg !25
-  call void @llvm.dbg.addr(metadata %struct.Pair* %p, metadata !20, metadata !DIExpression()), !dbg !26
-  %x = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !27
-  store i32 %a, i32* %x, align 4, !dbg !28
-  %y = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !34
-  store i32 %b, i32* %y, align 4, !dbg !35
-  %tobool = icmp ne i32 %cond, 0, !dbg !37
-  br i1 %tobool, label %if.then, label %if.else, !dbg !39
-
-if.then:                                          ; preds = %entry
-  %x1 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !40
-  store i32 0, i32* %x1, align 4, !dbg !42
-  %y2 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !43
-  store i32 %a, i32* %y2, align 4, !dbg !44
-  br label %if.end, !dbg !45
-
-if.else:                                          ; preds = %entry
-  %x3 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !46
-  store i32 %b, i32* %x3, align 4, !dbg !48
-  %y4 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !49
-  store i32 0, i32* %y4, align 4, !dbg !50
-  br label %if.end
-
-if.end:                                           ; preds = %if.else, %if.then
-  %1 = bitcast %struct.Pair* %p to i8*, !dbg !51
-  %2 = bitcast %struct.Pair* @pair to i8*, !dbg !51
-  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %1, i64 8, i32 4, i1 false), !dbg !51
-  ret void
-}
-
-; CHECK-LABEL: define void @if_else(i32 %cond, i32 %a, i32 %b)
-; CHECK: entry:
-; CHECK:   call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR:[0-9]+]], metadata ![[XFRAG:DIExpression\(DW_OP_LLVM_fragment, 0, 32\)]])
-; CHECK:   call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[YFRAG:DIExpression\(DW_OP_LLVM_fragment, 32, 32\)]])
-; CHECK: if.then:
-; CHECK:   call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[XFRAG]])
-; CHECK:   call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR]], metadata ![[YFRAG]])
-; CHECK: if.else:
-; CHECK:   call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[XFRAG]])
-; CHECK:   call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[YFRAG]])
-; CHECK: if.end:
-; CHECK:   %p.sroa.4.0 = phi i32 [ %a, %if.then ], [ 0, %if.else ]
-; CHECK:   %p.sroa.0.0 = phi i32 [ 0, %if.then ], [ %b, %if.else ]
-; CHECK:   call void @llvm.dbg.value(metadata i32 %p.sroa.0.0, metadata ![[PVAR]], metadata ![[XFRAG]])
-; CHECK:   call void @llvm.dbg.value(metadata i32 %p.sroa.4.0, metadata ![[PVAR]], metadata ![[YFRAG]])
-
-; CHECK: ![[PVAR]] = !DILocalVariable(name: "p", {{.*}})
-
-; Function Attrs: argmemonly nounwind
-declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #2
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.addr(metadata, metadata, metadata)
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !16)
-!9 = !DISubroutineType(types: !10)
-!10 = !{!11, !14, !14, !14}
-!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Pair", file: !1, line: 1, size: 64, elements: !12)
-!12 = !{!13, !15}
-!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32)
-!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!15 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !11, file: !1, line: 1, baseType: !14, size: 32, offset: 32)
-!16 = !{!17, !18, !19, !20}
-!17 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 2, type: !14)
-!18 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 2, type: !14)
-!19 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 2, type: !14)
-!20 = !DILocalVariable(name: "p", scope: !8, file: !1, line: 3, type: !11)
-!22 = !DILocation(line: 2, column: 42, scope: !8)
-!23 = !DILocation(line: 2, column: 35, scope: !8)
-!24 = !DILocation(line: 2, column: 25, scope: !8)
-!25 = !DILocation(line: 3, column: 3, scope: !8)
-!26 = !DILocation(line: 3, column: 15, scope: !8)
-!27 = !DILocation(line: 4, column: 5, scope: !8)
-!28 = !DILocation(line: 4, column: 7, scope: !8)
-!29 = !{!30, !31, i64 0}
-!30 = !{!"Pair", !31, i64 0, !31, i64 4}
-!31 = !{!"int", !32, i64 0}
-!32 = !{!"omnipotent char", !33, i64 0}
-!33 = !{!"Simple C/C++ TBAA"}
-!34 = !DILocation(line: 5, column: 5, scope: !8)
-!35 = !DILocation(line: 5, column: 7, scope: !8)
-!36 = !{!30, !31, i64 4}
-!37 = !DILocation(line: 6, column: 7, scope: !38)
-!38 = distinct !DILexicalBlock(scope: !8, file: !1, line: 6, column: 7)
-!39 = !DILocation(line: 6, column: 7, scope: !8)
-!40 = !DILocation(line: 7, column: 7, scope: !41)
-!41 = distinct !DILexicalBlock(scope: !38, file: !1, line: 6, column: 13)
-!42 = !DILocation(line: 7, column: 9, scope: !41)
-!43 = !DILocation(line: 8, column: 7, scope: !41)
-!44 = !DILocation(line: 8, column: 9, scope: !41)
-!45 = !DILocation(line: 9, column: 3, scope: !41)
-!46 = !DILocation(line: 10, column: 7, scope: !47)
-!47 = distinct !DILexicalBlock(scope: !38, file: !1, line: 9, column: 10)
-!48 = !DILocation(line: 10, column: 9, scope: !47)
-!49 = !DILocation(line: 11, column: 7, scope: !47)
-!50 = !DILocation(line: 11, column: 9, scope: !47)
-!51 = !DILocation(line: 13, column: 10, scope: !8)
-!52 = !{i64 0, i64 4, !53, i64 4, i64 4, !53}
-!53 = !{!31, !31, i64 0}
-!54 = !DILocation(line: 14, column: 1, scope: !8)