LLVM 24.0.0git
AMDGPUPromoteAlloca.cpp
Go to the documentation of this file.
1//===-- AMDGPUPromoteAlloca.cpp - Promote Allocas -------------------------===//
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// Eliminates allocas by either converting them into vectors or by migrating
10// them to local address space.
11//
12// Two passes are exposed by this file:
13// - "promote-alloca-to-vector", which runs early in the pipeline and only
14// promotes to vector. Promotion to vector is almost always profitable
15// except when the alloca is too big and the promotion would result in
16// very high register pressure.
17// - "promote-alloca", which does both promotion to vector and LDS and runs
18// much later in the pipeline. This runs after SROA because promoting to
19// LDS is of course less profitable than getting rid of the alloca or
20// vectorizing it, thus we only want to do it when the only alternative is
21// lowering the alloca to stack.
22//
23// Note that both of them exist for the old and new PMs. The new PM passes are
24// declared in AMDGPU.h and the legacy PM ones are declared here.s
25//
26//===----------------------------------------------------------------------===//
27
28#include "AMDGPU.h"
29#include "GCNSubtarget.h"
31#include "llvm/ADT/STLExtras.h"
38#include "llvm/IR/IRBuilder.h"
40#include "llvm/IR/IntrinsicsAMDGPU.h"
41#include "llvm/IR/IntrinsicsR600.h"
44#include "llvm/Pass.h"
48
49#define DEBUG_TYPE "amdgpu-promote-alloca"
50
51using namespace llvm;
52
53namespace {
54
55static cl::opt<bool>
56 DisablePromoteAllocaToVector("disable-promote-alloca-to-vector",
57 cl::desc("Disable promote alloca to vector"),
58 cl::init(false));
59
60static cl::opt<bool>
61 DisablePromoteAllocaToLDS("disable-promote-alloca-to-lds",
62 cl::desc("Disable promote alloca to LDS"),
63 cl::init(false));
64
65static cl::opt<unsigned> PromoteAllocaToVectorLimit(
66 "amdgpu-promote-alloca-to-vector-limit",
67 cl::desc("Maximum byte size to consider promote alloca to vector"),
68 cl::init(0));
69
70static cl::opt<unsigned> PromoteAllocaToVectorMaxRegs(
71 "amdgpu-promote-alloca-to-vector-max-regs",
73 "Maximum vector size (in 32b registers) to use when promoting alloca"),
74 cl::init(32));
75
76// Use up to 1/4 of available register budget for vectorization.
77// FIXME: Increase the limit for whole function budgets? Perhaps x2?
78static cl::opt<unsigned> PromoteAllocaToVectorVGPRRatio(
79 "amdgpu-promote-alloca-to-vector-vgpr-ratio",
80 cl::desc("Ratio of VGPRs to budget for promoting alloca to vectors"),
81 cl::init(4));
82
84 LoopUserWeight("promote-alloca-vector-loop-user-weight",
85 cl::desc("The bonus weight of users of allocas within loop "
86 "when sorting profitable allocas"),
87 cl::init(4));
88
89// We support vector indices of the form ((A * stride) >> shift) + B
90// VarIndex is A, VarMul is stride, VarShift is shift and ConstIndex is B. All
91// parts are optional.
92struct GEPToVectorIndex {
93 WeakTrackingVH VarIndex = nullptr; // defaults to 0
94 ConstantInt *VarMul = nullptr; // defaults to 1
95 ConstantInt *VarShift = nullptr; // defaults to 0
96 ConstantInt *ConstIndex = nullptr; // defaults to 0
97 Value *Full = nullptr;
98};
99
100struct MemTransferInfo {
101 ConstantInt *SrcIndex = nullptr;
102 ConstantInt *DestIndex = nullptr;
103};
104
105// Analysis for planning the different strategies of alloca promotion.
106struct AllocaAnalysis {
107 AllocaInst *Alloca = nullptr;
108 DenseSet<Value *> Pointers;
110 unsigned Score = 0;
111 bool HaveSelectOrPHI = false;
112 struct {
113 FixedVectorType *Ty = nullptr;
115 SmallVector<Instruction *> UsersToRemove;
118 } Vector;
119 struct {
120 bool Enable = false;
121 SmallVector<User *> Worklist;
122 } LDS;
123
124 explicit AllocaAnalysis(AllocaInst *Alloca) : Alloca(Alloca) {}
125};
126
127// Shared implementation which can do both promotion to vector and to LDS.
128class AMDGPUPromoteAllocaImpl {
129private:
130 const TargetMachine &TM;
131 LoopInfo &LI;
132 Module &Mod;
133 const DataLayout &DL;
134
135 // FIXME: This should be per-kernel.
136 uint32_t LocalMemLimit = 0;
137 uint32_t CurrentLocalMemUsage = 0;
138 unsigned MaxVGPRs;
139 unsigned VGPRBudgetRatio;
140 unsigned MaxVectorRegs;
141
142 bool IsAMDGCN = false;
143 bool IsAMDHSA = false;
144
145 std::pair<Value *, Value *> getLocalSizeYZ(IRBuilder<> &Builder);
146 Value *getWorkitemID(IRBuilder<> &Builder, unsigned N);
147
148 bool collectAllocaUses(AllocaAnalysis &AA) const;
149
150 /// Val is a derived pointer from Alloca. OpIdx0/OpIdx1 are the operand
151 /// indices to an instruction with 2 pointer inputs (e.g. select, icmp).
152 /// Returns true if both operands are derived from the same alloca. Val should
153 /// be the same value as one of the input operands of UseInst.
154 bool binaryOpIsDerivedFromSameAlloca(Value *Alloca, Value *Val,
155 Instruction *UseInst, int OpIdx0,
156 int OpIdx1) const;
157
158 /// Check whether we have enough local memory for promotion.
159 bool hasSufficientLocalMem(const Function &F);
160
161 FixedVectorType *getVectorTypeForAlloca(Type *AllocaTy) const;
162 void analyzePromoteToVector(AllocaAnalysis &AA) const;
163 void promoteAllocaToVector(AllocaAnalysis &AA);
164 void analyzePromoteToLDS(AllocaAnalysis &AA) const;
165 bool tryPromoteAllocaToLDS(AllocaAnalysis &AA, bool SufficientLDS,
166 SetVector<IntrinsicInst *> &DeferredIntrs);
167 void
168 finishDeferredAllocaToLDSPromotion(SetVector<IntrinsicInst *> &DeferredIntrs);
169
170 void scoreAlloca(AllocaAnalysis &AA) const;
171
172 void setFunctionLimits(const Function &F);
173
174public:
175 AMDGPUPromoteAllocaImpl(TargetMachine &TM, Module &M, LoopInfo &LI)
176 : TM(TM), LI(LI), Mod(M), DL(M.getDataLayout()) {
177 const Triple &TT = M.getTargetTriple();
178 IsAMDGCN = TT.isAMDGCN();
179 IsAMDHSA = TT.getOS() == Triple::AMDHSA;
180 }
181
182 bool run(Function &F, bool PromoteToLDS);
183};
184
185// FIXME: This can create globals so should be a module pass.
186class AMDGPUPromoteAlloca : public FunctionPass {
187public:
188 static char ID;
189
190 AMDGPUPromoteAlloca() : FunctionPass(ID) {}
191
192 bool runOnFunction(Function &F) override {
193 if (skipFunction(F))
194 return false;
195 if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>())
196 return AMDGPUPromoteAllocaImpl(
197 TPC->getTM<TargetMachine>(), *F.getParent(),
198 getAnalysis<LoopInfoWrapperPass>().getLoopInfo())
199 .run(F, /*PromoteToLDS*/ true);
200 return false;
201 }
202
203 StringRef getPassName() const override { return "AMDGPU Promote Alloca"; }
204
205 void getAnalysisUsage(AnalysisUsage &AU) const override {
206 AU.setPreservesCFG();
209 }
210};
211
212static unsigned getMaxVGPRs(unsigned LDSBytes, const TargetMachine &TM,
213 const Function &F) {
214 const GCNSubtarget &ST = TM.getSubtarget<GCNSubtarget>(F);
215
216 unsigned DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
217 unsigned MaxVGPRs = ST.getMaxNumVGPRs(
218 ST.getWavesPerEU(ST.getFlatWorkGroupSizes(F), LDSBytes, F).first,
219 DynamicVGPRBlockSize);
220
221 // A non-entry function has only 32 caller preserved registers.
222 // Do not promote alloca which will force spilling unless we know the function
223 // will be inlined.
224 if (!F.hasFnAttribute(Attribute::AlwaysInline) &&
225 !AMDGPU::isEntryFunctionCC(F.getCallingConv()))
226 MaxVGPRs = std::min(MaxVGPRs, 32u);
227 return MaxVGPRs;
228}
229
230} // end anonymous namespace
231
232char AMDGPUPromoteAlloca::ID = 0;
233
235 "AMDGPU promote alloca to vector or LDS", false, false)
236// Move LDS uses from functions to kernels before promote alloca for accurate
237// estimation of LDS available
238INITIALIZE_PASS_DEPENDENCY(AMDGPULowerModuleLDSLegacy)
240INITIALIZE_PASS_END(AMDGPUPromoteAlloca, DEBUG_TYPE,
241 "AMDGPU promote alloca to vector or LDS", false, false)
242
243char &llvm::AMDGPUPromoteAllocaID = AMDGPUPromoteAlloca::ID;
244
247 auto &LI = AM.getResult<LoopAnalysis>(F);
248 bool Changed = AMDGPUPromoteAllocaImpl(TM, *F.getParent(), LI)
249 .run(F, /*PromoteToLDS=*/true);
250 if (Changed) {
253 return PA;
254 }
255 return PreservedAnalyses::all();
256}
257
260 auto &LI = AM.getResult<LoopAnalysis>(F);
261 bool Changed = AMDGPUPromoteAllocaImpl(TM, *F.getParent(), LI)
262 .run(F, /*PromoteToLDS=*/false);
263 if (Changed) {
266 return PA;
267 }
268 return PreservedAnalyses::all();
269}
270
272 return new AMDGPUPromoteAlloca();
273}
274
275bool AMDGPUPromoteAllocaImpl::collectAllocaUses(AllocaAnalysis &AA) const {
276 const auto RejectUser = [&](Instruction *Inst, Twine Msg) {
277 LLVM_DEBUG(dbgs() << " Cannot promote alloca: " << Msg << "\n"
278 << " " << *Inst << "\n");
279 return false;
280 };
281
282 SmallVector<Instruction *, 4> WorkList({AA.Alloca});
283 while (!WorkList.empty()) {
284 auto *Cur = WorkList.pop_back_val();
285 if (find(AA.Pointers, Cur) != AA.Pointers.end())
286 continue;
287 AA.Pointers.insert(Cur);
288 for (auto &U : Cur->uses()) {
289 auto *Inst = cast<Instruction>(U.getUser());
290 if (isa<StoreInst>(Inst)) {
291 if (U.getOperandNo() != StoreInst::getPointerOperandIndex()) {
292 return RejectUser(Inst, "pointer escapes via store");
293 }
294 }
295 AA.Uses.push_back(&U);
296
297 if (isa<GetElementPtrInst>(U.getUser())) {
298 WorkList.push_back(Inst);
299 } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
300 // Only promote a select if we know that the other select operand is
301 // from another pointer that will also be promoted.
302 if (!binaryOpIsDerivedFromSameAlloca(AA.Alloca, Cur, SI, 1, 2))
303 return RejectUser(Inst, "select from mixed objects");
304 WorkList.push_back(Inst);
305 AA.HaveSelectOrPHI = true;
306 } else if (auto *Phi = dyn_cast<PHINode>(Inst)) {
307 // Repeat for phis.
308
309 // TODO: Handle more complex cases. We should be able to replace loops
310 // over arrays.
311 switch (Phi->getNumIncomingValues()) {
312 case 1:
313 break;
314 case 2:
315 if (!binaryOpIsDerivedFromSameAlloca(AA.Alloca, Cur, Phi, 0, 1))
316 return RejectUser(Inst, "phi from mixed objects");
317 break;
318 default:
319 return RejectUser(Inst, "phi with too many operands");
320 }
321
322 WorkList.push_back(Inst);
323 AA.HaveSelectOrPHI = true;
324 }
325 }
326 }
327 return true;
328}
329
330void AMDGPUPromoteAllocaImpl::scoreAlloca(AllocaAnalysis &AA) const {
331 LLVM_DEBUG(dbgs() << "Scoring: " << *AA.Alloca << "\n");
332 unsigned Score = 0;
333 // Increment score by one for each user + a bonus for users within loops.
334 for (auto *U : AA.Uses) {
335 Instruction *Inst = cast<Instruction>(U->getUser());
336 if (isa<GetElementPtrInst>(Inst) || isa<SelectInst>(Inst) ||
337 isa<PHINode>(Inst))
338 continue;
339 unsigned UserScore =
340 1 + (LoopUserWeight * LI.getLoopDepth(Inst->getParent()));
341 LLVM_DEBUG(dbgs() << " [+" << UserScore << "]:\t" << *Inst << "\n");
342 Score += UserScore;
343 }
344 LLVM_DEBUG(dbgs() << " => Final Score:" << Score << "\n");
345 AA.Score = Score;
346}
347
348void AMDGPUPromoteAllocaImpl::setFunctionLimits(const Function &F) {
349 // Load per function limits, overriding with global options where appropriate.
350 // R600 register tuples/aliasing are fragile with large vector promotions so
351 // apply architecture specific limit here.
352 const int R600MaxVectorRegs = 16;
353 MaxVectorRegs = F.getFnAttributeAsParsedInteger(
354 "amdgpu-promote-alloca-to-vector-max-regs",
355 IsAMDGCN ? PromoteAllocaToVectorMaxRegs : R600MaxVectorRegs);
356 if (PromoteAllocaToVectorMaxRegs.getNumOccurrences())
357 MaxVectorRegs = PromoteAllocaToVectorMaxRegs;
358 VGPRBudgetRatio = F.getFnAttributeAsParsedInteger(
359 "amdgpu-promote-alloca-to-vector-vgpr-ratio",
360 PromoteAllocaToVectorVGPRRatio);
361 if (PromoteAllocaToVectorVGPRRatio.getNumOccurrences())
362 VGPRBudgetRatio = PromoteAllocaToVectorVGPRRatio;
363}
364
365bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) {
366 if (DisablePromoteAllocaToLDS && DisablePromoteAllocaToVector)
367 return false;
368
369 bool SufficientLDS = PromoteToLDS && hasSufficientLocalMem(F);
370 MaxVGPRs = IsAMDGCN ? getMaxVGPRs(CurrentLocalMemUsage, TM, F) : 128;
371 setFunctionLimits(F);
372
373 unsigned VectorizationBudget =
374 (PromoteAllocaToVectorLimit ? PromoteAllocaToVectorLimit * 8
375 : (MaxVGPRs * 32)) /
376 VGPRBudgetRatio;
377
378 std::vector<AllocaAnalysis> Allocas;
379 for (Instruction &I : F.getEntryBlock()) {
380 if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
381 // Array allocations are probably not worth handling, since an allocation
382 // of the array type is the canonical form.
383 if (!AI->isStaticAlloca() || AI->isArrayAllocation())
384 continue;
385
386 LLVM_DEBUG(dbgs() << "Analyzing: " << *AI << '\n');
387
388 AllocaAnalysis AA{AI};
389 if (collectAllocaUses(AA)) {
390 analyzePromoteToVector(AA);
391 if (PromoteToLDS)
392 analyzePromoteToLDS(AA);
393 if (AA.Vector.Ty || AA.LDS.Enable) {
394 scoreAlloca(AA);
395 Allocas.push_back(std::move(AA));
396 }
397 }
398 }
399 }
400
401 stable_sort(Allocas,
402 [](const auto &A, const auto &B) { return A.Score > B.Score; });
403
404 // clang-format off
406 dbgs() << "Sorted Worklist:\n";
407 for (const auto &AA : Allocas)
408 dbgs() << " " << *AA.Alloca << "\n";
409 );
410 // clang-format on
411
412 bool Changed = false;
413 SetVector<IntrinsicInst *> DeferredIntrs;
414 for (AllocaAnalysis &AA : Allocas) {
415 if (AA.Vector.Ty) {
416 std::optional<TypeSize> Size = AA.Alloca->getAllocationSize(DL);
417 assert(Size); // Expected to succeed on non-array alloca.
418 const unsigned AllocaCost = Size->getFixedValue() * 8;
419 // First, check if we have enough budget to vectorize this alloca.
420 if (AllocaCost <= VectorizationBudget) {
421 promoteAllocaToVector(AA);
422 Changed = true;
423 assert((VectorizationBudget - AllocaCost) < VectorizationBudget &&
424 "Underflow!");
425 VectorizationBudget -= AllocaCost;
426 LLVM_DEBUG(dbgs() << " Remaining vectorization budget:"
427 << VectorizationBudget << "\n");
428 continue;
429 } else {
430 LLVM_DEBUG(dbgs() << "Alloca too big for vectorization (size:"
431 << AllocaCost << ", budget:" << VectorizationBudget
432 << "): " << *AA.Alloca << "\n");
433 }
434 }
435
436 if (AA.LDS.Enable &&
437 tryPromoteAllocaToLDS(AA, SufficientLDS, DeferredIntrs))
438 Changed = true;
439 }
440 finishDeferredAllocaToLDSPromotion(DeferredIntrs);
441
442 // NOTE: tryPromoteAllocaToVector removes the alloca, so Allocas contains
443 // dangling pointers. If we want to reuse it past this point, the loop above
444 // would need to be updated to remove successfully promoted allocas.
445
446 return Changed;
447}
448
449// Checks if the instruction I is a memset user of the alloca AI that we can
450// deal with. Currently, only non-volatile memsets that affect the whole alloca
451// are handled.
453 const DataLayout &DL) {
454 using namespace PatternMatch;
455 // For now we only care about non-volatile memsets that affect the whole type
456 // (start at index 0 and fill the whole alloca).
457 //
458 // TODO: Now that we moved to PromoteAlloca we could handle any memsets
459 // (except maybe volatile ones?) - we just need to use shufflevector if it
460 // only affects a subset of the vector.
461 const unsigned Size = DL.getTypeStoreSize(AI->getAllocatedType());
462 return I->getOperand(0) == AI &&
463 match(I->getOperand(2), m_SpecificInt(Size)) && !I->isVolatile();
464}
465
466static Value *calculateVectorIndex(Value *Ptr, AllocaAnalysis &AA) {
467 IRBuilder<> B(Ptr->getContext());
468
469 Ptr = Ptr->stripPointerCasts();
470 if (Ptr == AA.Alloca)
471 return B.getInt32(0);
472
473 auto *GEP = cast<GetElementPtrInst>(Ptr);
474 auto I = AA.Vector.GEPVectorIdx.find(GEP);
475 assert(I != AA.Vector.GEPVectorIdx.end() && "Must have entry for GEP!");
476
477 if (!I->second.Full) {
478 Value *Result = nullptr;
479 B.SetInsertPoint(GEP);
480
481 if (I->second.VarIndex) {
482 Result = I->second.VarIndex;
483 Result = B.CreateSExtOrTrunc(Result, B.getInt32Ty());
484
485 if (I->second.VarMul)
486 Result = B.CreateMul(Result, I->second.VarMul);
487
488 if (I->second.VarShift)
489 Result = B.CreateAShr(Result, I->second.VarShift, "", /*isExact*/ true);
490 }
491
492 if (I->second.ConstIndex) {
493 if (Result)
494 Result = B.CreateAdd(Result, I->second.ConstIndex);
495 else
496 Result = I->second.ConstIndex;
497 }
498
499 if (!Result)
500 Result = B.getInt32(0);
501
502 I->second.Full = Result;
503 }
504
505 return I->second.Full;
506}
507
508static std::optional<GEPToVectorIndex>
510 Type *VecElemTy, const DataLayout &DL) {
511 // TODO: Extracting a "multiple of X" from a GEP might be a useful generic
512 // helper.
513 LLVMContext &Ctx = GEP->getContext();
514 unsigned BW = DL.getIndexTypeSizeInBits(GEP->getType());
516 APInt ConstOffset(BW, 0);
517
518 // Walk backwards through nested GEPs to collect both constant and variable
519 // offsets, so that nested vector GEP chains can be lowered in one step.
520 //
521 // Given this IR fragment as input:
522 //
523 // %0 = alloca [10 x <2 x i32>], align 8, addrspace(5)
524 // %1 = getelementptr [10 x <2 x i32>], ptr addrspace(5) %0, i32 0, i32 %j
525 // %2 = getelementptr i8, ptr addrspace(5) %1, i32 4
526 // %3 = load i32, ptr addrspace(5) %2, align 4
527 //
528 // Combine both GEP operations in a single pass, producing:
529 // BasePtr = %0
530 // ConstOffset = 4
531 // VarOffsets = { %j -> element_size(<2 x i32>) }
532 //
533 // That lets us emit a single buffer_load directly into a VGPR, without ever
534 // allocating scratch memory for the intermediate pointer.
535 Value *CurPtr = GEP;
536 while (auto *CurGEP = dyn_cast<GetElementPtrInst>(CurPtr)) {
537 if (!CurGEP->collectOffset(DL, BW, VarOffsets, ConstOffset))
538 return {};
539
540 // Move to the next outer pointer.
541 CurPtr = CurGEP->getPointerOperand();
542 }
543
544 assert(CurPtr == Alloca && "GEP not based on alloca");
545
546 int64_t VecElemSize = DL.getTypeAllocSize(VecElemTy);
547 if (VarOffsets.size() > 1)
548 return {};
549
550 // We support vector indices of the form ((VarIndex * stride) >> shift) + B.
551 // IndexQuot represents B. Check that the constant offset is a multiple
552 // of the vector element size.
553 if (ConstOffset.srem(VecElemSize) != 0)
554 return {};
555 APInt IndexQuot = ConstOffset.sdiv(VecElemSize);
556
557 GEPToVectorIndex Result;
558
559 if (!ConstOffset.isZero())
560 Result.ConstIndex = ConstantInt::get(Ctx, IndexQuot.sextOrTrunc(BW));
561
562 // If there are no variable offsets, only a constant offset, then we're done.
563 if (VarOffsets.empty())
564 return Result;
565
566 // Scale is the stride in the (A * stride) part. Check that there is only one
567 // variable offset and extract the scale factor.
568 const auto &VarOffset = VarOffsets.front();
569 auto ScaleOpt = VarOffset.second.tryZExtValue();
570 if (!ScaleOpt || *ScaleOpt == 0)
571 return {};
572
573 uint64_t Scale = *ScaleOpt;
574 Result.VarIndex = VarOffset.first;
575 auto *OffsetType = dyn_cast<IntegerType>(Result.VarIndex->getType());
576 if (!OffsetType)
577 return {};
578
579 // The vector index for the variable part is: VarIndex * Scale / VecElemSize.
580 if (Scale >= (uint64_t)VecElemSize) {
581 if (Scale % VecElemSize != 0)
582 return {};
583
584 // Scale is a multiple of VecElemSize, so the index is just: VarIndex *
585 // (Scale / VecElemSize).
586 uint64_t VarMul = Scale / VecElemSize;
587 // Only the multiplier is needed.
588 if (VarMul != 1)
589 Result.VarMul = ConstantInt::get(Ctx, APInt(BW, VarMul));
590 } else {
591 if ((uint64_t)VecElemSize % Scale != 0)
592 return {};
593
594 // VecElemSize is a multiple of Scale, so the index is just: VarIndex /
595 // (VecElemSize / Scale).
596 uint64_t Divisor = VecElemSize / Scale;
597 // The divisor must be a power of 2 so we can use a right shift.
598 if (!isPowerOf2_64(Divisor))
599 return {};
600
601 // VarIndex must be known to be divisible by that divisor.
602 KnownBits KB = computeKnownBits(VarOffset.first, DL);
603 if (KB.countMinTrailingZeros() < Log2_64(Divisor))
604 return {};
605
606 Result.VarShift = ConstantInt::get(Ctx, APInt(BW, Log2_64(Divisor)));
607 }
608
609 return Result;
610}
611
612/// Promotes a single user of the alloca to a vector form.
613///
614/// \param Inst Instruction to be promoted.
615/// \param DL Module Data Layout.
616/// \param AA Alloca Analysis.
617/// \param VecStoreSize Size of \p VectorTy in bytes.
618/// \param ElementSize Size of \p VectorTy element type in bytes.
619/// \param CurVal Current value of the vector (e.g. last stored value)
620/// \param[out] DeferredLoads \p Inst is added to this vector if it can't
621/// be promoted now. This happens when promoting requires \p
622/// CurVal, but \p CurVal is nullptr.
623/// \return the stored value if \p Inst would have written to the alloca, or
624/// nullptr otherwise.
626 AllocaAnalysis &AA,
627 unsigned VecStoreSize,
628 unsigned ElementSize,
629 function_ref<Value *()> GetCurVal) {
630 // Note: we use InstSimplifyFolder because it can leverage the DataLayout
631 // to do more folding, especially in the case of vector splats.
634 Builder.SetInsertPoint(Inst);
635
636 Type *VecEltTy = AA.Vector.Ty->getElementType();
637
638 switch (Inst->getOpcode()) {
639 case Instruction::Load: {
640 Value *CurVal = GetCurVal();
641 Value *Index =
643
644 // We're loading the full vector.
645 Type *AccessTy = Inst->getType();
646 TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
647 if (Constant *CI = dyn_cast<Constant>(Index)) {
648 if (CI->isNullValue() && AccessSize == VecStoreSize) {
649 Inst->replaceAllUsesWith(
650 Builder.CreateBitPreservingCastChain(DL, CurVal, AccessTy));
651 return nullptr;
652 }
653 }
654
655 // Loading a subvector, or a scalar that spans several elements.
656 TypeSize EltSize = DL.getTypeStoreSize(VecEltTy);
657 assert(AccessSize.isKnownMultipleOf(EltSize) &&
658 "promotable access must cover a whole number of elements");
659 const unsigned NumLoadedElts = AccessSize / EltSize;
660 if (NumLoadedElts > 1) {
661 auto *SubVecTy = FixedVectorType::get(VecEltTy, NumLoadedElts);
662 assert(DL.getTypeStoreSize(SubVecTy) == DL.getTypeStoreSize(AccessTy));
663
664 // If idx is dynamic, then sandwich load with bitcasts.
665 // ie. VectorTy SubVecTy AccessTy
666 // <64 x i8> -> <16 x i8> <8 x i16>
667 // <64 x i8> -> <4 x i128> -> i128 -> <8 x i16>
668 // Extracting subvector with dynamic index has very large expansion in
669 // the amdgpu backend. Limit to pow2.
670 FixedVectorType *VectorTy = AA.Vector.Ty;
671 TypeSize NumBits = DL.getTypeStoreSize(SubVecTy) * 8u;
672 uint64_t LoadAlign = cast<LoadInst>(Inst)->getAlign().value();
673 bool IsAlignedLoad = NumBits <= (LoadAlign * 8u);
674 unsigned TotalNumElts = VectorTy->getNumElements();
675 bool IsProperlyDivisible = TotalNumElts % NumLoadedElts == 0;
676 if (!isa<ConstantInt>(Index) &&
677 llvm::isPowerOf2_32(SubVecTy->getNumElements()) &&
678 IsProperlyDivisible && IsAlignedLoad) {
679 IntegerType *NewElemTy = Builder.getIntNTy(NumBits);
680 const unsigned NewNumElts =
681 DL.getTypeStoreSize(VectorTy) * 8u / NumBits;
682 const unsigned LShrAmt = llvm::Log2_32(SubVecTy->getNumElements());
683 FixedVectorType *BitCastTy =
684 FixedVectorType::get(NewElemTy, NewNumElts);
685 Value *BCVal =
686 Builder.CreateBitPreservingCastChain(DL, CurVal, BitCastTy);
687 Value *NewIdx = Builder.CreateLShr(
688 Index, ConstantInt::get(Index->getType(), LShrAmt));
689 Value *ExtVal = Builder.CreateExtractElement(BCVal, NewIdx);
690 Value *BCOut =
691 Builder.CreateBitPreservingCastChain(DL, ExtVal, AccessTy);
692 Inst->replaceAllUsesWith(BCOut);
693 return nullptr;
694 }
695
696 Value *SubVec = PoisonValue::get(SubVecTy);
697 for (unsigned K = 0; K < NumLoadedElts; ++K) {
698 Value *CurIdx =
699 Builder.CreateAdd(Index, ConstantInt::get(Index->getType(), K));
700 SubVec = Builder.CreateInsertElement(
701 SubVec, Builder.CreateExtractElement(CurVal, CurIdx), K);
702 }
703
704 Inst->replaceAllUsesWith(
705 Builder.CreateBitPreservingCastChain(DL, SubVec, AccessTy));
706 return nullptr;
707 }
708
709 // We're loading one element.
710 Value *ExtractElement = Builder.CreateExtractElement(CurVal, Index);
711 if (AccessTy != VecEltTy)
712 ExtractElement = Builder.CreateBitOrPointerCast(ExtractElement, AccessTy);
713
714 Inst->replaceAllUsesWith(ExtractElement);
715 return nullptr;
716 }
717 case Instruction::Store: {
718 // For stores, it's a bit trickier and it depends on whether we're storing
719 // the full vector or not. If we're storing the full vector, we don't need
720 // to know the current value. If this is a store of a single element, we
721 // need to know the value.
723 Value *Index = calculateVectorIndex(SI->getPointerOperand(), AA);
724 Value *Val = SI->getValueOperand();
725
726 // We're storing the full vector, we can handle this without knowing CurVal.
727 Type *AccessTy = Val->getType();
728 TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
729 if (Constant *CI = dyn_cast<Constant>(Index)) {
730 if (CI->isNullValue() && AccessSize == VecStoreSize) {
731 Value *Result =
732 Builder.CreateBitPreservingCastChain(DL, Val, AA.Vector.Ty);
733 // If Result is a load from this alloca, it will later be RAUW'd and
734 // deleted. The SSAUpdater holds a raw Value* that RAUW doesn't update,
735 // leaving a dangling pointer. Wrap in a freeze to create a fresh value
736 // the SSAUpdater can safely hold; the freeze's operand is a proper IR
737 // use that RAUW does update.
738 if (isa<LoadInst>(Result))
739 Result = Builder.CreateFreeze(Result);
740 return Result;
741 }
742 }
743
744 // Storing a subvector, or a scalar that spans several elements.
745 TypeSize EltSize = DL.getTypeStoreSize(VecEltTy);
746 assert(AccessSize.isKnownMultipleOf(EltSize) &&
747 "promotable access must cover a whole number of elements");
748 const unsigned NumWrittenElts = AccessSize / EltSize;
749 if (NumWrittenElts > 1) {
750 const unsigned NumVecElts = AA.Vector.Ty->getNumElements();
751 auto *SubVecTy = FixedVectorType::get(VecEltTy, NumWrittenElts);
752 assert(DL.getTypeStoreSize(SubVecTy) == DL.getTypeStoreSize(AccessTy));
753
754 Val = Builder.CreateBitPreservingCastChain(DL, Val, SubVecTy);
755 Value *CurVec = GetCurVal();
756 for (unsigned K = 0, NumElts = std::min(NumWrittenElts, NumVecElts);
757 K < NumElts; ++K) {
758 Value *CurIdx =
759 Builder.CreateAdd(Index, ConstantInt::get(Index->getType(), K));
760 CurVec = Builder.CreateInsertElement(
761 CurVec, Builder.CreateExtractElement(Val, K), CurIdx);
762 }
763 return CurVec;
764 }
765
766 if (Val->getType() != VecEltTy)
767 Val = Builder.CreateBitOrPointerCast(Val, VecEltTy);
768 return Builder.CreateInsertElement(GetCurVal(), Val, Index);
769 }
770 case Instruction::Call: {
771 if (auto *MTI = dyn_cast<MemTransferInst>(Inst)) {
772 // For memcpy, we need to know curval.
773 ConstantInt *Length = cast<ConstantInt>(MTI->getLength());
774 unsigned NumCopied = Length->getZExtValue() / ElementSize;
775 MemTransferInfo *TI = &AA.Vector.TransferInfo[MTI];
776 unsigned SrcBegin = TI->SrcIndex->getZExtValue();
777 unsigned DestBegin = TI->DestIndex->getZExtValue();
778
779 SmallVector<int> Mask;
780 for (unsigned Idx = 0; Idx < AA.Vector.Ty->getNumElements(); ++Idx) {
781 if (Idx >= DestBegin && Idx < DestBegin + NumCopied) {
782 Mask.push_back(SrcBegin < AA.Vector.Ty->getNumElements()
783 ? SrcBegin++
785 } else {
786 Mask.push_back(Idx);
787 }
788 }
789
790 return Builder.CreateShuffleVector(GetCurVal(), Mask);
791 }
792
793 if (auto *MSI = dyn_cast<MemSetInst>(Inst)) {
794 // For memset, we don't need to know the previous value because we
795 // currently only allow memsets that cover the whole alloca.
796 Value *Elt = MSI->getOperand(1);
797 const unsigned BytesPerElt = DL.getTypeStoreSize(VecEltTy);
798 if (BytesPerElt > 1) {
799 Value *EltBytes = Builder.CreateVectorSplat(BytesPerElt, Elt);
800
801 // If the element type of the vector is a pointer, we need to first cast
802 // to an integer, then use a PtrCast.
803 if (VecEltTy->isPointerTy()) {
804 Type *PtrInt = Builder.getIntNTy(BytesPerElt * 8);
805 Elt = Builder.CreateBitCast(EltBytes, PtrInt);
806 Elt = Builder.CreateIntToPtr(Elt, VecEltTy);
807 } else
808 Elt = Builder.CreateBitCast(EltBytes, VecEltTy);
809 }
810
811 return Builder.CreateVectorSplat(AA.Vector.Ty->getElementCount(), Elt);
812 }
813
814 if (auto *Intr = dyn_cast<IntrinsicInst>(Inst)) {
815 if (Intr->getIntrinsicID() == Intrinsic::objectsize) {
816 Intr->replaceAllUsesWith(
817 Builder.getIntN(Intr->getType()->getIntegerBitWidth(),
818 DL.getTypeAllocSize(AA.Vector.Ty)));
819 return nullptr;
820 }
821 }
822
823 llvm_unreachable("Unsupported call when promoting alloca to vector");
824 }
825
826 default:
827 llvm_unreachable("Inconsistency in instructions promotable to vector");
828 }
829
830 llvm_unreachable("Did not return after promoting instruction!");
831}
832
833static bool isSupportedAccessType(FixedVectorType *VecTy, Type *AccessTy,
834 const DataLayout &DL) {
835 // An access that covers several elements can work if its size is a multiple
836 // of the size of the alloca's vector element type, since it can be split
837 // across consecutive elements. This covers accesses by a vector type, as well
838 // as scalar accesses that are wider than one element, which happens when an
839 // object is written one element at a time but read back in wider pieces.
840 //
841 // Examples:
842 // - VecTy = <8 x float>, AccessTy = <4 x float> -> OK
843 // - VecTy = <4 x double>, AccessTy = <2 x float> -> OK
844 // - VecTy = <4 x double>, AccessTy = <3 x float> -> NOT OK
845 // - 3*32 is not a multiple of 64
846 // - VecTy = <8 x i32>, AccessTy = i64 -> OK
847 //
848 // We could handle more complicated cases, but it'd make things a lot more
849 // complicated.
850 if (isa<FixedVectorType>(AccessTy) || AccessTy->isIntegerTy() ||
851 AccessTy->isFloatingPointTy()) {
852 TypeSize AccTS = DL.getTypeStoreSize(AccessTy);
853 TypeSize VecTS = DL.getTypeStoreSize(VecTy->getElementType());
854 // If the type size and the store size don't match, we would need to do more
855 // than just bitcast to translate between an extracted/insertable subvectors
856 // and the accessed value.
857 if (AccTS * 8 == DL.getTypeSizeInBits(AccessTy) && AccTS > VecTS &&
858 AccTS.isKnownMultipleOf(VecTS))
859 return true;
860 }
861
862 // An access that covers exactly one element only needs a cast.
864 DL);
865}
866
867/// Iterates over an instruction worklist that may contain multiple instructions
868/// from the same basic block, but in a different order.
869template <typename InstContainer>
870static void forEachWorkListItem(const InstContainer &WorkList,
871 std::function<void(Instruction *)> Fn) {
872 // Bucket up uses of the alloca by the block they occur in.
873 // This is important because we have to handle multiple defs/uses in a block
874 // ourselves: SSAUpdater is purely for cross-block references.
876 for (Instruction *User : WorkList)
877 UsesByBlock[User->getParent()].insert(User);
878
879 for (Instruction *User : WorkList) {
880 BasicBlock *BB = User->getParent();
881 auto &BlockUses = UsesByBlock[BB];
882
883 // Already processed, skip.
884 if (BlockUses.empty())
885 continue;
886
887 // Only user in the block, directly process it.
888 if (BlockUses.size() == 1) {
889 Fn(User);
890 continue;
891 }
892
893 // Multiple users in the block, do a linear scan to see users in order.
894 for (Instruction &Inst : *BB) {
895 if (!BlockUses.contains(&Inst))
896 continue;
897
898 Fn(&Inst);
899 }
900
901 // Clear the block so we know it's been processed.
902 BlockUses.clear();
903 }
904}
905
906/// Find an insert point after an alloca, after all other allocas clustered at
907/// the start of the block.
910 for (BasicBlock::iterator E = BB.end(); I != E && isa<AllocaInst>(*I); ++I)
911 ;
912 return I;
913}
914
916AMDGPUPromoteAllocaImpl::getVectorTypeForAlloca(Type *AllocaTy) const {
917 if (DisablePromoteAllocaToVector) {
918 LLVM_DEBUG(dbgs() << " Promote alloca to vectors is disabled\n");
919 return nullptr;
920 }
921
922 auto *VectorTy = dyn_cast<FixedVectorType>(AllocaTy);
923 if (auto *ArrayTy = dyn_cast<ArrayType>(AllocaTy)) {
924 uint64_t NumElems = 1;
925 Type *ElemTy;
926 do {
927 NumElems *= ArrayTy->getNumElements();
928 ElemTy = ArrayTy->getElementType();
929 } while ((ArrayTy = dyn_cast<ArrayType>(ElemTy)));
930
931 // Check for array of vectors
932 auto *InnerVectorTy = dyn_cast<FixedVectorType>(ElemTy);
933 if (InnerVectorTy) {
934 NumElems *= InnerVectorTy->getNumElements();
935 ElemTy = InnerVectorTy->getElementType();
936 }
937
938 if (VectorType::isValidElementType(ElemTy) && NumElems > 0) {
939 unsigned ElementSize = DL.getTypeSizeInBits(ElemTy) / 8;
940 if (ElementSize > 0) {
941 unsigned AllocaSize = DL.getTypeStoreSize(AllocaTy);
942 // Expand vector if required to match padding of inner type,
943 // i.e. odd size subvectors.
944 // Storage size of new vector must match that of alloca for correct
945 // behaviour of byte offsets and GEP computation.
946 if (NumElems * ElementSize != AllocaSize)
947 NumElems = AllocaSize / ElementSize;
948 if (NumElems > 0 && (AllocaSize % ElementSize) == 0)
949 VectorTy = FixedVectorType::get(ElemTy, NumElems);
950 }
951 }
952 }
953 if (!VectorTy) {
954 LLVM_DEBUG(dbgs() << " Cannot convert type to vector\n");
955 return nullptr;
956 }
957
958 const unsigned MaxElements =
959 (MaxVectorRegs * 32) / DL.getTypeSizeInBits(VectorTy->getElementType());
960
961 if (VectorTy->getNumElements() > MaxElements ||
962 VectorTy->getNumElements() < 2) {
963 LLVM_DEBUG(dbgs() << " " << *VectorTy
964 << " has an unsupported number of elements\n");
965 return nullptr;
966 }
967
968 Type *VecEltTy = VectorTy->getElementType();
969 unsigned ElementSizeInBits = DL.getTypeSizeInBits(VecEltTy);
970 if (ElementSizeInBits != DL.getTypeAllocSizeInBits(VecEltTy)) {
971 LLVM_DEBUG(dbgs() << " Cannot convert to vector if the allocation size "
972 "does not match the type's size\n");
973 return nullptr;
974 }
975
976 return VectorTy;
977}
978
979void AMDGPUPromoteAllocaImpl::analyzePromoteToVector(AllocaAnalysis &AA) const {
980 if (AA.HaveSelectOrPHI) {
981 LLVM_DEBUG(dbgs() << " Cannot convert to vector due to select or phi\n");
982 return;
983 }
984
985 Type *AllocaTy = AA.Alloca->getAllocatedType();
986 AA.Vector.Ty = getVectorTypeForAlloca(AllocaTy);
987 if (!AA.Vector.Ty)
988 return;
989
990 const auto RejectUser = [&](Instruction *Inst, Twine Msg) {
991 LLVM_DEBUG(dbgs() << " Cannot promote alloca to vector: " << Msg << "\n"
992 << " " << *Inst << "\n");
993 AA.Vector.Ty = nullptr;
994 };
995
996 Type *VecEltTy = AA.Vector.Ty->getElementType();
997 unsigned ElementSize = DL.getTypeSizeInBits(VecEltTy) / 8;
998 assert(ElementSize > 0);
999 for (auto *U : AA.Uses) {
1000 Instruction *Inst = cast<Instruction>(U->getUser());
1001
1002 if (Value *Ptr = getLoadStorePointerOperand(Inst)) {
1003 assert(!isa<StoreInst>(Inst) ||
1004 U->getOperandNo() == StoreInst::getPointerOperandIndex());
1005
1006 Type *AccessTy = getLoadStoreType(Inst);
1007 if (AccessTy->isAggregateType())
1008 return RejectUser(Inst, "unsupported load/store as aggregate");
1009 assert(!AccessTy->isAggregateType() || AccessTy->isArrayTy());
1010
1011 // Check that this is a simple access of a vector element.
1012 bool IsSimple = isa<LoadInst>(Inst) ? cast<LoadInst>(Inst)->isSimple()
1013 : cast<StoreInst>(Inst)->isSimple();
1014 if (!IsSimple)
1015 return RejectUser(Inst, "not a simple load or store");
1016
1017 Ptr = Ptr->stripPointerCasts();
1018
1019 // Alloca already accessed as vector.
1020 if (Ptr == AA.Alloca &&
1021 DL.getTypeStoreSize(AA.Alloca->getAllocatedType()) ==
1022 DL.getTypeStoreSize(AccessTy)) {
1023 AA.Vector.Worklist.push_back(Inst);
1024 continue;
1025 }
1026
1027 if (!isSupportedAccessType(AA.Vector.Ty, AccessTy, DL))
1028 return RejectUser(Inst, "not a supported access type");
1029
1030 AA.Vector.Worklist.push_back(Inst);
1031 continue;
1032 }
1033
1034 if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
1035 // If we can't compute a vector index from this GEP, then we can't
1036 // promote this alloca to vector.
1037 auto Index = computeGEPToVectorIndex(GEP, AA.Alloca, VecEltTy, DL);
1038 if (!Index)
1039 return RejectUser(Inst, "cannot compute vector index for GEP");
1040
1041 AA.Vector.GEPVectorIdx[GEP] = std::move(Index.value());
1042 AA.Vector.UsersToRemove.push_back(Inst);
1043 continue;
1044 }
1045
1046 if (MemSetInst *MSI = dyn_cast<MemSetInst>(Inst);
1047 MSI && isSupportedMemset(MSI, AA.Alloca, DL)) {
1048 AA.Vector.Worklist.push_back(Inst);
1049 continue;
1050 }
1051
1052 if (MemTransferInst *TransferInst = dyn_cast<MemTransferInst>(Inst)) {
1053 if (TransferInst->isVolatile())
1054 return RejectUser(Inst, "mem transfer inst is volatile");
1055
1056 ConstantInt *Len = dyn_cast<ConstantInt>(TransferInst->getLength());
1057 if (!Len || (Len->getZExtValue() % ElementSize))
1058 return RejectUser(Inst, "mem transfer inst length is non-constant or "
1059 "not a multiple of the vector element size");
1060
1061 auto getConstIndexIntoAlloca = [&](Value *Ptr) -> ConstantInt * {
1062 if (Ptr == AA.Alloca)
1063 return ConstantInt::get(Ptr->getContext(), APInt(32, 0));
1064
1066 const auto &GEPI = AA.Vector.GEPVectorIdx.find(GEP)->second;
1067 if (GEPI.VarIndex)
1068 return nullptr;
1069 if (GEPI.ConstIndex)
1070 return GEPI.ConstIndex;
1071 return ConstantInt::get(Ptr->getContext(), APInt(32, 0));
1072 };
1073
1074 MemTransferInfo *TI =
1075 &AA.Vector.TransferInfo.try_emplace(TransferInst).first->second;
1076 unsigned OpNum = U->getOperandNo();
1077 if (OpNum == 0) {
1078 Value *Dest = TransferInst->getDest();
1079 ConstantInt *Index = getConstIndexIntoAlloca(Dest);
1080 if (!Index)
1081 return RejectUser(Inst, "could not calculate constant dest index");
1082 TI->DestIndex = Index;
1083 } else {
1084 assert(OpNum == 1);
1085 Value *Src = TransferInst->getSource();
1086 ConstantInt *Index = getConstIndexIntoAlloca(Src);
1087 if (!Index)
1088 return RejectUser(Inst, "could not calculate constant src index");
1089 TI->SrcIndex = Index;
1090 }
1091 continue;
1092 }
1093
1094 if (auto *Intr = dyn_cast<IntrinsicInst>(Inst)) {
1095 if (Intr->getIntrinsicID() == Intrinsic::objectsize) {
1096 AA.Vector.Worklist.push_back(Inst);
1097 continue;
1098 }
1099 }
1100
1101 // Ignore assume-like intrinsics and comparisons used in assumes.
1102 if (isAssumeLikeIntrinsic(Inst)) {
1103 if (!Inst->use_empty())
1104 return RejectUser(Inst, "assume-like intrinsic cannot have any users");
1105 AA.Vector.UsersToRemove.push_back(Inst);
1106 continue;
1107 }
1108
1109 if (isa<ICmpInst>(Inst) && all_of(Inst->users(), [](User *U) {
1110 return isAssumeLikeIntrinsic(cast<Instruction>(U));
1111 })) {
1112 AA.Vector.UsersToRemove.push_back(Inst);
1113 continue;
1114 }
1115
1116 return RejectUser(Inst, "unhandled alloca user");
1117 }
1118
1119 // Follow-up check to ensure we've seen both sides of all transfer insts.
1120 for (const auto &Entry : AA.Vector.TransferInfo) {
1121 const MemTransferInfo &TI = Entry.second;
1122 if (!TI.SrcIndex || !TI.DestIndex)
1123 return RejectUser(Entry.first,
1124 "mem transfer inst between different objects");
1125 AA.Vector.Worklist.push_back(Entry.first);
1126 }
1127}
1128
1129void AMDGPUPromoteAllocaImpl::promoteAllocaToVector(AllocaAnalysis &AA) {
1130 LLVM_DEBUG(dbgs() << "Promoting to vectors: " << *AA.Alloca << '\n');
1131 LLVM_DEBUG(dbgs() << " type conversion: " << *AA.Alloca->getAllocatedType()
1132 << " -> " << *AA.Vector.Ty << '\n');
1133 const unsigned VecStoreSize = DL.getTypeStoreSize(AA.Vector.Ty);
1134
1135 Type *VecEltTy = AA.Vector.Ty->getElementType();
1136 const unsigned ElementSize = DL.getTypeSizeInBits(VecEltTy) / 8;
1137
1138 // Alloca is uninitialized memory. Imitate that by making the first value
1139 // undef.
1140 SSAUpdater Updater;
1141 Updater.Initialize(AA.Vector.Ty, "promotealloca");
1142
1143 BasicBlock *EntryBB = AA.Alloca->getParent();
1144 BasicBlock::iterator InitInsertPos =
1145 skipToNonAllocaInsertPt(*EntryBB, AA.Alloca->getIterator());
1146 IRBuilder<> Builder(&*InitInsertPos);
1147 Value *AllocaInitValue = Builder.CreateFreeze(PoisonValue::get(AA.Vector.Ty));
1148 AllocaInitValue->takeName(AA.Alloca);
1149
1150 Updater.AddAvailableValue(AA.Alloca->getParent(), AllocaInitValue);
1151
1152 // First handle the initial worklist, in basic block order.
1153 //
1154 // Insert a placeholder whenever we need the vector value at the top of a
1155 // basic block.
1157 forEachWorkListItem(AA.Vector.Worklist, [&](Instruction *I) {
1158 BasicBlock *BB = I->getParent();
1159 auto GetCurVal = [&]() -> Value * {
1160 if (Value *CurVal = Updater.FindValueForBlock(BB))
1161 return CurVal;
1162
1163 if (!Placeholders.empty() && Placeholders.back()->getParent() == BB)
1164 return Placeholders.back();
1165
1166 // If the current value in the basic block is not yet known, insert a
1167 // placeholder that we will replace later.
1168 IRBuilder<> Builder(I);
1169 auto *Placeholder = cast<Instruction>(Builder.CreateFreeze(
1170 PoisonValue::get(AA.Vector.Ty), "promotealloca.placeholder"));
1171 Placeholders.insert(Placeholder);
1172 return Placeholders.back();
1173 };
1174
1175 Value *Result = promoteAllocaUserToVector(I, DL, AA, VecStoreSize,
1176 ElementSize, GetCurVal);
1177 // If the returned result is a placeholder, it means the instruction does
1178 // not really modify the alloca. So no need to make it being available value
1179 // to SSAUpdater.
1180 // This will stop placeholder being cached in SSAUpdater. The cached
1181 // placeholder may cause stale pointer being referenced when doing
1182 // placeholder replacement.
1183 if (Result && (!isa<Instruction>(Result) ||
1184 !Placeholders.contains(cast<Instruction>(Result))))
1185 Updater.AddAvailableValue(BB, Result);
1186 });
1187
1188 // Now fixup the placeholders.
1189 for (Instruction *Placeholder : Placeholders) {
1190 Placeholder->replaceAllUsesWith(
1191 Updater.GetValueInMiddleOfBlock(Placeholder->getParent()));
1192 Placeholder->eraseFromParent();
1193 }
1194
1195 // Delete all instructions.
1196 for (Instruction *I : AA.Vector.Worklist) {
1197 assert(I->use_empty());
1198 I->eraseFromParent();
1199 }
1200
1201 // Delete all the users that are known to be removeable.
1202 for (Instruction *I : reverse(AA.Vector.UsersToRemove)) {
1203 I->dropDroppableUses();
1204 assert(I->use_empty());
1205 I->eraseFromParent();
1206 }
1207
1208 // Alloca should now be dead too.
1209 assert(AA.Alloca->use_empty());
1210 AA.Alloca->eraseFromParent();
1211}
1212
1213std::pair<Value *, Value *>
1214AMDGPUPromoteAllocaImpl::getLocalSizeYZ(IRBuilder<> &Builder) {
1215 Function &F = *Builder.GetInsertBlock()->getParent();
1217
1218 if (!IsAMDHSA) {
1219 CallInst *LocalSizeY = Builder.CreateIntrinsicWithoutFolding(
1220 Intrinsic::r600_read_local_size_y, {});
1221 CallInst *LocalSizeZ = Builder.CreateIntrinsicWithoutFolding(
1222 Intrinsic::r600_read_local_size_z, {});
1223
1224 ST.makeLIDRangeMetadata(LocalSizeY);
1225 ST.makeLIDRangeMetadata(LocalSizeZ);
1226
1227 return std::pair(LocalSizeY, LocalSizeZ);
1228 }
1229
1230 // We must read the size out of the dispatch pointer.
1231 assert(IsAMDGCN);
1232
1233 // We are indexing into this struct, and want to extract the workgroup_size_*
1234 // fields.
1235 //
1236 // typedef struct hsa_kernel_dispatch_packet_s {
1237 // uint16_t header;
1238 // uint16_t setup;
1239 // uint16_t workgroup_size_x ;
1240 // uint16_t workgroup_size_y;
1241 // uint16_t workgroup_size_z;
1242 // uint16_t reserved0;
1243 // uint32_t grid_size_x ;
1244 // uint32_t grid_size_y ;
1245 // uint32_t grid_size_z;
1246 //
1247 // uint32_t private_segment_size;
1248 // uint32_t group_segment_size;
1249 // uint64_t kernel_object;
1250 //
1251 // #ifdef HSA_LARGE_MODEL
1252 // void *kernarg_address;
1253 // #elif defined HSA_LITTLE_ENDIAN
1254 // void *kernarg_address;
1255 // uint32_t reserved1;
1256 // #else
1257 // uint32_t reserved1;
1258 // void *kernarg_address;
1259 // #endif
1260 // uint64_t reserved2;
1261 // hsa_signal_t completion_signal; // uint64_t wrapper
1262 // } hsa_kernel_dispatch_packet_t
1263 //
1264 CallInst *DispatchPtr =
1265 Builder.CreateIntrinsicWithoutFolding(Intrinsic::amdgcn_dispatch_ptr, {});
1266 DispatchPtr->addRetAttr(Attribute::NoAlias);
1267 DispatchPtr->addRetAttr(Attribute::NonNull);
1268 F.removeFnAttr("amdgpu-no-dispatch-ptr");
1269
1270 // Size of the dispatch packet struct.
1271 DispatchPtr->addDereferenceableRetAttr(64);
1272
1273 Type *I32Ty = Type::getInt32Ty(Mod.getContext());
1274
1275 // We could do a single 64-bit load here, but it's likely that the basic
1276 // 32-bit and extract sequence is already present, and it is probably easier
1277 // to CSE this. The loads should be mergeable later anyway.
1278 Value *GEPXY = Builder.CreateConstInBoundsGEP1_64(I32Ty, DispatchPtr, 1);
1279 LoadInst *LoadXY = Builder.CreateAlignedLoad(I32Ty, GEPXY, Align(4));
1280
1281 Value *GEPZU = Builder.CreateConstInBoundsGEP1_64(I32Ty, DispatchPtr, 2);
1282 LoadInst *LoadZU = Builder.CreateAlignedLoad(I32Ty, GEPZU, Align(4));
1283
1284 MDNode *MD = MDNode::get(Mod.getContext(), {});
1285 LoadXY->setMetadata(LLVMContext::MD_invariant_load, MD);
1286 LoadZU->setMetadata(LLVMContext::MD_invariant_load, MD);
1287 ST.makeLIDRangeMetadata(LoadZU);
1288
1289 // Extract y component. Upper half of LoadZU should be zero already.
1290 Value *Y = Builder.CreateLShr(LoadXY, 16);
1291
1292 return std::pair(Y, LoadZU);
1293}
1294
1295Value *AMDGPUPromoteAllocaImpl::getWorkitemID(IRBuilder<> &Builder,
1296 unsigned N) {
1297 Function *F = Builder.GetInsertBlock()->getParent();
1300 StringRef AttrName;
1301
1302 switch (N) {
1303 case 0:
1304 IntrID = IsAMDGCN ? (Intrinsic::ID)Intrinsic::amdgcn_workitem_id_x
1305 : (Intrinsic::ID)Intrinsic::r600_read_tidig_x;
1306 AttrName = "amdgpu-no-workitem-id-x";
1307 break;
1308 case 1:
1309 IntrID = IsAMDGCN ? (Intrinsic::ID)Intrinsic::amdgcn_workitem_id_y
1310 : (Intrinsic::ID)Intrinsic::r600_read_tidig_y;
1311 AttrName = "amdgpu-no-workitem-id-y";
1312 break;
1313
1314 case 2:
1315 IntrID = IsAMDGCN ? (Intrinsic::ID)Intrinsic::amdgcn_workitem_id_z
1316 : (Intrinsic::ID)Intrinsic::r600_read_tidig_z;
1317 AttrName = "amdgpu-no-workitem-id-z";
1318 break;
1319 default:
1320 llvm_unreachable("invalid dimension");
1321 }
1322
1323 Function *WorkitemIdFn = Intrinsic::getOrInsertDeclaration(&Mod, IntrID);
1324 CallInst *CI = Builder.CreateCall(WorkitemIdFn);
1325 ST.makeLIDRangeMetadata(CI);
1326 F->removeFnAttr(AttrName);
1327
1328 return CI;
1329}
1330
1331static bool isCallPromotable(CallInst *CI) {
1333 if (!II)
1334 return false;
1335
1336 switch (II->getIntrinsicID()) {
1337 case Intrinsic::memcpy:
1338 case Intrinsic::memmove:
1339 case Intrinsic::memset:
1340 case Intrinsic::lifetime_start:
1341 case Intrinsic::lifetime_end:
1342 case Intrinsic::invariant_start:
1343 case Intrinsic::invariant_end:
1344 case Intrinsic::launder_invariant_group:
1345 case Intrinsic::strip_invariant_group:
1346 case Intrinsic::objectsize:
1347 return true;
1348 default:
1349 return false;
1350 }
1351}
1352
1353bool AMDGPUPromoteAllocaImpl::binaryOpIsDerivedFromSameAlloca(
1354 Value *BaseAlloca, Value *Val, Instruction *Inst, int OpIdx0,
1355 int OpIdx1) const {
1356 // Figure out which operand is the one we might not be promoting.
1357 Value *OtherOp = Inst->getOperand(OpIdx0);
1358 if (Val == OtherOp)
1359 OtherOp = Inst->getOperand(OpIdx1);
1360
1362 return true;
1363
1364 // TODO: getUnderlyingObject will not work on a vector getelementptr
1365 Value *OtherObj = getUnderlyingObject(OtherOp);
1366 if (!isa<AllocaInst>(OtherObj))
1367 return false;
1368
1369 // TODO: We should be able to replace undefs with the right pointer type.
1370
1371 // TODO: If we know the other base object is another promotable
1372 // alloca, not necessarily this alloca, we can do this. The
1373 // important part is both must have the same address space at
1374 // the end.
1375 if (OtherObj != BaseAlloca) {
1376 LLVM_DEBUG(
1377 dbgs() << "Found a binary instruction with another alloca object\n");
1378 return false;
1379 }
1380
1381 return true;
1382}
1383
1384void AMDGPUPromoteAllocaImpl::analyzePromoteToLDS(AllocaAnalysis &AA) const {
1385 if (DisablePromoteAllocaToLDS) {
1386 LLVM_DEBUG(dbgs() << " Promote alloca to LDS is disabled\n");
1387 return;
1388 }
1389
1390 // Don't promote the alloca to LDS for shader calling conventions as the work
1391 // item ID intrinsics are not supported for these calling conventions.
1392 // Furthermore not all LDS is available for some of the stages.
1393 const Function &ContainingFunction = *AA.Alloca->getFunction();
1394 CallingConv::ID CC = ContainingFunction.getCallingConv();
1395
1396 switch (CC) {
1399 break;
1400 default:
1401 LLVM_DEBUG(
1402 dbgs()
1403 << " promote alloca to LDS not supported with calling convention.\n");
1404 return;
1405 }
1406
1407 for (Use *Use : AA.Uses) {
1408 auto *User = Use->getUser();
1409
1410 if (CallInst *CI = dyn_cast<CallInst>(User)) {
1411 if (!isCallPromotable(CI))
1412 return;
1413
1414 if (find(AA.LDS.Worklist, User) == AA.LDS.Worklist.end())
1415 AA.LDS.Worklist.push_back(User);
1416 continue;
1417 }
1418
1420 if (UseInst->getOpcode() == Instruction::PtrToInt)
1421 return;
1422
1423 if (LoadInst *LI = dyn_cast<LoadInst>(UseInst)) {
1424 if (LI->isVolatile())
1425 return;
1426 continue;
1427 }
1428
1429 if (StoreInst *SI = dyn_cast<StoreInst>(UseInst)) {
1430 if (SI->isVolatile())
1431 return;
1432 continue;
1433 }
1434
1435 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(UseInst)) {
1436 if (RMW->isVolatile())
1437 return;
1438 continue;
1439 }
1440
1441 if (AtomicCmpXchgInst *CAS = dyn_cast<AtomicCmpXchgInst>(UseInst)) {
1442 if (CAS->isVolatile())
1443 return;
1444 continue;
1445 }
1446
1447 // Only promote a select if we know that the other select operand
1448 // is from another pointer that will also be promoted.
1449 if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
1450 if (!binaryOpIsDerivedFromSameAlloca(AA.Alloca, Use->get(), ICmp, 0, 1))
1451 return;
1452
1453 // May need to rewrite constant operands.
1454 if (find(AA.LDS.Worklist, User) == AA.LDS.Worklist.end())
1455 AA.LDS.Worklist.push_back(ICmp);
1456 continue;
1457 }
1458
1460 // Be conservative if an address could be computed outside the bounds of
1461 // the alloca.
1462 if (!GEP->isInBounds())
1463 return;
1465 // Do not promote vector/aggregate type instructions. It is hard to track
1466 // their users.
1467
1468 // Do not promote addrspacecast.
1469 //
1470 // TODO: If we know the address is only observed through flat pointers, we
1471 // could still promote.
1472 return;
1473 }
1474
1475 if (find(AA.LDS.Worklist, User) == AA.LDS.Worklist.end())
1476 AA.LDS.Worklist.push_back(User);
1477 }
1478
1479 AA.LDS.Enable = true;
1480}
1481
1482bool AMDGPUPromoteAllocaImpl::hasSufficientLocalMem(const Function &F) {
1483
1484 FunctionType *FTy = F.getFunctionType();
1486
1487 // If the function has any arguments in the local address space, then it's
1488 // possible these arguments require the entire local memory space, so
1489 // we cannot use local memory in the pass.
1490 for (Type *ParamTy : FTy->params()) {
1491 PointerType *PtrTy = dyn_cast<PointerType>(ParamTy);
1492 if (PtrTy && PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
1493 LocalMemLimit = 0;
1494 LLVM_DEBUG(dbgs() << "Function has local memory argument. Promoting to "
1495 "local memory disabled.\n");
1496 return false;
1497 }
1498 }
1499
1500 LocalMemLimit = ST.getAddressableLocalMemorySize();
1501 if (LocalMemLimit == 0)
1502 return false;
1503
1505 SmallPtrSet<const Constant *, 8> VisitedConstants;
1507
1508 auto visitUsers = [&](const GlobalVariable *GV, const Constant *Val) -> bool {
1509 for (const User *U : Val->users()) {
1510 if (const Instruction *Use = dyn_cast<Instruction>(U)) {
1511 if (Use->getFunction() == &F)
1512 return true;
1513 } else {
1514 const Constant *C = cast<Constant>(U);
1515 if (VisitedConstants.insert(C).second)
1516 Stack.push_back(C);
1517 }
1518 }
1519
1520 return false;
1521 };
1522
1523 for (GlobalVariable &GV : Mod.globals()) {
1525 continue;
1526
1527 if (visitUsers(&GV, &GV)) {
1528 UsedLDS.insert(&GV);
1529 Stack.clear();
1530 continue;
1531 }
1532
1533 // For any ConstantExpr uses, we need to recursively search the users until
1534 // we see a function.
1535 while (!Stack.empty()) {
1536 const Constant *C = Stack.pop_back_val();
1537 if (visitUsers(&GV, C)) {
1538 UsedLDS.insert(&GV);
1539 Stack.clear();
1540 break;
1541 }
1542 }
1543 }
1544
1545 SmallVector<std::pair<uint64_t, Align>, 16> AllocatedSizes;
1546 AllocatedSizes.reserve(UsedLDS.size());
1547
1548 for (const GlobalVariable *GV : UsedLDS) {
1550 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
1551 uint64_t AllocSize = GV->getGlobalSize(DL);
1552
1553 // HIP uses an extern unsized array in local address space for dynamically
1554 // allocated shared memory. In that case, we have to disable the promotion.
1555 if (GV->hasExternalLinkage() && AllocSize == 0) {
1556 LocalMemLimit = 0;
1557 LLVM_DEBUG(dbgs() << "Function has a reference to externally allocated "
1558 "local memory. Promoting to local memory "
1559 "disabled.\n");
1560 return false;
1561 }
1562
1563 AllocatedSizes.emplace_back(AllocSize, Alignment);
1564 }
1565
1566 // Sort to try to estimate the worst case alignment padding
1567 //
1568 // FIXME: We should really do something to fix the addresses to a more optimal
1569 // value instead
1570 llvm::sort(AllocatedSizes, llvm::less_second());
1571
1572 // Check how much local memory is being used by global objects
1573 CurrentLocalMemUsage = 0;
1574
1575 // FIXME: Try to account for padding here. The real padding and address is
1576 // currently determined from the inverse order of uses in the function when
1577 // legalizing, which could also potentially change. We try to estimate the
1578 // worst case here, but we probably should fix the addresses earlier.
1579 for (auto Alloc : AllocatedSizes) {
1580 CurrentLocalMemUsage = alignTo(CurrentLocalMemUsage, Alloc.second);
1581 CurrentLocalMemUsage += Alloc.first;
1582 }
1583
1584 unsigned MaxOccupancy =
1585 ST.getWavesPerEU(ST.getFlatWorkGroupSizes(F), CurrentLocalMemUsage, F)
1586 .second;
1587
1588 // Round up to the next tier of usage.
1589 unsigned MaxSizeWithWaveCount =
1590 ST.getMaxLocalMemSizeWithWaveCount(MaxOccupancy, F);
1591
1592 // Program may already use more LDS than is usable at maximum occupancy.
1593 if (CurrentLocalMemUsage > MaxSizeWithWaveCount)
1594 return false;
1595
1596 LocalMemLimit = MaxSizeWithWaveCount;
1597
1598 LLVM_DEBUG(dbgs() << F.getName() << " uses " << CurrentLocalMemUsage
1599 << " bytes of LDS\n"
1600 << " Rounding size to " << MaxSizeWithWaveCount
1601 << " with a maximum occupancy of " << MaxOccupancy << '\n'
1602 << " and " << (LocalMemLimit - CurrentLocalMemUsage)
1603 << " available for promotion\n");
1604
1605 return true;
1606}
1607
1608// FIXME: Should try to pick the most likely to be profitable allocas first.
1609bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToLDS(
1610 AllocaAnalysis &AA, bool SufficientLDS,
1611 SetVector<IntrinsicInst *> &DeferredIntrs) {
1612 LLVM_DEBUG(dbgs() << "Trying to promote to LDS: " << *AA.Alloca << '\n');
1613
1614 // Not likely to have sufficient local memory for promotion.
1615 if (!SufficientLDS)
1616 return false;
1617
1618 IRBuilder<> Builder(AA.Alloca);
1619
1620 const Function &ContainingFunction = *AA.Alloca->getParent()->getParent();
1621 const AMDGPUSubtarget &ST = AMDGPUSubtarget::get(TM, ContainingFunction);
1622 unsigned WorkGroupSize = ST.getFlatWorkGroupSizes(ContainingFunction).second;
1623
1624 Align Alignment = AA.Alloca->getAlign();
1625
1626 // FIXME: This computed padding is likely wrong since it depends on inverse
1627 // usage order.
1628 //
1629 // FIXME: It is also possible that if we're allowed to use all of the memory
1630 // could end up using more than the maximum due to alignment padding.
1631
1632 uint32_t NewSize = alignTo(CurrentLocalMemUsage, Alignment);
1633 std::optional<TypeSize> ElemSize = AA.Alloca->getAllocationSize(DL);
1634 if (!ElemSize || ElemSize->isScalable())
1635 return false;
1636 TypeSize AllocSize = WorkGroupSize * *ElemSize;
1637 NewSize += AllocSize.getFixedValue();
1638
1639 if (NewSize > LocalMemLimit) {
1640 LLVM_DEBUG(dbgs() << " " << AllocSize
1641 << " bytes of local memory not available to promote\n");
1642 return false;
1643 }
1644
1645 CurrentLocalMemUsage = NewSize;
1646
1647 LLVM_DEBUG(dbgs() << "Promoting alloca to local memory\n");
1648
1649 Function *F = AA.Alloca->getFunction();
1650
1651 Type *GVTy = ArrayType::get(AA.Alloca->getAllocatedType(), WorkGroupSize);
1654 Twine(F->getName()) + Twine('.') + AA.Alloca->getName(), nullptr,
1657 GV->setAlignment(AA.Alloca->getAlign());
1658
1659 Value *TCntY, *TCntZ;
1660
1661 std::tie(TCntY, TCntZ) = getLocalSizeYZ(Builder);
1662 Value *TIdX = getWorkitemID(Builder, 0);
1663 Value *TIdY = getWorkitemID(Builder, 1);
1664 Value *TIdZ = getWorkitemID(Builder, 2);
1665
1666 Value *Tmp0 = Builder.CreateMul(TCntY, TCntZ, "", true, true);
1667 Tmp0 = Builder.CreateMul(Tmp0, TIdX);
1668 Value *Tmp1 = Builder.CreateMul(TIdY, TCntZ, "", true, true);
1669 Value *TID = Builder.CreateAdd(Tmp0, Tmp1);
1670 TID = Builder.CreateAdd(TID, TIdZ);
1671
1672 LLVMContext &Context = Mod.getContext();
1674
1675 Value *Offset = Builder.CreateInBoundsGEP(GVTy, GV, Indices);
1676 AA.Alloca->mutateType(Offset->getType());
1677 AA.Alloca->replaceAllUsesWith(Offset);
1678 AA.Alloca->eraseFromParent();
1679
1681
1682 for (Value *V : AA.LDS.Worklist) {
1684 if (!Call) {
1685 if (ICmpInst *CI = dyn_cast<ICmpInst>(V)) {
1686 Value *LHS = CI->getOperand(0);
1687 Value *RHS = CI->getOperand(1);
1688
1689 Type *NewTy = LHS->getType()->getWithNewType(NewPtrTy);
1691 CI->setOperand(0, Constant::getNullValue(NewTy));
1692
1694 CI->setOperand(1, Constant::getNullValue(NewTy));
1695
1696 continue;
1697 }
1698
1699 // The operand's value should be corrected on its own and we don't want to
1700 // touch the users.
1702 continue;
1703
1704 assert(V->getType()->isPtrOrPtrVectorTy());
1705
1706 Type *NewTy = V->getType()->getWithNewType(NewPtrTy);
1707 V->mutateType(NewTy);
1708
1709 // Adjust the types of any constant operands.
1712 SI->setOperand(1, Constant::getNullValue(NewTy));
1713
1715 SI->setOperand(2, Constant::getNullValue(NewTy));
1716 } else if (PHINode *Phi = dyn_cast<PHINode>(V)) {
1717 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) {
1719 Phi->getIncomingValue(I)))
1720 Phi->setIncomingValue(I, Constant::getNullValue(NewTy));
1721 }
1722 }
1723
1724 continue;
1725 }
1726
1728 Builder.SetInsertPoint(Intr);
1729 switch (Intr->getIntrinsicID()) {
1730 case Intrinsic::lifetime_start:
1731 case Intrinsic::lifetime_end:
1732 // These intrinsics are for address space 0 only
1733 Intr->eraseFromParent();
1734 continue;
1735 case Intrinsic::memcpy:
1736 case Intrinsic::memmove:
1737 // These have 2 pointer operands. In case if second pointer also needs
1738 // to be replaced we defer processing of these intrinsics until all
1739 // other values are processed.
1740 DeferredIntrs.insert(Intr);
1741 continue;
1742 case Intrinsic::memset: {
1743 MemSetInst *MemSet = cast<MemSetInst>(Intr);
1744 Builder.CreateMemSet(MemSet->getRawDest(), MemSet->getValue(),
1745 MemSet->getLength(), MemSet->getDestAlign(),
1746 MemSet->isVolatile());
1747 Intr->eraseFromParent();
1748 continue;
1749 }
1750 case Intrinsic::invariant_start:
1751 case Intrinsic::invariant_end:
1752 case Intrinsic::launder_invariant_group:
1753 case Intrinsic::strip_invariant_group: {
1754 assert(Intr->getArgOperand(Intr->arg_size() - 1)->getType() == NewPtrTy &&
1755 "pointer operand should already have been promoted");
1757 Intr->getModule(), Intr->getIntrinsicID(), NewPtrTy);
1758 Intr->mutateType(NewF->getReturnType());
1759 Intr->setCalledFunction(NewF);
1760 continue;
1761 }
1762 case Intrinsic::objectsize: {
1763 Value *Src = Intr->getOperand(0);
1764
1765 Value *NewCall = Builder.CreateIntrinsic(
1766 Intrinsic::objectsize,
1768 {Src, Intr->getOperand(1), Intr->getOperand(2), Intr->getOperand(3)});
1769 Intr->replaceAllUsesWith(NewCall);
1770 Intr->eraseFromParent();
1771 continue;
1772 }
1773 default:
1774 Intr->print(errs());
1775 llvm_unreachable("Don't know how to promote alloca intrinsic use.");
1776 }
1777 }
1778
1779 return true;
1780}
1781
1782void AMDGPUPromoteAllocaImpl::finishDeferredAllocaToLDSPromotion(
1783 SetVector<IntrinsicInst *> &DeferredIntrs) {
1784
1785 for (IntrinsicInst *Intr : DeferredIntrs) {
1786 IRBuilder<> Builder(Intr);
1787 Builder.SetInsertPoint(Intr);
1789 assert(ID == Intrinsic::memcpy || ID == Intrinsic::memmove);
1790
1792 auto *B = Builder.CreateMemTransferInst(
1793 ID, MI->getRawDest(), MI->getDestAlign(), MI->getRawSource(),
1794 MI->getSourceAlign(), MI->getLength(), MI->isVolatile());
1795
1796 for (unsigned I = 0; I != 2; ++I) {
1797 if (uint64_t Bytes = Intr->getParamDereferenceableBytes(I)) {
1798 B->addDereferenceableParamAttr(I, Bytes);
1799 }
1800 }
1801
1802 Intr->eraseFromParent();
1803 }
1804}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static Value * promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL, AllocaAnalysis &AA, unsigned VecStoreSize, unsigned ElementSize, function_ref< Value *()> GetCurVal)
Promotes a single user of the alloca to a vector form.
AMDGPU promote alloca to vector or LDS
static bool isSupportedAccessType(FixedVectorType *VecTy, Type *AccessTy, const DataLayout &DL)
static void forEachWorkListItem(const InstContainer &WorkList, std::function< void(Instruction *)> Fn)
Iterates over an instruction worklist that may contain multiple instructions from the same basic bloc...
static std::optional< GEPToVectorIndex > computeGEPToVectorIndex(GetElementPtrInst *GEP, AllocaInst *Alloca, Type *VecElemTy, const DataLayout &DL)
static bool isSupportedMemset(MemSetInst *I, AllocaInst *AI, const DataLayout &DL)
static BasicBlock::iterator skipToNonAllocaInsertPt(BasicBlock &BB, BasicBlock::iterator I)
Find an insert point after an alloca, after all other allocas clustered at the start of the block.
static bool isCallPromotable(CallInst *CI)
static Value * calculateVectorIndex(Value *Ptr, AllocaAnalysis &AA)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
@ Enable
static bool runOnFunction(Function &F, bool PostInlining)
AMD GCN specific subclass of TargetSubtarget.
#define DEBUG_TYPE
Hexagon Common GEP
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
Remove Loads Into Fake Uses
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Target-Independent Code Generator Pass Configuration Options pass.
Value * RHS
Value * LHS
static const AMDGPUSubtarget & get(const MachineFunction &MF)
Class for arbitrary precision integers.
Definition APInt.h:78
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:377
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
Definition APInt.cpp:1673
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Definition APInt.cpp:1086
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
Definition APInt.cpp:1774
an instruction to allocate memory on the stack
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:278
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:459
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
uint64_t getParamDereferenceableBytes(unsigned i) const
Extract the number of dereferenceable bytes for a call or parameter (0=unknown).
void addDereferenceableRetAttr(uint64_t Bytes)
adds the dereferenceable attribute to the list of attributes.
void addRetAttr(Attribute::AttrKind Kind)
Adds the attribute to the return value.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI bool isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL)
Check whether a bitcast, inttoptr, or ptrtoint cast between these types is valid and a no-op.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:312
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
Class to represent function types.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:217
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
bool hasExternalLinkage() const
void setUnnamedAddr(UnnamedAddr Val)
unsigned getAddressSpace() const
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
Type * getValueType() const
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
This instruction compares its operands according to the predicate given to the constructor.
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Definition IRBuilder.h:1942
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1540
BasicBlock * GetInsertBlock() const
Definition IRBuilder.h:175
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Definition IRBuilder.h:2027
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Definition IRBuilder.h:608
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1430
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2569
Value * CreateConstInBoundsGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0, const Twine &Name="")
Definition IRBuilder.h:2069
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:181
LLVM_ABI CallInst * CreateMemTransferInst(Intrinsic::ID IntrID, Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, Value *Size, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1464
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2908
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
Definition LoopInfo.h:594
The legacy pass manager's analysis pass to compute loop information.
Definition LoopInfo.h:619
Metadata node.
Definition Metadata.h:1069
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
bool empty() const
Definition MapVector.h:79
size_type size() const
Definition MapVector.h:58
std::pair< KeyT, ValueT > & front()
Definition MapVector.h:81
Value * getLength() const
Value * getRawDest() const
MaybeAlign getDestAlign() const
bool isVolatile() const
Value * getValue() const
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition Pass.cpp:113
Class to represent pointers.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Definition Type.cpp:887
static LLVM_ABI 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.
Definition Analysis.h:112
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
Helper class for SSA formation on a set of values defined in multiple blocks.
Definition SSAUpdater.h:39
LLVM_ABI void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
LLVM_ABI Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
LLVM_ABI void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
This class represents the LLVM 'select' instruction.
A vector that has set insertion semantics.
Definition SetVector.h:57
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
Definition SetVector.h:258
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
size_type size() const
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.
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:345
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
static unsigned getPointerOperandIndex()
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Primary interface to the complete machine description for the target machine.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition Type.h:274
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:314
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:303
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
void setOperand(unsigned i, Value *Val)
Definition User.h:212
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
iterator_range< user_iterator > users()
Definition Value.h:428
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:713
bool use_empty() const
Definition Value.h:348
void mutateType(Type *Ty)
Mutate the type of this Value to be of the specified type.
Definition Value.h:809
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
Type * getElementType() const
Value handle that is nullable, but tries to track the Value.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:180
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
@ LOCAL_ADDRESS
Address space for local memory.
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
unsigned getDynamicVGPRBlockSize(const Function &F)
@ Entry
Definition COFF.h:862
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
bool match(Val *V, const Pattern &P)
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
@ Length
Definition DWP.cpp:577
void stable_sort(R &&Range)
Definition STLExtras.h:2116
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1765
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
LLVM_ABI bool isAssumeLikeIntrinsic(const Instruction *I)
Return true if it is an intrinsic that cannot be speculated but also cannot trap.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
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...
Definition Casting.h:547
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAMDGPUPromoteAlloca()
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
char & AMDGPUPromoteAllocaID
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
#define N
AMDGPUPromoteAllocaPass(TargetMachine &TM)
Definition AMDGPU.h:338
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
Definition KnownBits.h:256
A MapVector that performs no allocations if smaller than a certain size.
Definition MapVector.h:342
Function object to check whether the second component of a container supported by std::get (like std:...
Definition STLExtras.h:1448