<div dir="ltr">Repro is in <a href="https://crbug.com/1198356#c1">https://crbug.com/1198356#c1</a><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Apr 12, 2021 at 6:46 PM Arthur Eubanks <<a href="mailto:aeubanks@google.com">aeubanks@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">A heads up, this is causing crashes in ThinLTO on Chrome (both Windows and Linux): <a href="https://crbug.com/1198356" target="_blank">https://crbug.com/1198356</a>. I'll see if I can come up with a nice reproducer. <div><br></div><div>ld.lld: ../../llvm/lib/Bitcode/Reader/MetadataLoader.cpp:1071: void llvm::MetadataLoader::MetadataLoaderImpl::lazyLoadOneMetadata(unsigned int, (anonymous namespace)::(anonymous namespace)::PlaceholderQueue &): Assertion `ID < (MDStringRef.size()) + GlobalMetadataBitPosIndex.size()' failed.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Apr 12, 2021 at 8:57 AM Stephen Tozer via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Stephen Tozer<br>
Date: 2021-04-12T16:57:29+01:00<br>
New Revision: f2e4f3eff3c9135d92840016f8ed4540cdd1313b<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/f2e4f3eff3c9135d92840016f8ed4540cdd1313b" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/f2e4f3eff3c9135d92840016f8ed4540cdd1313b</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/f2e4f3eff3c9135d92840016f8ed4540cdd1313b.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/f2e4f3eff3c9135d92840016f8ed4540cdd1313b.diff</a><br>
<br>
LOG: Reapply "[DebugInfo] Use variadic debug values to salvage BinOps and GEP instrs with non-const operands"<br>
<br>
The causes of the previous build errors have been fixed in revisions<br>
aa3e78a59fdf3b211be72f1b3221af831665e67d, and<br>
140757bfaaa00110a92d2247a910c847e6e3bcc8<br>
<br>
This reverts commit f40976bd01032f4905dde361e709166704581077.<br>
<br>
Added: <br>
    llvm/test/DebugInfo/salvage-gep.ll<br>
    llvm/test/DebugInfo/salvage-nonconst-binop.ll<br>
<br>
Modified: <br>
    llvm/include/llvm/IR/DebugInfoMetadata.h<br>
    llvm/include/llvm/IR/Instructions.h<br>
    llvm/include/llvm/IR/IntrinsicInst.h<br>
    llvm/include/llvm/IR/Operator.h<br>
    llvm/include/llvm/Transforms/Utils/Local.h<br>
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
    llvm/lib/IR/DebugInfoMetadata.cpp<br>
    llvm/lib/IR/Instructions.cpp<br>
    llvm/lib/IR/IntrinsicInst.cpp<br>
    llvm/lib/IR/Operator.cpp<br>
    llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
    llvm/lib/Transforms/Utils/Local.cpp<br>
    llvm/test/DebugInfo/NVPTX/debug-info.ll<br>
    llvm/test/Transforms/InstCombine/debuginfo-sink.ll<br>
    llvm/test/Transforms/Reassociate/undef_intrinsics_when_deleting_instructions.ll<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h<br>
