<div dir="ltr">Hi Stephen,<div><br></div><div>This patch appears to be causing a use of uninitialized memory detected on the <a href="https://lab.llvm.org:8011/#/builders/74">MSan bot</a>.  Could you please take a look?</div><div><br></div><font face="monospace">==1571992==WARNING: MemorySanitizer: use-of-uninitialized-value<br>    #0 0xbcf31b0 in llvm::InstCombinerImpl::visitTrunc(llvm::TruncInst&) llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp<br>    #1 0xbb57e54 in llvm::InstVisitor<llvm::InstCombinerImpl, llvm::Instruction*>::visit(llvm::Instruction&) llvm-project/llvm/include/llvm/IR/Instruction.def:184:1<br>    #2 0xbb52196 in llvm::InstCombinerImpl::run() llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:3730:31<br>    #3 0xbb6088b in combineInstructionsOverFunction(llvm::Function&, llvm::InstCombineWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::ProfileSummaryInfo*, unsigned int, llvm::LoopInfo*) llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:4020:13<br>    #4 0xbb593cb in llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:4051:8<br>    #5 0xe5c2ba1 in llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function> >::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:85:17<br>    #6 0xaf42024 in llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function> >::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm-project/llvm/include/llvm/IR/PassManager.h:517:21<br>    #7 0x3b9cf71 in llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function> >, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function> >::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:85:17<br>    #8 0xaf5b7d7 in llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm-project/llvm/lib/IR/PassManager.cpp:117:22<br>    #9 0x296c961 in llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:85:17<br>    #10 0xaf3bd24 in llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm-project/llvm/include/llvm/IR/PassManager.h:517:21<br>    #11 0x293e9c5 in llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::StringRef>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool) llvm-project/llvm/tools/opt/NewPMDriver.cpp:449:7<br>    #12 0x299f1e5 in main llvm-project/llvm/tools/opt/opt.cpp:819:12<br>    #13 0x7fed4cd9fd09 in __libc_start_main csu/../csu/libc-start.c:308:16<br>    #14 0x28ac269 in _start (llvm_build_msan/bin/opt+0x28ac269)<br><br>SUMMARY: MemorySanitizer: use-of-uninitialized-value llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp in llvm::InstCombinerImpl::visitTrunc(llvm::TruncInst&)</font><br><div> <br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Mar 8, 2021 at 6:37 AM Stephen Tozer via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">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: gbtozers<br>
Date: 2021-03-08T14:36:13Z<br>
New Revision: e5d958c45629ccd2f5b5f7432756be1d0fcf052c<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/e5d958c45629ccd2f5b5f7432756be1d0fcf052c" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/e5d958c45629ccd2f5b5f7432756be1d0fcf052c</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/e5d958c45629ccd2f5b5f7432756be1d0fcf052c.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/e5d958c45629ccd2f5b5f7432756be1d0fcf052c.diff</a><br>
<br>
LOG: [DebugInfo] Support DIArgList in DbgVariableIntrinsic<br>
<br>
This patch updates DbgVariableIntrinsics to support use of a DIArgList for the<br>
location operand, resulting in a significant change to its interface. This patch<br>
does not update all IR passes to support multiple location operands in a<br>
dbg.value; the only change is to update the DbgVariableIntrinsic interface and<br>
its uses. All code outside of the intrinsic classes assumes that an intrinsic<br>
will always have exactly one location operand; they will still support<br>
DIArgLists, but only if they contain exactly one Value.<br>
<br>
Among other changes, the setOperand and setArgOperand functions in<br>
DbgVariableIntrinsic have been made private. This is to prevent code from<br>
setting the operands of these intrinsics directly, which could easily result in<br>
incorrect/invalid operands being set. This does not prevent these functions from<br>
being called on a debug intrinsic at all, as they can still be called on any<br>
CallInst pointer; it is assumed that any code directly setting the operands on a<br>
generic call instruction is doing so safely. The intention for making these<br>
functions private is to prevent DIArgLists from being overwritten by code that's<br>
naively trying to replace one of the Values it points to, and also to fail fast<br>
if a DbgVariableIntrinsic is updated to use a DIArgList without a valid<br>
corresponding DIExpression.<br>
<br>
Added: <br>
<br>
<br>
Modified: <br>
    llvm/include/llvm/IR/IntrinsicInst.h<br>
    llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
    llvm/lib/CodeGen/CodeGenPrepare.cpp<br>
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
    llvm/lib/IR/Constants.cpp<br>
    llvm/lib/IR/IntrinsicInst.cpp<br>
    llvm/lib/IR/Verifier.cpp<br>
    llvm/lib/Target/AArch64/AArch64StackTagging.cpp<br>
    llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp<br>
    llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp<br>
    llvm/lib/Transforms/Scalar/ADCE.cpp<br>
    llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp<br>
    llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp<br>
    llvm/lib/Transforms/Utils/CodeExtractor.cpp<br>
    llvm/lib/Transforms/Utils/LCSSA.cpp<br>
    llvm/lib/Transforms/Utils/Local.cpp<br>
    llvm/lib/Transforms/Utils/LoopRotationUtils.cpp<br>
    llvm/unittests/Transforms/Utils/LocalTest.cpp<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h<br>
index a7dec8837bf8..a138e4bea8c0 100644<br>
--- a/llvm/include/llvm/IR/IntrinsicInst.h<br>
+++ b/llvm/include/llvm/IR/IntrinsicInst.h<br>
@@ -24,6 +24,7 @@<br>
 #define LLVM_IR_INTRINSICINST_H<br>
<br>
 #include "llvm/IR/Constants.h"<br>
+#include "llvm/IR/DebugInfoMetadata.h"<br>
 #include "llvm/IR/DerivedTypes.h"<br>
 #include "llvm/IR/FPEnv.h"<br>
 #include "llvm/IR/Function.h"<br>
