LLVM 20.0.0git
SPIRVDuplicatesTracker.cpp
Go to the documentation of this file.
1//===-- SPIRVDuplicatesTracker.cpp - SPIR-V Duplicates Tracker --*- 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// General infrastructure for keeping track of the values that according to
10// the SPIR-V binary layout should be global to the whole module.
11//
12//===----------------------------------------------------------------------===//
13
15#include "SPIRVInstrInfo.h"
16
17#define DEBUG_TYPE "build-dep-graph"
18
19using namespace llvm;
20
21template <typename T>
22void SPIRVGeneralDuplicatesTracker::prebuildReg2Entry(
23 SPIRVDuplicatesTracker<T> &DT, SPIRVReg2EntryTy &Reg2Entry,
24 const SPIRVInstrInfo *TII) {
25 for (auto &TPair : DT.getAllUses()) {
26 for (auto &RegPair : TPair.second) {
27 const MachineFunction *MF = RegPair.first;
28 Register R = RegPair.second;
30 if (!MI || (TPair.second.getIsConst() && !TII->isConstantInstr(*MI)))
31 continue;
32 Reg2Entry[&MI->getOperand(0)] = &TPair.second;
33 }
34 }
35}
36
38 std::vector<SPIRV::DTSortableEntry *> &Graph, const SPIRVInstrInfo *TII,
39 MachineModuleInfo *MMI = nullptr) {
40 SPIRVReg2EntryTy Reg2Entry;
41 prebuildReg2Entry(TT, Reg2Entry, TII);
42 prebuildReg2Entry(CT, Reg2Entry, TII);
43 prebuildReg2Entry(GT, Reg2Entry, TII);
44 prebuildReg2Entry(FT, Reg2Entry, TII);
45 prebuildReg2Entry(AT, Reg2Entry, TII);
46 prebuildReg2Entry(MT, Reg2Entry, TII);
47 prebuildReg2Entry(ST, Reg2Entry, TII);
48
49 for (auto &Op2E : Reg2Entry) {
50 SPIRV::DTSortableEntry *E = Op2E.second;
51 Graph.push_back(E);
52 for (auto &U : *E) {
53 const MachineRegisterInfo &MRI = U.first->getRegInfo();
54 MachineInstr *MI = MRI.getUniqueVRegDef(U.second);
55 if (!MI)
56 continue;
57 assert(MI && MI->getParent() && "No MachineInstr created yet");
58 for (auto i = MI->getNumDefs(); i < MI->getNumOperands(); i++) {
59 MachineOperand &Op = MI->getOperand(i);
60 if (!Op.isReg())
61 continue;
62 MachineInstr *VRegDef = MRI.getVRegDef(Op.getReg());
63 // References to a function via function pointers generate virtual
64 // registers without a definition. We are able to resolve this
65 // reference using Globar Register info into an OpFunction instruction
66 // but do not expect to find it in Reg2Entry.
67 if (MI->getOpcode() == SPIRV::OpConstantFunctionPointerINTEL && i == 2)
68 continue;
69 MachineOperand *RegOp = &VRegDef->getOperand(0);
70 if (Reg2Entry.count(RegOp) == 0 &&
71 (MI->getOpcode() != SPIRV::OpVariable || i != 3)) {
72 // try to repair the unexpected code pattern
73 bool IsFixed = false;
74 if (VRegDef->getOpcode() == TargetOpcode::G_CONSTANT &&
75 RegOp->isReg() && MRI.getType(RegOp->getReg()).isScalar()) {
76 const Constant *C = VRegDef->getOperand(1).getCImm();
77 add(C, MI->getParent()->getParent(), RegOp->getReg());
78 auto Iter = CT.Storage.find(C);
79 if (Iter != CT.Storage.end()) {
80 SPIRV::DTSortableEntry &MissedEntry = Iter->second;
81 Reg2Entry[RegOp] = &MissedEntry;
82 IsFixed = true;
83 }
84 }
85 if (!IsFixed) {
86 std::string DiagMsg;
87 raw_string_ostream OS(DiagMsg);
88 OS << "Unexpected pattern while building a dependency "
89 "graph.\nInstruction: ";
90 MI->print(OS);
91 OS << "Operand: ";
92 Op.print(OS);
93 OS << "\nOperand definition: ";
94 VRegDef->print(OS);
95 report_fatal_error(DiagMsg.c_str());
96 }
97 }
98 if (Reg2Entry.count(RegOp))
99 E->addDep(Reg2Entry[RegOp]);
100 }
101
102 if (E->getIsFunc()) {
103 MachineInstr *Next = MI->getNextNode();
104 if (Next && (Next->getOpcode() == SPIRV::OpFunction ||
105 Next->getOpcode() == SPIRV::OpFunctionParameter)) {
106 E->addDep(Reg2Entry[&Next->getOperand(0)]);
107 }
108 }
109 }
110 }
111
112#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
113 if (MMI) {
114 const Module *M = MMI->getModule();
115 for (auto F = M->begin(), E = M->end(); F != E; ++F) {
116 const MachineFunction *MF = MMI->getMachineFunction(*F);
117 if (!MF)
118 continue;
119 for (const MachineBasicBlock &MBB : *MF) {
120 for (const MachineInstr &CMI : MBB) {
121 MachineInstr &MI = const_cast<MachineInstr &>(CMI);
122 MI.dump();
123 if (MI.getNumExplicitDefs() > 0 &&
124 Reg2Entry.count(&MI.getOperand(0))) {
125 dbgs() << "\t[";
127 Reg2Entry.lookup(&MI.getOperand(0))->getDeps())
128 dbgs() << Register::virtReg2Index(D->lookup(MF)) << ", ";
129 dbgs() << "]\n";
130 }
131 }
132 }
133 }
134 }
135#endif
136}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This is an important base class in LLVM.
Definition: Constant.h:42
This class represents an Operation in the Expression.
bool print(raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:36
size_type count(const KeyT &Key) const
Definition: MapVector.h:165
ValueT lookup(const KeyT &Key) const
Definition: MapVector.h:110
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Definition: Pass.cpp:130
void dump() const
Definition: Pass.cpp:136
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
static unsigned virtReg2Index(Register Reg)
Convert a virtual register number to a 0-based index.
Definition: Register.h:77
void add(const Type *Ty, const MachineFunction *MF, Register R)
void buildDepsGraph(std::vector< SPIRV::DTSortableEntry * > &Graph, const SPIRVInstrInfo *TII, MachineModuleInfo *MMI)
void addDep(DTSortableEntry *E)
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:661
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167