[llvm] f2e4f3e - Reapply "[DebugInfo] Use variadic debug values to salvage BinOps and GEP instrs with non-const operands"

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 12 20:16:38 PDT 2021


Repro is in https://crbug.com/1198356#c1

On Mon, Apr 12, 2021 at 6:46 PM Arthur Eubanks <aeubanks at google.com> wrote:

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


More information about the llvm-commits mailing list