@@ -146,10 +147,78 @@ class DbgInfoIntrinsic : public IntrinsicInst {<br>
 /// This is the common base class for debug info intrinsics for variables.<br>
 class DbgVariableIntrinsic : public DbgInfoIntrinsic {<br>
 public:<br>
-  /// Get the location corresponding to the variable referenced by the debug<br>
+  // Iterator for ValueAsMetadata that internally uses direct pointer iteration<br>
+  // over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the<br>
+  // ValueAsMetadata .<br>
+  class location_op_iterator<br>
+      : public iterator_facade_base<location_op_iterator,<br>
+                                    std::bidirectional_iterator_tag, Value *> {<br>
+    PointerUnion<ValueAsMetadata *, ValueAsMetadata **> I;<br>
+<br>
+  public:<br>
+    location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {}<br>
+    location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {}<br>
+<br>
+    location_op_iterator(const location_op_iterator &R) : I(R.I) {}<br>
+    location_op_iterator &operator=(const location_op_iterator &R) {<br>
+      I = R.I;<br>
+      return *this;<br>
+    }<br>
+    bool operator==(const location_op_iterator &RHS) const {<br>
+      return I == RHS.I;<br>
+    }<br>
+    const Value *operator*() const {<br>
+      ValueAsMetadata *VAM = I.is<ValueAsMetadata *>()<br>
+                                 ? I.get<ValueAsMetadata *>()<br>
+                                 : *I.get<ValueAsMetadata **>();<br>
+      return VAM->getValue();<br>
+    };<br>
+    Value *operator*() {<br>
+      ValueAsMetadata *VAM = I.is<ValueAsMetadata *>()<br>
+                                 ? I.get<ValueAsMetadata *>()<br>
+                                 : *I.get<ValueAsMetadata **>();<br>
+      return VAM->getValue();<br>
+    }<br>
+    location_op_iterator &operator++() {<br>
+      if (I.is<ValueAsMetadata *>())<br>
+        I = I.get<ValueAsMetadata *>() + 1;<br>
+      else<br>
+        I = I.get<ValueAsMetadata **>() + 1;<br>
+      return *this;<br>
+    }<br>
+    location_op_iterator &operator--() {<br>
+      if (I.is<ValueAsMetadata *>())<br>
+        I = I.get<ValueAsMetadata *>() - 1;<br>
+      else<br>
+        I = I.get<ValueAsMetadata **>() - 1;<br>
+      return *this;<br>
+    }<br>
+  };<br>
+<br>
+  /// Get the locations corresponding to the variable referenced by the debug<br>
   /// info intrinsic.  Depending on the intrinsic, this could be the<br>
   /// variable's value or its address.<br>
-  Value *getVariableLocation(bool AllowNullOp = true) const;<br>
+  iterator_range<location_op_iterator> location_ops() const;<br>
+<br>
+  Value *getVariableLocationOp(unsigned OpIdx) const;<br>
+<br>
+  void replaceVariableLocationOp(Value *OldValue, Value *NewValue);<br>
+<br>
+  void setVariable(DILocalVariable *NewVar) {<br>
+    setArgOperand(1, MetadataAsValue::get(NewVar->getContext(), NewVar));<br>
+  }<br>
+<br>
+  void setExpression(DIExpression *NewExpr) {<br>
+    setArgOperand(2, MetadataAsValue::get(NewExpr->getContext(), NewExpr));<br>
+  }<br>
+<br>
+  unsigned getNumVariableLocationOps() const {<br>
+    if (hasArgList())<br>
+      return cast<DIArgList>(getRawLocation())->getArgs().size();<br>
+    return 1;<br>
+  }<br>
+<br>
+  bool hasArgList() const { return isa<DIArgList>(getRawLocation()); }<br>
<br>
   /// Does this describe the address of a local variable. True for dbg.addr<br>
   /// and dbg.declare, but not dbg.value, which describes its value.<br>
@@ -157,6 +226,24 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {<br>
     return getIntrinsicID() != Intrinsic::dbg_value;<br>
   }<br>
<br>
+  void setUndef() {<br>
+    // TODO: When/if we remove duplicate values from DIArgLists, we don't need<br>
+    // this set anymore.<br>
+    SmallPtrSet<Value *, 4> RemovedValues;<br>
+    for (Value *OldValue : location_ops()) {<br>
+      if (!RemovedValues.insert(OldValue).second)<br>
+        continue;<br>
+      Value *Undef = UndefValue::get(OldValue->getType());<br>
+      replaceVariableLocationOp(OldValue, Undef);<br>
+    }<br>
+  }<br>
+<br>
+  bool isUndef() const {<br>
+    return (getNumVariableLocationOps() == 0 &&<br>
+            !getExpression()->isComplex()) ||<br>
+           any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); });<br>
+  }<br>
+<br>
   DILocalVariable *getVariable() const {<br>
     return cast<DILocalVariable>(getRawVariable());<br>
   }<br>
@@ -165,6 +252,10 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {<br>
     return cast<DIExpression>(getRawExpression());<br>
   }<br>
<br>
+  Metadata *getRawLocation() const {<br>
+    return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();<br>
+  }<br>
+<br>
   Metadata *getRawVariable() const {<br>
     return cast<MetadataAsValue>(getArgOperand(1))->getMetadata();<br>
   }<br>
@@ -193,12 +284,21 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {<br>
     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));<br>
   }<br>
   /// @}<br>
+private:<br>
+  void setArgOperand(unsigned i, Value *v) {<br>
+    DbgInfoIntrinsic::setArgOperand(i, v);<br>
+  }<br>
+  void setOperand(unsigned i, Value *v) { DbgInfoIntrinsic::setOperand(i, v); }<br>
 };<br>
