LLVM 24.0.0git
SPIRVPrepareGlobals.cpp
Go to the documentation of this file.
1//===-- SPIRVPrepareGlobals.cpp - Prepare IR SPIRV globals ------*- 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// The pass:
10// - transforms IR globals that cannot be trivially mapped to SPIRV into
11// something that is trival to lower;
12// - for AMDGCN flavoured SPIRV, it assigns unique IDs to the specialisation
13// constants associated with feature predicates, which were inserted by the
14// FE when expanding calls to __builtin_amdgcn_processor_is or
15// __builtin_amdgcn_is_invocable
16//
17//===----------------------------------------------------------------------===//
18
19#include "SPIRV.h"
20#include "SPIRVUtils.h"
21
22#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/IR/IntrinsicsSPIRV.h"
26#include "llvm/IR/Module.h"
27#include "llvm/Support/Debug.h"
28
29#include <string>
30
31#define DEBUG_TYPE "spirv-prepare-globals"
32
33using namespace llvm;
34
35namespace {
36
37struct SPIRVPrepareGlobalsImpl {
38 bool runOnModule(Module &M);
39};
40
41struct SPIRVPrepareGlobalsLegacy : public ModulePass {
42 static char ID;
43 SPIRVPrepareGlobalsLegacy() : ModulePass(ID) {}
44
45 StringRef getPassName() const override {
46 return "SPIRV prepare global variables";
47 }
48
49 bool runOnModule(Module &M) override {
50 return SPIRVPrepareGlobalsImpl().runOnModule(M);
51 }
52};
53
54// The backend does not support GlobalAlias. Replace aliases with their aliasees
55// when possible and remove them from the module.
56bool tryReplaceAliasWithAliasee(GlobalAlias &GA) {
57 // According to the lang ref, aliases cannot be replaced if either the alias
58 // or the aliasee are interposable. We only replace in the case that both
59 // are not interposable.
60 if (GA.isInterposable()) {
61 LLVM_DEBUG(dbgs() << "Skipping interposable alias: " << GA.getName()
62 << "\n");
63 return false;
64 }
65
66 auto *AO = dyn_cast<GlobalObject>(GA.getAliasee());
67 if (!AO) {
68 LLVM_DEBUG(dbgs() << "Skipping alias whose aliasee is not a GlobalObject: "
69 << GA.getName() << "\n");
70 return false;
71 }
72
73 if (AO->isInterposable()) {
74 LLVM_DEBUG(dbgs() << "Skipping interposable aliasee: " << AO->getName()
75 << "\n");
76 return false;
77 }
78
79 LLVM_DEBUG(dbgs() << "Replacing alias " << GA.getName()
80 << " with aliasee: " << AO->getName() << "\n");
81
82 GA.replaceAllUsesWith(AO);
83 if (GA.isDiscardableIfUnused()) {
84 GA.eraseFromParent();
85 }
86
87 return true;
88}
89
90bool tryAssignPredicateSpecConstIDs(Module &M, Function *F) {
92 for (auto &&U : F->users()) {
93 auto *CI = dyn_cast<CallInst>(U);
94 if (!CI)
95 continue;
96
97 auto *SpecID = dyn_cast<ConstantInt>(CI->getArgOperand(0));
98 if (!SpecID)
99 continue;
100
101 unsigned ID = SpecID->getZExtValue();
102 if (ID != UINT32_MAX)
103 continue;
104
105 // Replace placeholder Specialisation Constant IDs with unique IDs
106 // associated with the predicate being evaluated, which is encoded via
107 // spv_assign_name.
108 auto *MD =
109 cast<MDNode>(cast<MetadataAsValue>(CI->getOperand(2))->getMetadata());
110 auto *P = cast<MDString>(MD->getOperand(0));
111
112 ID = IDs.try_emplace(P->getString(), IDs.size()).first->second;
113 CI->setArgOperand(0, ConstantInt::get(CI->getArgOperand(0)->getType(), ID));
114 }
115
116 if (IDs.empty())
117 return false;
118
119 // Store the predicate -> ID mapping as a fixed format string
120 // (predicate ID\0...), for later use during SPIR-V consumption.
121 std::string Tmp;
122 for (auto &&[Predicate, SpecID] : IDs)
123 Tmp.append(Predicate).append(" ").append(utostr(SpecID)).push_back('\0');
124
125 Constant *PredSpecIDStr =
126 ConstantDataArray::getString(M.getContext(), Tmp, false);
127
128 new GlobalVariable(M, PredSpecIDStr->getType(), true,
130 PredSpecIDStr, "llvm.amdgcn.feature.predicate.ids");
131
132 return true;
133}
134
135bool SPIRVPrepareGlobalsImpl::runOnModule(Module &M) {
136 bool Changed = false;
137
138 for (GlobalAlias &GA : make_early_inc_range(M.aliases())) {
139 Changed |= tryReplaceAliasWithAliasee(GA);
140 }
141
142 if (M.getTargetTriple().getVendor() != Triple::AMD)
143 return Changed;
144
145 // TODO: Currently, for AMDGCN flavoured SPIR-V, the symbol can only be
146 // inserted via feature predicate use, but in the future this will need
147 // revisiting if we start making more liberal use of the intrinsic.
149 &M, Intrinsic::spv_named_boolean_spec_constant))
150 Changed |= tryAssignPredicateSpecConstIDs(M, F);
151
152 return Changed;
153}
154char SPIRVPrepareGlobalsLegacy::ID = 0;
155
156} // namespace
157
158INITIALIZE_PASS(SPIRVPrepareGlobalsLegacy, "spirv-prepare-globals",
159 "SPIRV prepare global variables", false, false)
160
163 return SPIRVPrepareGlobalsImpl().runOnModule(M) ? PreservedAnalyses::none()
165}
166
167namespace llvm {
169 return new SPIRVPrepareGlobalsLegacy();
170}
171} // namespace llvm
This file defines the StringMap class.
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:722
const Constant * getAliasee() const
Definition GlobalAlias.h:87
static bool isDiscardableIfUnused(LinkageTypes Linkage)
Whether the definition of this global may be discarded if it is not used in its compilation unit.
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
LLVM_ABI bool isInterposable(bool CheckNoIPA=true) const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
Definition Globals.cpp:178
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:68
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
unsigned size() const
Definition StringMap.h:104
bool empty() const
Definition StringMap.h:103
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:129
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition StringMap.h:370
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
Changed
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
std::string utostr(uint64_t X, bool isNeg=false)
ModulePass * createSPIRVPrepareGlobalsPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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