LLVM: lib/Target/AMDGPU/AMDGPUMemoryUtils.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

19#include "llvm/IR/IntrinsicsAMDGPU.h"

21

22#define DEBUG_TYPE "amdgpu-memory-utils"

23

24using namespace llvm;

25

27

32

33

34

35

36

37

38

39

40

41

44 while (true) {

46 return TTy;

48 if (STy->getNumElements() != 1)

49 return nullptr;

50 Ty = STy->getElementType(0);

51 continue;

52 }

54 Ty = ATy->getElementType();

55 continue;

56 }

57 return nullptr;

58 }

59}

60

63 return Ty->getName() == "amdgcn.named.barrier" ? Ty : nullptr;

64 return nullptr;

65}

66

75

78 return false;

79 }

81 return true;

82 }

84

85

86

87 return false;

88 }

90

91

92 return false;

93 }

94 return true;

95}

96

98

99

100

101

102

103

104

105

106

107

108

109

110

112 for (auto &GV : M.globals())

116}

117

121

122

123 for (auto &GV : M.globals()) {

125 continue;

130 kernels[F].insert(&GV);

131 else

132 Functions[F].insert(&GV);

133 }

134 }

135 }

136}

137

139

143

144

146 for (Function &F : M.functions()) {

148 if (F.hasAddressTaken(nullptr,

149 false,

150 false,

151 true,

152 false)) {

153 AddressTakenFuncs.insert(&F);

154 }

155 }

156

157

159 for (Function *F : AddressTakenFuncs) {

160 set_union(VariablesReachableThroughFunctionPointer, DirectMapFunction[F]);

161 }

162

163 auto FunctionMakesUnknownCall = [&](const Function *F) -> bool {

164 assert(F->isDeclaration());

166 if (!R.second->getFunction())

167 return true;

168 }

169 return false;

170 };

171

172

174

175

176

177 for (Function &F : M.functions()) {

178 if (F.isDeclaration() && FunctionMakesUnknownCall(&F)) {

181 VariablesReachableThroughFunctionPointer);

182 }

183 }

184 }

185

186

187

188 for (Function &Func : M.functions()) {

189 if (Func.isDeclaration() || isKernel(Func))

190 continue;

191

194

195 while (!wip.empty()) {

197

198

199

200 set_union(TransitiveMapFunction[&Func], DirectMapFunction[F]);

201

203 Function *Ith = R.second->getFunction();

204 if (Ith) {

208 }

209 }

210 }

211 }

212 }

213

214

215

216 for (Function *F : AddressTakenFuncs) {

217 set_union(VariablesReachableThroughFunctionPointer,

218 TransitiveMapFunction[F]);

219 }

220

221

222

224

225 for (Function &Func : M.functions()) {

226 if (Func.isDeclaration() || isKernel(Func))

227 continue;

228

230 Function *Ith = R.second->getFunction();

231 if (Ith) {

232 set_union(IndirectMapKernel[&Func], TransitiveMapFunction[Ith]);

233 }

234 }

235

236

237

238 bool SeesUnknownCalls = [&]() {

241

242 while (!WorkList.empty()) {

244

246 if (!CallRecord.second)

247 continue;

248

249 Function *Callee = CallRecord.second->getFunction();

250 if (!Callee)

251 return true;

252

253 if (Visited.insert(Callee).second)

255 }

256 }

257 return false;

258 }();

259

260 if (SeesUnknownCalls) {

261 set_union(IndirectMapKernel[&Func],

262 VariablesReachableThroughFunctionPointer);

263 }

264 }

265

266

267

268

269

270

271

272

273

274 std::optional HasAbsoluteGVs;

275 bool HasSpecialGVs = false;

276 for (auto &Map : {DirectMapKernel, IndirectMapKernel}) {

277 for (auto &[Fn, GVs] : Map) {

278 for (auto *GV : GVs) {

279 bool IsAbsolute = GV->isAbsoluteSymbolRef();

280 bool IsDirectMapDynLDSGV =

282 if (IsDirectMapDynLDSGV)

283 continue;

285 if (IsAbsolute) {

286 DirectMapKernel[Fn].erase(GV);

287 IndirectMapKernel[Fn].erase(GV);

288 }

289 HasSpecialGVs = true;

290 continue;

291 }

292 if (HasAbsoluteGVs.has_value()) {

293 if (*HasAbsoluteGVs != IsAbsolute) {

295 "module cannot mix absolute and non-absolute LDS GVs");

296 }

297 } else

298 HasAbsoluteGVs = IsAbsolute;

299 }

300 }

301 }

302

303

304

305 if (HasAbsoluteGVs && *HasAbsoluteGVs)

307

