mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
463930d1cb
With this patch we're now accounting for two more cases which should be considered 'valid throughout': First, where RangeEnd is ScopeEnd. Second, where RangeEnd comes before ScopeEnd when including meta instructions, but are both preceded by the same non-meta instruction. CTMark shows a geomean binary size reduction of 1.5% for RelWithDebInfo builds. `llvm-locstats` (using D85636) shows a very small variable location coverage change in 2 of 10 binaries, but it is in the order of 10s of bytes which lines up with my expectations. I've added a test which checks both of these new cases. The first check in the test isn't strictly necessary for this patch. But I'm not sure that it is explicitly tested anywhere else, and is useful for the final patch in the series. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D86151
154 lines
5.3 KiB
C++
154 lines
5.3 KiB
C++
//===- llvm/CodeGen/DbgEntityHistoryCalculator.h ----------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H
|
|
#define LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H
|
|
|
|
#include "llvm/ADT/MapVector.h"
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/CodeGen/LexicalScopes.h"
|
|
#include <utility>
|
|
|
|
namespace llvm {
|
|
|
|
class DILocalVariable;
|
|
class DILocation;
|
|
class DINode;
|
|
class MachineFunction;
|
|
class MachineInstr;
|
|
class TargetRegisterInfo;
|
|
|
|
/// Record instruction ordering so we can query their relative positions within
|
|
/// a function. Meta instructions are given the same ordinal as the preceding
|
|
/// non-meta instruction. Class state is invalid if MF is modified after
|
|
/// calling initialize.
|
|
class InstructionOrdering {
|
|
public:
|
|
void initialize(const MachineFunction &MF);
|
|
void clear() { InstNumberMap.clear(); }
|
|
|
|
/// Check if instruction \p A comes before \p B, where \p A and \p B both
|
|
/// belong to the MachineFunction passed to initialize().
|
|
bool isBefore(const MachineInstr *A, const MachineInstr *B) const;
|
|
|
|
private:
|
|
/// Each instruction is assigned an order number.
|
|
DenseMap<const MachineInstr *, unsigned> InstNumberMap;
|
|
};
|
|
|
|
/// For each user variable, keep a list of instruction ranges where this
|
|
/// variable is accessible. The variables are listed in order of appearance.
|
|
class DbgValueHistoryMap {
|
|
public:
|
|
/// Index in the entry vector.
|
|
typedef size_t EntryIndex;
|
|
|
|
/// Special value to indicate that an entry is valid until the end of the
|
|
/// function.
|
|
static const EntryIndex NoEntry = std::numeric_limits<EntryIndex>::max();
|
|
|
|
/// Specifies a change in a variable's debug value history.
|
|
///
|
|
/// There exist two types of entries:
|
|
///
|
|
/// * Debug value entry:
|
|
///
|
|
/// A new debug value becomes live. If the entry's \p EndIndex is \p NoEntry,
|
|
/// the value is valid until the end of the function. For other values, the
|
|
/// index points to the entry in the entry vector that ends this debug
|
|
/// value. The ending entry can either be an overlapping debug value, or
|
|
/// an instruction that clobbers the value.
|
|
///
|
|
/// * Clobbering entry:
|
|
///
|
|
/// This entry's instruction clobbers one or more preceding
|
|
/// register-described debug values that have their end index
|
|
/// set to this entry's position in the entry vector.
|
|
class Entry {
|
|
friend DbgValueHistoryMap;
|
|
|
|
public:
|
|
enum EntryKind { DbgValue, Clobber };
|
|
|
|
Entry(const MachineInstr *Instr, EntryKind Kind)
|
|
: Instr(Instr, Kind), EndIndex(NoEntry) {}
|
|
|
|
const MachineInstr *getInstr() const { return Instr.getPointer(); }
|
|
EntryIndex getEndIndex() const { return EndIndex; }
|
|
EntryKind getEntryKind() const { return Instr.getInt(); }
|
|
|
|
bool isClobber() const { return getEntryKind() == Clobber; }
|
|
bool isDbgValue() const { return getEntryKind() == DbgValue; }
|
|
bool isClosed() const { return EndIndex != NoEntry; }
|
|
|
|
void endEntry(EntryIndex EndIndex);
|
|
|
|
private:
|
|
PointerIntPair<const MachineInstr *, 1, EntryKind> Instr;
|
|
EntryIndex EndIndex;
|
|
};
|
|
using Entries = SmallVector<Entry, 4>;
|
|
using InlinedEntity = std::pair<const DINode *, const DILocation *>;
|
|
using EntriesMap = MapVector<InlinedEntity, Entries>;
|
|
|
|
private:
|
|
EntriesMap VarEntries;
|
|
|
|
public:
|
|
bool startDbgValue(InlinedEntity Var, const MachineInstr &MI,
|
|
EntryIndex &NewIndex);
|
|
EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI);
|
|
|
|
Entry &getEntry(InlinedEntity Var, EntryIndex Index) {
|
|
auto &Entries = VarEntries[Var];
|
|
return Entries[Index];
|
|
}
|
|
|
|
/// Drop location ranges which exist entirely outside each variable's scope.
|
|
void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes,
|
|
const InstructionOrdering &Ordering);
|
|
bool empty() const { return VarEntries.empty(); }
|
|
void clear() { VarEntries.clear(); }
|
|
EntriesMap::const_iterator begin() const { return VarEntries.begin(); }
|
|
EntriesMap::const_iterator end() const { return VarEntries.end(); }
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
LLVM_DUMP_METHOD void dump() const;
|
|
#endif
|
|
};
|
|
|
|
/// For each inlined instance of a source-level label, keep the corresponding
|
|
/// DBG_LABEL instruction. The DBG_LABEL instruction could be used to generate
|
|
/// a temporary (assembler) label before it.
|
|
class DbgLabelInstrMap {
|
|
public:
|
|
using InlinedEntity = std::pair<const DINode *, const DILocation *>;
|
|
using InstrMap = MapVector<InlinedEntity, const MachineInstr *>;
|
|
|
|
private:
|
|
InstrMap LabelInstr;
|
|
|
|
public:
|
|
void addInstr(InlinedEntity Label, const MachineInstr &MI);
|
|
|
|
bool empty() const { return LabelInstr.empty(); }
|
|
void clear() { LabelInstr.clear(); }
|
|
InstrMap::const_iterator begin() const { return LabelInstr.begin(); }
|
|
InstrMap::const_iterator end() const { return LabelInstr.end(); }
|
|
};
|
|
|
|
void calculateDbgEntityHistory(const MachineFunction *MF,
|
|
const TargetRegisterInfo *TRI,
|
|
DbgValueHistoryMap &DbgValues,
|
|
DbgLabelInstrMap &DbgLabels);
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H
|