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