index e60124ea80b44..42d0b618a9171 100644<br>
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h<br>
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h<br>
@@ -2589,6 +2589,16 @@ class DIExpression : public MDNode {<br>
   // return it's sign information.<br>
   llvm::Optional<SignedOrUnsignedConstant> isConstant() const;<br>
<br>
+  /// Return the number of unique location operands referred to (via<br>
+  /// DW_OP_LLVM_arg) in this expression; this is not necessarily the number of<br>
+  /// instances of DW_OP_LLVM_arg within the expression.<br>
+  /// For example, for the expression:<br>
+  ///   (DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_plus,<br>
+  ///    DW_OP_LLVM_arg 0, DW_OP_mul)<br>
+  /// This function would return 2, as there are two unique location operands<br>
+  /// (0 and 1).<br>
+  uint64_t getNumLocationOperands() const;<br>
+<br>
   using element_iterator = ArrayRef<uint64_t>::iterator;<br>
<br>
   element_iterator elements_begin() const { return getElements().begin(); }<br>
@@ -2731,6 +2741,10 @@ class DIExpression : public MDNode {<br>
   /// return true with an offset of zero.<br>
   bool extractIfOffset(int64_t &Offset) const;<br>
<br>
+  /// Returns true iff this DIExpression contains at least one instance of<br>
+  /// `DW_OP_LLVM_arg, n` for all n in [0, N).<br>
+  bool hasAllLocationOps(unsigned N) const;<br>
+<br>
   /// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF<br>
   /// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address<br>
   /// Space>.<br>
<br>
diff  --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h<br>
index a0f0897eac8d4..14ba509f424e7 100644<br>
--- a/llvm/include/llvm/IR/Instructions.h<br>
+++ b/llvm/include/llvm/IR/Instructions.h<br>
@@ -1122,7 +1122,9 @@ class GetElementPtrInst : public Instruction {<br>
   /// must be at least as wide as the IntPtr type for the address space of<br>
   /// the base GEP pointer.<br>
   bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const;<br>
-<br>
+  bool collectOffset(const DataLayout &DL, unsigned BitWidth,<br>
+                     SmallDenseMap<Value *, APInt, 8> &VariableOffsets,<br>
+                     APInt &ConstantOffset) const;<br>
   // Methods for support type inquiry through isa, cast, and dyn_cast:<br>
   static bool classof(const Instruction *I) {<br>
     return (I->getOpcode() == Instruction::GetElementPtr);<br>
<br>
diff  --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h<br>
index e217f973b4b83..eb9b498cf7d46 100644<br>
--- a/llvm/include/llvm/IR/IntrinsicInst.h<br>
+++ b/llvm/include/llvm/IR/IntrinsicInst.h<br>
@@ -204,6 +204,11 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {<br>
<br>
   void replaceVariableLocationOp(Value *OldValue, Value *NewValue);<br>
   void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue);<br>
+  /// Adding a new location operand will always result in this intrinsic using<br>
+  /// an ArgList, and must always be accompanied by a new expression that uses<br>
+  /// the new operand.<br>
+  void addVariableLocationOps(ArrayRef<Value *> NewValues,<br>
+                              DIExpression *NewExpr);<br>
<br>
   void setVariable(DILocalVariable *NewVar) {<br>
     setArgOperand(1, MetadataAsValue::get(NewVar->getContext(), NewVar));<br>
<br>
diff  --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h<br>
index 03bcea3d91f62..303539fd0bfc2 100644<br>
--- a/llvm/include/llvm/IR/Operator.h<br>
+++ b/llvm/include/llvm/IR/Operator.h<br>
@@ -576,6 +576,12 @@ class GEPOperator<br>
       Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL,<br>
       APInt &Offset,<br>
       function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr);<br>
+<br>
+  /// Collect the offset of this GEP as a map of Values to their associated<br>
+  /// APInt multipliers, as well as a total Constant Offset.<br>
+  bool collectOffset(const DataLayout &DL, unsigned BitWidth,<br>
+                     SmallDenseMap<Value *, APInt, 8> &VariableOffsets,<br>
+                     APInt &ConstantOffset) const;<br>
 };<br>
<br>
 class PtrToIntOperator<br>
<br>
diff  --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h<br>
index f7efeeb56fd34..bb57a378c69dc 100644<br>
--- a/llvm/include/llvm/Transforms/Utils/Local.h<br>
+++ b/llvm/include/llvm/Transforms/Utils/Local.h<br>
@@ -314,7 +314,8 @@ void salvageDebugInfoForDbgValues(Instruction &I,<br>
 /// appended to the expression. \p LocNo: the index of the location operand to<br>
 /// which \p I applies, should be 0 for debug info without a DIArgList.<br>
 DIExpression *salvageDebugInfoImpl(Instruction &I, DIExpression *DIExpr,<br>
-                                   bool StackVal, unsigned LocNo);<br>
+                                   bool StackVal, unsigned LocNo,<br>
+                                   SmallVectorImpl<Value *> &AdditionalValues);<br>
<br>
 /// Point debug users of \p From to \p To or salvage them. Use this function<br>
 /// only when replacing all uses of \p From with \p To, with a guarantee that<br>
<br>
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
index 9e14e85bcefb1..be1c00c90ff48 100644<br>
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
@@ -1238,6 +1238,10 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,<br>
 }<br>
<br>
 void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {<br>
+  // TODO: For the variadic implementation, instead of only checking the fail<br>
+  // state of `handleDebugValue`, we need know specifically which values were<br>
+  // invalid, so that we attempt to salvage only those values when processing<br>
+  // a DIArgList.<br>
   assert(!DDI.getDI()->hasArgList() &&<br>
          "Not implemented for variadic dbg_values");<br>
   Value *V = DDI.getDI()->getValue(0);<br>
@@ -1261,16 +1265,21 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {<br>
   while (isa<Instruction>(V)) {<br>
     Instruction &VAsInst = *cast<Instruction>(V);<br>
     // Temporary "0", awaiting real implementation.<br>
-    DIExpression *NewExpr = salvageDebugInfoImpl(VAsInst, Expr, StackValue, 0);<br>
+    SmallVector<Value *, 4> AdditionalValues;<br>
+    DIExpression *SalvagedExpr =<br>
+        salvageDebugInfoImpl(VAsInst, Expr, StackValue, 0, AdditionalValues);<br>
<br>
     // If we cannot salvage any further, and haven't yet found a suitable debug<br>
     // expression, bail out.<br>
-    if (!NewExpr)<br>
+    // TODO: If AdditionalValues isn't empty, then the salvage can only be<br>
+    // represented with a DBG_VALUE_LIST, so we give up. When we have support<br>
+    // here for variadic dbg_values, remove that condition.<br>
+    if (!SalvagedExpr || !AdditionalValues.empty())<br>
       break;<br>
<br>
     // New value and expr now represent this debuginfo.<br>
     V = VAsInst.getOperand(0);<br>
-    Expr = NewExpr;<br>
+    Expr = SalvagedExpr;<br>
<br>
     // Some kind of simplification occurred: check whether the operand of the<br>
     // salvaged debug expression can be encoded in this DAG.<br>
<br>
diff  --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp<br>
index 1299acdc4723d..936a303daf714 100644<br>
--- a/llvm/lib/IR/DebugInfoMetadata.cpp<br>
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp<br>
@@ -1244,6 +1244,17 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const {<br>
   return false;<br>
 }<br>
<br>
+bool DIExpression::hasAllLocationOps(unsigned N) const {<br>
+  SmallDenseSet<uint64_t, 4> SeenOps;<br>
+  for (auto ExprOp : expr_ops())<br>
+    if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)<br>
+      SeenOps.insert(ExprOp.getArg(0));<br>
+  for (uint64_t Idx = 0; Idx < N; ++Idx)<br>
+    if (!is_contained(SeenOps, Idx))<br>
+      return false;<br>
+  return true;<br>
+}<br>
+<br>
 const DIExpression *DIExpression::extractAddressClass(const DIExpression *Expr,<br>
                                                       unsigned &AddrClass) {<br>
   // FIXME: This seems fragile. Nothing that verifies that these elements<br>
@@ -1458,6 +1469,16 @@ Optional<DIExpression *> DIExpression::createFragmentExpression(<br>
   return DIExpression::get(Expr->getContext(), Ops);<br>
 }<br>
<br>
+uint64_t DIExpression::getNumLocationOperands() const {<br>
+  uint64_t Result = 0;<br>
+  for (auto ExprOp : expr_ops())<br>
+    if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)<br>
+      Result = std::max(Result, ExprOp.getArg(0) + 1);<br>
+  assert(hasAllLocationOps(Result) &&<br>
+         "Expression is missing one or more location operands.");<br>
+  return Result;<br>
+}<br>
+<br>
 llvm::Optional<DIExpression::SignedOrUnsignedConstant><br>
 DIExpression::isConstant() const {<br>
<br>
<br>
diff  --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp<br>
index 8ddadf410d56b..397561ccfbe85 100644<br>
--- a/llvm/lib/IR/Instructions.cpp<br>
+++ b/llvm/lib/IR/Instructions.cpp<br>
@@ -1806,6 +1806,15 @@ bool GetElementPtrInst::accumulateConstantOffset(const DataLayout &DL,<br>
   return cast<GEPOperator>(this)->accumulateConstantOffset(DL, Offset);<br>
 }<br>
<br>
+bool GetElementPtrInst::collectOffset(<br>
+    const DataLayout &DL, unsigned BitWidth,<br>
+    SmallDenseMap<Value *, APInt, 8> &VariableOffsets,<br>
+    APInt &ConstantOffset) const {<br>
+  // Delegate to the generic GEPOperator implementation.<br>
+  return cast<GEPOperator>(this)->collectOffset(DL, BitWidth, VariableOffsets,<br>
+                                                ConstantOffset);<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 //                           ExtractElementInst Implementation<br>
 //===----------------------------------------------------------------------===//<br>
<br>
diff  --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp<br>
index 14b87328e48ad..80198d470650f 100644<br>
--- a/llvm/lib/IR/IntrinsicInst.cpp<br>
+++ b/llvm/lib/IR/IntrinsicInst.cpp<br>
@@ -118,6 +118,23 @@ void DbgVariableIntrinsic::replaceVariableLocationOp(unsigned OpIdx,<br>
       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));<br>
 }<br>
<br>
+void DbgVariableIntrinsic::addVariableLocationOps(ArrayRef<Value *> NewValues,<br>
+                                                  DIExpression *NewExpr) {<br>
+  assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() +<br>
+                                    NewValues.size()) &&<br>
+         "NewExpr for debug variable intrinsic does not reference every "<br>
+         "location operand.");<br>
+  assert(!is_contained(NewValues, nullptr) && "New values must be non-null");<br>
+  setArgOperand(2, MetadataAsValue::get(getContext(), NewExpr));<br>
+  SmallVector<ValueAsMetadata *, 4> MDs;<br>
+  for (auto *VMD : location_ops())<br>
+    MDs.push_back(getAsMetadata(VMD));<br>
+  for (auto *VMD : NewValues)<br>
+    MDs.push_back(getAsMetadata(VMD));<br>
+  setArgOperand(<br>
+      0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));<br>
+}<br>
+<br>
 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {<br>
   if (auto Fragment = getExpression()->getFragmentInfo())<br>
     return Fragment->SizeInBits;<br>
<br>
diff  --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp<br>
index 69181f35827bf..e030cb5522755 100644<br>
--- a/llvm/lib/IR/Operator.cpp<br>
+++ b/llvm/lib/IR/Operator.cpp<br>
@@ -142,4 +142,61 @@ bool GEPOperator::accumulateConstantOffset(<br>
   }<br>
   return true;<br>
 }<br>
+<br>
+bool GEPOperator::collectOffset(<br>
+    const DataLayout &DL, unsigned BitWidth,<br>
+    SmallDenseMap<Value *, APInt, 8> &VariableOffsets,<br>
+    APInt &ConstantOffset) const {<br>
+  assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) &&<br>
+         "The offset bit width does not match DL specification.");<br>
+<br>
+  auto CollectConstantOffset = [&](APInt Index, uint64_t Size) {<br>
+    Index = Index.sextOrTrunc(BitWidth);<br>
+    APInt IndexedSize = APInt(BitWidth, Size);<br>
+    ConstantOffset += Index * IndexedSize;<br>
+  };<br>
+<br>
+  for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);<br>
+       GTI != GTE; ++GTI) {<br>
+    // Scalable vectors are multiplied by a runtime constant.<br>
+    bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType());<br>
+<br>
+    Value *V = GTI.getOperand();<br>
+    StructType *STy = GTI.getStructTypeOrNull();<br>
+    // Handle ConstantInt if possible.<br>
+    if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {<br>
+      if (ConstOffset->isZero())<br>
+        continue;<br>
+      // If the type is scalable and the constant is not zero (vscale * n * 0 =<br>
+      // 0) bailout.<br>
+      // TODO: If the runtime value is accessible at any point before DWARF<br>
+      // emission, then we could potentially keep a forward reference to it<br>
+      // in the debug value to be filled in later.<br>
+      if (ScalableType)<br>
+        return false;<br>
+      // Handle a struct index, which adds its field offset to the pointer.<br>
+      if (STy) {<br>
+        unsigned ElementIdx = ConstOffset->getZExtValue();<br>
+        const StructLayout *SL = DL.getStructLayout(STy);<br>
+        // Element offset is in bytes.<br>
+        CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)),<br>
+                              1);<br>
+        continue;<br>
+      }<br>
+      CollectConstantOffset(ConstOffset->getValue(),<br>
+                            DL.getTypeAllocSize(GTI.getIndexedType()));<br>
+      continue;<br>
+    }<br>
+<br>
+    if (STy || ScalableType)<br>
+      return false;<br>
+    // Insert an initial offset of 0 for V iff none exists already, then<br>
+    // increment the offset by IndexedSize.<br>
+    VariableOffsets.try_emplace(V, BitWidth, 0);<br>
+    APInt IndexedSize =<br>
+        APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType()));<br>
+    VariableOffsets[V] += IndexedSize;<br>
+  }<br>
+  return true;<br>
+}<br>
 } // namespace llvm<br>
