2019-01-16 01:40:37 +01:00
|
|
|
//===- CSEInfo.cpp ------------------------------===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// 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
|
2019-01-16 01:40:37 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
Sink all InitializePasses.h includes
This file lists every pass in LLVM, and is included by Pass.h, which is
very popular. Every time we add, remove, or rename a pass in LLVM, it
caused lots of recompilation.
I found this fact by looking at this table, which is sorted by the
number of times a file was changed over the last 100,000 git commits
multiplied by the number of object files that depend on it in the
current checkout:
recompiles touches affected_files header
342380 95 3604 llvm/include/llvm/ADT/STLExtras.h
314730 234 1345 llvm/include/llvm/InitializePasses.h
307036 118 2602 llvm/include/llvm/ADT/APInt.h
213049 59 3611 llvm/include/llvm/Support/MathExtras.h
170422 47 3626 llvm/include/llvm/Support/Compiler.h
162225 45 3605 llvm/include/llvm/ADT/Optional.h
158319 63 2513 llvm/include/llvm/ADT/Triple.h
140322 39 3598 llvm/include/llvm/ADT/StringRef.h
137647 59 2333 llvm/include/llvm/Support/Error.h
131619 73 1803 llvm/include/llvm/Support/FileSystem.h
Before this change, touching InitializePasses.h would cause 1345 files
to recompile. After this change, touching it only causes 550 compiles in
an incremental rebuild.
Reviewers: bkramer, asbirlea, bollu, jdoerfert
Differential Revision: https://reviews.llvm.org/D70211
2019-11-13 22:15:01 +01:00
|
|
|
#include "llvm/InitializePasses.h"
|
2021-04-21 16:00:30 +02:00
|
|
|
#include "llvm/Support/Error.h"
|
2019-01-16 01:40:37 +01:00
|
|
|
|
|
|
|
#define DEBUG_TYPE "cseinfo"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
char llvm::GISelCSEAnalysisWrapperPass::ID = 0;
|
Sink all InitializePasses.h includes
This file lists every pass in LLVM, and is included by Pass.h, which is
very popular. Every time we add, remove, or rename a pass in LLVM, it
caused lots of recompilation.
I found this fact by looking at this table, which is sorted by the
number of times a file was changed over the last 100,000 git commits
multiplied by the number of object files that depend on it in the
current checkout:
recompiles touches affected_files header
342380 95 3604 llvm/include/llvm/ADT/STLExtras.h
314730 234 1345 llvm/include/llvm/InitializePasses.h
307036 118 2602 llvm/include/llvm/ADT/APInt.h
213049 59 3611 llvm/include/llvm/Support/MathExtras.h
170422 47 3626 llvm/include/llvm/Support/Compiler.h
162225 45 3605 llvm/include/llvm/ADT/Optional.h
158319 63 2513 llvm/include/llvm/ADT/Triple.h
140322 39 3598 llvm/include/llvm/ADT/StringRef.h
137647 59 2333 llvm/include/llvm/Support/Error.h
131619 73 1803 llvm/include/llvm/Support/FileSystem.h
Before this change, touching InitializePasses.h would cause 1345 files
to recompile. After this change, touching it only causes 550 compiles in
an incremental rebuild.
Reviewers: bkramer, asbirlea, bollu, jdoerfert
Differential Revision: https://reviews.llvm.org/D70211
2019-11-13 22:15:01 +01:00
|
|
|
GISelCSEAnalysisWrapperPass::GISelCSEAnalysisWrapperPass()
|
|
|
|
: MachineFunctionPass(ID) {
|
|
|
|
initializeGISelCSEAnalysisWrapperPassPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
2019-01-16 01:40:37 +01:00
|
|
|
INITIALIZE_PASS_BEGIN(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
|
|
|
|
"Analysis containing CSE Info", false, true)
|
|
|
|
INITIALIZE_PASS_END(GISelCSEAnalysisWrapperPass, DEBUG_TYPE,
|
|
|
|
"Analysis containing CSE Info", false, true)
|
|
|
|
|
|
|
|
/// -------- UniqueMachineInstr -------------//
|
|
|
|
|
|
|
|
void UniqueMachineInstr::Profile(FoldingSetNodeID &ID) {
|
|
|
|
GISelInstProfileBuilder(ID, MI->getMF()->getRegInfo()).addNodeID(MI);
|
|
|
|
}
|
|
|
|
/// -----------------------------------------
|
|
|
|
|
2019-04-15 06:53:46 +02:00
|
|
|
/// --------- CSEConfigFull ---------- ///
|
|
|
|
bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
|
2019-01-16 01:40:37 +01:00
|
|
|
switch (Opc) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case TargetOpcode::G_ADD:
|
|
|
|
case TargetOpcode::G_AND:
|
|
|
|
case TargetOpcode::G_ASHR:
|
|
|
|
case TargetOpcode::G_LSHR:
|
|
|
|
case TargetOpcode::G_MUL:
|
|
|
|
case TargetOpcode::G_OR:
|
|
|
|
case TargetOpcode::G_SHL:
|
|
|
|
case TargetOpcode::G_SUB:
|
|
|
|
case TargetOpcode::G_XOR:
|
|
|
|
case TargetOpcode::G_UDIV:
|
|
|
|
case TargetOpcode::G_SDIV:
|
|
|
|
case TargetOpcode::G_UREM:
|
|
|
|
case TargetOpcode::G_SREM:
|
|
|
|
case TargetOpcode::G_CONSTANT:
|
|
|
|
case TargetOpcode::G_FCONSTANT:
|
2020-02-04 04:49:00 +01:00
|
|
|
case TargetOpcode::G_IMPLICIT_DEF:
|
2019-01-16 01:40:37 +01:00
|
|
|
case TargetOpcode::G_ZEXT:
|
|
|
|
case TargetOpcode::G_SEXT:
|
|
|
|
case TargetOpcode::G_ANYEXT:
|
|
|
|
case TargetOpcode::G_UNMERGE_VALUES:
|
|
|
|
case TargetOpcode::G_TRUNC:
|
[globalisel] Rename G_GEP to G_PTR_ADD
Summary:
G_GEP is rather poorly named. It's a simple pointer+scalar addition and
doesn't support any of the complexities of getelementptr. I therefore
propose that we rename it. There's a G_PTR_MASK so let's follow that
convention and go with G_PTR_ADD
Reviewers: volkan, aditya_nandakumar, bogner, rovka, arsenm
Subscribers: sdardis, jvesely, wdng, nhaehnle, hiraditya, jrtc27, atanasyan, arphaman, Petar.Avramovic, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69734
2019-11-01 21:18:00 +01:00
|
|
|
case TargetOpcode::G_PTR_ADD:
|
2020-07-18 01:03:20 +02:00
|
|
|
case TargetOpcode::G_EXTRACT:
|
2019-01-16 01:40:37 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc) {
|
2020-02-04 04:49:00 +01:00
|
|
|
return Opc == TargetOpcode::G_CONSTANT || Opc == TargetOpcode::G_IMPLICIT_DEF;
|
2019-01-16 01:40:37 +01:00
|
|
|
}
|
2019-04-15 06:53:46 +02:00
|
|
|
|
|
|
|
std::unique_ptr<CSEConfigBase>
|
|
|
|
llvm::getStandardCSEConfigForOpt(CodeGenOpt::Level Level) {
|
|
|
|
std::unique_ptr<CSEConfigBase> Config;
|
|
|
|
if (Level == CodeGenOpt::None)
|
2019-08-15 17:54:37 +02:00
|
|
|
Config = std::make_unique<CSEConfigConstantOnly>();
|
2019-04-15 06:53:46 +02:00
|
|
|
else
|
2019-08-15 17:54:37 +02:00
|
|
|
Config = std::make_unique<CSEConfigFull>();
|
2019-04-15 06:53:46 +02:00
|
|
|
return Config;
|
|
|
|
}
|
|
|
|
|
2019-01-16 01:40:37 +01:00
|
|
|
/// -----------------------------------------
|
|
|
|
|
|
|
|
/// -------- GISelCSEInfo -------------//
|
|
|
|
void GISelCSEInfo::setMF(MachineFunction &MF) {
|
|
|
|
this->MF = &MF;
|
|
|
|
this->MRI = &MF.getRegInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
GISelCSEInfo::~GISelCSEInfo() {}
|
|
|
|
|
|
|
|
bool GISelCSEInfo::isUniqueMachineInstValid(
|
|
|
|
const UniqueMachineInstr &UMI) const {
|
|
|
|
// Should we check here and assert that the instruction has been fully
|
|
|
|
// constructed?
|
|
|
|
// FIXME: Any other checks required to be done here? Remove this method if
|
|
|
|
// none.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::invalidateUniqueMachineInstr(UniqueMachineInstr *UMI) {
|
|
|
|
bool Removed = CSEMap.RemoveNode(UMI);
|
|
|
|
(void)Removed;
|
|
|
|
assert(Removed && "Invalidation called on invalid UMI");
|
|
|
|
// FIXME: Should UMI be deallocated/destroyed?
|
|
|
|
}
|
|
|
|
|
|
|
|
UniqueMachineInstr *GISelCSEInfo::getNodeIfExists(FoldingSetNodeID &ID,
|
|
|
|
MachineBasicBlock *MBB,
|
|
|
|
void *&InsertPos) {
|
|
|
|
auto *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
if (Node) {
|
|
|
|
if (!isUniqueMachineInstValid(*Node)) {
|
|
|
|
invalidateUniqueMachineInstr(Node);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Node->MI->getParent() != MBB)
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return Node;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::insertNode(UniqueMachineInstr *UMI, void *InsertPos) {
|
|
|
|
handleRecordedInsts();
|
|
|
|
assert(UMI);
|
|
|
|
UniqueMachineInstr *MaybeNewNode = UMI;
|
|
|
|
if (InsertPos)
|
|
|
|
CSEMap.InsertNode(UMI, InsertPos);
|
|
|
|
else
|
|
|
|
MaybeNewNode = CSEMap.GetOrInsertNode(UMI);
|
|
|
|
if (MaybeNewNode != UMI) {
|
|
|
|
// A similar node exists in the folding set. Let's ignore this one.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert(InstrMapping.count(UMI->MI) == 0 &&
|
|
|
|
"This instruction should not be in the map");
|
|
|
|
InstrMapping[UMI->MI] = MaybeNewNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
UniqueMachineInstr *GISelCSEInfo::getUniqueInstrForMI(const MachineInstr *MI) {
|
|
|
|
assert(shouldCSE(MI->getOpcode()) && "Trying to CSE an unsupported Node");
|
|
|
|
auto *Node = new (UniqueInstrAllocator) UniqueMachineInstr(MI);
|
|
|
|
return Node;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::insertInstr(MachineInstr *MI, void *InsertPos) {
|
|
|
|
assert(MI);
|
|
|
|
// If it exists in temporary insts, remove it.
|
|
|
|
TemporaryInsts.remove(MI);
|
|
|
|
auto *Node = getUniqueInstrForMI(MI);
|
|
|
|
insertNode(Node, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineInstr *GISelCSEInfo::getMachineInstrIfExists(FoldingSetNodeID &ID,
|
|
|
|
MachineBasicBlock *MBB,
|
|
|
|
void *&InsertPos) {
|
|
|
|
handleRecordedInsts();
|
|
|
|
if (auto *Inst = getNodeIfExists(ID, MBB, InsertPos)) {
|
2019-02-09 00:34:11 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "CSEInfo::Found Instr " << *Inst->MI;);
|
2019-01-16 01:40:37 +01:00
|
|
|
return const_cast<MachineInstr *>(Inst->MI);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::countOpcodeHit(unsigned Opc) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
if (OpcodeHitTable.count(Opc))
|
|
|
|
OpcodeHitTable[Opc] += 1;
|
|
|
|
else
|
|
|
|
OpcodeHitTable[Opc] = 1;
|
|
|
|
#endif
|
|
|
|
// Else do nothing.
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::recordNewInstruction(MachineInstr *MI) {
|
|
|
|
if (shouldCSE(MI->getOpcode())) {
|
|
|
|
TemporaryInsts.insert(MI);
|
2019-02-09 00:34:11 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "CSEInfo::Recording new MI " << *MI);
|
2019-01-16 01:40:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::handleRecordedInst(MachineInstr *MI) {
|
|
|
|
assert(shouldCSE(MI->getOpcode()) && "Invalid instruction for CSE");
|
|
|
|
auto *UMI = InstrMapping.lookup(MI);
|
2019-02-09 00:34:11 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "CSEInfo::Handling recorded MI " << *MI);
|
2019-01-16 01:40:37 +01:00
|
|
|
if (UMI) {
|
|
|
|
// Invalidate this MI.
|
|
|
|
invalidateUniqueMachineInstr(UMI);
|
|
|
|
InstrMapping.erase(MI);
|
|
|
|
}
|
|
|
|
/// Now insert the new instruction.
|
|
|
|
if (UMI) {
|
|
|
|
/// We'll reuse the same UniqueMachineInstr to avoid the new
|
|
|
|
/// allocation.
|
|
|
|
*UMI = UniqueMachineInstr(MI);
|
|
|
|
insertNode(UMI, nullptr);
|
|
|
|
} else {
|
|
|
|
/// This is a new instruction. Allocate a new UniqueMachineInstr and
|
|
|
|
/// Insert.
|
|
|
|
insertInstr(MI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::handleRemoveInst(MachineInstr *MI) {
|
|
|
|
if (auto *UMI = InstrMapping.lookup(MI)) {
|
|
|
|
invalidateUniqueMachineInstr(UMI);
|
|
|
|
InstrMapping.erase(MI);
|
|
|
|
}
|
|
|
|
TemporaryInsts.remove(MI);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::handleRecordedInsts() {
|
|
|
|
while (!TemporaryInsts.empty()) {
|
|
|
|
auto *MI = TemporaryInsts.pop_back_val();
|
|
|
|
handleRecordedInst(MI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GISelCSEInfo::shouldCSE(unsigned Opc) const {
|
|
|
|
assert(CSEOpt.get() && "CSEConfig not set");
|
|
|
|
return CSEOpt->shouldCSEOpc(Opc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::erasingInstr(MachineInstr &MI) { handleRemoveInst(&MI); }
|
|
|
|
void GISelCSEInfo::createdInstr(MachineInstr &MI) { recordNewInstruction(&MI); }
|
|
|
|
void GISelCSEInfo::changingInstr(MachineInstr &MI) {
|
|
|
|
// For now, perform erase, followed by insert.
|
|
|
|
erasingInstr(MI);
|
|
|
|
createdInstr(MI);
|
|
|
|
}
|
|
|
|
void GISelCSEInfo::changedInstr(MachineInstr &MI) { changingInstr(MI); }
|
|
|
|
|
|
|
|
void GISelCSEInfo::analyze(MachineFunction &MF) {
|
|
|
|
setMF(MF);
|
|
|
|
for (auto &MBB : MF) {
|
|
|
|
if (MBB.empty())
|
|
|
|
continue;
|
|
|
|
for (MachineInstr &MI : MBB) {
|
|
|
|
if (!shouldCSE(MI.getOpcode()))
|
|
|
|
continue;
|
2019-02-04 15:05:33 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "CSEInfo::Add MI: " << MI);
|
2019-01-16 01:40:37 +01:00
|
|
|
insertInstr(&MI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GISelCSEInfo::releaseMemory() {
|
2019-02-09 00:34:11 +01:00
|
|
|
print();
|
2019-01-16 01:40:37 +01:00
|
|
|
CSEMap.clear();
|
|
|
|
InstrMapping.clear();
|
|
|
|
UniqueInstrAllocator.Reset();
|
|
|
|
TemporaryInsts.clear();
|
|
|
|
CSEOpt.reset();
|
|
|
|
MRI = nullptr;
|
|
|
|
MF = nullptr;
|
|
|
|
#ifndef NDEBUG
|
|
|
|
OpcodeHitTable.clear();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-07-01 17:25:30 +02:00
|
|
|
#ifndef NDEBUG
|
|
|
|
static const char *stringify(const MachineInstr *MI, std::string &S) {
|
|
|
|
raw_string_ostream OS(S);
|
|
|
|
OS << *MI;
|
|
|
|
return OS.str().c_str();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-18 23:42:49 +01:00
|
|
|
Error GISelCSEInfo::verify() {
|
|
|
|
#ifndef NDEBUG
|
2021-07-01 17:25:30 +02:00
|
|
|
std::string S1, S2;
|
2020-02-18 23:42:49 +01:00
|
|
|
handleRecordedInsts();
|
|
|
|
// For each instruction in map from MI -> UMI,
|
|
|
|
// Profile(MI) and make sure UMI is found for that profile.
|
|
|
|
for (auto &It : InstrMapping) {
|
|
|
|
FoldingSetNodeID TmpID;
|
|
|
|
GISelInstProfileBuilder(TmpID, *MRI).addNodeID(It.first);
|
|
|
|
void *InsertPos;
|
|
|
|
UniqueMachineInstr *FoundNode =
|
|
|
|
CSEMap.FindNodeOrInsertPos(TmpID, InsertPos);
|
|
|
|
if (FoundNode != It.second)
|
|
|
|
return createStringError(std::errc::not_supported,
|
|
|
|
"CSEMap mismatch, InstrMapping has MIs without "
|
2021-07-01 17:25:30 +02:00
|
|
|
"corresponding Nodes in CSEMap:\n%s",
|
|
|
|
stringify(It.second->MI, S1));
|
2020-02-18 23:42:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// For every node in the CSEMap, make sure that the InstrMapping
|
|
|
|
// points to it.
|
2021-02-13 08:44:33 +01:00
|
|
|
for (const UniqueMachineInstr &UMI : CSEMap) {
|
2020-02-18 23:42:49 +01:00
|
|
|
if (!InstrMapping.count(UMI.MI))
|
|
|
|
return createStringError(std::errc::not_supported,
|
2021-07-01 17:25:30 +02:00
|
|
|
"Node in CSE without InstrMapping:\n%s",
|
|
|
|
stringify(UMI.MI, S1));
|
2020-02-18 23:42:49 +01:00
|
|
|
|
|
|
|
if (InstrMapping[UMI.MI] != &UMI)
|
|
|
|
return createStringError(std::make_error_code(std::errc::not_supported),
|
2021-07-01 17:25:30 +02:00
|
|
|
"Mismatch in CSE mapping:\n%s\n%s",
|
|
|
|
stringify(InstrMapping[UMI.MI]->MI, S1),
|
|
|
|
stringify(UMI.MI, S2));
|
2020-02-18 23:42:49 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2019-01-16 01:40:37 +01:00
|
|
|
void GISelCSEInfo::print() {
|
2019-02-09 00:34:11 +01:00
|
|
|
LLVM_DEBUG(for (auto &It
|
|
|
|
: OpcodeHitTable) {
|
|
|
|
dbgs() << "CSEInfo::CSE Hit for Opc " << It.first << " : " << It.second
|
|
|
|
<< "\n";
|
|
|
|
};);
|
2019-01-16 01:40:37 +01:00
|
|
|
}
|
|
|
|
/// -----------------------------------------
|
|
|
|
// ---- Profiling methods for FoldingSetNode --- //
|
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeID(const MachineInstr *MI) const {
|
|
|
|
addNodeIDMBB(MI->getParent());
|
|
|
|
addNodeIDOpcode(MI->getOpcode());
|
|
|
|
for (auto &Op : MI->operands())
|
|
|
|
addNodeIDMachineOperand(Op);
|
|
|
|
addNodeIDFlag(MI->getFlags());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeIDOpcode(unsigned Opc) const {
|
|
|
|
ID.AddInteger(Opc);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
2020-02-13 20:30:50 +01:00
|
|
|
GISelInstProfileBuilder::addNodeIDRegType(const LLT Ty) const {
|
2019-01-16 01:40:37 +01:00
|
|
|
uint64_t Val = Ty.getUniqueRAWLLTData();
|
|
|
|
ID.AddInteger(Val);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeIDRegType(const TargetRegisterClass *RC) const {
|
|
|
|
ID.AddPointer(RC);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeIDRegType(const RegisterBank *RB) const {
|
|
|
|
ID.AddPointer(RB);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeIDImmediate(int64_t Imm) const {
|
|
|
|
ID.AddInteger(Imm);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
2020-06-08 16:04:19 +02:00
|
|
|
GISelInstProfileBuilder::addNodeIDRegNum(Register Reg) const {
|
2019-01-16 01:40:37 +01:00
|
|
|
ID.AddInteger(Reg);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
2020-06-08 16:04:19 +02:00
|
|
|
GISelInstProfileBuilder::addNodeIDRegType(const Register Reg) const {
|
2019-01-16 01:40:37 +01:00
|
|
|
addNodeIDMachineOperand(MachineOperand::CreateReg(Reg, false));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeIDMBB(const MachineBasicBlock *MBB) const {
|
|
|
|
ID.AddPointer(MBB);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeIDFlag(unsigned Flag) const {
|
|
|
|
if (Flag)
|
|
|
|
ID.AddInteger(Flag);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2020-08-27 17:54:33 +02:00
|
|
|
const GISelInstProfileBuilder &
|
|
|
|
GISelInstProfileBuilder::addNodeIDReg(Register Reg) const {
|
|
|
|
LLT Ty = MRI.getType(Reg);
|
|
|
|
if (Ty.isValid())
|
|
|
|
addNodeIDRegType(Ty);
|
|
|
|
|
|
|
|
if (const RegClassOrRegBank &RCOrRB = MRI.getRegClassOrRegBank(Reg)) {
|
|
|
|
if (const auto *RB = RCOrRB.dyn_cast<const RegisterBank *>())
|
|
|
|
addNodeIDRegType(RB);
|
|
|
|
else if (const auto *RC = RCOrRB.dyn_cast<const TargetRegisterClass *>())
|
|
|
|
addNodeIDRegType(RC);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2019-01-16 01:40:37 +01:00
|
|
|
const GISelInstProfileBuilder &GISelInstProfileBuilder::addNodeIDMachineOperand(
|
|
|
|
const MachineOperand &MO) const {
|
|
|
|
if (MO.isReg()) {
|
Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVM
Summary:
This clang-tidy check is looking for unsigned integer variables whose initializer
starts with an implicit cast from llvm::Register and changes the type of the
variable to llvm::Register (dropping the llvm:: where possible).
Partial reverts in:
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
X86FixupLEAs.cpp - Some functions return unsigned and arguably should be MCRegister
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
HexagonBitSimplify.cpp - Function takes BitTracker::RegisterRef which appears to be unsigned&
MachineVerifier.cpp - Ambiguous operator==() given MCRegister and const Register
PPCFastISel.cpp - No Register::operator-=()
PeepholeOptimizer.cpp - TargetInstrInfo::optimizeLoadInstr() takes an unsigned&
MachineTraceMetrics.cpp - MachineTraceMetrics lacks a suitable constructor
Manual fixups in:
ARMFastISel.cpp - ARMEmitLoad() now takes a Register& instead of unsigned&
HexagonSplitDouble.cpp - Ternary operator was ambiguous between unsigned/Register
HexagonConstExtenders.cpp - Has a local class named Register, used llvm::Register instead of Register.
PPCFastISel.cpp - PPCEmitLoad() now takes a Register& instead of unsigned&
Depends on D65919
Reviewers: arsenm, bogner, craig.topper, RKSimon
Reviewed By: arsenm
Subscribers: RKSimon, craig.topper, lenary, aemerson, wuzish, jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65962
llvm-svn: 369041
2019-08-15 21:22:08 +02:00
|
|
|
Register Reg = MO.getReg();
|
2019-01-16 01:40:37 +01:00
|
|
|
if (!MO.isDef())
|
|
|
|
addNodeIDRegNum(Reg);
|
2020-06-08 15:49:34 +02:00
|
|
|
|
2020-08-27 17:54:33 +02:00
|
|
|
// Profile the register properties.
|
|
|
|
addNodeIDReg(Reg);
|
2019-01-16 01:40:37 +01:00
|
|
|
assert(!MO.isImplicit() && "Unhandled case");
|
|
|
|
} else if (MO.isImm())
|
|
|
|
ID.AddInteger(MO.getImm());
|
|
|
|
else if (MO.isCImm())
|
|
|
|
ID.AddPointer(MO.getCImm());
|
|
|
|
else if (MO.isFPImm())
|
|
|
|
ID.AddPointer(MO.getFPImm());
|
|
|
|
else if (MO.isPredicate())
|
|
|
|
ID.AddInteger(MO.getPredicate());
|
|
|
|
else
|
|
|
|
llvm_unreachable("Unhandled operand type");
|
|
|
|
// Handle other types
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2019-04-15 06:53:46 +02:00
|
|
|
GISelCSEInfo &
|
|
|
|
GISelCSEAnalysisWrapper::get(std::unique_ptr<CSEConfigBase> CSEOpt,
|
|
|
|
bool Recompute) {
|
2019-01-16 01:40:37 +01:00
|
|
|
if (!AlreadyComputed || Recompute) {
|
2020-02-18 23:42:49 +01:00
|
|
|
Info.releaseMemory();
|
2019-01-16 01:40:37 +01:00
|
|
|
Info.setCSEConfig(std::move(CSEOpt));
|
|
|
|
Info.analyze(*MF);
|
|
|
|
AlreadyComputed = true;
|
|
|
|
}
|
|
|
|
return Info;
|
|
|
|
}
|
|
|
|
void GISelCSEAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.setPreservesAll();
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GISelCSEAnalysisWrapperPass::runOnMachineFunction(MachineFunction &MF) {
|
|
|
|
releaseMemory();
|
|
|
|
Wrapper.setMF(MF);
|
|
|
|
return false;
|
|
|
|
}
|