diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h @@ -655,6 +655,14 @@ const DbgValueProperties &Properties); }; +/// Types for recording sets of variable fragments that overlap. For a given +/// local variable, we record all other fragments of that variable that could +/// overlap it, to reduce search time. +using FragmentOfVar = + std::pair; +using OverlapMap = + DenseMap>; + /// Collection of DBG_VALUEs observed when traversing a block. Records each /// variable and the value the DBG_VALUE refers to. Requires the machine value /// location dataflow algorithm to have run already, so that values can be @@ -672,9 +680,12 @@ MapVector Vars; DenseMap Scopes; MachineBasicBlock *MBB = nullptr; + const OverlapMap &OverlappingFragments; + DbgValueProperties EmptyProperties; public: - VLocTracker() {} + VLocTracker(const OverlapMap &O, const DIExpression *EmptyExpr) + : OverlappingFragments(O), EmptyProperties(EmptyExpr, false) {} void defVar(const MachineInstr &MI, const DbgValueProperties &Properties, Optional ID) { @@ -689,6 +700,8 @@ if (!Result.second) Result.first->second = Rec; Scopes[Var] = MI.getDebugLoc().get(); + + considerOverlaps(Var, MI.getDebugLoc().get()); } void defVar(const MachineInstr &MI, const MachineOperand &MO) { @@ -704,16 +717,37 @@ if (!Result.second) Result.first->second = Rec; Scopes[Var] = MI.getDebugLoc().get(); + + considerOverlaps(Var, MI.getDebugLoc().get()); } -}; -/// Types for recording sets of variable fragments that overlap. For a given -/// local variable, we record all other fragments of that variable that could -/// overlap it, to reduce search time. -using FragmentOfVar = - std::pair; -using OverlapMap = - DenseMap>; + void considerOverlaps(const DebugVariable &Var, const DILocation *Loc) { + auto Overlaps = OverlappingFragments.find( + {Var.getVariable(), Var.getFragmentOrDefault()}); + if (Overlaps == OverlappingFragments.end()) + return; + + // Otherwise: terminate any overlapped variable locations. + for (auto FragmentInfo : Overlaps->second) { + // The "empty" fragment is stored as DebugVariable::DefaultFragment, so + // that it overlaps with everything, however its cannonical representation + // in a DebugVariable is as "None". + Optional OptFragmentInfo = FragmentInfo; + if (DebugVariable::isDefaultFragment(FragmentInfo)) + OptFragmentInfo = None; + + DebugVariable Overlapped(Var.getVariable(), OptFragmentInfo, + Var.getInlinedAt()); + DbgValue Rec = DbgValue(EmptyProperties, DbgValue::Undef); + + // Attempt insertion; overwrite if it's already mapped. + auto Result = Vars.insert(std::make_pair(Overlapped, Rec)); + if (!Result.second) + Result.first->second = Rec; + Scopes[Overlapped] = Loc; + } + } +}; // XXX XXX docs class InstrRefBasedLDV : public LDVImpl { diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -1657,9 +1657,10 @@ /// fragments of that DILocalVariable which overlap. This reduces work during /// the data-flow stage from "Find any overlapping fragments" to "Check if the /// known-to-overlap fragments are present". -/// \param MI A previously unprocessed DEBUG_VALUE instruction to analyze for +/// \param MI A previously unprocessed debug instruction to analyze for /// fragment usage. void InstrRefBasedLDV::accumulateFragmentMap(MachineInstr &MI) { + assert(MI.isDebugValue() || MI.isDebugRef()); DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); FragmentInfo ThisFragment = MIVar.getFragmentOrDefault(); @@ -1761,7 +1762,7 @@ for (auto &MI : MBB) { process(MI); // Also accumulate fragment map. - if (MI.isDebugValue()) + if (MI.isDebugValue() || MI.isDebugRef()) accumulateFragmentMap(MI); // Create a map from the instruction number (if present) to the @@ -2929,7 +2930,7 @@ ++MaxNumBlocks; MLocTransfer.resize(MaxNumBlocks); - vlocs.resize(MaxNumBlocks); + vlocs.resize(MaxNumBlocks, VLocTracker(OverlapFragments, EmptyExpr)); SavedLiveIns.resize(MaxNumBlocks); initialSetup(MF); @@ -3074,6 +3075,8 @@ BBNumToRPO.clear(); DebugInstrNumToInstr.clear(); DebugPHINumToValue.clear(); + OverlapFragments.clear(); + SeenFragments.clear(); return Changed; } diff --git a/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir b/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir --- a/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir +++ b/llvm/test/DebugInfo/MIR/X86/live-debug-values-fragments.mir @@ -1,4 +1,4 @@ -# RUN: llc %s -o - -run-pass=livedebugvalues -experimental-debug-variable-locations=false | FileCheck %s +# RUN: llc %s -o - -run-pass=livedebugvalues -experimental-debug-variable-locations=true | FileCheck %s # # The first func tests that, for two independent variable fragments defined in # blocks 1 and 2, _both_ their locations are propagated into the exit block. @@ -15,10 +15,10 @@ # # CHECK-LABEL: foo # CHECK-LABEL: bb.3.bb3: -# CHECK: DBG_VALUE $ebx, $noreg, !{{[0-9]+}}, -# CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 32, 32) -# CHECK-NEXT: DBG_VALUE $eax, $noreg, !{{[0-9]+}}, +# CHECK: DBG_VALUE $ecx, $noreg, !{{[0-9]+}}, # CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 0, 32) +# CHECK-NEXT: DBG_VALUE $ebx, $noreg, !{{[0-9]+}}, +# CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 32, 32) # CHECK-NEXT: XOR32rr # CHECK-NEXT: RET64 # @@ -37,7 +37,7 @@ # CHECK-LABEL: bb.2.bb2: # CHECK-NOT: DBG_VALUE -# CHECK: DBG_VALUE $ax, $noreg, !{{[0-9]+}}, +# CHECK: DBG_VALUE $cx, $noreg, !{{[0-9]+}}, # CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 8, 16) # CHECK-NEXT: MOV32rr # CHECK-NEXT: ADD32ri8 @@ -46,10 +46,10 @@ # CHECK-NEXT: JMP_1 # CHECK-LABEL: bb.3.bb3: -# CHECK: DBG_VALUE $ebx, $noreg, !{{[0-9]+}}, -# CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 32, 32) -# CHECK-NEXT: DBG_VALUE $ax, $noreg, !{{[0-9]+}}, +# CHECK: DBG_VALUE $cx, $noreg, !{{[0-9]+}}, # CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 8, 16) +# CHECK-NEXT: DBG_VALUE $ebx, $noreg, !{{[0-9]+}}, +# CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 32, 32) # CHECK-NEXT: XOR32rr # CHECK-NEXT: RET64 diff --git a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp --- a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp +++ b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp @@ -49,6 +49,7 @@ DILocalVariable *FuncVariable; DIBasicType *LongInt; DIExpression *EmptyExpr; + LiveDebugValues::OverlapMap Overlaps; DebugLoc OutermostLoc, InBlockLoc, NotNestedBlockLoc, InlinedLoc; @@ -169,7 +170,7 @@ void addVTracker() { ASSERT_TRUE(LDV); - VTracker = std::make_unique(); + VTracker = std::make_unique(Overlaps, EmptyExpr); LDV->VTracker = &*VTracker; } @@ -2515,7 +2516,7 @@ AssignBlocks.insert(MBB0); SmallVector VLocs; - VLocs.resize(1); + VLocs.resize(1, VLocTracker(Overlaps, EmptyExpr)); InstrRefBasedLDV::LiveInsT Output; @@ -2579,7 +2580,7 @@ AssignBlocks.insert(MBB3); SmallVector VLocs; - VLocs.resize(4); + VLocs.resize(4, VLocTracker(Overlaps, EmptyExpr)); InstrRefBasedLDV::LiveInsT Output; @@ -2792,7 +2793,7 @@ AssignBlocks.insert(MBB2); SmallVector VLocs; - VLocs.resize(3); + VLocs.resize(3, VLocTracker(Overlaps, EmptyExpr)); InstrRefBasedLDV::LiveInsT Output; @@ -3048,7 +3049,7 @@ AssignBlocks.insert(MBB4); SmallVector VLocs; - VLocs.resize(5); + VLocs.resize(5, VLocTracker(Overlaps, EmptyExpr)); InstrRefBasedLDV::LiveInsT Output;