aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/lib/CodeGen/GlobalISel/LostDebugLocObserver.cpp
blob: 6d606e5550f1a3534f62ee1a0c53fb8e6a0f706e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//===----- llvm/CodeGen/GlobalISel/LostDebugLocObserver.cpp -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// Tracks DebugLocs between checkpoints and verifies that they are transferred.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"

using namespace llvm;

#define LOC_DEBUG(X) DEBUG_WITH_TYPE(DebugType.str().c_str(), X)

void LostDebugLocObserver::analyzeDebugLocations() {
  if (LostDebugLocs.empty()) {
    LOC_DEBUG(dbgs() << ".. No debug info was present\n");
    return;
  }
  if (PotentialMIsForDebugLocs.empty()) {
    LOC_DEBUG(
        dbgs() << ".. No instructions to carry debug info (dead code?)\n");
    return;
  }

  LOC_DEBUG(dbgs() << ".. Searching " << PotentialMIsForDebugLocs.size()
                   << " instrs for " << LostDebugLocs.size() << " locations\n");
  SmallPtrSet<MachineInstr *, 4> FoundIn;
  for (MachineInstr *MI : PotentialMIsForDebugLocs) {
    if (!MI->getDebugLoc())
      continue;
    // Check this first in case there's a matching line-0 location on both input
    // and output.
    if (MI->getDebugLoc().getLine() == 0) {
      LOC_DEBUG(
          dbgs() << ".. Assuming line-0 location covers remainder (if any)\n");
      return;
    }
    if (LostDebugLocs.erase(MI->getDebugLoc())) {
      LOC_DEBUG(dbgs() << ".. .. found " << MI->getDebugLoc() << " in " << *MI);
      FoundIn.insert(MI);
      continue;
    }
  }
  if (LostDebugLocs.empty())
    return;

  NumLostDebugLocs += LostDebugLocs.size();
  LOC_DEBUG({
    dbgs() << ".. Lost locations:\n";
    for (const DebugLoc &Loc : LostDebugLocs) {
      dbgs() << ".. .. ";
      Loc.print(dbgs());
      dbgs() << "\n";
    }
    dbgs() << ".. MIs with matched locations:\n";
    for (MachineInstr *MI : FoundIn)
      if (PotentialMIsForDebugLocs.erase(MI))
        dbgs() << ".. .. " << *MI;
    dbgs() << ".. Remaining MIs with unmatched/no locations:\n";
    for (const MachineInstr *MI : PotentialMIsForDebugLocs)
      dbgs() << ".. .. " << *MI;
  });
}

void LostDebugLocObserver::checkpoint(bool CheckDebugLocs) {
  if (CheckDebugLocs)
    analyzeDebugLocations();
  PotentialMIsForDebugLocs.clear();
  LostDebugLocs.clear();
}

void LostDebugLocObserver::createdInstr(MachineInstr &MI) {
  PotentialMIsForDebugLocs.insert(&MI);
}

static bool irTranslatorNeverAddsLocations(unsigned Opcode) {
  switch (Opcode) {
  default:
    return false;
  case TargetOpcode::G_CONSTANT:
  case TargetOpcode::G_FCONSTANT:
  case TargetOpcode::G_IMPLICIT_DEF:
  case TargetOpcode::G_GLOBAL_VALUE:
    return true;
  }
}

void LostDebugLocObserver::erasingInstr(MachineInstr &MI) {
  if (irTranslatorNeverAddsLocations(MI.getOpcode()))
    return;

  PotentialMIsForDebugLocs.erase(&MI);
  if (MI.getDebugLoc())
    LostDebugLocs.insert(MI.getDebugLoc());
}

void LostDebugLocObserver::changingInstr(MachineInstr &MI) {
  if (irTranslatorNeverAddsLocations(MI.getOpcode()))
    return;

  PotentialMIsForDebugLocs.erase(&MI);
  if (MI.getDebugLoc())
    LostDebugLocs.insert(MI.getDebugLoc());
}

void LostDebugLocObserver::changedInstr(MachineInstr &MI) {
  PotentialMIsForDebugLocs.insert(&MI);
}