1 | //===----- llvm/CodeGen/GlobalISel/LostDebugLocObserver.cpp -----*- C++ -*-===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | /// Tracks DebugLocs between checkpoints and verifies that they are transferred. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h" |
14 | |
15 | using namespace llvm; |
16 | |
17 | #define LOC_DEBUG(X) DEBUG_WITH_TYPE(DebugType.str().c_str(), X) |
18 | |
19 | void LostDebugLocObserver::analyzeDebugLocations() { |
20 | if (LostDebugLocs.empty()) { |
21 | LOC_DEBUG(dbgs() << ".. No debug info was present\n"); |
22 | return; |
23 | } |
24 | if (PotentialMIsForDebugLocs.empty()) { |
25 | LOC_DEBUG( |
26 | dbgs() << ".. No instructions to carry debug info (dead code?)\n"); |
27 | return; |
28 | } |
29 | |
30 | LOC_DEBUG(dbgs() << ".. Searching "<< PotentialMIsForDebugLocs.size() |
31 | << " instrs for "<< LostDebugLocs.size() << " locations\n"); |
32 | SmallPtrSet<MachineInstr *, 4> FoundIn; |
33 | for (MachineInstr *MI : PotentialMIsForDebugLocs) { |
34 | if (!MI->getDebugLoc()) |
35 | continue; |
36 | // Check this first in case there's a matching line-0 location on both input |
37 | // and output. |
38 | if (MI->getDebugLoc().getLine() == 0) { |
39 | LOC_DEBUG( |
40 | dbgs() << ".. Assuming line-0 location covers remainder (if any)\n"); |
41 | return; |
42 | } |
43 | if (LostDebugLocs.erase(V: MI->getDebugLoc())) { |
44 | LOC_DEBUG(dbgs() << ".. .. found "<< MI->getDebugLoc() << " in "<< *MI); |
45 | FoundIn.insert(Ptr: MI); |
46 | continue; |
47 | } |
48 | } |
49 | if (LostDebugLocs.empty()) |
50 | return; |
51 | |
52 | NumLostDebugLocs += LostDebugLocs.size(); |
53 | LOC_DEBUG({ |
54 | dbgs() << ".. Lost locations:\n"; |
55 | for (const DebugLoc &Loc : LostDebugLocs) { |
56 | dbgs() << ".. .. "; |
57 | Loc.print(dbgs()); |
58 | dbgs() << "\n"; |
59 | } |
60 | dbgs() << ".. MIs with matched locations:\n"; |
61 | for (MachineInstr *MI : FoundIn) |
62 | if (PotentialMIsForDebugLocs.erase(MI)) |
63 | dbgs() << ".. .. "<< *MI; |
64 | dbgs() << ".. Remaining MIs with unmatched/no locations:\n"; |
65 | for (const MachineInstr *MI : PotentialMIsForDebugLocs) |
66 | dbgs() << ".. .. "<< *MI; |
67 | }); |
68 | } |
69 | |
70 | void LostDebugLocObserver::checkpoint(bool CheckDebugLocs) { |
71 | if (CheckDebugLocs) |
72 | analyzeDebugLocations(); |
73 | PotentialMIsForDebugLocs.clear(); |
74 | LostDebugLocs.clear(); |
75 | } |
76 | |
77 | void LostDebugLocObserver::createdInstr(MachineInstr &MI) { |
78 | PotentialMIsForDebugLocs.insert(Ptr: &MI); |
79 | } |
80 | |
81 | static bool irTranslatorNeverAddsLocations(unsigned Opcode) { |
82 | switch (Opcode) { |
83 | default: |
84 | return false; |
85 | case TargetOpcode::G_CONSTANT: |
86 | case TargetOpcode::G_FCONSTANT: |
87 | case TargetOpcode::G_IMPLICIT_DEF: |
88 | case TargetOpcode::G_GLOBAL_VALUE: |
89 | return true; |
90 | } |
91 | } |
92 | |
93 | void LostDebugLocObserver::erasingInstr(MachineInstr &MI) { |
94 | if (irTranslatorNeverAddsLocations(Opcode: MI.getOpcode())) |
95 | return; |
96 | |
97 | PotentialMIsForDebugLocs.erase(Ptr: &MI); |
98 | if (MI.getDebugLoc()) |
99 | LostDebugLocs.insert(V: MI.getDebugLoc()); |
100 | } |
101 | |
102 | void LostDebugLocObserver::changingInstr(MachineInstr &MI) { |
103 | if (irTranslatorNeverAddsLocations(Opcode: MI.getOpcode())) |
104 | return; |
105 | |
106 | PotentialMIsForDebugLocs.erase(Ptr: &MI); |
107 | if (MI.getDebugLoc()) |
108 | LostDebugLocs.insert(V: MI.getDebugLoc()); |
109 | } |
110 | |
111 | void LostDebugLocObserver::changedInstr(MachineInstr &MI) { |
112 | PotentialMIsForDebugLocs.insert(Ptr: &MI); |
113 | } |
114 |