19#include "llvm/IR/IntrinsicsAMDGPU.h"
23#define DEBUG_TYPE "amdgpu-memory-utils"
36 Source.getAllMetadata(MD);
37 for (
const auto [
ID,
N] : MD) {
39 case LLVMContext::MD_dbg:
40 case LLVMContext::MD_invariant_load:
41 case LLVMContext::MD_nontemporal:
65 if (STy->getNumElements() != 1)
67 Ty = STy->getElementType(0);
71 Ty = ATy->getElementType();
80 return Ty->
getName() ==
"amdgcn.named.barrier" ? Ty :
nullptr;
129 for (
auto &GV : M.globals())
140 for (
auto &GV : M.globals()) {
147 kernels[
F].insert(&GV);
149 Functions[
F].insert(&GV);
165 if (
F.hasAddressTaken(
nullptr,
177 set_union(VariablesReachableThroughFunctionPointer, DirectMapFunction[
F]);
180 auto FunctionMakesUnknownCall = [&](
const Function *
F) ->
bool {
183 if (!R.second->getFunction())
195 if (!
F.isDeclaration() && FunctionMakesUnknownCall(&
F)) {
198 VariablesReachableThroughFunctionPointer);
205 for (
Function &Func : M.functions()) {
206 if (Func.isDeclaration() ||
isKernel(Func))
212 while (!wip.
empty()) {
217 set_union(TransitiveMapFunction[&Func], DirectMapFunction[
F]);
220 Function *Ith = R.second->getFunction();
234 set_union(VariablesReachableThroughFunctionPointer,
235 TransitiveMapFunction[
F]);
242 for (
Function &Func : M.functions()) {
243 if (Func.isDeclaration() || !
isKernel(Func))
247 Function *Ith = R.second->getFunction();
249 set_union(IndirectMapKernel[&Func], TransitiveMapFunction[Ith]);
255 bool SeesUnknownCalls = [&]() {
259 while (!WorkList.
empty()) {
263 if (!CallRecord.second)
266 Function *Callee = CallRecord.second->getFunction();
270 if (Visited.
insert(Callee).second)
277 if (SeesUnknownCalls) {
279 VariablesReachableThroughFunctionPointer);
291 std::optional<bool> HasAbsoluteGVs;
292 bool HasSpecialGVs =
false;
293 for (
auto &Map : {DirectMapKernel, IndirectMapKernel}) {
294 for (
auto &[Fn, GVs] : Map) {
295 for (
auto *GV : GVs) {
296 bool IsAbsolute = GV->isAbsoluteSymbolRef();
297 bool IsDirectMapDynLDSGV =
299 if (IsDirectMapDynLDSGV)
303 DirectMapKernel[Fn].erase(GV);
304 IndirectMapKernel[Fn].erase(GV);
306 HasSpecialGVs =
true;
309 if (HasAbsoluteGVs.has_value()) {
310 if (*HasAbsoluteGVs != IsAbsolute) {
312 "module cannot mix absolute and non-absolute LDS GVs");
315 HasAbsoluteGVs = IsAbsolute;
322 if (HasAbsoluteGVs && *HasAbsoluteGVs)
325 return {std::move(DirectMapKernel), std::move(IndirectMapKernel),
336 bool SeenUnknownCall =
false;
338 while (!WorkList.
empty()) {
341 for (
auto &CallRecord : *CG[
F]) {
342 if (!CallRecord.second)
345 Function *Callee = CallRecord.second->getFunction();
347 if (!SeenUnknownCall) {
348 SeenUnknownCall =
true;
365 Callee->removeFnAttr(Attr);
366 if (Visited.
insert(Callee).second)
380 switch (
II->getIntrinsicID()) {
381 case Intrinsic::amdgcn_s_barrier:
382 case Intrinsic::amdgcn_s_cluster_barrier:
383 case Intrinsic::amdgcn_s_barrier_signal:
384 case Intrinsic::amdgcn_s_barrier_signal_var:
385 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
386 case Intrinsic::amdgcn_s_barrier_init:
387 case Intrinsic::amdgcn_s_barrier_join:
388 case Intrinsic::amdgcn_s_barrier_wait:
389 case Intrinsic::amdgcn_s_barrier_leave:
390 case Intrinsic::amdgcn_s_get_barrier_state:
391 case Intrinsic::amdgcn_s_wakeup_barrier:
392 case Intrinsic::amdgcn_wave_barrier:
393 case Intrinsic::amdgcn_sched_barrier:
394 case Intrinsic::amdgcn_sched_group_barrier:
395 case Intrinsic::amdgcn_iglp_opt:
404 const auto checkNoAlias = [
AA, Ptr](
auto I) ->
bool {
405 return I &&
AA->isNoAlias(
I->getPointerOperand(), Ptr);
422 LLVM_DEBUG(
dbgs() <<
"Checking clobbering of: " << *Load <<
'\n');
432 while (!WorkList.
empty()) {
434 if (!Visited.
insert(MA).second)
454 for (
const auto &
Use : Phi->incoming_values())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
uint64_t IntrinsicInst * II
This file defines generic set operations that may be used on set's of different types,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
std::pair< std::optional< WeakTrackingVH >, CallGraphNode * > CallRecord
A pair of the calling instruction (a call or invoke) and the call graph node being called.
The basic data container for the call graph of a Module of IR.
CallGraphNode * getExternalCallingNode() const
Returns the CallGraphNode which is used to represent undetermined calls into the callgraph.
A parsed version of the target data layout string in and methods for querying it.
Implements a dense probed hash-table based set.
const Function & getFunction() const
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Represents a read-write access to memory, whether it is a must-alias, or a may-alias.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
Represents phi nodes for memory accesses.
This is the generic walker interface for walkers of MemorySSA.
MemoryAccess * getClobberingMemoryAccess(const Instruction *I, BatchAAResults &AA)
Given a memory Mod/Ref/ModRef'ing instruction, calling this will give you the nearest dominating Memo...
Encapsulates MemorySSA, including all data associated with memory accesses.
LLVM_ABI MemorySSAWalker * getWalker()
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
A Module instance is used to store all the information related to an LLVM module.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
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.
Represent a constant reference to a string, i.e.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
StringRef getName() const
Return the name for this target extension type.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
iterator_range< user_iterator > users()
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Abstract Attribute helper functions.
@ LOCAL_ADDRESS
Address space for local memory.
bool isDynamicLDS(const GlobalVariable &GV)
void removeFnAttrFromReachable(CallGraph &CG, Function *KernelRoot, ArrayRef< StringRef > FnAttrs)
Strip FnAttr attribute from any functions where we may have introduced its use.
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
void getUsesOfLDSByFunction(const CallGraph &CG, Module &M, FunctionVariableMap &kernels, FunctionVariableMap &Functions)
bool isReallyAClobber(const Value *Ptr, MemoryDef *Def, AAResults *AA)
Given a Def clobbering a load from Ptr according to the MSSA check if this is actually a memory updat...
LDSUsesInfoTy getTransitiveUsesOfLDS(const CallGraph &CG, Module &M)
static TargetExtType * getTargetExtType(const GlobalVariable &GV)
DenseMap< Function *, DenseSet< GlobalVariable * > > FunctionVariableMap
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
bool isLDSVariableToLower(const GlobalVariable &GV)
bool eliminateConstantExprUsesOfLDSFromAllInstructions(Module &M)
Align getAlign(const DataLayout &DL, const GlobalVariable *GV)
void copyMetadataForWidenedLoad(LoadInst &Dest, const LoadInst &Source)
bool isClobberedInFunction(const LoadInst *Load, MemorySSA *MSSA, AAResults *AA)
Check is a Load is clobbered in its function.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.
LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
This struct is a compact representation of a valid (non-zero power of two) alignment.