brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.0 KiB · 47c7676 Raw
302 lines · c
1//===------------ SPIRVMapping.h - 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-exception6//7//===----------------------------------------------------------------------===//8//9// General infrastructure for keeping track of the values that according to10// the SPIR-V binary layout should be global to the whole module.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H15#define LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H16 17#include "MCTargetDesc/SPIRVBaseInfo.h"18#include "MCTargetDesc/SPIRVMCTargetDesc.h"19#include "SPIRVUtils.h"20#include "llvm/ADT/DenseMap.h"21#include "llvm/ADT/Hashing.h"22#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"23#include "llvm/CodeGen/MachineModuleInfo.h"24 25namespace llvm {26namespace SPIRV {27 28inline size_t to_hash(const MachineInstr *MI) {29  hash_code H = llvm::hash_combine(MI->getOpcode(), MI->getNumOperands());30  for (unsigned I = MI->getNumDefs(); I < MI->getNumOperands(); ++I) {31    const MachineOperand &MO = MI->getOperand(I);32    if (MO.getType() == MachineOperand::MO_CImmediate)33      H = llvm::hash_combine(H, MO.getType(), MO.getCImm());34    else if (MO.getType() == MachineOperand::MO_FPImmediate)35      H = llvm::hash_combine(H, MO.getType(), MO.getFPImm());36    else37      H = llvm::hash_combine(H, MO.getType());38  }39  return H;40}41 42using MIHandle = std::tuple<const MachineInstr *, Register, size_t>;43 44inline MIHandle getMIKey(const MachineInstr *MI) {45  return std::make_tuple(MI, MI->getOperand(0).getReg(), SPIRV::to_hash(MI));46}47 48using IRHandle = std::tuple<const void *, unsigned, unsigned>;49using IRHandleMF = std::pair<IRHandle, const MachineFunction *>;50 51inline IRHandleMF getIRHandleMF(IRHandle Handle, const MachineFunction *MF) {52  return std::make_pair(Handle, MF);53}54 55enum SpecialTypeKind {56  STK_Empty = 0,57  STK_Image,58  STK_SampledImage,59  STK_Sampler,60  STK_Pipe,61  STK_DeviceEvent,62  STK_ElementPointer,63  STK_Type,64  STK_Value,65  STK_MachineInstr,66  STK_VkBuffer,67  STK_Padding,68  STK_ExplictLayoutType,69  STK_Last = -170};71 72union ImageAttrs {73  struct BitFlags {74    unsigned Dim : 3;75    unsigned Depth : 2;76    unsigned Arrayed : 1;77    unsigned MS : 1;78    unsigned Sampled : 2;79    unsigned ImageFormat : 6;80    unsigned AQ : 2;81  } Flags;82  unsigned Val;83 84  ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS,85             unsigned Sampled, unsigned ImageFormat, unsigned AQ = 0) {86    Val = 0;87    Flags.Dim = Dim;88    Flags.Depth = Depth;89    Flags.Arrayed = Arrayed;90    Flags.MS = MS;91    Flags.Sampled = Sampled;92    Flags.ImageFormat = ImageFormat;93    Flags.AQ = AQ;94  }95};96 97inline IRHandle irhandle_image(const Type *SampledTy, unsigned Dim,98                               unsigned Depth, unsigned Arrayed, unsigned MS,99                               unsigned Sampled, unsigned ImageFormat,100                               unsigned AQ = 0) {101  return std::make_tuple(102      SampledTy,103      ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,104      SpecialTypeKind::STK_Image);105}106 107inline IRHandle irhandle_sampled_image(const Type *SampledTy,108                                       const MachineInstr *ImageTy) {109  assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);110  unsigned AC = AccessQualifier::AccessQualifier::None;111  if (ImageTy->getNumOperands() > 8)112    AC = ImageTy->getOperand(8).getImm();113  return std::make_tuple(114      SampledTy,115      ImageAttrs(116          ImageTy->getOperand(2).getImm(), ImageTy->getOperand(3).getImm(),117          ImageTy->getOperand(4).getImm(), ImageTy->getOperand(5).getImm(),118          ImageTy->getOperand(6).getImm(), ImageTy->getOperand(7).getImm(), AC)119          .Val,120      SpecialTypeKind::STK_SampledImage);121}122 123inline IRHandle irhandle_sampler() {124  return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);125}126 127inline IRHandle irhandle_pipe(uint8_t AQ) {128  return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);129}130 131inline IRHandle irhandle_event() {132  return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);133}134 135inline IRHandle irhandle_pointee(const Type *ElementType,136                                 unsigned AddressSpace) {137  return std::make_tuple(unifyPtrType(ElementType), AddressSpace,138                         SpecialTypeKind::STK_ElementPointer);139}140 141inline IRHandle irhandle_ptr(const void *Ptr, unsigned Arg,142                             enum SpecialTypeKind STK) {143  return std::make_tuple(Ptr, Arg, STK);144}145 146inline IRHandle irhandle_vkbuffer(const Type *ElementType,147                                  StorageClass::StorageClass SC,148                                  bool IsWriteable) {149  return std::make_tuple(ElementType, (SC << 1) | IsWriteable,150                         SpecialTypeKind::STK_VkBuffer);151}152 153inline IRHandle irhandle_padding() {154  return std::make_tuple(nullptr, 0, SpecialTypeKind::STK_Padding);155}156 157inline IRHandle irhandle_explict_layout_type(const Type *Ty) {158  const Type *WrpTy = unifyPtrType(Ty);159  return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_ExplictLayoutType);160}161 162inline IRHandle handle(const Type *Ty) {163  const Type *WrpTy = unifyPtrType(Ty);164  return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_Type);165}166 167inline IRHandle handle(const Value *V) {168  return irhandle_ptr(V, V->getValueID(), STK_Value);169}170 171inline IRHandle handle(const MachineInstr *KeyMI) {172  return irhandle_ptr(KeyMI, SPIRV::to_hash(KeyMI), STK_MachineInstr);173}174 175inline bool type_has_layout_decoration(const Type *T) {176  return (isa<StructType>(T) || isa<ArrayType>(T));177}178 179} // namespace SPIRV180 181// Bi-directional mappings between LLVM entities and (v-reg, machine function)182// pairs support management of unique SPIR-V definitions per machine function183// per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).184class SPIRVIRMapping {185  DenseMap<SPIRV::IRHandleMF, SPIRV::MIHandle> Vregs;186  DenseMap<const MachineInstr *, SPIRV::IRHandleMF> Defs;187 188public:189  bool add(SPIRV::IRHandle Handle, const MachineInstr *MI) {190    if (auto DefIt = Defs.find(MI); DefIt != Defs.end()) {191      auto [ExistHandle, ExistMF] = DefIt->second;192      if (Handle == ExistHandle && MI->getMF() == ExistMF)193        return false; // already exists194      // invalidate the record195      Vregs.erase(DefIt->second);196      Defs.erase(DefIt);197    }198    SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MI->getMF());199    SPIRV::MIHandle MIKey = SPIRV::getMIKey(MI);200    auto It1 = Vregs.try_emplace(HandleMF, MIKey);201    if (!It1.second) {202      // there is an expired record that we need to invalidate203      Defs.erase(std::get<0>(It1.first->second));204      // update the record205      It1.first->second = MIKey;206    }207    [[maybe_unused]] auto It2 = Defs.try_emplace(MI, HandleMF);208    assert(It2.second);209    return true;210  }211  bool erase(const MachineInstr *MI) {212    bool Res = false;213    if (auto It = Defs.find(MI); It != Defs.end()) {214      Res = Vregs.erase(It->second);215      Defs.erase(It);216    }217    return Res;218  }219  const MachineInstr *findMI(SPIRV::IRHandle Handle,220                             const MachineFunction *MF) {221    SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MF);222    auto It = Vregs.find(HandleMF);223    if (It == Vregs.end())224      return nullptr;225    auto [MI, Reg, Hash] = It->second;226    const MachineInstr *Def = MF->getRegInfo().getVRegDef(Reg);227    if (!Def || Def != MI || SPIRV::to_hash(MI) != Hash) {228      // there is an expired record that we need to invalidate229      erase(MI);230      return nullptr;231    }232    assert(Defs.contains(MI) && Defs.find(MI)->second == HandleMF);233    return MI;234  }235  Register find(SPIRV::IRHandle Handle, const MachineFunction *MF) {236    const MachineInstr *MI = findMI(Handle, MF);237    return MI ? MI->getOperand(0).getReg() : Register();238  }239 240  // helpers241  bool add(const Type *PointeeTy, unsigned AddressSpace,242           const MachineInstr *MI) {243    return add(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MI);244  }245  Register find(const Type *PointeeTy, unsigned AddressSpace,246                const MachineFunction *MF) {247    return find(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);248  }249  const MachineInstr *findMI(const Type *PointeeTy, unsigned AddressSpace,250                             const MachineFunction *MF) {251    return findMI(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);252  }253 254  bool add(const Value *V, const MachineInstr *MI) {255    return add(SPIRV::handle(V), MI);256  }257 258  bool add(const Type *T, bool RequiresExplicitLayout, const MachineInstr *MI) {259    if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T)) {260      return add(SPIRV::irhandle_explict_layout_type(T), MI);261    }262    return add(SPIRV::handle(T), MI);263  }264 265  bool add(const MachineInstr *Obj, const MachineInstr *MI) {266    return add(SPIRV::handle(Obj), MI);267  }268 269  Register find(const Value *V, const MachineFunction *MF) {270    return find(SPIRV::handle(V), MF);271  }272 273  Register find(const Type *T, bool RequiresExplicitLayout,274                const MachineFunction *MF) {275    if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))276      return find(SPIRV::irhandle_explict_layout_type(T), MF);277    return find(SPIRV::handle(T), MF);278  }279 280  Register find(const MachineInstr *MI, const MachineFunction *MF) {281    return find(SPIRV::handle(MI), MF);282  }283 284  const MachineInstr *findMI(const Value *Obj, const MachineFunction *MF) {285    return findMI(SPIRV::handle(Obj), MF);286  }287 288  const MachineInstr *findMI(const Type *T, bool RequiresExplicitLayout,289                             const MachineFunction *MF) {290    if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))291      return findMI(SPIRV::irhandle_explict_layout_type(T), MF);292    return findMI(SPIRV::handle(T), MF);293  }294 295  const MachineInstr *findMI(const MachineInstr *Obj,296                             const MachineFunction *MF) {297    return findMI(SPIRV::handle(Obj), MF);298  }299};300} // namespace llvm301#endif // LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H302