LLVM 24.0.0git
NVPTXCanonicalizeDynamicShared.cpp
Go to the documentation of this file.
1//===-- NVPTXCanonicalizeDynamicShared.cpp - Merge dynamic shared decls ---===//
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// Every unsized `.extern .shared` array names the start of the same dynamic
10// shared memory allocation, so `extern __shared__ int a[]` and
11// `extern __shared__ float b[]` are the same address. LLVM sees two distinct
12// global variables, which alias analysis treats as disjoint objects, and can
13// then reorder or forward a store through @a past a load through @b.
14//
15// This pass gives all such declarations one underlying object. It redirects
16// their uses to a single declaration that carries the strongest alignment and
17// the debug info of each source variable, and erases the others unless a used
18// list names them.
19//
20//===----------------------------------------------------------------------===//
21
22#include "NVPTX.h"
24#include "llvm/IR/Constants.h"
27#include "llvm/IR/Module.h"
28#include "llvm/Pass.h"
29
30using namespace llvm;
31
32static bool isDynamicSharedDecl(const GlobalVariable &GV) {
33 const auto *AT = dyn_cast<ArrayType>(GV.getValueType());
34 return GV.isDeclaration() && GV.hasExternalLinkage() && AT &&
35 AT->getNumElements() == 0 &&
37}
38
41 if (!List)
42 return;
43 auto *AT = cast<ArrayType>(List->getValueType());
45 for (GlobalValue *V : Values)
47 V, AT->getElementType()));
48 List->setInitializer(ConstantArray::get(AT, Init));
49}
50
53 for (GlobalVariable &GV : M.globals())
54 if (isDynamicSharedDecl(GV))
55 DynSharedDecls.push_back(&GV);
56 if (DynSharedDecls.size() < 2)
57 return false;
58
59 // Redirecting uses also rewrites the used lists. Rebuild them at the end so
60 // that they keep naming the original symbols.
61 SmallVector<GlobalValue *, 8> Used, CompilerUsed;
62 GlobalVariable *UsedList = collectUsedGlobalVariables(M, Used, false);
63 GlobalVariable *CompilerUsedList =
64 collectUsedGlobalVariables(M, CompilerUsed, true);
66 InUsedList.insert_range(CompilerUsed);
67
68 const DataLayout &DL = M.getDataLayout();
69 GlobalVariable *Canonical = nullptr;
70 Align MaxAlign;
71 bool Changed = false;
72 for (GlobalVariable *GV : DynSharedDecls) {
73 GV->removeDeadConstantUsers();
74 if (GV->use_empty())
75 continue;
76 MaxAlign = std::max(MaxAlign, DL.getValueOrABITypeAlignment(
77 GV->getAlign(), GV->getValueType()));
78 if (!Canonical) {
79 Canonical = GV;
80 continue;
81 }
82
83 // A write through any name may change what the others read.
84 if (!GV->isConstant())
85 Canonical->setConstant(false);
86
87 // Each source variable keeps its name and type at the common address.
89 GV->getDebugInfo(GVEs);
90 for (DIGlobalVariableExpression *GVE : GVEs)
91 Canonical->addDebugInfo(GVE);
92 GV->eraseMetadata(LLVMContext::MD_dbg);
93
94 GV->replaceAllUsesWith(Canonical);
95 if (!InUsedList.contains(GV))
96 GV->eraseFromParent();
97 Changed = true;
98 }
99 if (Changed)
100 Canonical->setAlignment(MaxAlign);
101
102 restoreUsedList(UsedList, Used);
103 restoreUsedList(CompilerUsedList, CompilerUsed);
104 return Changed;
105}
106
107namespace {
108class NVPTXCanonicalizeDynamicSharedLegacyPass : public ModulePass {
109public:
110 static char ID;
111 NVPTXCanonicalizeDynamicSharedLegacyPass() : ModulePass(ID) {}
112
113 bool runOnModule(Module &M) override { return canonicalizeDynamicShared(M); }
114};
115} // namespace
116
117char NVPTXCanonicalizeDynamicSharedLegacyPass::ID = 0;
118
119INITIALIZE_PASS(NVPTXCanonicalizeDynamicSharedLegacyPass,
120 "nvptx-canonicalize-dynamic-shared",
121 "Merge NVPTX dynamic shared memory declarations", false, false)
122
124 return new NVPTXCanonicalizeDynamicSharedLegacyPass();
125}
126
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
static void restoreUsedList(GlobalVariable *List, ArrayRef< GlobalValue * > Values)
static bool canonicalizeDynamicShared(Module &M)
static bool isDynamicSharedDecl(const GlobalVariable &GV)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the SmallPtrSet class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
A pair of DIGlobalVariable and DIExpression.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
bool hasExternalLinkage() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
unsigned getAddressSpace() const
Type * getValueType() const
void setConstant(bool Val)
LLVM_ABI void addDebugInfo(DIGlobalVariableExpression *GV)
Attach a DIGlobalVariableExpression.
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
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
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
void insert_range(Range &&R)
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This is an optimization pass for GlobalISel generic memory operations.
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr from_range_t from_range
ModulePass * createNVPTXCanonicalizeDynamicSharedLegacyPass()
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
LLVM_ABI GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
Definition Module.cpp:966
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39