blob: 6d606e5550f1a3534f62ee1a0c53fb8e6a0f706e [file] [log] [blame]
//===----- 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);
}