Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
35269 views
//===-- SPIRVDuplicatesTracker.h - SPIR-V Duplicates Tracker ----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// General infrastructure for keeping track of the values that according to9// the SPIR-V binary layout should be global to the whole module.10//11//===----------------------------------------------------------------------===//1213#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H14#define LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H1516#include "MCTargetDesc/SPIRVBaseInfo.h"17#include "MCTargetDesc/SPIRVMCTargetDesc.h"18#include "SPIRVUtils.h"19#include "llvm/ADT/DenseMap.h"20#include "llvm/ADT/MapVector.h"21#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"22#include "llvm/CodeGen/MachineModuleInfo.h"2324#include <type_traits>2526namespace llvm {27namespace SPIRV {28// NOTE: using MapVector instead of DenseMap because it helps getting29// everything ordered in a stable manner for a price of extra (NumKeys)*PtrSize30// memory and expensive removals which do not happen anyway.31class DTSortableEntry : public MapVector<const MachineFunction *, Register> {32SmallVector<DTSortableEntry *, 2> Deps;3334struct FlagsTy {35unsigned IsFunc : 1;36unsigned IsGV : 1;37// NOTE: bit-field default init is a C++20 feature.38FlagsTy() : IsFunc(0), IsGV(0) {}39};40FlagsTy Flags;4142public:43// Common hoisting utility doesn't support function, because their hoisting44// require hoisting of params as well.45bool getIsFunc() const { return Flags.IsFunc; }46bool getIsGV() const { return Flags.IsGV; }47void setIsFunc(bool V) { Flags.IsFunc = V; }48void setIsGV(bool V) { Flags.IsGV = V; }4950const SmallVector<DTSortableEntry *, 2> &getDeps() const { return Deps; }51void addDep(DTSortableEntry *E) { Deps.push_back(E); }52};5354enum SpecialTypeKind {55STK_Empty = 0,56STK_Image,57STK_SampledImage,58STK_Sampler,59STK_Pipe,60STK_DeviceEvent,61STK_Pointer,62STK_Last = -163};6465using SpecialTypeDescriptor = std::tuple<const Type *, unsigned, unsigned>;6667union ImageAttrs {68struct BitFlags {69unsigned Dim : 3;70unsigned Depth : 2;71unsigned Arrayed : 1;72unsigned MS : 1;73unsigned Sampled : 2;74unsigned ImageFormat : 6;75unsigned AQ : 2;76} Flags;77unsigned Val;7879ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS,80unsigned Sampled, unsigned ImageFormat, unsigned AQ = 0) {81Val = 0;82Flags.Dim = Dim;83Flags.Depth = Depth;84Flags.Arrayed = Arrayed;85Flags.MS = MS;86Flags.Sampled = Sampled;87Flags.ImageFormat = ImageFormat;88Flags.AQ = AQ;89}90};9192inline SpecialTypeDescriptor93make_descr_image(const Type *SampledTy, unsigned Dim, unsigned Depth,94unsigned Arrayed, unsigned MS, unsigned Sampled,95unsigned ImageFormat, unsigned AQ = 0) {96return std::make_tuple(97SampledTy,98ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,99SpecialTypeKind::STK_Image);100}101102inline SpecialTypeDescriptor103make_descr_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy) {104assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);105return std::make_tuple(106SampledTy,107ImageAttrs(108ImageTy->getOperand(2).getImm(), ImageTy->getOperand(3).getImm(),109ImageTy->getOperand(4).getImm(), ImageTy->getOperand(5).getImm(),110ImageTy->getOperand(6).getImm(), ImageTy->getOperand(7).getImm(),111ImageTy->getOperand(8).getImm())112.Val,113SpecialTypeKind::STK_SampledImage);114}115116inline SpecialTypeDescriptor make_descr_sampler() {117return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);118}119120inline SpecialTypeDescriptor make_descr_pipe(uint8_t AQ) {121return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);122}123124inline SpecialTypeDescriptor make_descr_event() {125return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);126}127128inline SpecialTypeDescriptor make_descr_pointee(const Type *ElementType,129unsigned AddressSpace) {130return std::make_tuple(ElementType, AddressSpace,131SpecialTypeKind::STK_Pointer);132}133} // namespace SPIRV134135template <typename KeyTy> class SPIRVDuplicatesTrackerBase {136public:137// NOTE: using MapVector instead of DenseMap helps getting everything ordered138// in a stable manner for a price of extra (NumKeys)*PtrSize memory and139// expensive removals which don't happen anyway.140using StorageTy = MapVector<KeyTy, SPIRV::DTSortableEntry>;141142private:143StorageTy Storage;144145public:146void add(KeyTy V, const MachineFunction *MF, Register R) {147if (find(V, MF).isValid())148return;149150Storage[V][MF] = R;151if (std::is_same<Function,152typename std::remove_const<153typename std::remove_pointer<KeyTy>::type>::type>() ||154std::is_same<Argument,155typename std::remove_const<156typename std::remove_pointer<KeyTy>::type>::type>())157Storage[V].setIsFunc(true);158if (std::is_same<GlobalVariable,159typename std::remove_const<160typename std::remove_pointer<KeyTy>::type>::type>())161Storage[V].setIsGV(true);162}163164Register find(KeyTy V, const MachineFunction *MF) const {165auto iter = Storage.find(V);166if (iter != Storage.end()) {167auto Map = iter->second;168auto iter2 = Map.find(MF);169if (iter2 != Map.end())170return iter2->second;171}172return Register();173}174175const StorageTy &getAllUses() const { return Storage; }176177private:178StorageTy &getAllUses() { return Storage; }179180// The friend class needs to have access to the internal storage181// to be able to build dependency graph, can't declare only one182// function a 'friend' due to the incomplete declaration at this point183// and mutual dependency problems.184friend class SPIRVGeneralDuplicatesTracker;185};186187template <typename T>188class SPIRVDuplicatesTracker : public SPIRVDuplicatesTrackerBase<const T *> {};189190template <>191class SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor>192: public SPIRVDuplicatesTrackerBase<SPIRV::SpecialTypeDescriptor> {};193194class SPIRVGeneralDuplicatesTracker {195SPIRVDuplicatesTracker<Type> TT;196SPIRVDuplicatesTracker<Constant> CT;197SPIRVDuplicatesTracker<GlobalVariable> GT;198SPIRVDuplicatesTracker<Function> FT;199SPIRVDuplicatesTracker<Argument> AT;200SPIRVDuplicatesTracker<MachineInstr> MT;201SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor> ST;202203// NOTE: using MOs instead of regs to get rid of MF dependency to be able204// to use flat data structure.205// NOTE: replacing DenseMap with MapVector doesn't affect overall correctness206// but makes LITs more stable, should prefer DenseMap still due to207// significant perf difference.208using SPIRVReg2EntryTy =209MapVector<MachineOperand *, SPIRV::DTSortableEntry *>;210211template <typename T>212void prebuildReg2Entry(SPIRVDuplicatesTracker<T> &DT,213SPIRVReg2EntryTy &Reg2Entry);214215public:216void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,217MachineModuleInfo *MMI);218219void add(const Type *Ty, const MachineFunction *MF, Register R) {220TT.add(unifyPtrType(Ty), MF, R);221}222223void add(const Type *PointeeTy, unsigned AddressSpace,224const MachineFunction *MF, Register R) {225ST.add(SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF,226R);227}228229void add(const Constant *C, const MachineFunction *MF, Register R) {230CT.add(C, MF, R);231}232233void add(const GlobalVariable *GV, const MachineFunction *MF, Register R) {234GT.add(GV, MF, R);235}236237void add(const Function *F, const MachineFunction *MF, Register R) {238FT.add(F, MF, R);239}240241void add(const Argument *Arg, const MachineFunction *MF, Register R) {242AT.add(Arg, MF, R);243}244245void add(const MachineInstr *MI, const MachineFunction *MF, Register R) {246MT.add(MI, MF, R);247}248249void add(const SPIRV::SpecialTypeDescriptor &TD, const MachineFunction *MF,250Register R) {251ST.add(TD, MF, R);252}253254Register find(const Type *Ty, const MachineFunction *MF) {255return TT.find(unifyPtrType(Ty), MF);256}257258Register find(const Type *PointeeTy, unsigned AddressSpace,259const MachineFunction *MF) {260return ST.find(261SPIRV::make_descr_pointee(unifyPtrType(PointeeTy), AddressSpace), MF);262}263264Register find(const Constant *C, const MachineFunction *MF) {265return CT.find(const_cast<Constant *>(C), MF);266}267268Register find(const GlobalVariable *GV, const MachineFunction *MF) {269return GT.find(const_cast<GlobalVariable *>(GV), MF);270}271272Register find(const Function *F, const MachineFunction *MF) {273return FT.find(const_cast<Function *>(F), MF);274}275276Register find(const Argument *Arg, const MachineFunction *MF) {277return AT.find(const_cast<Argument *>(Arg), MF);278}279280Register find(const MachineInstr *MI, const MachineFunction *MF) {281return MT.find(const_cast<MachineInstr *>(MI), MF);282}283284Register find(const SPIRV::SpecialTypeDescriptor &TD,285const MachineFunction *MF) {286return ST.find(TD, MF);287}288289const SPIRVDuplicatesTracker<Type> *getTypes() { return &TT; }290};291} // namespace llvm292#endif // LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H293294295