63 ToErase.eraseFromParent();
67 if (!
G.isThreadLocal())
70 G.dropDroppableUses();
72 if (!
G.isConstantUsed())
78 OS <<
"Accelerator does not support the thread_local variable "
85 auto U = std::move(Tmp.
back());
88 if (!Visited.
insert(U).second)
91 if (isa<Instruction>(U))
92 I = cast<Instruction>(U);
94 Tmp.
insert(Tmp.
end(), U->user_begin(), U->user_end());
95 }
while (!
I && !Tmp.
empty());
97 assert(
I &&
"thread_local global should have at least one non-constant use.");
99 G.getContext().diagnose(
107 while (!M.functions().empty())
109 while (!M.globals().empty())
111 while (!M.aliases().empty())
113 while (!M.ifuncs().empty())
118 unsigned GlobAS = M.getDataLayout().getDefaultGlobalsAddressSpace();
119 for (
auto &&
G : M.globals()) {
123 if (
G.isThreadLocal())
127 if (
G.getAddressSpace() != GlobAS)
129 if (
G.getLinkage() != GlobalVariable::ExternalLinkage)
132 G.setLinkage(GlobalVariable::ExternalWeakLinkage);
133 G.setInitializer(
nullptr);
134 G.setExternallyInitialized(
true);
142 if (
auto F = dyn_cast<Function>(
C))
150 return !
F.isIntrinsic() && !Reachable.
contains(&
F);
164 const auto Dx =
F->getName().rfind(
"__hipstdpar_unsupported");
169 const auto N =
F->getName().substr(0, Dx);
175 OS <<
"Accelerator does not support the ASM block:\n"
176 << cast<ConstantDataArray>(CB->
getArgOperand(0))->getAsCString();
178 OS <<
"Accelerator does not support the " <<
N <<
" function.";
180 auto Caller = CB->
getParent()->getParent();
182 Caller->getContext().diagnose(
194 for (
auto &&CGN : CGA) {
198 Reachable.
insert(CGN.first);
202 auto F = std::move(Tmp.back());
205 for (
auto &&
N : *CGA[
F]) {
208 if (!
N.second->getFunction())
210 if (Reachable.contains(
N.second->getFunction()))
214 dyn_cast<CallBase>(*
N.first)))
217 Reachable.insert(
N.second->getFunction());
218 Tmp.push_back(
N.second->getFunction());
220 }
while (!std::empty(Tmp));
223 if (std::empty(Reachable))
233static constexpr std::pair<StringLiteral, StringLiteral>
ReplaceMap[]{
234 {
"aligned_alloc",
"__hipstdpar_aligned_alloc"},
235 {
"calloc",
"__hipstdpar_calloc"},
236 {
"free",
"__hipstdpar_free"},
237 {
"malloc",
"__hipstdpar_malloc"},
238 {
"memalign",
"__hipstdpar_aligned_alloc"},
239 {
"posix_memalign",
"__hipstdpar_posix_aligned_alloc"},
240 {
"realloc",
"__hipstdpar_realloc"},
241 {
"reallocarray",
"__hipstdpar_realloc_array"},
242 {
"_ZdaPv",
"__hipstdpar_operator_delete"},
243 {
"_ZdaPvm",
"__hipstdpar_operator_delete_sized"},
244 {
"_ZdaPvSt11align_val_t",
"__hipstdpar_operator_delete_aligned"},
245 {
"_ZdaPvmSt11align_val_t",
"__hipstdpar_operator_delete_aligned_sized"},
246 {
"_ZdlPv",
"__hipstdpar_operator_delete"},
247 {
"_ZdlPvm",
"__hipstdpar_operator_delete_sized"},
248 {
"_ZdlPvSt11align_val_t",
"__hipstdpar_operator_delete_aligned"},
249 {
"_ZdlPvmSt11align_val_t",
"__hipstdpar_operator_delete_aligned_sized"},
250 {
"_Znam",
"__hipstdpar_operator_new"},
251 {
"_ZnamRKSt9nothrow_t",
"__hipstdpar_operator_new_nothrow"},
252 {
"_ZnamSt11align_val_t",
"__hipstdpar_operator_new_aligned"},
253 {
"_ZnamSt11align_val_tRKSt9nothrow_t",
254 "__hipstdpar_operator_new_aligned_nothrow"},
256 {
"_Znwm",
"__hipstdpar_operator_new"},
257 {
"_ZnwmRKSt9nothrow_t",
"__hipstdpar_operator_new_nothrow"},
258 {
"_ZnwmSt11align_val_t",
"__hipstdpar_operator_new_aligned"},
259 {
"_ZnwmSt11align_val_tRKSt9nothrow_t",
260 "__hipstdpar_operator_new_aligned_nothrow"},
261 {
"__builtin_calloc",
"__hipstdpar_calloc"},
262 {
"__builtin_free",
"__hipstdpar_free"},
263 {
"__builtin_malloc",
"__hipstdpar_malloc"},
264 {
"__builtin_operator_delete",
"__hipstdpar_operator_delete"},
265 {
"__builtin_operator_new",
"__hipstdpar_operator_new"},
266 {
"__builtin_realloc",
"__hipstdpar_realloc"},
267 {
"__libc_calloc",
"__hipstdpar_calloc"},
268 {
"__libc_free",
"__hipstdpar_free"},
269 {
"__libc_malloc",
"__hipstdpar_malloc"},
270 {
"__libc_memalign",
"__hipstdpar_aligned_alloc"},
271 {
"__libc_realloc",
"__hipstdpar_realloc"}
282 if (!AllocReplacements.
contains(
F.getName()))
285 if (
auto R = M.getFunction(AllocReplacements[
F.getName()])) {
286 F.replaceAllUsesWith(R);
291 OS <<
"cannot be interposed, missing: " << AllocReplacements[
F.getName()]
292 <<
". Tried to run the allocation interposition pass without the "
293 <<
"replacement functions available.";
301 if (
auto F = M.getFunction(
"__hipstdpar_hidden_free")) {
302 auto LibcFree = M.getOrInsertFunction(
"__libc_free",
F->getFunctionType(),
304 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.