Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -1463,6 +1463,12 @@ case dwarf::DW_OP_push_object_address: case dwarf::DW_OP_over: case dwarf::DW_OP_consts: + case dwarf::DW_OP_eq: + case dwarf::DW_OP_ne: + case dwarf::DW_OP_gt: + case dwarf::DW_OP_ge: + case dwarf::DW_OP_lt: + case dwarf::DW_OP_le: break; } } Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -1982,6 +1982,29 @@ } } +uint64_t getDwarfOpForIcmpPred(CmpInst::Predicate Pred) { + switch (Pred) { + case CmpInst::ICMP_EQ: + return dwarf::DW_OP_eq; + case CmpInst::ICMP_NE: + return dwarf::DW_OP_ne; + case CmpInst::ICMP_UGT: + case CmpInst::ICMP_SGT: + return dwarf::DW_OP_gt; + case CmpInst::ICMP_UGE: + case CmpInst::ICMP_SGE: + return dwarf::DW_OP_ge; + case CmpInst::ICMP_ULT: + case CmpInst::ICMP_SLT: + return dwarf::DW_OP_lt; + case CmpInst::ICMP_ULE: + case CmpInst::ICMP_SLE: + return dwarf::DW_OP_le; + default: + return 0; + } +} + Value *getSalvageOpsForBinOp(BinaryOperator *BI, uint64_t CurrentLocOps, SmallVectorImpl &Opcodes, SmallVectorImpl &AdditionalValues) { @@ -2021,6 +2044,35 @@ return BI->getOperand(0); } +Value *getSalvageOpsForIcmpOp(ICmpInst *Icmp, uint64_t CurrentLocOps, + SmallVectorImpl &Opcodes, + SmallVectorImpl &AdditionalValues) { + // Only salvage debug info for IcmpInst that have at least one constant + // integer operand, to prevent the explosion of the DIExpression. + auto *ConstInt = dyn_cast(Icmp->getOperand(1)); + if (!ConstInt) + return nullptr; + // Values wider than 64 bits cannot be represented within a DIExpression. + if (ConstInt->getBitWidth() > 64) + return nullptr; + + // Add salvaged binary operator to expression stack, if it has a valid + // representation in a DIExpression. + uint64_t DwarfIcmpOp = getDwarfOpForIcmpPred(Icmp->getPredicate()); + if (!DwarfIcmpOp) + return nullptr; + + if (!CurrentLocOps) { + Opcodes.append({dwarf::DW_OP_LLVM_arg, 0}); + CurrentLocOps = 1; + } + Opcodes.append({dwarf::DW_OP_LLVM_arg, CurrentLocOps}); + AdditionalValues.push_back(ConstInt); + + Opcodes.push_back(DwarfIcmpOp); + return Icmp->getOperand(0); +} + Value *llvm::salvageDebugInfoImpl(Instruction &I, uint64_t CurrentLocOps, SmallVectorImpl &Ops, SmallVectorImpl &AdditionalValues) { @@ -2060,6 +2112,8 @@ return getSalvageOpsForGEP(GEP, DL, CurrentLocOps, Ops, AdditionalValues); if (auto *BI = dyn_cast(&I)) return getSalvageOpsForBinOp(BI, CurrentLocOps, Ops, AdditionalValues); + if (auto *IC = dyn_cast(&I)) + return getSalvageOpsForIcmpOp(IC, CurrentLocOps, Ops, AdditionalValues); // *Not* to do: we should not attempt to salvage load instructions, // because the validity and lifetime of a dbg.value containing Index: llvm/test/DebugInfo/salvage-icmp.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/salvage-icmp.ll @@ -0,0 +1,43 @@ +; RUN: opt %s -passes=dce -S | FileCheck %s + +; Tests the results of salvaging variadic dbg.values that use the same SSA value +; multiple times. + +; CHECK: call void @llvm.dbg.value(metadata !DIArgList(i32 %a, i32 0), +; CHECK-SAME: ![[VAR_C:[0-9]+]], +; CHECK-SAME: !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_ne, DW_OP_stack_value)) + +; CHECK: ![[VAR_C]] = !DILocalVariable(name: "c" + +define i32 @"?multiply@@YAHHH@Z"(i32 %a, i32 %b) !dbg !8 { +entry: + %icmp1 = icmp ne i32 %a, 0, !dbg !15 + call void @llvm.dbg.value(metadata !DIArgList(i1 %icmp1), 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@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)