<br>
diff  --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
index 65aa06e63b570..692ba125473cd 100644<br>
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
@@ -2101,10 +2101,15 @@ void coro::salvageDebugInfo(<br>
     } else if (auto *StInst = dyn_cast<StoreInst>(Storage)) {<br>
       Storage = StInst->getOperand(0);<br>
     } else if (auto *GEPInst = dyn_cast<GetElementPtrInst>(Storage)) {<br>
-      Expr = llvm::salvageDebugInfoImpl(*GEPInst, Expr,<br>
-                                        /*WithStackValue=*/false, 0);<br>
-      if (!Expr)<br>
-        return;<br>
+      SmallVector<Value *> AdditionalValues;<br>
+      DIExpression *SalvagedExpr = llvm::salvageDebugInfoImpl(<br>
+          *GEPInst, Expr,<br>
+          /*WithStackValue=*/false, 0, AdditionalValues);<br>
+      // Debug declares cannot currently handle additional location<br>
+      // operands.<br>
+      if (!SalvagedExpr || !AdditionalValues.empty())<br>
+        break;<br>
+      Expr = SalvagedExpr;<br>
       Storage = GEPInst->getOperand(0);<br>
     } else if (auto *BCInst = dyn_cast<llvm::BitCastInst>(Storage))<br>
       Storage = BCInst->getOperand(0);<br>
<br>
diff  --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp<br>
index e285f8aa7a20d..4730e8ffcdbb8 100644<br>
--- a/llvm/lib/Transforms/Utils/Local.cpp<br>
+++ b/llvm/lib/Transforms/Utils/Local.cpp<br>
@@ -1816,17 +1816,26 @@ void llvm::salvageDebugInfoForDbgValues(<br>
         is_contained(DIILocation, &I) &&<br>
         "DbgVariableIntrinsic must use salvaged instruction as its location");<br>
     unsigned LocNo = std::distance(DIILocation.begin(), find(DIILocation, &I));<br>
-<br>
-    DIExpression *DIExpr =<br>
-        salvageDebugInfoImpl(I, DII->getExpression(), StackValue, LocNo);<br>
+    SmallVector<Value *, 4> AdditionalValues;<br>
+    DIExpression *SalvagedExpr = salvageDebugInfoImpl(<br>
+        I, DII->getExpression(), StackValue, LocNo, AdditionalValues);<br>
<br>
     // salvageDebugInfoImpl should fail on examining the first element of<br>
     // DbgUsers, or none of them.<br>
-    if (!DIExpr)<br>
+    if (!SalvagedExpr)<br>
       break;<br>
<br>
     DII->replaceVariableLocationOp(&I, I.getOperand(0));<br>
