64 ToErase.eraseFromParent();
68 if (!
G.isThreadLocal())
71 G.dropDroppableUses();
73 if (!
G.isConstantUsed())
79 OS <<
"Accelerator does not support the thread_local variable "
86 auto U = std::move(Tmp.
back());
92 if (isa<Instruction>(U))
93 I = cast<Instruction>(U);
95 Tmp.
insert(Tmp.
end(), U->user_begin(), U->user_end());
98 }
while (!
I && !Tmp.
empty());
100 assert(
I &&
"thread_local global should have at least one non-constant use.");
102 G.getContext().diagnose(
110 while (!M.functions().empty())
112 while (!M.globals().empty())
114 while (!M.aliases().empty())
116 while (!M.ifuncs().empty())
121 unsigned GlobAS = M.getDataLayout().getDefaultGlobalsAddressSpace();
122 for (
auto &&
G : M.globals()) {
126 if (
G.isThreadLocal())
130 if (
G.getAddressSpace() != GlobAS)
132 if (
G.getLinkage() != GlobalVariable::ExternalLinkage)
135 G.setLinkage(GlobalVariable::ExternalWeakLinkage);
136 G.setInitializer(
nullptr);
137 G.setExternallyInitialized(
true);
145 if (
auto F = dyn_cast<Function>(
C))
153 return !
F.isIntrinsic() && !Reachable.
contains(&
F);
167 const auto Dx =
F->getName().rfind(
"__hipstdpar_unsupported");
172 const auto N =
F->getName().substr(0, Dx);
178 OS <<
"Accelerator does not support the ASM block:\n"
179 << cast<ConstantDataArray>(CB->
getArgOperand(0))->getAsCString();
181 OS <<
"Accelerator does not support the " <<
N <<
" function.";
183 auto Caller = CB->
getParent()->getParent();
185 Caller->getContext().diagnose(
197 for (
auto &&CGN : CGA) {
201 Reachable.
insert(CGN.first);
205 auto F = std::move(Tmp.back());
208 for (
auto &&
N : *CGA[
F]) {
211 if (!
N.second->getFunction())
213 if (Reachable.contains(
N.second->getFunction()))
217 dyn_cast<CallBase>(*
N.first)))
220 Reachable.insert(
N.second->getFunction());
221 Tmp.push_back(
N.second->getFunction());
223 }
while (!std::empty(Tmp));
226 if (std::empty(Reachable))
236static constexpr std::pair<StringLiteral, StringLiteral>
ReplaceMap[]{
237 {
"aligned_alloc",
"__hipstdpar_aligned_alloc"},
238 {
"calloc",
"__hipstdpar_calloc"},
239 {
"free",
"__hipstdpar_free"},
240 {
"malloc",
"__hipstdpar_malloc"},
241 {
"memalign",
"__hipstdpar_aligned_alloc"},
242 {
"posix_memalign",
"__hipstdpar_posix_aligned_alloc"},
243 {
"realloc",
"__hipstdpar_realloc"},
244 {
"reallocarray",
"__hipstdpar_realloc_array"},
245 {
"_ZdaPv",
"__hipstdpar_operator_delete"},
246 {
"_ZdaPvm",
"__hipstdpar_operator_delete_sized"},
247 {
"_ZdaPvSt11align_val_t",
"__hipstdpar_operator_delete_aligned"},
248 {
"_ZdaPvmSt11align_val_t",
"__hipstdpar_operator_delete_aligned_sized"},
249 {
"_ZdlPv",
"__hipstdpar_operator_delete"},
250 {
"_ZdlPvm",
"__hipstdpar_operator_delete_sized"},
251 {
"_ZdlPvSt11align_val_t",
"__hipstdpar_operator_delete_aligned"},
252 {
"_ZdlPvmSt11align_val_t",
"__hipstdpar_operator_delete_aligned_sized"},
253 {
"_Znam",
"__hipstdpar_operator_new"},
254 {
"_ZnamRKSt9nothrow_t",
"__hipstdpar_operator_new_nothrow"},
255 {
"_ZnamSt11align_val_t",
"__hipstdpar_operator_new_aligned"},
256 {
"_ZnamSt11align_val_tRKSt9nothrow_t",
257 "__hipstdpar_operator_new_aligned_nothrow"},
259 {
"_Znwm",
"__hipstdpar_operator_new"},
260 {
"_ZnwmRKSt9nothrow_t",
"__hipstdpar_operator_new_nothrow"},
261 {
"_ZnwmSt11align_val_t",
"__hipstdpar_operator_new_aligned"},
262 {
"_ZnwmSt11align_val_tRKSt9nothrow_t",
263 "__hipstdpar_operator_new_aligned_nothrow"},
264 {
"__builtin_calloc",
"__hipstdpar_calloc"},
265 {
"__builtin_free",
"__hipstdpar_free"},
266 {
"__builtin_malloc",
"__hipstdpar_malloc"},
267 {
"__builtin_operator_delete",
"__hipstdpar_operator_delete"},
268 {
"__builtin_operator_new",
"__hipstdpar_operator_new"},
269 {
"__builtin_realloc",
"__hipstdpar_realloc"},
270 {
"__libc_calloc",
"__hipstdpar_calloc"},
271 {
"__libc_free",
"__hipstdpar_free"},
272 {
"__libc_malloc",
"__hipstdpar_malloc"},
273 {
"__libc_memalign",
"__hipstdpar_aligned_alloc"},
274 {
"__libc_realloc",
"__hipstdpar_realloc"}
285 if (!AllocReplacements.
contains(
F.getName()))
288 if (
auto R = M.getFunction(AllocReplacements[
F.getName()])) {
289 F.replaceAllUsesWith(R);
294 OS <<
"cannot be interposed, missing: " << AllocReplacements[
F.getName()]
295 <<
". Tried to run the allocation interposition pass without the "
296 <<
"replacement functions available.";
304 if (
auto F = M.getFunction(
"__hipstdpar_hidden_free")) {
305 auto LibcFree = M.getOrInsertFunction(
"__libc_free",
F->getFunctionType(),
307 F->replaceAllUsesWith(LibcFree.getCallee());
ReachingDefAnalysis InstSet & ToRemove
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static constexpr std::pair< StringLiteral, StringLiteral > ReplaceMap[]
static void maybeHandleGlobals(Module &M)
static bool isAcceleratorExecutionRoot(const Function *F)
static void eraseFromModule(T &ToErase)
static void removeUnreachableFunctions(const SmallPtrSet< const Function *, N > &Reachable, Module &M)
static bool checkIfSupported(GlobalVariable &G)
static void clearModule(Module &M)
AcceleratorCodeSelection - Identify all functions reachable from a kernel, removing those that are un...
Module.h This file contains the declarations for the Module class.
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Value * getArgOperand(unsigned i) const
An analysis pass to compute the CallGraph for a Module.
This is an important base class in LLVM.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Diagnostic information for unsupported feature in backend.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
A Module instance is used to store all the information related to an LLVM module.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
iterator insert(iterator I, T &&Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static constexpr size_t npos
const ParentTy * getParent() const
A raw_ostream that writes to an std::string.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
void removeFromUsedLists(Module &M, function_ref< bool(Constant *)> ShouldRemove)
Removes global values from the llvm.used and llvm.compiler.used arrays.