diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp @@ -263,12 +263,25 @@ bool LLVM::DbgValueOp::canUsesBeRemoved( const SmallPtrSetImpl &blockingUses, SmallVectorImpl &newBlockingUses) { - return true; + // There is only one operand that we can remove the use of. + if (blockingUses.size() != 1) + return false; + + return (*blockingUses.begin())->get() == getValue(); } DeletionKind LLVM::DbgValueOp::removeBlockingUses( const SmallPtrSetImpl &blockingUses, RewriterBase &rewriter) { - return DeletionKind::Delete; + // Rewriter by default is after '*this', but we need it before '*this'. + rewriter.setInsertionPoint(*this); + + // Rather than dropping the debug value, replace it with undef to preserve the + // debug local variable info. This allows the debugger to inform the user that + // the variable has been optimized out. + auto undef = + rewriter.create(getValue().getLoc(), getValue().getType()); + rewriter.updateRootInPlace(*this, [&] { getValueMutable().assign(undef); }); + return DeletionKind::Keep; } //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/LLVMIR/mem2reg-dbginfo.mlir b/mlir/test/Dialect/LLVMIR/mem2reg-dbginfo.mlir --- a/mlir/test/Dialect/LLVMIR/mem2reg-dbginfo.mlir +++ b/mlir/test/Dialect/LLVMIR/mem2reg-dbginfo.mlir @@ -76,9 +76,10 @@ } // CHECK-LABEL: llvm.func @always_drop_promoted_declare +// CHECK: %[[UNDEF:.*]] = llvm.mlir.undef // CHECK-NOT: = llvm.alloca // CHECK-NOT: llvm.intr.dbg.declare -// CHECK-NOT: llvm.intr.dbg.value +// CHECK: llvm.intr.dbg.value #{{.*}} = %[[UNDEF]] llvm.func @always_drop_promoted_declare() { %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x i64 {alignment = 8 : i64} : (i32) -> !llvm.ptr