-    DII->setExpression(DIExpr);<br>
+    if (AdditionalValues.empty()) {<br>
+      DII->setExpression(SalvagedExpr);<br>
+    } else if (isa<DbgValueInst>(DII)) {<br>
+      DII->addVariableLocationOps(AdditionalValues, SalvagedExpr);<br>
+    } else {<br>
+      // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is<br>
+      // currently only valid for stack value expressions.<br>
+      Value *Undef = UndefValue::get(I.getOperand(0)->getType());<br>
+      DII->replaceVariableLocationOp(I.getOperand(0), Undef);<br>
+    }<br>
     LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n');<br>
     Salvaged = true;<br>
   }<br>
@@ -1841,12 +1850,27 @@ void llvm::salvageDebugInfoForDbgValues(<br>
 }<br>
<br>
 bool getSalvageOpsForGEP(GetElementPtrInst *GEP, const DataLayout &DL,<br>
-                         SmallVectorImpl<uint64_t> &Opcodes) {<br>
+                         uint64_t CurrentLocOps,<br>
+                         SmallVectorImpl<uint64_t> &Opcodes,<br>
+                         SmallVectorImpl<Value *> &AdditionalValues) {<br>
   unsigned BitWidth = DL.getIndexSizeInBits(GEP->getPointerAddressSpace());<br>
-  // Rewrite a constant GEP into a DIExpression.<br>
+  // Rewrite a GEP into a DIExpression.<br>
+  SmallDenseMap<Value *, APInt, 8> VariableOffsets;<br>
   APInt ConstantOffset(BitWidth, 0);<br>
-  if (!GEP->accumulateConstantOffset(DL, ConstantOffset))<br>
+  if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset))<br>
     return false;<br>
+  if (!VariableOffsets.empty() && !CurrentLocOps) {<br>
+    Opcodes.insert(Opcodes.begin(), {dwarf::DW_OP_LLVM_arg, 0});<br>
+    CurrentLocOps = 1;<br>
+  }<br>
+  for (auto Offset : VariableOffsets) {<br>
+    AdditionalValues.push_back(Offset.first);<br>
+    assert(Offset.second.isStrictlyPositive() &&<br>
+           "Expected strictly positive multiplier for offset.");<br>
+    Opcodes.append({dwarf::DW_OP_LLVM_arg, CurrentLocOps++, dwarf::DW_OP_constu,<br>
+                    Offset.second.getZExtValue(), dwarf::DW_OP_mul,<br>
+                    dwarf::DW_OP_plus});<br>
+  }<br>
   DIExpression::appendOffset(Opcodes, ConstantOffset.getSExtValue());<br>
   return true;<br>
 }<br>
@@ -1881,23 +1905,35 @@ uint64_t getDwarfOpForBinOp(Instruction::BinaryOps Opcode) {<br>
   }<br>
 }<br>