308 return {std::move(DirectMapKernel), std::move(IndirectMapKernel),

309 HasSpecialGVs};

310}

311

316

319 bool SeenUnknownCall = false;

320

321 while (!WorkList.empty()) {

323

324 for (auto &CallRecord : *CG[F]) {

325 if (!CallRecord.second)

326 continue;

327

328 Function *Callee = CallRecord.second->getFunction();

329 if (!Callee) {

330 if (!SeenUnknownCall) {

331 SeenUnknownCall = true;

332

333

334

335

338 ExternalCallRecord.second->getFunction();

339 assert(PotentialCallee);

340 if (isKernel(*PotentialCallee)) {

343 }

344 }

345 }

346 } else {

348 Callee->removeFnAttr(Attr);

349 if (Visited.insert(Callee).second)

351 }

352 }

353 }

354}

355

357 Instruction *DefInst = Def->getMemoryInst();

358

360 return false;

361

363 switch (II->getIntrinsicID()) {

364 case Intrinsic::amdgcn_s_barrier:

365 case Intrinsic::amdgcn_s_cluster_barrier:

366 case Intrinsic::amdgcn_s_barrier_signal:

367 case Intrinsic::amdgcn_s_barrier_signal_var:

368 case Intrinsic::amdgcn_s_barrier_signal_isfirst:

369 case Intrinsic::amdgcn_s_barrier_init:

370 case Intrinsic::amdgcn_s_barrier_join:

371 case Intrinsic::amdgcn_s_barrier_wait:

372 case Intrinsic::amdgcn_s_barrier_leave:

373 case Intrinsic::amdgcn_s_get_barrier_state:

374 case Intrinsic::amdgcn_wave_barrier:

375 case Intrinsic::amdgcn_sched_barrier:

376 case Intrinsic::amdgcn_sched_group_barrier:

377 case Intrinsic::amdgcn_iglp_opt:

378 return false;

379 default:

380 break;

381 }

382 }

383

384

385

386 const auto checkNoAlias = [AA, Ptr](auto I) -> bool {

387 return I && AA->isNoAlias(I->getPointerOperand(), Ptr);

388 };

389

392 return false;

393

394 return true;

395}

396

403

404 LLVM_DEBUG(dbgs() << "Checking clobbering of: " << *Load << '\n');

405

406

407

408

409

410

411

412

413

414 while (!WorkList.empty()) {

416 if (!Visited.insert(MA).second)

417 continue;

418

420 continue;

421

423 LLVM_DEBUG(dbgs() << " Def: " << *Def->getMemoryInst() << '\n');

424

427 return true;

428 }

429

432 continue;

433 }

434

436 for (const auto &Use : Phi->incoming_values())

438 }

439

441 return false;

442}

443

444}

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,...

ArrayRef - 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.

bool isConstant() const

If the value is a global constant, its value is immutable throughout the runtime execution of the pro...

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.

StringRef - 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)

Definition AMDGPUMemoryUtils.cpp:67

void removeFnAttrFromReachable(CallGraph &CG, Function *KernelRoot, ArrayRef< StringRef > FnAttrs)

Strip FnAttr attribute from any functions where we may have introduced its use.

Definition AMDGPUMemoryUtils.cpp:312

LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)

void getUsesOfLDSByFunction(const CallGraph &CG, Module &M, FunctionVariableMap &kernels, FunctionVariableMap &Functions)

Definition AMDGPUMemoryUtils.cpp:118

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...

Definition AMDGPUMemoryUtils.cpp:356

LDSUsesInfoTy getTransitiveUsesOfLDS(const CallGraph &CG, Module &M)

Definition AMDGPUMemoryUtils.cpp:138

static TargetExtType * getTargetExtType(const GlobalVariable &GV)

Definition AMDGPUMemoryUtils.cpp:42

DenseMap< Function *, DenseSet< GlobalVariable * > > FunctionVariableMap

TargetExtType * isNamedBarrier(const GlobalVariable &GV)

Definition AMDGPUMemoryUtils.cpp:61

bool isLDSVariableToLower(const GlobalVariable &GV)

Definition AMDGPUMemoryUtils.cpp:76

bool eliminateConstantExprUsesOfLDSFromAllInstructions(Module &M)

Definition AMDGPUMemoryUtils.cpp:97

Align getAlign(const DataLayout &DL, const GlobalVariable *GV)

Definition AMDGPUMemoryUtils.cpp:28

bool isClobberedInFunction(const LoadInst *Load, MemorySSA *MSSA, AAResults *AA)

Check is a Load is clobbered in its function.

Definition AMDGPUMemoryUtils.cpp:397

This is an optimization pass for GlobalISel generic memory operations.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - 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 - 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 - 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.