diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -536,6 +536,10 @@ /// (or DBG_PHI). void finalizeDebugInstrRefs(); + /// Returns true if the function's variable locations should be tracked with + /// instruction referencing. + bool useDebugInstrRef() const; + MachineFunction(Function &F, const LLVMTargetMachine &Target, const TargetSubtargetInfo &STI, unsigned FunctionNum, MachineModuleInfo &MMI); diff --git a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/LiveDebugValues.cpp @@ -99,12 +99,7 @@ bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) { if (!TheImpl) { TPC = getAnalysisIfAvailable(); - - bool InstrRefBased = false; - if (TPC) { - auto &TM = TPC->getTM(); - InstrRefBased = TM.Options.ValueTrackingVariableLocations; - } + bool InstrRefBased = MF.useDebugInstrRef(); // Allow the user to force selection of InstrRef LDV. InstrRefBased |= ForceInstrRefLDV; diff --git a/llvm/lib/CodeGen/LiveDebugVariables.cpp b/llvm/lib/CodeGen/LiveDebugVariables.cpp --- a/llvm/lib/CodeGen/LiveDebugVariables.cpp +++ b/llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -1314,12 +1314,7 @@ // Have we been asked to track variable locations using instruction // referencing? - bool InstrRef = false; - auto *TPC = getAnalysisIfAvailable(); - if (TPC) { - auto &TM = TPC->getTM(); - InstrRef = TM.Options.ValueTrackingVariableLocations; - } + bool InstrRef = mf.useDebugInstrRef(); if (!pImpl) pImpl = new LDVImpl(this); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -1174,7 +1174,7 @@ MI.getOperand(0).setIsDebug(); }; - if (!getTarget().Options.ValueTrackingVariableLocations) + if (!useDebugInstrRef()) return; for (auto &MBB : *this) { @@ -1221,6 +1221,24 @@ } } +bool MachineFunction::useDebugInstrRef() const { + // Disable instr-ref at -O0: it's very slow (in compile time). We can still + // have optimized code inlined into this unoptimized code, however with + // fewer and less aggressive optimizations happening, coverage and accuracy + // should not suffer. + if (getTarget().getOptLevel() == CodeGenOpt::None) + return false; + + // Don't use instr-ref if this function is marked optnone. + if (F.hasFnAttribute(Attribute::OptimizeNone)) + return false; + + if (getTarget().Options.ValueTrackingVariableLocations) + return true; + + return false; +} + /// \} //===----------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1264,7 +1264,7 @@ // If using instruction referencing, mutate this into a DBG_INSTR_REF, // to be later patched up by finalizeDebugInstrRefs. Tack a deref onto // the expression, we don't have an "indirect" flag in DBG_INSTR_REF. - if (TM.Options.ValueTrackingVariableLocations && Op->isReg()) { + if (FuncInfo.MF->useDebugInstrRef() && Op->isReg()) { Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); Builder->getOperand(1).ChangeToImmediate(0); auto *NewExpr = @@ -1323,7 +1323,7 @@ // If using instruction referencing, mutate this into a DBG_INSTR_REF, // to be later patched up by finalizeDebugInstrRefs. - if (TM.Options.ValueTrackingVariableLocations) { + if (FuncInfo.MF->useDebugInstrRef()) { Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); Builder->getOperand(1).ChangeToImmediate(0); } diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp --- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -1340,5 +1340,5 @@ TRI(MF->getSubtarget().getRegisterInfo()), TLI(MF->getSubtarget().getTargetLowering()), MBB(mbb), InsertPos(insertpos) { - EmitDebugInstrRefs = TM.Options.ValueTrackingVariableLocations; + EmitDebugInstrRefs = MF->useDebugInstrRef(); } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5515,7 +5515,7 @@ // we've been asked to pursue. auto MakeVRegDbgValue = [&](Register Reg, DIExpression *FragExpr, bool Indirect) { - if (Reg.isVirtual() && TM.Options.ValueTrackingVariableLocations) { + if (Reg.isVirtual() && MF.useDebugInstrRef()) { // For VRegs, in instruction referencing mode, create a DBG_INSTR_REF // pointing at the VReg, which will be patched up later. auto &Inst = TII->get(TargetOpcode::DBG_INSTR_REF); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -575,7 +575,7 @@ LiveInMap.insert(LI); // Insert DBG_VALUE instructions for function arguments to the entry block. - bool InstrRef = TM.Options.ValueTrackingVariableLocations; + bool InstrRef = MF->useDebugInstrRef(); for (unsigned i = 0, e = FuncInfo->ArgDbgValues.size(); i != e; ++i) { MachineInstr *MI = FuncInfo->ArgDbgValues[e - i - 1]; assert(MI->getOpcode() != TargetOpcode::DBG_VALUE_LIST && diff --git a/llvm/test/DebugInfo/X86/instr-ref-opt-levels.ll b/llvm/test/DebugInfo/X86/instr-ref-opt-levels.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/instr-ref-opt-levels.ll @@ -0,0 +1,73 @@ +; RUN: llc -mtriple=x86_64-- %s -o - -O0 -stop-before=finalize-isel \ +; RUN: -experimental-debug-variable-locations \ +; RUN: | FileCheck %s --check-prefix=O0 --implicit-check-not=DBG_INSTR_REF +; RUN: llc -mtriple=x86_64-- %s -o - -O2 -stop-before=finalize-isel \ +; RUN: -experimental-debug-variable-locations \ +; RUN: | FileCheck %s --check-prefix=O2 --implicit-check-not=DBG_VALUE +; RUN: llc -mtriple=x86_64-- %s -o - -stop-before=finalize-isel \ +; RUN: -fast-isel -experimental-debug-variable-locations \ +; RUN: | FileCheck %s --check-prefix=FASTISEL --implicit-check-not=DBG_VALUE + +; Test that instruction-referencing variable locations are issued at -O2, but +; normal DBG_VALUEs are issued at -O0. This behaviour is desired as the former +; is slow when applied to unoptimized code. +; (Copy + pasted from ./dead-store-elimination-marks-undef.ll), + +; O0-LABEL: name: main +; O0: DBG_VALUE +; O0-LABEL: name: fn_optnone +; O0: DBG_VALUE + +; O2-LABEL: name: main +; O2: DBG_INSTR_REF +; O2-LABEL: name: fn_optnone +; O2: DBG_VALUE + +; FASTISEL-LABEL: name: main +; FASTISEL: DBG_INSTR_REF +; FASTISEL-LABEL: name: fn_optnone +; FASTISEL: DBG_VALUE + +@b = common dso_local local_unnamed_addr global i32 0, align 1 + +define dso_local i32 @main() local_unnamed_addr !dbg !7 { + %1 = alloca i32, align 4 + %2 = load i32, i32* @b, align 1, !dbg !13 + call void @llvm.dbg.value(metadata i32 %2, metadata !12, metadata !DIExpression()), !dbg !13 + store i32 %2, i32* %1, align 4, !dbg !13 + ret i32 0, !dbg !13 +} + +define dso_local i32 @fn_optnone() local_unnamed_addr #0 !dbg !27 { + %1 = alloca i32, align 4 + %2 = load i32, i32* @b, align 1, !dbg !33 + call void @llvm.dbg.value(metadata i32 %2, metadata !32, metadata !DIExpression()), !dbg !33 + store i32 %2, i32* %1, align 4, !dbg !33 + ret i32 0, !dbg !33 +} + +attributes #0 = {optnone noinline} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2, nameTableKind: None) +!1 = !DIFile(filename: "dead-store-elimination-marks-undef.ll", directory: "/temp/bz45080") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!6 = !{!"clang version 10.0.0"} +!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "l_2864", scope: !7, file: !1, line: 4, type: !10) +!13 = !DILocation(line: 5, column: 12, scope: !7) +!27 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !31) +!31 = !{!32} +!32 = !DILocalVariable(name: "l_2864", scope: !27, file: !1, line: 4, type: !10) +!33 = !DILocation(line: 5, column: 12, scope: !27)