<br>
-bool getSalvageOpsForBinOp(BinaryOperator *BI,<br>
-                           SmallVectorImpl<uint64_t> &Opcodes) {<br>
-  // Rewrite binary operations with constant integer operands.<br>
+bool getSalvageOpsForBinOp(BinaryOperator *BI, uint64_t CurrentLocOps,<br>
+                           SmallVectorImpl<uint64_t> &Opcodes,<br>
+                           SmallVectorImpl<Value *> &AdditionalValues) {<br>
+  // Handle binary operations with constant integer operands as a special case.<br>
   auto *ConstInt = dyn_cast<ConstantInt>(BI->getOperand(1));<br>
-  if (!ConstInt || ConstInt->getBitWidth() > 64)<br>
+  // Values wider than 64 bits cannot be represented within a DIExpression.<br>
+  if (ConstInt && ConstInt->getBitWidth() > 64)<br>
     return false;<br>
-  uint64_t Val = ConstInt->getSExtValue();<br>
+<br>
   Instruction::BinaryOps BinOpcode = BI->getOpcode();<br>
-  // Add or Sub Instructions with a constant operand can potentially be<br>
-  // simplified.<br>
-  if (BinOpcode == Instruction::Add || BinOpcode == Instruction::Sub) {<br>
-    uint64_t Offset = BinOpcode == Instruction::Add ? Val : -int64_t(Val);<br>
-    DIExpression::appendOffset(Opcodes, Offset);<br>
-    return true;<br>
+  // Push any Constant Int operand onto the expression stack.<br>
+  if (ConstInt) {<br>
+    uint64_t Val = ConstInt->getSExtValue();<br>
+    // Add or Sub Instructions with a constant operand can potentially be<br>
+    // simplified.<br>
+    if (BinOpcode == Instruction::Add || BinOpcode == Instruction::Sub) {<br>
+      uint64_t Offset = BinOpcode == Instruction::Add ? Val : -int64_t(Val);<br>
+      DIExpression::appendOffset(Opcodes, Offset);<br>
+      return true;<br>
+    }<br>
+    Opcodes.append({dwarf::DW_OP_constu, Val});<br>
+  } else {<br>
+    if (!CurrentLocOps) {<br>
+      Opcodes.append({dwarf::DW_OP_LLVM_arg, 0});<br>
+      CurrentLocOps = 1;<br>
+    }<br>
+    Opcodes.append({dwarf::DW_OP_LLVM_arg, CurrentLocOps});<br>
+    AdditionalValues.push_back(BI->getOperand(1));<br>
   }<br>
-  // Add constant int operand to expression stack.<br>
-  Opcodes.append({dwarf::DW_OP_constu, Val});<br>
<br>
   // Add salvaged binary operator to expression stack, if it has a valid<br>
   // representation in a DIExpression.<br>
@@ -1909,9 +1945,11 @@ bool getSalvageOpsForBinOp(BinaryOperator *BI,<br>
   return true;<br>
 }<br>
<br>
-DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,<br>
-                                         DIExpression *SrcDIExpr,<br>
-                                         bool WithStackValue, unsigned LocNo) {<br>
+DIExpression *<br>
+llvm::salvageDebugInfoImpl(Instruction &I, DIExpression *SrcDIExpr,<br>
+                           bool WithStackValue, unsigned LocNo,<br>
+                           SmallVectorImpl<Value *> &AdditionalValues) {<br>
+  uint64_t CurrentLocOps = SrcDIExpr->getNumLocationOperands();<br>
   auto &M = *I.getModule();<br>
   auto &DL = M.getDataLayout();<br>
<br>
@@ -1925,7 +1963,7 @@ DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,<br>
   };<br>
<br>
   // initializer-list helper for applying operators to the source DIExpression.<br>
-  auto applyOps = [&](ArrayRef<uint64_t> Opcodes) -> DIExpression * {<br>
+  auto applyOps = [&](ArrayRef<uint64_t> Opcodes) {<br>
     SmallVector<uint64_t, 8> Ops(Opcodes.begin(), Opcodes.end());<br>
     return doSalvage(Ops);<br>
   };<br>
@@ -1951,15 +1989,15 @@ DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,<br>
<br>
   SmallVector<uint64_t, 8> Ops;<br>
   if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {<br>
-    if (getSalvageOpsForGEP(GEP, DL, Ops))<br>
+    if (getSalvageOpsForGEP(GEP, DL, CurrentLocOps, Ops, AdditionalValues))<br>
       return doSalvage(Ops);<br>
   } else if (auto *BI = dyn_cast<BinaryOperator>(&I)) {<br>
-    if (getSalvageOpsForBinOp(BI, Ops))<br>
+    if (getSalvageOpsForBinOp(BI, CurrentLocOps, Ops, AdditionalValues))<br>
       return doSalvage(Ops);<br>
   }<br>
-    // *Not* to do: we should not attempt to salvage load instructions,<br>
-    // because the validity and lifetime of a dbg.value containing<br>
-    // DW_OP_deref becomes <br>
diff icult to analyze. See PR40628 for examples.<br>
+  // *Not* to do: we should not attempt to salvage load instructions,<br>
+  // because the validity and lifetime of a dbg.value containing<br>
+  // DW_OP_deref becomes <br>
diff icult to analyze. See PR40628 for examples.<br>
   return nullptr;<br>
 }<br>
<br>
<br>
diff  --git a/llvm/test/DebugInfo/NVPTX/debug-info.ll b/llvm/test/DebugInfo/NVPTX/debug-info.ll<br>
index 08a7e037ec490..15ea41e8ebdd4 100644<br>
--- a/llvm/test/DebugInfo/NVPTX/debug-info.ll<br>
+++ b/llvm/test/DebugInfo/NVPTX/debug-info.ll<br>
@@ -702,12 +702,12 @@ if.end:                                           ; preds = %if.then, %entry<br>
 ; CHECK-NEXT:  }<br>
 ; CHECK-NEXT:  .section        .debug_info<br>
 ; CHECK-NEXT:  {<br>
-; CHECK-NEXT:.b32 10029                              // Length of Unit<br>
+; CHECK-NEXT:.b32 10034                              // Length of Unit<br>
 ; CHECK-NEXT:.b8 2                                   // DWARF version number<br>
 ; CHECK-NEXT:.b8 0<br>
 ; CHECK-NEXT:.b32 .debug_abbrev                      // Offset Into Abbrev. Section<br>
 ; CHECK-NEXT:.b8 8                                   // Address Size (in bytes)<br>
-; CHECK-NEXT:.b8 1                                   // Abbrev [1] 0xb:0x2726 DW_TAG_compile_unit<br>
+; CHECK-NEXT:.b8 1                                   // Abbrev [1] 0xb:0x272b DW_TAG_compile_unit<br>
 ; CHECK-NEXT:.b8 0                                   // DW_AT_producer<br>
 ; CHECK-NEXT:.b8 4                                   // DW_AT_language<br>
 ; CHECK-NEXT:.b8 0<br>
@@ -8306,7 +8306,7 @@ if.end:                                           ; preds = %if.then, %entry<br>
 ; CHECK-NEXT:.b8 3                                   // DW_AT_decl_line<br>
 ; CHECK-NEXT:.b32 3345                               // DW_AT_type<br>
 ; CHECK-NEXT:.b8 0                                   // End Of Children Mark<br>
-; CHECK-NEXT:.b8 40                                  // Abbrev [40] 0x2671:0xbf DW_TAG_subprogram<br>
+; CHECK-NEXT:.b8 40                                  // Abbrev [40] 0x2671:0xc4 DW_TAG_subprogram<br>
 ; CHECK-NEXT:.b64 Lfunc_begin0                       // DW_AT_low_pc<br>
 ; CHECK-NEXT:.b64 Lfunc_end0                         // DW_AT_high_pc<br>
 ; CHECK-NEXT:.b8 1                                   // DW_AT_frame_base<br>
@@ -8386,7 +8386,7 @@ if.end:                                           ; preds = %if.then, %entry<br>
 ; CHECK-NEXT:.b8 12                                  // DW_AT_call_file<br>
 ; CHECK-NEXT:.b8 6                                   // DW_AT_call_line<br>
 ; CHECK-NEXT:.b8 37                                  // DW_AT_call_column<br>
-; CHECK-NEXT:.b8 43                                  // Abbrev [43] 0x2711:0x1e DW_TAG_inlined_subroutine<br>
+; CHECK-NEXT:.b8 43                                  // Abbrev [43] 0x2711:0x23 DW_TAG_inlined_subroutine<br>
 ; CHECK-NEXT:.b32 9791                               // DW_AT_abstract_origin<br>
 ; CHECK-NEXT:.b64 Ltmp9                              // DW_AT_low_pc<br>
 ; CHECK-NEXT:.b64 Ltmp10                             // DW_AT_high_pc<br>
@@ -8395,6 +8395,8 @@ if.end:                                           ; preds = %if.then, %entry<br>
 ; CHECK-NEXT:.b8 5                                   // DW_AT_call_column<br>
 ; CHECK-NEXT:.b8 44                                  // Abbrev [44] 0x2729:0x5 DW_TAG_formal_parameter<br>
 ; CHECK-NEXT:.b32 9820                               // DW_AT_abstract_origin<br>
+; CHECK-NEXT:.b8 44                                  // Abbrev [44] 0x272e:0x5 DW_TAG_formal_parameter<br>
+; CHECK-NEXT:.b32 9829                               // DW_AT_abstract_origin<br>
 ; CHECK-NEXT:.b8 0                                   // End Of Children Mark<br>
 ; CHECK-NEXT:.b8 0                                   // End Of Children Mark<br>
 ; CHECK-NEXT:.b8 0                                   // End Of Children Mark<br>
<br>
diff  --git a/llvm/test/DebugInfo/salvage-gep.ll b/llvm/test/DebugInfo/salvage-gep.ll<br>
new file mode 100644<br>
index 0000000000000..6c31b0ff61de6<br>
--- /dev/null<br>
+++ b/llvm/test/DebugInfo/salvage-gep.ll<br>
@@ -0,0 +1,56 @@<br>
+; RUN: opt %s -dce -S | FileCheck %s<br>
+<br>
+; Tests the salvaging of GEP instructions, specifically struct indexing and<br>
+; non-constant array indexing.<br>
+<br>
+%struct.S = type { i32, i32 }<br>
+<br>
+; CHECK: call void @llvm.dbg.value(metadata !DIArgList(%struct.S* %ptr, i64 %offset),<br>
+; CHECK-SAME: ![[VAR_OFFSET_PTR:[0-9]+]],<br>
+; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 8, DW_OP_mul, DW_OP_plus, DW_OP_plus_uconst, 4, DW_OP_stack_value))<br>
+<br>
+; CHECK: ![[VAR_OFFSET_PTR]] = !DILocalVariable(name: "offset_ptr"<br>
+<br>
+define void @"?foo@@YAXPEAUS@@_J@Z"(%struct.S* %ptr, i64 %offset) !dbg !8 {<br>
+entry:<br>
+  call void @llvm.dbg.value(metadata i64 %offset, metadata !20, metadata !DIExpression()), !dbg !24<br>
+  call void @llvm.dbg.value(metadata %struct.S* %ptr, metadata !21, metadata !DIExpression()), !dbg !24<br>
+  %arrayidx = getelementptr inbounds %struct.S, %struct.S* %ptr, i64 %offset, !dbg !25<br>
+  %b = getelementptr inbounds %struct.S, %struct.S* %arrayidx, i32 0, i32 1, !dbg !25<br>
+  call void @llvm.dbg.value(metadata i32* %b, metadata !22, metadata !DIExpression()), !dbg !24<br>
+  ret void, !dbg !26<br>
+}<br>
+<br>
+declare void @llvm.dbg.value(metadata, metadata, metadata)<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!3, !4, !5, !6}<br>
+!llvm.ident = !{!7}<br>
+<br>
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)<br>
+!1 = !DIFile(filename: "salvage-gep.cpp", directory: "/")<br>
+!2 = !{}<br>
+!3 = !{i32 2, !"CodeView", i32 1}<br>
+!4 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!5 = !{i32 1, !"wchar_size", i32 2}<br>
+!6 = !{i32 7, !"PIC Level", i32 2}<br>
+!7 = !{!"clang version 11.0.0"}<br>
+!8 = distinct !DISubprogram(name: "foo", linkageName: "?foo@@YAXPEAUS@@_J@Z", scope: !9, file: !9, line: 7, type: !10, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !19)<br>
+!9 = !DIFile(filename: ".\\salvage-gep.cpp", directory: "/")<br>
+!10 = !DISubroutineType(types: !11)<br>
+!11 = !{null, !12, !18}<br>
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)<br>
+!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !9, line: 2, size: 64, flags: DIFlagTypePassByValue, elements: !14, identifier: ".?AUS@@")<br>
+!14 = !{!15, !17}<br>
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !13, file: !9, line: 3, baseType: !16, size: 32)<br>
+!16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+!17 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !13, file: !9, line: 4, baseType: !16, size: 32, offset: 32)<br>
+!18 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)<br>
+!19 = !{!20, !21, !22}<br>
+!20 = !DILocalVariable(name: "offset", arg: 2, scope: !8, file: !9, line: 7, type: !18)<br>
+!21 = !DILocalVariable(name: "ptr", arg: 1, scope: !8, file: !9, line: 7, type: !12)<br>
+!22 = !DILocalVariable(name: "offset_ptr", scope: !8, file: !9, line: 8, type: !23)<br>
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64)<br>
+!24 = !DILocation(line: 0, scope: !8)<br>
+!25 = !DILocation(line: 8, scope: !8)<br>
+!26 = !DILocation(line: 9, scope: !8)<br>
<br>
diff  --git a/llvm/test/DebugInfo/salvage-nonconst-binop.ll b/llvm/test/DebugInfo/salvage-nonconst-binop.ll<br>
new file mode 100644<br>
index 0000000000000..b470bc1ad2a91<br>
--- /dev/null<br>
+++ b/llvm/test/DebugInfo/salvage-nonconst-binop.ll<br>
@@ -0,0 +1,45 @@<br>
+; RUN: opt %s -dce -S | FileCheck %s<br>
+<br>
+; Tests the salvaging of binary operators that use more than one non-constant<br>
+; SSA value.<br>
+<br>
+; CHECK: call void @llvm.dbg.value(metadata !DIArgList(i32 %a, i32 %b),<br>
+; CHECK-SAME: ![[VAR_C:[0-9]+]],<br>
+; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value))<br>
+<br>
+; CHECK: ![[VAR_C]] = !DILocalVariable(name: "c"<br>
+<br>
+define i32 @"?multiply@@YAHHH@Z"(i32 %a, i32 %b) !dbg !8 {<br>
+entry:<br>
+  call void @llvm.dbg.value(metadata i32 %b, metadata !12, metadata !DIExpression()), !dbg !13<br>
+  call void @llvm.dbg.value(metadata i32 %a, metadata !14, metadata !DIExpression()), !dbg !13<br>
+  %add = add nsw i32 %a, %b, !dbg !15<br>
+  call void @llvm.dbg.value(metadata i32 %add, metadata !16, metadata !DIExpression()), !dbg !13<br>
+  %mul = mul nsw i32 %a, %b, !dbg !17<br>
+  ret i32 %mul, !dbg !17<br>
+}<br>
+<br>
+declare void @llvm.dbg.value(metadata, metadata, metadata)<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!3, !4, !5, !6}<br>
+!llvm.ident = !{!7}<br>
+<br>
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)<br>
+!1 = !DIFile(filename: "test.cpp", directory: "/")<br>
+!2 = !{}<br>
+!3 = !{i32 2, !"CodeView", i32 1}<br>
+!4 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!5 = !{i32 1, !"wchar_size", i32 2}<br>
+!6 = !{i32 7, !"PIC Level", i32 2}<br>
+!7 = !{!"clang version 11.0.0"}<br>
+!8 = distinct !DISubprogram(name: "multiply", linkageName: "?multiply@@YAHHH@Z", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)<br>
+!9 = !DISubroutineType(types: !10)<br>
+!10 = !{!11, !11, !11}<br>
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+!12 = !DILocalVariable(name: "b", arg: 2, scope: !8, file: !1, line: 1, type: !11)<br>
+!13 = !DILocation(line: 0, scope: !8)<br>
+!14 = !DILocalVariable(name: "a", arg: 1, scope: !8, file: !1, line: 1, type: !11)<br>
+!15 = !DILocation(line: 2, scope: !8)<br>
+!16 = !DILocalVariable(name: "c", scope: !8, file: !1, line: 2, type: !11)<br>
+!17 = !DILocation(line: 3, scope: !8)<br>
<br>
diff  --git a/llvm/test/Transforms/InstCombine/debuginfo-sink.ll b/llvm/test/Transforms/InstCombine/debuginfo-sink.ll<br>
index 5a8cc78b08c2d..3fb27637022ad 100644<br>
--- a/llvm/test/Transforms/InstCombine/debuginfo-sink.ll<br>
+++ b/llvm/test/Transforms/InstCombine/debuginfo-sink.ll<br>
@@ -33,23 +33,25 @@ sink1:<br>
 ; value range.<br>
<br>
 ; CHECK-LABEL: define i32 @bar(<br>
-; CHECK:       call void @llvm.dbg.value(metadata i32* undef,<br>
+; CHECK:       call void @llvm.dbg.value(metadata <vscale x 4 x i32>* undef,<br>
 ; CHECK-NEXT:  br label %sink2<br>
<br>
-define i32 @bar(i32 *%a, i32 %b) !dbg !70 {<br>
+define i32 @bar(<vscale x 4 x i32>* %a, i32 %b) !dbg !70 {<br>
 entry:<br>
-  %gep = getelementptr i32, i32 *%a, i32 %b<br>
-  call void @llvm.dbg.value(metadata i32* %gep, metadata !73, metadata !12), !dbg !74<br>
+  %gep = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %a, i32 %b<br>
+  call void @llvm.dbg.value(metadata <vscale x 4 x i32>* %gep, metadata !73, metadata !12), !dbg !74<br>
   br label %sink2<br>
<br>
 sink2:<br>
 ; CHECK-LABEL: sink2:<br>
-; CHECK:       call void @llvm.dbg.value(metadata i32* %gep,<br>
+; CHECK:       call void @llvm.dbg.value(metadata <vscale x 4 x i32>* %gep,<br>
 ; CHECK-SAME:                    metadata !{{[0-9]+}}, metadata !DIExpression())<br>
 ; CHECK-NEXT:  load<br>
+; CHECK-NEXT:  extractelement<br>
 ; CHECK-NEXT:  ret<br>
-  %0 = load i32, i32* %gep<br>
-  ret i32 %0<br>
+  %0 = load <vscale x 4 x i32>, <vscale x 4 x i32>* %gep<br>
+  %extract = extractelement <vscale x 4 x i32> %0, i32 1<br>
+  ret i32 %extract<br>
 }<br>
<br>
 ; This GEP is sunk, and has multiple debug uses in the same block. Check that<br>
<br>
diff  --git a/llvm/test/Transforms/Reassociate/undef_intrinsics_when_deleting_instructions.ll b/llvm/test/Transforms/Reassociate/undef_intrinsics_when_deleting_instructions.ll<br>
index 98c51c5cf8bb3..349da85cc80f7 100644<br>
--- a/llvm/test/Transforms/Reassociate/undef_intrinsics_when_deleting_instructions.ll<br>
+++ b/llvm/test/Transforms/Reassociate/undef_intrinsics_when_deleting_instructions.ll<br>
@@ -1,95 +1,73 @@<br>
-; RUN: opt < %s -reassociate -S | FileCheck %s<br>
+; RUN: opt < %s -reassociate -S | FileCheck %s<br>
+<br>
+; Check that reassociate pass now undefs debug intrinsics that reference a value<br>
+; that gets dropped and cannot be salvaged.<br>
+<br>
+; CHECK-NOT: %add = fadd fast float %a, %b<br>
+; CHECK: call void @llvm.dbg.value(metadata float undef, metadata [[VAR_X:![0-9]+]], metadata !DIExpression())<br>
+<br>
+; CHECK-LABEL: if.then:<br>
+; CHECK-NOT: %add1 = fadd fast float %add, %c<br>
+; CHECK: call void @llvm.dbg.value(metadata float undef, metadata [[VAR_Y:![0-9]+]], metadata !DIExpression())<br>
+; CHECK-LABEL: !0 =<br>
+; CHECK-DAG: [[VAR_Y]] = !DILocalVariable(name: "y"<br>
+; CHECK-DAG: [[VAR_X]] = !DILocalVariable(name: "x"<br>
+<br>
+define float @"?foo@@YAMMMMM@Z"(float %a, float %b, float %c, float %d) !dbg !8 {<br>
+entry:<br>
+  call void @llvm.dbg.value(metadata float %d, metadata !12, metadata !DIExpression()), !dbg !13<br>
+  call void @llvm.dbg.value(metadata float %c, metadata !14, metadata !DIExpression()), !dbg !13<br>
+  call void @llvm.dbg.value(metadata float %b, metadata !15, metadata !DIExpression()), !dbg !13<br>
+  call void @llvm.dbg.value(metadata float %a, metadata !16, metadata !DIExpression()), !dbg !13<br>
+  %add = fadd fast float %a, %b, !dbg !17<br>
+  call void @llvm.dbg.value(metadata float %add, metadata !18, metadata !DIExpression()), !dbg !13<br>
+  %cmp = fcmp fast oeq float %d, 4.000000e+00, !dbg !19<br>
+  br i1 %cmp, label %if.then, label %return, !dbg !19<br>
<br>
-; Check that reassociate pass now undefs debug intrinsics that reference a value<br>
-; that gets dropped and cannot be salvaged.<br>
+if.then:                                          ; preds = %entry<br>
+  %add1 = fadd fast float %add, %c, !dbg !20<br>
+  call void @llvm.dbg.value(metadata float %add1, metadata !23, metadata !DIExpression()), !dbg !24<br>
+  %sub = fsub fast float %add, 1.200000e+01, !dbg !25<br>
+  %sub2 = fsub fast float %add1, %sub, !dbg !25<br>
+  %mul = fmul fast float %sub2, 2.000000e+01, !dbg !25<br>
+  %div = fdiv fast float %mul, 3.000000e+00, !dbg !25<br>
+  br label %return, !dbg !25<br>
<br>
-define hidden i32 @main() local_unnamed_addr {<br>
-entry:<br>
-  %foo = alloca i32, align 4, !dbg !20<br>
-  %foo.0.foo.0..sroa_cast = bitcast i32* %foo to i8*, !dbg !20<br>
-  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %foo.0.foo.0..sroa_cast), !dbg !20<br>
-  store volatile i32 4, i32* %foo, align 4, !dbg !20, !tbaa !21<br>
-  %foo.0.foo.0. = load volatile i32, i32* %foo, align 4, !dbg !25, !tbaa !21<br>
-  %foo.0.foo.0.15 = load volatile i32, i32* %foo, align 4, !dbg !27, !tbaa !21<br>
-  %foo.0.foo.0.16 = load volatile i32, i32* %foo, align 4, !dbg !28, !tbaa !21<br>
-  ; CHECK-NOT: %add = add nsw i32 %foo.0.foo.0., %foo.0.foo.0.15<br>
-  %add = add nsw i32 %foo.0.foo.0., %foo.0.foo.0.15, !dbg !29<br>
-  ; CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata [[VAR_A:![0-9]+]], metadata !DIExpression())<br>
-  call void @llvm.dbg.value(metadata i32 %add, metadata !19, metadata !DIExpression()), !dbg !26<br>
-  %foo.0.foo.0.17 = load volatile i32, i32* %foo, align 4, !dbg !30, !tbaa !21<br>
-  %cmp = icmp eq i32 %foo.0.foo.0.17, 4, !dbg !30<br>
-  br i1 %cmp, label %if.then, label %if.end, !dbg !32<br>
-<br>
-  ; CHECK-LABEL: if.then:<br>
-if.then:<br>
-  ; CHECK-NOT: %add1 = add nsw i32 %add, %foo.0.foo.0.16<br>
-  %add1 = add nsw i32 %add, %foo.0.foo.0.16, !dbg !33<br>
-  ; CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata [[VAR_A]], metadata !DIExpression())<br>
-  call void @llvm.dbg.value(metadata i32 %add1, metadata !19, metadata !DIExpression()), !dbg !26<br>
-  ; CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata [[VAR_CHEESE:![0-9]+]], metadata !DIExpression())<br>
-  call void @llvm.dbg.value(metadata i32 %add, metadata !18, metadata !DIExpression()), !dbg !26<br>
-  %sub = add nsw i32 %add, -12, !dbg !34<br>
-  %sub3 = sub nsw i32 %add1, %sub, !dbg !34<br>
-  %mul = mul nsw i32 %sub3, 20, !dbg !36<br>
-  %div = sdiv i32 %mul, 3, !dbg !37<br>
-  br label %if.end, !dbg !38<br>
-<br>
-if.end:<br>
-  %a.0 = phi i32 [ %div, %if.then ], [ 0, %entry ], !dbg !39<br>
-  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %foo.0.foo.0..sroa_cast), !dbg !40<br>
-  ret i32 %a.0, !dbg !41<br>
+return:                                           ; preds = %entry, %if.then<br>
+  %retval.0 = phi float [ %div, %if.then ], [ 0.000000e+00, %entry ], !dbg !13<br>
+  ret float %retval.0, !dbg !26<br>
 }<br>
<br>
-declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1<br>
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #2<br>
-declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1<br>
-declare void @llvm.dbg.value(metadata, metadata, metadata) #2<br>
+declare void @llvm.dbg.value(metadata, metadata, metadata)<br>
<br>
 !<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
 !llvm.module.flags = !{!3, !4, !5, !6}<br>
 !llvm.ident = !{!7}<br>
<br>
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, debugInfoForProfiling: true, nameTableKind: None)<br>
-!1 = !DIFile(filename: "test.cpp", directory: "F:\")<br>
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)<br>
+!1 = !DIFile(filename: "undef_intrinsics_when_deleting_instructions.cpp", directory: "/")<br>
 !2 = !{}<br>
-!3 = !{i32 2, !"Dwarf Version", i32 4}<br>
+!3 = !{i32 2, !"CodeView", i32 1}<br>
 !4 = !{i32 2, !"Debug Info Version", i32 3}<br>
 !5 = !{i32 1, !"wchar_size", i32 2}<br>
 !6 = !{i32 7, !"PIC Level", i32 2}<br>
-!7 = !{!"clang version 10.0.0"}<br>
-!8 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13)<br>
-!9 = !DIFile(filename: "./test.cpp", directory: "F:\")<br>
-!10 = !DISubroutineType(types: !11)<br>
-!11 = !{!12}<br>
-!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
-!13 = !{!14, !16, !17, !18, !19}<br>
-!14 = !DILocalVariable(name: "foo", scope: !8, file: !9, line: 2, type: !15)<br>
-!15 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !12)<br>
-!16 = !DILocalVariable(name: "read1", scope: !8, file: !9, line: 3, type: !12)<br>
-!17 = !DILocalVariable(name: "read2", scope: !8, file: !9, line: 4, type: !12)<br>
-; CHECK: [[VAR_CHEESE]] = !DILocalVariable(name: "cheese"<br>
-!18 = !DILocalVariable(name: "cheese", scope: !8, file: !9, line: 6, type: !12)<br>
-; CHECK: [[VAR_A]] = !DILocalVariable(name: "a"<br>
-!19 = !DILocalVariable(name: "a", scope: !8, file: !9, line: 7, type: !12)<br>
-!20 = !DILocation(line: 2, scope: !8)<br>
-!21 = !{!22, !22, i64 0}<br>
-!22 = !{!"int", !23, i64 0}<br>
-!23 = !{!"omnipotent char", !24, i64 0}<br>
-!24 = !{!"Simple C++ TBAA"}<br>
-!25 = !DILocation(line: 3, scope: !8)<br>
-!26 = !DILocation(line: 0, scope: !8)<br>
-!27 = !DILocation(line: 4, scope: !8)<br>
-!28 = !DILocation(line: 6, scope: !8)<br>
-!29 = !DILocation(line: 7, scope: !8)<br>
-!30 = !DILocation(line: 10, scope: !31)<br>
-!31 = distinct !DILexicalBlock(scope: !8, file: !9, line: 10)<br>
-!32 = !DILocation(line: 10, scope: !8)<br>
-!33 = !DILocation(line: 8, scope: !8)<br>
-!34 = !DILocation(line: 12, scope: !35)<br>
-!35 = distinct !DILexicalBlock(scope: !31, file: !9, line: 10)<br>
-!36 = !DILocation(line: 13, scope: !35)<br>
-!37 = !DILocation(line: 14, scope: !35)<br>
-!38 = !DILocation(line: 15, scope: !35)<br>
-!39 = !DILocation(line: 0, scope: !31)<br>
-!40 = !DILocation(line: 20, scope: !8)<br>
-!41 = !DILocation(line: 19, scope: !8)<br>
+!7 = !{!"clang version 11.0.0"}<br>
+!8 = distinct !DISubprogram(name: "foo", linkageName: "?foo@@YAMMMMM@Z", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)<br>
+!9 = !DISubroutineType(types: !10)<br>
+!10 = !{!11, !11, !11, !11, !11}<br>
+!11 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)<br>
+!12 = !DILocalVariable(name: "d", arg: 4, scope: !8, file: !1, line: 1, type: !11)<br>
+!13 = !DILocation(line: 0, scope: !8)<br>
+!14 = !DILocalVariable(name: "c", arg: 3, scope: !8, file: !1, line: 1, type: !11)<br>
+!15 = !DILocalVariable(name: "b", arg: 2, scope: !8, file: !1, line: 1, type: !11)<br>
+!16 = !DILocalVariable(name: "a", arg: 1, scope: !8, file: !1, line: 1, type: !11)<br>
+!17 = !DILocation(line: 2, scope: !8)<br>
+!18 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !11)<br>
+!19 = !DILocation(line: 3, scope: !8)<br>
+!20 = !DILocation(line: 4, scope: !21)<br>
+!21 = distinct !DILexicalBlock(scope: !22, file: !1, line: 3)<br>
+!22 = distinct !DILexicalBlock(scope: !8, file: !1, line: 3)<br>
+!23 = !DILocalVariable(name: "y", scope: !21, file: !1, line: 4, type: !11)<br>
+!24 = !DILocation(line: 0, scope: !21)<br>
+!25 = !DILocation(line: 5, scope: !21)<br>
+!26 = !DILocation(line: 8, scope: !8)<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>
</blockquote></div>