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
14#include "SPIRVDuplicatesTracker.h"
15
16using namespace llvm;
17
18template <typename T>
19void SPIRVGeneralDuplicatesTracker::prebuildReg2Entry(
20 SPIRVDuplicatesTracker<T> &DT, SPIRVReg2EntryTy &Reg2Entry) {
21 for (auto &TPair : DT.getAllUses()) {
22 for (auto &RegPair : TPair.second) {
23 const MachineFunction *MF = RegPair.first;
24 Register R = RegPair.second;
25 MachineInstr *MI = MF->getRegInfo().getUniqueVRegDef(Reg: R);
26 if (!MI)
27 continue;
28 Reg2Entry[&MI->getOperand(i: 0)] = &TPair.second;
29 }
30 }
31}
32
33void SPIRVGeneralDuplicatesTracker::buildDepsGraph(
34 std::vector<SPIRV::DTSortableEntry *> &Graph,
35 MachineModuleInfo *MMI = nullptr) {
36 SPIRVReg2EntryTy Reg2Entry;
37 prebuildReg2Entry(DT&: TT, Reg2Entry);
38 prebuildReg2Entry(DT&: CT, Reg2Entry);
39 prebuildReg2Entry(DT&: GT, Reg2Entry);
40 prebuildReg2Entry(DT&: FT, Reg2Entry);
41 prebuildReg2Entry(DT&: AT, Reg2Entry);
42 prebuildReg2Entry(DT&: MT, Reg2Entry);
43 prebuildReg2Entry(DT&: ST, Reg2Entry);
44
45 for (auto &Op2E : Reg2Entry) {
46 SPIRV::DTSortableEntry *E = Op2E.second;
47 Graph.push_back(x: E);
48 for (auto &U : *E) {
49 const MachineRegisterInfo &MRI = U.first->getRegInfo();
50 MachineInstr *MI = MRI.getUniqueVRegDef(Reg: U.second);
51 if (!MI)
52 continue;
53 assert(MI && MI->getParent() && "No MachineInstr created yet");
54 for (auto i = MI->getNumDefs(); i < MI->getNumOperands(); i++) {
55 MachineOperand &Op = MI->getOperand(i);
56 if (!Op.isReg())
57 continue;
58 MachineInstr *VRegDef = MRI.getVRegDef(Reg: Op.getReg());
59 // References to a function via function pointers generate virtual
60 // registers without a definition. We are able to resolve this
61 // reference using Globar Register info into an OpFunction instruction
62 // but do not expect to find it in Reg2Entry.
63 if (MI->getOpcode() == SPIRV::OpConstantFunctionPointerINTEL && i == 2)
64 continue;
65 MachineOperand *RegOp = &VRegDef->getOperand(i: 0);
66 assert((MI->getOpcode() == SPIRV::OpVariable && i == 3) ||
67 Reg2Entry.count(RegOp));
68 if (Reg2Entry.count(Key: RegOp))
69 E->addDep(E: Reg2Entry[RegOp]);
70 }
71
72 if (E->getIsFunc()) {
73 MachineInstr *Next = MI->getNextNode();
74 if (Next && (Next->getOpcode() == SPIRV::OpFunction ||
75 Next->getOpcode() == SPIRV::OpFunctionParameter)) {
76 E->addDep(E: Reg2Entry[&Next->getOperand(i: 0)]);
77 }
78 }
79 }
80 }
81
82#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
83 if (MMI) {
84 const Module *M = MMI->getModule();
85 for (auto F = M->begin(), E = M->end(); F != E; ++F) {
86 const MachineFunction *MF = MMI->getMachineFunction(F: *F);
87 if (!MF)
88 continue;
89 for (const MachineBasicBlock &MBB : *MF) {
90 for (const MachineInstr &CMI : MBB) {
91 MachineInstr &MI = const_cast<MachineInstr &>(CMI);
92 MI.dump();
93 if (MI.getNumExplicitDefs() > 0 &&
94 Reg2Entry.count(Key: &MI.getOperand(i: 0))) {
95 dbgs() << "\t[";
96 for (SPIRV::DTSortableEntry *D :
97 Reg2Entry.lookup(Key: &MI.getOperand(i: 0))->getDeps())
98 dbgs() << Register::virtReg2Index(Reg: D->lookup(Key: MF)) << ", ";
99 dbgs() << "]\n";
100 }
101 }
102 }
103 }
104 }
105#endif
106}
107

source code of llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp