Index: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h +++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h @@ -2340,6 +2340,12 @@ int64_t Offset = 0, bool DerefAfter = false, bool StackValue = false); + /// Prepend \p DIExpr with the given opcodes and optionally turn it into a + /// stack value. + static DIExpression *doPrepend(const DIExpression *DIExpr, + SmallVectorImpl &Ops, + bool StackValue = false); + /// Create a DIExpression to describe one part of an aggregate variable that /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation /// will be appended to the elements of \c Expr. If \c Expr already contains Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -341,6 +341,7 @@ case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: case dwarf::DW_OP_mul: + case dwarf::DW_OP_or: emitOp(Op->getOp()); break; case dwarf::DW_OP_deref: Index: llvm/trunk/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/trunk/lib/IR/DebugInfoMetadata.cpp +++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp @@ -706,6 +706,7 @@ case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: case dwarf::DW_OP_mul: + case dwarf::DW_OP_or: case dwarf::DW_OP_deref: case dwarf::DW_OP_xderef: break; @@ -772,6 +773,12 @@ if (DerefAfter) Ops.push_back(dwarf::DW_OP_deref); + return doPrepend(Expr, Ops, StackValue); +} + +DIExpression *DIExpression::doPrepend(const DIExpression *Expr, + SmallVectorImpl &Ops, + bool StackValue) { if (Expr) for (auto Op : Expr->expr_ops()) { // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment. Index: llvm/trunk/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/Local.cpp +++ llvm/trunk/lib/Transforms/Utils/Local.cpp @@ -1497,16 +1497,27 @@ return MetadataAsValue::get(I.getContext(), ValueAsMetadata::get(V)); }; - auto applyOffset = [&](DbgInfoIntrinsic *DII, uint64_t Offset) { + auto doSalvage = [&](DbgInfoIntrinsic *DII, SmallVectorImpl &Ops) { auto *DIExpr = DII->getExpression(); - DIExpr = DIExpression::prepend(DIExpr, DIExpression::NoDeref, Offset, - DIExpression::NoDeref, - DIExpression::WithStackValue); + DIExpr = DIExpression::doPrepend(DIExpr, Ops, + DIExpression::WithStackValue); DII->setOperand(0, wrapMD(I.getOperand(0))); DII->setOperand(2, MetadataAsValue::get(I.getContext(), DIExpr)); DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); }; + auto applyOffset = [&](DbgInfoIntrinsic *DII, uint64_t Offset) { + SmallVector Ops; + DIExpression::appendOffset(Ops, Offset); + doSalvage(DII, Ops); + }; + + auto applyOps = [&](DbgInfoIntrinsic *DII, + std::initializer_list Opcodes) { + SmallVector Ops(Opcodes); + doSalvage(DII, Ops); + }; + if (isa(&I) || isa(&I)) { // Bitcasts are entirely irrelevant for debug info. Rewrite dbg.value, // dbg.addr, and dbg.declare to use the cast's source. @@ -1525,11 +1536,17 @@ for (auto *DII : DbgUsers) applyOffset(DII, Offset.getSExtValue()); } else if (auto *BI = dyn_cast(&I)) { - if (BI->getOpcode() == Instruction::Add) + if (BI->getOpcode() == Instruction::Add || + BI->getOpcode() == Instruction::Or) if (auto *ConstInt = dyn_cast(I.getOperand(1))) - if (ConstInt->getBitWidth() <= 64) + if (ConstInt->getBitWidth() <= 64) { + uint64_t Val = ConstInt->getSExtValue(); for (auto *DII : DbgUsers) - applyOffset(DII, ConstInt->getSExtValue()); + if (BI->getOpcode() == Instruction::Add) + applyOffset(DII, Val); + else if (BI->getOpcode() == Instruction::Or) + applyOps(DII, {dwarf::DW_OP_constu, Val, dwarf::DW_OP_or}); + } } else if (isa(&I)) { MetadataAsValue *AddrMD = wrapMD(I.getOperand(0)); for (auto *DII : DbgUsers) { Index: llvm/trunk/test/Transforms/InstCombine/debuginfo-dce-or.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/debuginfo-dce-or.ll +++ llvm/trunk/test/Transforms/InstCombine/debuginfo-dce-or.ll @@ -0,0 +1,44 @@ +; RUN: opt -instcombine %s -o - -S | FileCheck %s + +source_filename = "test.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux" + +define void @salvage_or(i64 %context) !dbg !9 { +entry: + %0 = or i64 %context, 256, !dbg !18 +; CHECK: call void @llvm.dbg.value(metadata i64 %context, +; CHECK-SAME: metadata !DIExpression(DW_OP_constu, 256, DW_OP_or, DW_OP_stack_value)) + call void @llvm.dbg.value(metadata i64 %0, metadata !14, metadata !16), !dbg !19 + ret void, !dbg !20 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) #0 + +attributes #0 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 7.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3) +!1 = !DIFile(filename: "test.c", directory: "/") +!2 = !{} +!3 = !{} +!4 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!5 = !{i32 2, !"Dwarf Version", i32 4} +!6 = !{i32 2, !"Debug Info Version", i32 3} +!7 = !{i32 1, !"PIC Level", i32 2} +!8 = !{!"clang version 7.0.0"} +!9 = distinct !DISubprogram(name: "salvage_or", scope: !1, file: !1, line: 91, type: !10, isLocal: false, isDefinition: true, scopeLine: 93, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12) +!10 = !DISubroutineType(types: !11) +!11 = !{!4} +!12 = !{!13, !14} +!13 = !DILocalVariable(name: "context", arg: 2, scope: !9, file: !1, line: 92, type: !4) +!14 = !DILocalVariable(name: "master", scope: !9, file: !1, line: 94, type: !4) +!15 = !{} +!16 = !DIExpression() +!17 = !DILexicalBlockFile(scope: !9, file: !1, discriminator: 2) +!18 = !DILocation(line: 94, column: 18, scope: !17) +!19 = !DILocation(line: 94, column: 18, scope: !9) +!20 = !DILocation(line: 126, column: 1, scope: !9)