xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp (revision 8aac90f18aef7c9eea906c3ff9a001ca7b94f375)
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(ST, Reg2Entry);
43 
44   for (auto &Op2E : Reg2Entry) {
45     SPIRV::DTSortableEntry *E = Op2E.second;
46     Graph.push_back(E);
47     for (auto &U : *E) {
48       const MachineRegisterInfo &MRI = U.first->getRegInfo();
49       MachineInstr *MI = MRI.getUniqueVRegDef(U.second);
50       if (!MI)
51         continue;
52       assert(MI && MI->getParent() && "No MachineInstr created yet");
53       for (auto i = MI->getNumDefs(); i < MI->getNumOperands(); i++) {
54         MachineOperand &Op = MI->getOperand(i);
55         if (!Op.isReg())
56           continue;
57         MachineOperand *RegOp = &MRI.getVRegDef(Op.getReg())->getOperand(0);
58         assert((MI->getOpcode() == SPIRV::OpVariable && i == 3) ||
59                Reg2Entry.count(RegOp));
60         if (Reg2Entry.count(RegOp))
61           E->addDep(Reg2Entry[RegOp]);
62       }
63 
64       if (E->getIsFunc()) {
65         MachineInstr *Next = MI->getNextNode();
66         if (Next && (Next->getOpcode() == SPIRV::OpFunction ||
67                      Next->getOpcode() == SPIRV::OpFunctionParameter)) {
68           E->addDep(Reg2Entry[&Next->getOperand(0)]);
69         }
70       }
71     }
72   }
73 
74 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
75   if (MMI) {
76     const Module *M = MMI->getModule();
77     for (auto F = M->begin(), E = M->end(); F != E; ++F) {
78       const MachineFunction *MF = MMI->getMachineFunction(*F);
79       if (!MF)
80         continue;
81       for (const MachineBasicBlock &MBB : *MF) {
82         for (const MachineInstr &CMI : MBB) {
83           MachineInstr &MI = const_cast<MachineInstr &>(CMI);
84           MI.dump();
85           if (MI.getNumExplicitDefs() > 0 &&
86               Reg2Entry.count(&MI.getOperand(0))) {
87             dbgs() << "\t[";
88             for (SPIRV::DTSortableEntry *D :
89                  Reg2Entry.lookup(&MI.getOperand(0))->getDeps())
90               dbgs() << Register::virtReg2Index(D->lookup(MF)) << ", ";
91             dbgs() << "]\n";
92           }
93         }
94       }
95     }
96   }
97 #endif
98 }
99