xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp (revision 5036d9652a5701d00e9e40ea942c278e9f77d33d)
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 
16 using namespace llvm;
17 
18 template <typename T>
19 void 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(R);
26       if (!MI)
27         continue;
28       Reg2Entry[&MI->getOperand(0)] = &TPair.second;
29     }
30   }
31 }
32 
33 void SPIRVGeneralDuplicatesTracker::buildDepsGraph(
34     std::vector<SPIRV::DTSortableEntry *> &Graph,
35     MachineModuleInfo *MMI = nullptr) {
36   SPIRVReg2EntryTy Reg2Entry;
37   prebuildReg2Entry(TT, Reg2Entry);
38   prebuildReg2Entry(CT, Reg2Entry);
39   prebuildReg2Entry(GT, Reg2Entry);
40   prebuildReg2Entry(FT, Reg2Entry);
41   prebuildReg2Entry(AT, Reg2Entry);
42   prebuildReg2Entry(MT, Reg2Entry);
43   prebuildReg2Entry(ST, Reg2Entry);
44 
45   for (auto &Op2E : Reg2Entry) {
46     SPIRV::DTSortableEntry *E = Op2E.second;
47     Graph.push_back(E);
48     for (auto &U : *E) {
49       const MachineRegisterInfo &MRI = U.first->getRegInfo();
50       MachineInstr *MI = MRI.getUniqueVRegDef(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(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(0);
66         assert((MI->getOpcode() == SPIRV::OpVariable && i == 3) ||
67                Reg2Entry.count(RegOp));
68         if (Reg2Entry.count(RegOp))
69           E->addDep(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(Reg2Entry[&Next->getOperand(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);
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(&MI.getOperand(0))) {
95             dbgs() << "\t[";
96             for (SPIRV::DTSortableEntry *D :
97                  Reg2Entry.lookup(&MI.getOperand(0))->getDeps())
98               dbgs() << Register::virtReg2Index(D->lookup(MF)) << ", ";
99             dbgs() << "]\n";
100           }
101         }
102       }
103     }
104   }
105 #endif
106 }
107