<br>
 /// This represents the llvm.dbg.declare instruction.<br>
 class DbgDeclareInst : public DbgVariableIntrinsic {<br>
 public:<br>
-  Value *getAddress() const { return getVariableLocation(); }<br>
+  Value *getAddress() const {<br>
+    assert(getNumVariableLocationOps() == 1 &&<br>
+           "dbg.declare must have exactly 1 location operand.");<br>
+    return getVariableLocationOp(0);<br>
+  }<br>
<br>
   /// \name Casting methods<br>
   /// @{<br>
@@ -214,7 +314,11 @@ class DbgDeclareInst : public DbgVariableIntrinsic {<br>
 /// This represents the llvm.dbg.addr instruction.<br>
 class DbgAddrIntrinsic : public DbgVariableIntrinsic {<br>
 public:<br>
-  Value *getAddress() const { return getVariableLocation(); }<br>
+  Value *getAddress() const {<br>
+    assert(getNumVariableLocationOps() == 1 &&<br>
+           "dbg.addr must have exactly 1 location operand.");<br>
+    return getVariableLocationOp(0);<br>
+  }<br>
<br>
   /// \name Casting methods<br>
   /// @{<br>
@@ -229,8 +333,13 @@ class DbgAddrIntrinsic : public DbgVariableIntrinsic {<br>
 /// This represents the llvm.dbg.value instruction.<br>
 class DbgValueInst : public DbgVariableIntrinsic {<br>
 public:<br>
-  Value *getValue() const {<br>
-    return getVariableLocation(/* AllowNullOp = */ false);<br>
+  // The default argument should only be used in ISel, and the default option<br>
+  // should be removed once ISel support for multiple location ops is complete.<br>
+  Value *getValue(unsigned OpIdx = 0) const {<br>
+    return getVariableLocationOp(OpIdx);<br>
+  }<br>
+  iterator_range<location_op_iterator> getValues() const {<br>
+    return location_ops();<br>
   }<br>
<br>
   /// \name Casting methods<br>
<br>
diff  --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
index 0567f96c9c25..0cf547c57d9d 100644<br>
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
@@ -550,8 +550,7 @@ class MetadataLoader::MetadataLoaderImpl {<br>
               SmallVector<uint64_t, 8> Ops;<br>
               Ops.append(std::next(DIExpr->elements_begin()),<br>
                          DIExpr->elements_end());<br>
-              auto *E = DIExpression::get(Context, Ops);<br>
-              DDI->setOperand(2, MetadataAsValue::get(Context, E));<br>
+              DDI->setExpression(DIExpression::get(Context, Ops));<br>
             }<br>
   }<br>
<br>
<br>
diff  --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp<br>
index f4bf55d773a3..6e806b0c73a7 100644<br>
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp<br>
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp<br>
@@ -2883,11 +2883,8 @@ class TypePromotionTransaction {<br>
       // including the debug uses. Since we are undoing the replacements,<br>
       // the original debug uses must also be reinstated to maintain the<br>
       // correctness and utility of debug value instructions.<br>
-      for (auto *DVI: DbgValues) {<br>
-        LLVMContext &Ctx = Inst->getType()->getContext();<br>
-        auto *MV = MetadataAsValue::get(Ctx, ValueAsMetadata::get(Inst));<br>
-        DVI->setOperand(0, MV);<br>
-      }<br>
+      for (auto *DVI : DbgValues)<br>
+        DVI->replaceVariableLocationOp(DVI->getVariableLocationOp(0), Inst);<br>
     }<br>
   };<br>
<br>
@@ -7878,7 +7875,7 @@ bool CodeGenPrepare::fixupDbgValue(Instruction *I) {<br>
   DbgValueInst &DVI = *cast<DbgValueInst>(I);<br>
<br>
   // Does this dbg.value refer to a sunk address calculation?<br>
-  Value *Location = DVI.getVariableLocation();<br>
+  Value *Location = DVI.getVariableLocationOp(0);<br>
   WeakTrackingVH SunkAddrVH = SunkAddrs[Location];<br>
   Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr;<br>
   if (SunkAddr) {<br>
@@ -7886,8 +7883,7 @@ bool CodeGenPrepare::fixupDbgValue(Instruction *I) {<br>
     // opportunity to be accurately lowered. This update may change the type of<br>
     // pointer being referred to; however this makes no <br>
diff erence to debugging<br>
     // information, and we can't generate bitcasts that may affect codegen.<br>
-    DVI.setOperand(0, MetadataAsValue::get(DVI.getContext(),<br>
-                                           ValueAsMetadata::get(SunkAddr)));<br>
+    DVI.replaceVariableLocationOp(Location, SunkAddr);<br>
     return true;<br>
   }<br>
   return false;<br>
<br>
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
index 39730d03502b..f869b2c41f9f 100644<br>
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
@@ -1191,8 +1191,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,<br>
                           << "in EmitFuncArgumentDbgValue\n");<br>
     } else {<br>
       LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");<br>
-      auto Undef =<br>
-          UndefValue::get(DDI.getDI()->getVariableLocation()->getType());<br>
+      auto Undef = UndefValue::get(DDI.getDI()->getValue()->getType());<br>
       auto SDV =<br>
           DAG.getConstantDbgValue(Variable, Expr, Undef, dl, DbgSDNodeOrder);<br>
       DAG.AddDbgValue(SDV, nullptr, false);<br>
@@ -1246,7 +1245,7 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {<br>
   // This was the final opportunity to salvage this debug information, and it<br>
   // couldn't be done. Place an undef DBG_VALUE at this location to terminate<br>
   // any earlier variable location.<br>
-  auto Undef = UndefValue::get(DDI.getDI()->getVariableLocation()->getType());<br>
+  auto Undef = UndefValue::get(DDI.getDI()->getValue()->getType());<br>
   auto SDV = DAG.getConstantDbgValue(Var, Expr, Undef, DL, SDNodeOrder);<br>
   DAG.AddDbgValue(SDV, nullptr, false);<br>
<br>
@@ -5885,7 +5884,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,<br>
     LLVM_DEBUG(dbgs() << "SelectionDAG visiting debug intrinsic: " << DI<br>
                       << "\n");<br>
     // Check if address has undef value.<br>
-    const Value *Address = DI.getVariableLocation();<br>
+    const Value *Address = DI.getVariableLocationOp(0);<br>
     if (!Address || isa<UndefValue>(Address) ||<br>
         (Address->use_empty() && !isa<Argument>(Address))) {<br>
       LLVM_DEBUG(dbgs() << "Dropping debug info for " << DI<br>
<br>
diff  --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp<br>
index ef0e5f6dd087..62760ff7aec2 100644<br>
--- a/llvm/lib/IR/Constants.cpp<br>
+++ b/llvm/lib/IR/Constants.cpp<br>
@@ -721,6 +721,12 @@ static bool removeDeadUsersOfConstant(const Constant *C) {<br>
       return false; // Constant wasn't dead<br>
   }<br>
<br>
+  // If C is only used by metadata, it should not be preserved but should have<br>
+  // its uses replaced.<br>
+  if (C->isUsedByMetadata()) {<br>
+    const_cast<Constant *>(C)->replaceAllUsesWith(<br>
+        UndefValue::get(C->getType()));<br>
+  }<br>
   const_cast<Constant*>(C)->destroyConstant();<br>
   return true;<br>
 }<br>
<br>
diff  --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp<br>
index 3d1ea2853591..3d3f734ba5e0 100644<br>
--- a/llvm/lib/IR/IntrinsicInst.cpp<br>
+++ b/llvm/lib/IR/IntrinsicInst.cpp<br>
@@ -38,18 +38,65 @@ using namespace llvm;<br>
 /// intrinsics for variables.<br>
 ///<br>
<br>
-Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {<br>
-  Value *Op = getArgOperand(0);<br>
-  if (AllowNullOp && !Op)<br>
+iterator_range<DbgVariableIntrinsic::location_op_iterator><br>
+DbgVariableIntrinsic::location_ops() const {<br>
+  auto *MD = getRawLocation();<br>
+  assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");<br>
+<br>
+  // If operand is ValueAsMetadata, return a range over just that operand.<br>
+  if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {<br>
+    return {location_op_iterator(VAM), location_op_iterator(VAM + 1)};<br>
+  }<br>
+  // If operand is DIArgList, return a range over its args.<br>
+  if (auto *AL = dyn_cast<DIArgList>(MD))<br>
+    return {location_op_iterator(AL->args_begin()),<br>
+            location_op_iterator(AL->args_end())};<br>
+  // Operand must be an empty metadata tuple, so return empty iterator.<br>
+  return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)),<br>
+          location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))};<br>
+}<br>
+<br>
+Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const {<br>
+  auto *MD = getRawLocation();<br>
+  assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");<br>
+  if (auto *AL = dyn_cast<DIArgList>(MD))<br>
+    return AL->getArgs()[OpIdx]->getValue();<br>
+  if (isa<MDNode>(MD))<br>
     return nullptr;<br>
+  assert(<br>
+      isa<ValueAsMetadata>(MD) &&<br>
+      "Attempted to get location operand from DbgVariableIntrinsic with none.");<br>
+  auto *V = cast<ValueAsMetadata>(MD);<br>
+  assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a "<br>
+                       "single location operand.");<br>
+  return V->getValue();<br>
+}<br>
<br>
-  auto *MD = cast<MetadataAsValue>(Op)->getMetadata();<br>
-  if (auto *V = dyn_cast<ValueAsMetadata>(MD))<br>
-    return V->getValue();<br>
+static ValueAsMetadata *getAsMetadata(Value *V) {<br>
+  return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>(<br>
+                                       cast<MetadataAsValue>(V)->getMetadata())<br>
+                                 : ValueAsMetadata::get(V);<br>
+}<br>
<br>
-  // When the value goes to null, it gets replaced by an empty MDNode.<br>
-  assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");<br>
-  return nullptr;<br>
+void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,<br>
+                                                     Value *NewValue) {<br>
+  assert(NewValue && "Values must be non-null");<br>
+  auto Locations = location_ops();<br>
+  auto OldIt = find(Locations, OldValue);<br>
+  assert(OldIt != Locations.end() && "OldValue must be a current location");<br>
+  if (!hasArgList()) {<br>
+    Value *NewOperand = isa<MetadataAsValue>(NewValue)<br>
+                            ? NewValue<br>
+                            : MetadataAsValue::get(<br>
+                                  getContext(), ValueAsMetadata::get(NewValue));<br>
+    return setArgOperand(0, NewOperand);<br>
+  }<br>
+  SmallVector<ValueAsMetadata *, 4> MDs;<br>
+  ValueAsMetadata *NewOperand = getAsMetadata(NewValue);<br>
+  for (auto *VMD : Locations)<br>
+    MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD));<br>
+  setArgOperand(<br>
+      0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));<br>
 }<br>
