xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1753f127fSDimitry Andric //===-- SPIRVDuplicatesTracker.cpp - SPIR-V Duplicates Tracker --*- C++ -*-===//
2753f127fSDimitry Andric //
3753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6753f127fSDimitry Andric //
7753f127fSDimitry Andric //===----------------------------------------------------------------------===//
8753f127fSDimitry Andric //
9753f127fSDimitry Andric // General infrastructure for keeping track of the values that according to
10753f127fSDimitry Andric // the SPIR-V binary layout should be global to the whole module.
11753f127fSDimitry Andric //
12753f127fSDimitry Andric //===----------------------------------------------------------------------===//
13753f127fSDimitry Andric 
14753f127fSDimitry Andric #include "SPIRVDuplicatesTracker.h"
15753f127fSDimitry Andric 
16753f127fSDimitry Andric using namespace llvm;
17753f127fSDimitry Andric 
18753f127fSDimitry Andric template <typename T>
19753f127fSDimitry Andric void SPIRVGeneralDuplicatesTracker::prebuildReg2Entry(
20753f127fSDimitry Andric     SPIRVDuplicatesTracker<T> &DT, SPIRVReg2EntryTy &Reg2Entry) {
21753f127fSDimitry Andric   for (auto &TPair : DT.getAllUses()) {
22753f127fSDimitry Andric     for (auto &RegPair : TPair.second) {
23753f127fSDimitry Andric       const MachineFunction *MF = RegPair.first;
24753f127fSDimitry Andric       Register R = RegPair.second;
25753f127fSDimitry Andric       MachineInstr *MI = MF->getRegInfo().getUniqueVRegDef(R);
26753f127fSDimitry Andric       if (!MI)
27753f127fSDimitry Andric         continue;
28753f127fSDimitry Andric       Reg2Entry[&MI->getOperand(0)] = &TPair.second;
29753f127fSDimitry Andric     }
30753f127fSDimitry Andric   }
31753f127fSDimitry Andric }
32753f127fSDimitry Andric 
33753f127fSDimitry Andric void SPIRVGeneralDuplicatesTracker::buildDepsGraph(
34753f127fSDimitry Andric     std::vector<SPIRV::DTSortableEntry *> &Graph,
35753f127fSDimitry Andric     MachineModuleInfo *MMI = nullptr) {
36753f127fSDimitry Andric   SPIRVReg2EntryTy Reg2Entry;
37753f127fSDimitry Andric   prebuildReg2Entry(TT, Reg2Entry);
38753f127fSDimitry Andric   prebuildReg2Entry(CT, Reg2Entry);
39753f127fSDimitry Andric   prebuildReg2Entry(GT, Reg2Entry);
40753f127fSDimitry Andric   prebuildReg2Entry(FT, Reg2Entry);
41753f127fSDimitry Andric   prebuildReg2Entry(AT, Reg2Entry);
42*0fca6ea1SDimitry Andric   prebuildReg2Entry(MT, Reg2Entry);
43bdd1243dSDimitry Andric   prebuildReg2Entry(ST, Reg2Entry);
44753f127fSDimitry Andric 
45753f127fSDimitry Andric   for (auto &Op2E : Reg2Entry) {
46753f127fSDimitry Andric     SPIRV::DTSortableEntry *E = Op2E.second;
47753f127fSDimitry Andric     Graph.push_back(E);
48753f127fSDimitry Andric     for (auto &U : *E) {
49753f127fSDimitry Andric       const MachineRegisterInfo &MRI = U.first->getRegInfo();
50753f127fSDimitry Andric       MachineInstr *MI = MRI.getUniqueVRegDef(U.second);
51753f127fSDimitry Andric       if (!MI)
52753f127fSDimitry Andric         continue;
53753f127fSDimitry Andric       assert(MI && MI->getParent() && "No MachineInstr created yet");
54753f127fSDimitry Andric       for (auto i = MI->getNumDefs(); i < MI->getNumOperands(); i++) {
55753f127fSDimitry Andric         MachineOperand &Op = MI->getOperand(i);
56753f127fSDimitry Andric         if (!Op.isReg())
57753f127fSDimitry Andric           continue;
58*0fca6ea1SDimitry Andric         MachineInstr *VRegDef = MRI.getVRegDef(Op.getReg());
59*0fca6ea1SDimitry Andric         // References to a function via function pointers generate virtual
60*0fca6ea1SDimitry Andric         // registers without a definition. We are able to resolve this
61*0fca6ea1SDimitry Andric         // reference using Globar Register info into an OpFunction instruction
62*0fca6ea1SDimitry Andric         // but do not expect to find it in Reg2Entry.
63*0fca6ea1SDimitry Andric         if (MI->getOpcode() == SPIRV::OpConstantFunctionPointerINTEL && i == 2)
64*0fca6ea1SDimitry Andric           continue;
65*0fca6ea1SDimitry Andric         MachineOperand *RegOp = &VRegDef->getOperand(0);
66753f127fSDimitry Andric         assert((MI->getOpcode() == SPIRV::OpVariable && i == 3) ||
67753f127fSDimitry Andric                Reg2Entry.count(RegOp));
68753f127fSDimitry Andric         if (Reg2Entry.count(RegOp))
69753f127fSDimitry Andric           E->addDep(Reg2Entry[RegOp]);
70753f127fSDimitry Andric       }
71753f127fSDimitry Andric 
72753f127fSDimitry Andric       if (E->getIsFunc()) {
73753f127fSDimitry Andric         MachineInstr *Next = MI->getNextNode();
74753f127fSDimitry Andric         if (Next && (Next->getOpcode() == SPIRV::OpFunction ||
75753f127fSDimitry Andric                      Next->getOpcode() == SPIRV::OpFunctionParameter)) {
76753f127fSDimitry Andric           E->addDep(Reg2Entry[&Next->getOperand(0)]);
77753f127fSDimitry Andric         }
78753f127fSDimitry Andric       }
79753f127fSDimitry Andric     }
80753f127fSDimitry Andric   }
81753f127fSDimitry Andric 
826246ae0bSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
83753f127fSDimitry Andric   if (MMI) {
84753f127fSDimitry Andric     const Module *M = MMI->getModule();
85753f127fSDimitry Andric     for (auto F = M->begin(), E = M->end(); F != E; ++F) {
86753f127fSDimitry Andric       const MachineFunction *MF = MMI->getMachineFunction(*F);
87753f127fSDimitry Andric       if (!MF)
88753f127fSDimitry Andric         continue;
89753f127fSDimitry Andric       for (const MachineBasicBlock &MBB : *MF) {
90753f127fSDimitry Andric         for (const MachineInstr &CMI : MBB) {
91753f127fSDimitry Andric           MachineInstr &MI = const_cast<MachineInstr &>(CMI);
92753f127fSDimitry Andric           MI.dump();
93753f127fSDimitry Andric           if (MI.getNumExplicitDefs() > 0 &&
94753f127fSDimitry Andric               Reg2Entry.count(&MI.getOperand(0))) {
95753f127fSDimitry Andric             dbgs() << "\t[";
96753f127fSDimitry Andric             for (SPIRV::DTSortableEntry *D :
97753f127fSDimitry Andric                  Reg2Entry.lookup(&MI.getOperand(0))->getDeps())
98753f127fSDimitry Andric               dbgs() << Register::virtReg2Index(D->lookup(MF)) << ", ";
99753f127fSDimitry Andric             dbgs() << "]\n";
100753f127fSDimitry Andric           }
101753f127fSDimitry Andric         }
102753f127fSDimitry Andric       }
103753f127fSDimitry Andric     }
104753f127fSDimitry Andric   }
1056246ae0bSDimitry Andric #endif
106753f127fSDimitry Andric }
107