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
15using namespace llvm;
16
17#define LOC_DEBUG(X) DEBUG_WITH_TYPE(DebugType.str().c_str(), X)
18
19void 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
70void LostDebugLocObserver::checkpoint(bool CheckDebugLocs) {
71 if (CheckDebugLocs)
72 analyzeDebugLocations();
73 PotentialMIsForDebugLocs.clear();
74 LostDebugLocs.clear();
75}
76
77void LostDebugLocObserver::createdInstr(MachineInstr &MI) {
78 PotentialMIsForDebugLocs.insert(Ptr: &MI);
79}
80
81static 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
93void 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
102void 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
111void LostDebugLocObserver::changedInstr(MachineInstr &MI) {
112 PotentialMIsForDebugLocs.insert(Ptr: &MI);
113}
114