<br>
 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {<br>
<br>
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp<br>
index be8663553b52..b7a002b0573b 100644<br>
--- a/llvm/lib/IR/Verifier.cpp<br>
+++ b/llvm/lib/IR/Verifier.cpp<br>
@@ -5371,7 +5371,7 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) {<br>
 }<br>
<br>
 void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) {<br>
-  auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata();<br>
+  auto *MD = DII.getRawLocation();<br>
   AssertDI(isa<ValueAsMetadata>(MD) || isa<DIArgList>(MD) ||<br>
                (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()),<br>
            "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD);<br>
<br>
diff  --git a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp<br>
index ab49e0c3f937..793db06f79ad 100644<br>
--- a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp<br>
+++ b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp<br>
@@ -284,6 +284,7 @@ class InitializerBuilder {<br>
 class AArch64StackTagging : public FunctionPass {<br>
   struct AllocaInfo {<br>
     AllocaInst *AI;<br>
+    TrackingVH<Instruction> OldAI; // Track through RAUW to replace debug uses.<br>
     SmallVector<IntrinsicInst *, 2> LifetimeStart;<br>
     SmallVector<IntrinsicInst *, 2> LifetimeEnd;<br>
     SmallVector<DbgVariableIntrinsic *, 2> DbgVariableIntrinsics;<br>
@@ -557,12 +558,13 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {<br>
       Instruction *I = &*IT;<br>
       if (auto *AI = dyn_cast<AllocaInst>(I)) {<br>
         Allocas[AI].AI = AI;<br>
+        Allocas[AI].OldAI = AI;<br>
         continue;<br>
       }<br>
<br>
       if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(I)) {<br>
         if (auto *AI =<br>
-                dyn_cast_or_null<AllocaInst>(DVI->getVariableLocation())) {<br>
+                dyn_cast_or_null<AllocaInst>(DVI->getVariableLocationOp(0))) {<br>
           Allocas[AI].DbgVariableIntrinsics.push_back(DVI);<br>
         }<br>
         continue;<br>
@@ -705,9 +707,7 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {<br>
<br>
     // Fixup debug intrinsics to point to the new alloca.<br>
     for (auto DVI : Info.DbgVariableIntrinsics)<br>
-      DVI->setArgOperand(<br>
-          0,<br>
-          MetadataAsValue::get(F->getContext(), LocalAsMetadata::get(Info.AI)));<br>
+      DVI->replaceVariableLocationOp(Info.OldAI, Info.AI);<br>
   }<br>
<br>
   // If we have instrumented at least one alloca, all unrecognized lifetime<br>
<br>
diff  --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
index 16b59f279ff9..accd3a6ce16a 100644<br>
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp<br>
@@ -2156,6 +2156,7 @@ void coro::salvageDebugInfo(<br>
   // function argument and convert into a DIExpression.<br>
   bool OutermostLoad = true;<br>
   Value *Storage = DDI->getAddress();<br>
+  Value *OriginalStorage = Storage;<br>
   while (Storage) {<br>
     if (auto *LdInst = dyn_cast<LoadInst>(Storage)) {<br>
       Storage = LdInst->getOperand(0);<br>
@@ -2206,10 +2207,8 @@ void coro::salvageDebugInfo(<br>
     if (Expr && Expr->isComplex())<br>
       Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);<br>
   }<br>
-  auto &VMContext = DDI->getFunction()->getContext();<br>
-  DDI->setOperand(<br>
-      0, MetadataAsValue::get(VMContext, ValueAsMetadata::get(Storage)));<br>
-  DDI->setOperand(2, MetadataAsValue::get(VMContext, Expr));<br>
+  DDI->replaceVariableLocationOp(OriginalStorage, Storage);<br>
+  DDI->setExpression(Expr);<br>
   if (auto *InsertPt = dyn_cast_or_null<Instruction>(Storage))<br>
     DDI->moveAfter(InsertPt);<br>
 }<br>
<br>
diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp<br>
index 54811628de95..62f761995257 100644<br>
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp<br>
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp<br>
@@ -3582,10 +3582,6 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {<br>
     if (!isa<DbgDeclareInst>(DII))<br>
       return false;<br>
<br>
-    if (isa<CastInst>(I))<br>
-      DII->setOperand(<br>
-          0, MetadataAsValue::get(I->getContext(),<br>
-                                  ValueAsMetadata::get(I->getOperand(0))));<br>
     return true;<br>
   };<br>
<br>
<br>
diff  --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp<br>
index fedd9bfc977e..e02076c74420 100644<br>
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp<br>
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp<br>
@@ -1153,9 +1153,10 @@ bool HWAddressSanitizer::instrumentStack(<br>
       // to put it at the beginning of the expression.<br>
       SmallVector<uint64_t, 8> NewOps = {dwarf::DW_OP_LLVM_tag_offset,<br>
                                          RetagMask(N)};<br>
-      DDI->setArgOperand(<br>
-          2, MetadataAsValue::get(*C, DIExpression::prependOpcodes(<br>
-                                          DDI->getExpression(), NewOps)));<br>
+      auto Locations = DDI->location_ops();<br>
+      unsigned LocNo = std::distance(Locations.begin(), find(Locations, AI));<br>
+      DDI->setExpression(<br>
+          DIExpression::appendOpsToArg(DDI->getExpression(), NewOps, LocNo));<br>
     }<br>
<br>
     size_t Size = getAllocaSizeInBytes(*AI);<br>
@@ -1219,7 +1220,7 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {<br>
<br>
       if (auto *DDI = dyn_cast<DbgVariableIntrinsic>(&Inst))<br>
         if (auto *Alloca =<br>
-                dyn_cast_or_null<AllocaInst>(DDI->getVariableLocation()))<br>
+                dyn_cast_or_null<AllocaInst>(DDI->getVariableLocationOp(0)))<br>
           AllocaDbgMap[Alloca].push_back(DDI);<br>
<br>
       if (InstrumentLandingPads && isa<LandingPadInst>(Inst))<br>
@@ -1300,10 +1301,9 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {<br>
       for (auto &Inst : BB)<br>
         if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst))<br>
           if (auto *AI =<br>
-                  dyn_cast_or_null<AllocaInst>(DVI->getVariableLocation()))<br>
+                  dyn_cast_or_null<AllocaInst>(DVI->getVariableLocationOp(0)))<br>
             if (auto *NewAI = AllocaToPaddedAllocaMap.lookup(AI))<br>
-              DVI->setArgOperand(<br>
-                  0, MetadataAsValue::get(*C, LocalAsMetadata::get(NewAI)));<br>
+              DVI->replaceVariableLocationOp(AI, NewAI);<br>
     for (auto &P : AllocaToPaddedAllocaMap)<br>
       P.first->eraseFromParent();<br>
   }<br>
<br>
diff  --git a/llvm/lib/Transforms/Scalar/ADCE.cpp b/llvm/lib/Transforms/Scalar/ADCE.cpp<br>
index ce4e5e575fbf..c8fb9d106e32 100644<br>
--- a/llvm/lib/Transforms/Scalar/ADCE.cpp<br>
+++ b/llvm/lib/Transforms/Scalar/ADCE.cpp<br>
@@ -521,7 +521,7 @@ bool AggressiveDeadCodeElimination::removeDeadInstructions() {<br>
         // If intrinsic is pointing at a live SSA value, there may be an<br>
         // earlier optimization bug: if we know the location of the variable,<br>
         // why isn't the scope of the location alive?<br>
-        if (Value *V = DII->getVariableLocation())<br>
+        if (Value *V = DII->getVariableLocationOp(0))<br>
           if (Instruction *II = dyn_cast<Instruction>(V))<br>
             if (isLive(II))<br>
               dbgs() << "Dropping debug info for " << *DII << "\n";<br>
<br>
diff  --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp<br>
index 3e26ef205d15..facbfce86d8e 100644<br>
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp<br>
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp<br>
@@ -5836,7 +5836,7 @@ static void DbgGatherEqualValues(Loop *L, ScalarEvolution &SE,<br>
       auto DVI = dyn_cast<DbgValueInst>(&I);<br>
       if (!DVI)<br>
         continue;<br>
-      auto V = DVI->getVariableLocation();<br>
+      auto V = DVI->getVariableLocationOp(0);<br>
       if (!V || !SE.isSCEVable(V->getType()))<br>
         continue;<br>
       auto DbgValueSCEV = SE.getSCEV(V);<br>
@@ -5862,7 +5862,7 @@ static void DbgApplyEqualValues(EqualValuesMap &DbgValueToEqualSet) {<br>
   for (auto A : DbgValueToEqualSet) {<br>
     auto DVI = A.first;<br>
     // Only update those that are now undef.<br>
-    if (!isa_and_nonnull<UndefValue>(DVI->getVariableLocation()))<br>
+    if (!isa_and_nonnull<UndefValue>(DVI->getVariableLocationOp(0)))<br>
       continue;<br>
     for (auto EV : A.second) {<br>
       auto V = std::get<WeakVH>(EV);<br>
@@ -5870,14 +5870,13 @@ static void DbgApplyEqualValues(EqualValuesMap &DbgValueToEqualSet) {<br>
         continue;<br>
       auto DbgDIExpr = std::get<DIExpression *>(EV);<br>
       auto Offset = std::get<int64_t>(EV);<br>
-      auto &Ctx = DVI->getContext();<br>
-      DVI->setOperand(0, MetadataAsValue::get(Ctx, ValueAsMetadata::get(V)));<br>
+      DVI->replaceVariableLocationOp(DVI->getVariableLocationOp(0), V);<br>
       if (Offset) {<br>
         SmallVector<uint64_t, 8> Ops;<br>
         DIExpression::appendOffset(Ops, Offset);<br>
         DbgDIExpr = DIExpression::prependOpcodes(DbgDIExpr, Ops, true);<br>
       }<br>
-      DVI->setOperand(2, MetadataAsValue::get(Ctx, DbgDIExpr));<br>
+      DVI->setExpression(DbgDIExpr);<br>
       break;<br>
     }<br>
   }<br>
<br>
diff  --git a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp<br>
index ff9132206231..0cb9771b6e86 100644<br>
--- a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp<br>
+++ b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp<br>
@@ -267,7 +267,7 @@ bool SpeculativeExecutionPass::considerHoistingFromTo(<br>
     // Debug variable has special operand to check it's not hoisted.<br>
     if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(U)) {<br>
       if (const auto *I =<br>
-              dyn_cast_or_null<Instruction>(DVI->getVariableLocation()))<br>
+              dyn_cast_or_null<Instruction>(DVI->getVariableLocationOp(0)))<br>
         if (NotHoisted.count(I) == 0)<br>
           return true;<br>
       return false;<br>
<br>
diff  --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp<br>
index b9f886d6217d..2b0ee77f4c9b 100644<br>
--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp<br>
+++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp<br>
@@ -1514,7 +1514,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,<br>
     // If the location isn't a constant or an instruction, delete the<br>
     // intrinsic.<br>
     auto *DVI = cast<DbgVariableIntrinsic>(DII);<br>
-    Value *Location = DVI->getVariableLocation();<br>
+    Value *Location = DVI->getVariableLocationOp(0);<br>
     if (!Location ||<br>
         (!isa<Constant>(Location) && !isa<Instruction>(Location))) {<br>
       DebugIntrinsicsToDelete.push_back(DVI);<br>
@@ -1537,7 +1537,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,<br>
           NewSP, OldVar->getName(), OldVar->getFile(), OldVar->getLine(),<br>
           OldVar->getType(), /*AlwaysPreserve=*/false, DINode::FlagZero,<br>
           OldVar->getAlignInBits());<br>
-    DVI->setArgOperand(1, MetadataAsValue::get(Ctx, NewVar));<br>
+    DVI->setVariable(cast<DILocalVariable>(NewVar));<br>
   }<br>
   for (auto *DII : DebugIntrinsicsToDelete)<br>
     DII->eraseFromParent();<br>
<br>
diff  --git a/llvm/lib/Transforms/Utils/LCSSA.cpp b/llvm/lib/Transforms/Utils/LCSSA.cpp<br>
index 7437701f5339..c5328784d813 100644<br>
--- a/llvm/lib/Transforms/Utils/LCSSA.cpp<br>
+++ b/llvm/lib/Transforms/Utils/LCSSA.cpp<br>
@@ -236,7 +236,6 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,<br>
     llvm::findDbgValues(DbgValues, I);<br>
<br>
     // Update pre-existing debug value uses that reside outside the loop.<br>
-    auto &Ctx = I->getContext();<br>
     for (auto DVI : DbgValues) {<br>
       BasicBlock *UserBB = DVI->getParent();<br>
       if (InstBB == UserBB || L->contains(UserBB))<br>
@@ -247,7 +246,7 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,<br>
       Value *V = AddedPHIs.size() == 1 ? AddedPHIs[0]<br>
                                        : SSAUpdate.FindValueForBlock(UserBB);<br>
       if (V)<br>
-        DVI->setOperand(0, MetadataAsValue::get(Ctx, ValueAsMetadata::get(V)));<br>
+        DVI->replaceVariableLocationOp(I, V);<br>
     }<br>
<br>
     // SSAUpdater might have inserted phi-nodes inside other loops. We'll need<br>
<br>
diff  --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp<br>
index c6775d4f3f09..93e5b941c208 100644<br>
--- a/llvm/lib/Transforms/Utils/Local.cpp<br>
+++ b/llvm/lib/Transforms/Utils/Local.cpp<br>
@@ -566,8 +566,7 @@ bool llvm::replaceDbgUsesWithUndef(Instruction *I) {<br>
   findDbgUsers(DbgUsers, I);<br>
   for (auto *DII : DbgUsers) {<br>
     Value *Undef = UndefValue::get(I->getType());<br>
-    DII->setOperand(0, MetadataAsValue::get(DII->getContext(),<br>
-                                            ValueAsMetadata::get(Undef)));<br>
+    DII->replaceVariableLocationOp(I, Undef);<br>
   }<br>
   return !DbgUsers.empty();<br>
 }<br>
@@ -1389,7 +1388,7 @@ static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) {<br>
   // VLA). Try to use the size of the alloca that the dbg intrinsic describes<br>
   // intead.<br>
   if (DII->isAddressOfVariable())<br>
-    if (auto *AI = dyn_cast_or_null<AllocaInst>(DII->getVariableLocation()))<br>
+    if (auto *AI = dyn_cast_or_null<AllocaInst>(DII->getVariableLocationOp(0)))<br>
       if (Optional<TypeSize> FragmentSize = AI->getAllocationSizeInBits(DL)) {<br>
         assert(ValueSize.isScalable() == FragmentSize->isScalable() &&<br>
                "Both sizes should agree on the scalable flag.");<br>
@@ -1597,7 +1596,8 @@ void llvm::insertDebugValuesForPHIs(BasicBlock *BB,<br>
   ValueToValueMapTy DbgValueMap;<br>
   for (auto &I : *BB) {<br>
     if (auto DbgII = dyn_cast<DbgVariableIntrinsic>(&I)) {<br>
-      if (auto *Loc = dyn_cast_or_null<PHINode>(DbgII->getVariableLocation()))<br>
+      if (auto *Loc =<br>
+              dyn_cast_or_null<PHINode>(DbgII->getVariableLocationOp(0)))<br>
         DbgValueMap.insert({Loc, DbgII});<br>
     }<br>
   }<br>
@@ -1607,19 +1607,18 @@ void llvm::insertDebugValuesForPHIs(BasicBlock *BB,<br>
   // Then iterate through the new PHIs and look to see if they use one of the<br>
   // previously mapped PHIs. If so, insert a new dbg.value intrinsic that will<br>
   // propagate the info through the new PHI.<br>
-  LLVMContext &C = BB->getContext();<br>
   for (auto PHI : InsertedPHIs) {<br>
     BasicBlock *Parent = PHI->getParent();<br>
     // Avoid inserting an intrinsic into an EH block.<br>
     if (Parent->getFirstNonPHI()->isEHPad())<br>
       continue;<br>
-    auto PhiMAV = MetadataAsValue::get(C, ValueAsMetadata::get(PHI));<br>
     for (auto VI : PHI->operand_values()) {<br>
       auto V = DbgValueMap.find(VI);<br>
       if (V != DbgValueMap.end()) {<br>
         auto *DbgII = cast<DbgVariableIntrinsic>(V->second);<br>
-        Instruction *NewDbgII = DbgII->clone();<br>
-        NewDbgII->setOperand(0, PhiMAV);<br>
+        DbgVariableIntrinsic *NewDbgII =<br>
+            cast<DbgVariableIntrinsic>(DbgII->clone());<br>
+        NewDbgII->replaceVariableLocationOp(VI, PHI);<br>
         auto InsertionPt = Parent->getFirstInsertionPt();<br>
         assert(InsertionPt != Parent->end() && "Ill-formed basic block");<br>
         NewDbgII->insertBefore(&*InsertionPt);<br>
@@ -1736,11 +1735,6 @@ void llvm::replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress,<br>
           replaceOneDbgValueForAlloca(DVI, NewAllocaAddress, Builder, Offset);<br>
 }<br>
<br>
-/// Wrap \p V in a ValueAsMetadata instance.<br>
-static MetadataAsValue *wrapValueInMetadata(LLVMContext &C, Value *V) {<br>
-  return MetadataAsValue::get(C, ValueAsMetadata::get(V));<br>
-}<br>
-<br>
 /// Where possible to salvage debug information for \p I do so<br>
 /// and return True. If not possible mark undef and return False.<br>
 void llvm::salvageDebugInfo(Instruction &I) {<br>
@@ -1751,9 +1745,7 @@ void llvm::salvageDebugInfo(Instruction &I) {<br>
<br>
 void llvm::salvageDebugInfoForDbgValues(<br>
     Instruction &I, ArrayRef<DbgVariableIntrinsic *> DbgUsers) {<br>
-  auto &Ctx = I.getContext();<br>
   bool Salvaged = false;<br>
-  auto wrapMD = [&](Value *V) { return wrapValueInMetadata(Ctx, V); };<br>
<br>
   for (auto *DII : DbgUsers) {<br>
     // Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they<br>
@@ -1769,8 +1761,8 @@ void llvm::salvageDebugInfoForDbgValues(<br>
     if (!DIExpr)<br>
       break;<br>
<br>
-    DII->setOperand(0, wrapMD(I.getOperand(0)));<br>
-    DII->setOperand(2, MetadataAsValue::get(Ctx, DIExpr));<br>
+    DII->replaceVariableLocationOp(&I, I.getOperand(0));<br>
+    DII->setExpression(DIExpr);<br>
     LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n');<br>
     Salvaged = true;<br>
   }<br>
@@ -1780,8 +1772,7 @@ void llvm::salvageDebugInfoForDbgValues(<br>
<br>
   for (auto *DII : DbgUsers) {<br>
     Value *Undef = UndefValue::get(I.getType());<br>
-    DII->setOperand(0, MetadataAsValue::get(DII->getContext(),<br>
-                                            ValueAsMetadata::get(Undef)));<br>
+    DII->replaceVariableLocationOp(&I, Undef);<br>
   }<br>
 }<br>
<br>
@@ -1925,13 +1916,12 @@ static bool rewriteDebugUsers(<br>
     if (UndefOrSalvage.count(DII))<br>
       continue;<br>
<br>
-    LLVMContext &Ctx = DII->getContext();<br>
     DbgValReplacement DVR = RewriteExpr(*DII);<br>
     if (!DVR)<br>
       continue;<br>
<br>
-    DII->setOperand(0, wrapValueInMetadata(Ctx, &To));<br>
-    DII->setOperand(2, MetadataAsValue::get(Ctx, *DVR));<br>
+    DII->replaceVariableLocationOp(&From, &To);<br>
+    DII->setExpression(*DVR);<br>
     LLVM_DEBUG(dbgs() << "REWRITE:  " << *DII << '\n');<br>
     Changed = true;<br>
   }<br>
<br>
diff  --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp<br>
index b678efdc8d88..784d0e437ba0 100644<br>
--- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp<br>
+++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp<br>
@@ -179,9 +179,7 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader,<br>
         NewVal = SSA.GetValueInMiddleOfBlock(UserBB);<br>
       else<br>
         NewVal = UndefValue::get(OrigHeaderVal->getType());<br>
-      DbgValue->setOperand(0,<br>
-                           MetadataAsValue::get(OrigHeaderVal->getContext(),<br>
-                                                ValueAsMetadata::get(NewVal)));<br>
+      DbgValue->replaceVariableLocationOp(OrigHeaderVal, NewVal);<br>
     }<br>
   }<br>
 }<br>
@@ -390,7 +388,8 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {<br>
     using DbgIntrinsicHash =<br>
       std::pair<std::pair<Value *, DILocalVariable *>, DIExpression *>;<br>
     auto makeHash = [](DbgVariableIntrinsic *D) -> DbgIntrinsicHash {<br>
-      return {{D->getVariableLocation(), D->getVariable()}, D->getExpression()};<br>
+      return {{D->getVariableLocationOp(0), D->getVariable()},<br>
+              D->getExpression()};<br>
     };<br>
     SmallDenseSet<DbgIntrinsicHash, 8> DbgIntrinsics;<br>
     for (auto I = std::next(OrigPreheader->rbegin()), E = OrigPreheader->rend();<br>
<br>
diff  --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp<br>
index a57a18ce0be1..f2fce5e7d55d 100644<br>
--- a/llvm/unittests/Transforms/Utils/LocalTest.cpp<br>
+++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp<br>
@@ -524,7 +524,9 @@ struct SalvageDebugInfoTest : ::testing::Test {<br>
   }<br>
<br>
   bool doesDebugValueDescribeX(const DbgValueInst &DI) {<br>
-    const auto &CI = *cast<ConstantInt>(DI.getValue());<br>
+    if (DI.getNumVariableLocationOps() != 1)<br>
+      return false;<br>
+    const auto &CI = *cast<ConstantInt>(DI.getValue(0));<br>
     if (CI.isZero())<br>
       return DI.getExpression()->getElements().equals(<br>
           {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_stack_value});<br>
@@ -534,7 +536,9 @@ struct SalvageDebugInfoTest : ::testing::Test {<br>
   }<br>
<br>
   bool doesDebugValueDescribeY(const DbgValueInst &DI) {<br>
-    const auto &CI = *cast<ConstantInt>(DI.getValue());<br>
+    if (DI.getNumVariableLocationOps() != 1)<br>
+      return false;<br>
+    const auto &CI = *cast<ConstantInt>(DI.getVariableLocationOp(0));<br>
     if (CI.isZero())<br>
       return DI.getExpression()->getElements().equals(<br>
           {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_plus_uconst, 2,<br>
@@ -758,13 +762,15 @@ TEST(Local, ReplaceAllDbgUsesWith) {<br>
   EXPECT_TRUE(replaceAllDbgUsesWith(A, F_, F_, DT));<br>
<br>
   auto *ADbgVal = cast<DbgValueInst>(A.getNextNode());<br>
-  EXPECT_EQ(ConstantInt::get(A.getType(), 0), ADbgVal->getVariableLocation());<br>
+  EXPECT_EQ(ADbgVal->getNumVariableLocationOps(), 1);<br>
+  EXPECT_EQ(ConstantInt::get(A.getType(), 0), ADbgVal->getVariableLocationOp(0));<br>
<br>
   // Introduce a use-before-def. Check that the dbg.values for %f become undef.<br>
   EXPECT_TRUE(replaceAllDbgUsesWith(F_, G, G, DT));<br>
<br>
   auto *FDbgVal = cast<DbgValueInst>(F_.getNextNode());<br>
-  EXPECT_TRUE(isa<UndefValue>(FDbgVal->getVariableLocation()));<br>
+  EXPECT_EQ(FDbgVal->getNumVariableLocationOps(), 1);<br>
+  EXPECT_TRUE(FDbgVal->isUndef());<br>
<br>
   SmallVector<DbgValueInst *, 1> FDbgVals;<br>
   findDbgValues(FDbgVals, &F_);<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>