LLVM 22.0.0git
SPIRVPushConstantAccess.cpp
Go to the documentation of this file.
1//===- SPIRVPushConstantAccess.cpp - Translate CBuffer Loads ----*- 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// This pass changes the types of all the globals in the PushConstant
10// address space into a target extension type, and makes all references
11// to this global go though a custom SPIR-V intrinsic.
12//
13// This allows the backend to properly lower the push constant struct type
14// to a fully laid out type, and generate the proper OpAccessChain.
15//
16//===----------------------------------------------------------------------===//
17
19#include "SPIRV.h"
20#include "SPIRVSubtarget.h"
21#include "SPIRVTargetMachine.h"
22#include "SPIRVUtils.h"
24#include "llvm/IR/IRBuilder.h"
25#include "llvm/IR/IntrinsicsSPIRV.h"
26#include "llvm/IR/Module.h"
28
29#define DEBUG_TYPE "spirv-pushconstant-access"
30using namespace llvm;
31
34 for (GlobalVariable &GV : M.globals()) {
35 if (GV.getAddressSpace() !=
36 storageClassToAddressSpace(SPIRV::StorageClass::PushConstant))
37 continue;
38
39 GV.removeDeadConstantUsers();
40 PushConstants.push_back(&GV);
41 }
42
43 for (GlobalVariable *GV : PushConstants) {
45 M.getContext(), "spirv.PushConstant", {GV->getValueType()});
46 GlobalVariable *NewGV = new GlobalVariable(
47 M, PCType, GV->isConstant(), GV->getLinkage(),
48 /* initializer= */ nullptr, GV->getName(),
49 /* InsertBefore= */ GV, GV->getThreadLocalMode(), GV->getAddressSpace(),
50 GV->isExternallyInitialized());
51
52 SmallVector<User *, 4> Users(GV->user_begin(), GV->user_end());
53 for (User *U : Users) {
55 IRBuilder<> Builder(I);
56 Value *GetPointerCall = Builder.CreateIntrinsic(
57 NewGV->getType(), Intrinsic::spv_pushconstant_getpointer, {NewGV});
58 GR->buildAssignPtr(Builder, GV->getValueType(), GetPointerCall);
59
60 for (unsigned N = 0; N < I->getNumOperands(); ++N) {
61 if (I->getOperand(N) == GV)
62 I->setOperand(N, GetPointerCall);
63 }
64 }
65
66 GV->eraseFromParent();
67 }
68
69 return true;
70}
71
74 const SPIRVSubtarget *ST = TM.getSubtargetImpl();
75 SPIRVGlobalRegistry *GR = ST->getSPIRVGlobalRegistry();
78}
79
80namespace {
81class SPIRVPushConstantAccessLegacy : public ModulePass {
82 SPIRVTargetMachine *TM = nullptr;
83
84public:
85 bool runOnModule(Module &M) override {
86 const SPIRVSubtarget *ST = TM->getSubtargetImpl();
87 SPIRVGlobalRegistry *GR = ST->getSPIRVGlobalRegistry();
88 return replacePushConstantAccesses(M, GR);
89 }
90 StringRef getPassName() const override {
91 return "SPIRV push constant Access";
92 }
93 SPIRVPushConstantAccessLegacy(SPIRVTargetMachine *TM)
94 : ModulePass(ID), TM(TM) {}
95
96 static char ID; // Pass identification.
97};
98char SPIRVPushConstantAccessLegacy::ID = 0;
99} // end anonymous namespace
100
101INITIALIZE_PASS(SPIRVPushConstantAccessLegacy, DEBUG_TYPE,
102 "SPIRV push constant Access", false, false)
103
106 return new SPIRVPushConstantAccessLegacy(TM);
107}
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
iv Induction Variable Users
Definition IVUsers.cpp:48
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool replacePushConstantAccesses(Module &M, SPIRVGlobalRegistry *GR)
PointerType * getType() const
Global values are always pointers.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2788
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
const SPIRVSubtarget * getSubtargetImpl() const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
static LLVM_ABI TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
Definition Type.cpp:907
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM Value Representation.
Definition Value.h:75
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
ModulePass * createSPIRVPushConstantAccessLegacyPass(SPIRVTargetMachine *TM)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition SPIRVUtils.h:244
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
#define N