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 DVGPR wave launches with a single VGPR block allocated.
222 if (DynamicVGPRBlockSize != 0 &&
223 AMDGPU::isEntryFunctionCC(F.getCallingConv()))
224 MaxVGPRs = std::min(MaxVGPRs, DynamicVGPRBlockSize);
225
226 // A non-entry function has only 32 caller preserved registers.
227 // Do not promote alloca which will force spilling unless we know the function
228 // will be inlined.
229 if (!F.hasFnAttribute(Attribute::AlwaysInline) &&
230 !AMDGPU::isEntryFunctionCC(F.getCallingConv()))
231 MaxVGPRs = std::min(MaxVGPRs, 32u);
232 return MaxVGPRs;
233}
234
235} // end anonymous namespace
236
237char AMDGPUPromoteAlloca::ID = 0;
238
240 "AMDGPU promote alloca to vector or LDS", false, false)
241// Move LDS uses from functions to kernels before promote alloca for accurate
242// estimation of LDS available
243INITIALIZE_PASS_DEPENDENCY(AMDGPULowerModuleLDSLegacy)
245INITIALIZE_PASS_END(AMDGPUPromoteAlloca, DEBUG_TYPE,
246 "AMDGPU promote alloca to vector or LDS", false, false)
247
248char &llvm::AMDGPUPromoteAllocaID = AMDGPUPromoteAlloca::ID;
249
252 auto &LI = AM.getResult<LoopAnalysis>(F);
253 bool Changed = AMDGPUPromoteAllocaImpl(TM, *F.getParent(), LI)
254 .run(F, /*PromoteToLDS=*/true);
255 if (Changed) {
258 return PA;
259 }
260 return PreservedAnalyses::all();
261}
262
265 auto &LI = AM.getResult<LoopAnalysis>(F);
266 bool Changed = AMDGPUPromoteAllocaImpl(TM, *F.getParent(), LI)
267 .run(F, /*PromoteToLDS=*/false);
268 if (Changed) {
271 return PA;
272 }
273 return PreservedAnalyses::all();
274}
275
277 return new AMDGPUPromoteAlloca();
278}
279
280bool AMDGPUPromoteAllocaImpl::collectAllocaUses(AllocaAnalysis &AA) const {
281 const auto RejectUser = [&](Instruction *Inst, Twine Msg) {
282 LLVM_DEBUG(dbgs() << " Cannot promote alloca: " << Msg << "\n"
283 << " " << *Inst << "\n");
284 return false;
285 };
286
287 SmallVector<Instruction *, 4> WorkList({AA.Alloca});
288 while (!WorkList.empty()) {
289 auto *Cur = WorkList.pop_back_val();
290 if (find(AA.Pointers, Cur) != AA.Pointers.end())
291 continue;
292 AA.Pointers.insert(Cur);
293 for (auto &U : Cur->uses()) {
294 auto *Inst = cast<Instruction>(U.getUser());
295 if (isa<StoreInst>(Inst)) {
296 if (U.getOperandNo() != StoreInst::getPointerOperandIndex()) {
297 return RejectUser(Inst, "pointer escapes via store");
298 }
299 }
300 AA.Uses.push_back(&U);
301
302 if (isa<GetElementPtrInst>(U.getUser())) {
303 WorkList.push_back(Inst);
304 } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
305 // Only promote a select if we know that the other select operand is
306 // from another pointer that will also be promoted.
307 if (!binaryOpIsDerivedFromSameAlloca(AA.Alloca, Cur, SI, 1, 2))
308 return RejectUser(Inst, "select from mixed objects");
309 WorkList.push_back(Inst);
310 AA.HaveSelectOrPHI = true;
311 } else if (auto *Phi = dyn_cast<PHINode>(Inst)) {
312 // Repeat for phis.
313
314 // TODO: Handle more complex cases. We should be able to replace loops
315 // over arrays.
316 switch (Phi->getNumIncomingValues()) {
317 case 1:
318 break;
319 case 2:
320 if (!binaryOpIsDerivedFromSameAlloca(AA.Alloca, Cur, Phi, 0, 1))
321 return RejectUser(Inst, "phi from mixed objects");
322 break;
323 default:
324 return RejectUser(Inst, "phi with too many operands");
325 }
326
327 WorkList.push_back(Inst);
328 AA.HaveSelectOrPHI = true;
329 }
330 }
331 }
332 return true;
333}
334
335void AMDGPUPromoteAllocaImpl::scoreAlloca(AllocaAnalysis &AA) const {
336 LLVM_DEBUG(dbgs() << "Scoring: " << *AA.Alloca << "\n");
337 unsigned Score = 0;
338 // Increment score by one for each user + a bonus for users within loops.
339 for (auto *U : AA.Uses) {
340 Instruction *Inst = cast<Instruction>(U->getUser());
341 if (isa<GetElementPtrInst>(Inst) || isa<SelectInst>(Inst) ||
342 isa<PHINode>(Inst))
343 continue;
344 unsigned UserScore =
345 1 + (LoopUserWeight * LI.getLoopDepth(Inst->getParent()));
346 LLVM_DEBUG(dbgs() << " [+" << UserScore << "]:\t" << *Inst << "\n");
347 Score += UserScore;
348 }
349 LLVM_DEBUG(dbgs() << " => Final Score:" << Score << "\n");
350 AA.Score = Score;
351}
352
353void AMDGPUPromoteAllocaImpl::setFunctionLimits(const Function &F) {
354 // Load per function limits, overriding with global options where appropriate.
355 // R600 register tuples/aliasing are fragile with large vector promotions so
356 // apply architecture specific limit here.
357 const int R600MaxVectorRegs = 16;
358 MaxVectorRegs = F.getFnAttributeAsParsedInteger(
359 "amdgpu-promote-alloca-to-vector-max-regs",
360 IsAMDGCN ? PromoteAllocaToVectorMaxRegs : R600MaxVectorRegs);
361 if (PromoteAllocaToVectorMaxRegs.getNumOccurrences())
362 MaxVectorRegs = PromoteAllocaToVectorMaxRegs;
363 VGPRBudgetRatio = F.getFnAttributeAsParsedInteger(
364 "amdgpu-promote-alloca-to-vector-vgpr-ratio",
365 PromoteAllocaToVectorVGPRRatio);
366 if (PromoteAllocaToVectorVGPRRatio.getNumOccurrences())
367 VGPRBudgetRatio = PromoteAllocaToVectorVGPRRatio;
368}
369
370bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) {
371 if (DisablePromoteAllocaToLDS && DisablePromoteAllocaToVector)
372 return false;
373
374 bool SufficientLDS = PromoteToLDS && hasSufficientLocalMem(F);
375 MaxVGPRs = IsAMDGCN ? getMaxVGPRs(CurrentLocalMemUsage, TM, F) : 128;
376 setFunctionLimits(F);
377
378 unsigned VectorizationBudget =
379 (PromoteAllocaToVectorLimit ? PromoteAllocaToVectorLimit * 8
380 : (MaxVGPRs * 32)) /
381 VGPRBudgetRatio;
382
383 std::vector<AllocaAnalysis> Allocas;
384 for (Instruction &I : F.getEntryBlock()) {
385 if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
386 // Array allocations are probably not worth handling, since an allocation
387 // of the array type is the canonical form.
388 if (!AI->isStaticAlloca() || AI->isArrayAllocation())
389 continue;
390
391 LLVM_DEBUG(dbgs() << "Analyzing: " << *AI << '\n');
392
393 AllocaAnalysis AA{AI};
394 if (collectAllocaUses(AA)) {
395 analyzePromoteToVector(AA);
396 if (PromoteToLDS)
397 analyzePromoteToLDS(AA);
398 if (AA.Vector.Ty || AA.LDS.Enable) {
399 scoreAlloca(AA);
400 Allocas.push_back(std::move(AA));
401 }
402 }
403 }
404 }
405
406 stable_sort(Allocas,
407 [](const auto &A, const auto &B) { return A.Score > B.Score; });
408
409 // clang-format off
411 dbgs() << "Sorted Worklist:\n";
412 for (const auto &AA : Allocas)
413 dbgs() << " " << *AA.Alloca << "\n";
414 );
415 // clang-format on
416
417 bool Changed = false;
418 SetVector<IntrinsicInst *> DeferredIntrs;
419 for (AllocaAnalysis &AA : Allocas) {
420 if (AA.Vector.Ty) {
421 std::optional<TypeSize> Size = AA.Alloca->getAllocationSize(DL);
422 assert(Size); // Expected to succeed on non-array alloca.
423 const unsigned AllocaCost = Size->getFixedValue() * 8;
424 // First, check if we have enough budget to vectorize this alloca.
425 if (AllocaCost <= VectorizationBudget) {
426 promoteAllocaToVector(AA);
427 Changed = true;
428 assert((VectorizationBudget - AllocaCost) < VectorizationBudget &&
429 "Underflow!");
430 VectorizationBudget -= AllocaCost;
431 LLVM_DEBUG(dbgs() << " Remaining vectorization budget:"
432 << VectorizationBudget << "\n");
433 continue;
434 } else {
435 LLVM_DEBUG(dbgs() << "Alloca too big for vectorization (size:"
436 << AllocaCost << ", budget:" << VectorizationBudget
437 << "): " << *AA.Alloca << "\n");
438 }
439 }
440
441 if (AA.LDS.Enable &&
442 tryPromoteAllocaToLDS(AA, SufficientLDS, DeferredIntrs))
443 Changed = true;
444 }
445 finishDeferredAllocaToLDSPromotion(DeferredIntrs);
446
447 // NOTE: tryPromoteAllocaToVector removes the alloca, so Allocas contains
448 // dangling pointers. If we want to reuse it past this point, the loop above
449 // would need to be updated to remove successfully promoted allocas.
450
451 return Changed;
452}
453
454// Checks if the instruction I is a memset user of the alloca AI that we can
455// deal with. Currently, only non-volatile memsets that affect the whole alloca
456// are handled.
458 const DataLayout &DL) {
459 using namespace PatternMatch;
460 // For now we only care about non-volatile memsets that affect the whole type
461 // (start at index 0 and fill the whole alloca).
462 //
463 // TODO: Now that we moved to PromoteAlloca we could handle any memsets
464 // (except maybe volatile ones?) - we just need to use shufflevector if it
465 // only affects a subset of the vector.
466 const unsigned Size = DL.getTypeStoreSize(AI->getAllocatedType());
467 return I->getOperand(0) == AI &&
468 match(I->getOperand(2), m_SpecificInt(Size)) && !I->isVolatile();
469}
470
471static Value *calculateVectorIndex(Value *Ptr, AllocaAnalysis &AA) {
472 IRBuilder<> B(Ptr->getContext());
473
474 Ptr = Ptr->stripPointerCasts();
475 if (Ptr == AA.Alloca)
476 return B.getInt32(0);
477
478 auto *GEP = cast<GetElementPtrInst>(Ptr);
479 auto I = AA.Vector.GEPVectorIdx.find(GEP);
480 assert(I != AA.Vector.GEPVectorIdx.end() && "Must have entry for GEP!");
481
482 if (!I->second.Full) {
483 Value *Result = nullptr;
484 B.SetInsertPoint(GEP);
485
486 if (I->second.VarIndex) {
487 Result = I->second.VarIndex;
488 Result = B.CreateSExtOrTrunc(Result, B.getInt32Ty());
489
490 if (I->second.VarMul)
491 Result = B.CreateMul(Result, I->second.VarMul);
492
493 if (I->second.VarShift)
494 Result = B.CreateAShr(Result, I->second.VarShift, "", /*isExact*/ true);
495 }
496
497 if (I->second.ConstIndex) {
498 if (Result)
499 Result = B.CreateAdd(Result, I->second.ConstIndex);
500 else
501 Result = I->second.ConstIndex;
502 }
503
504 if (!Result)
505 Result = B.getInt32(0);
506
507 I->second.Full = Result;
508 }
509
510 return I->second.Full;
511}
512
513static std::optional<GEPToVectorIndex>
515 Type *VecElemTy, const DataLayout &DL) {
516 // TODO: Extracting a "multiple of X" from a GEP might be a useful generic
517 // helper.
518 LLVMContext &Ctx = GEP->getContext();
519 unsigned BW = DL.getIndexTypeSizeInBits(GEP->getType());
521 APInt ConstOffset(BW, 0);
522
523 // Walk backwards through nested GEPs to collect both constant and variable
524 // offsets, so that nested vector GEP chains can be lowered in one step.
525 //
526 // Given this IR fragment as input:
527 //
528 // %0 = alloca [10 x <2 x i32>], align 8, addrspace(5)
529 // %1 = getelementptr [10 x <2 x i32>], ptr addrspace(5) %0, i32 0, i32 %j
530 // %2 = getelementptr i8, ptr addrspace(5) %1, i32 4
531 // %3 = load i32, ptr addrspace(5) %2, align 4
532 //
533 // Combine both GEP operations in a single pass, producing:
534 // BasePtr = %0
535 // ConstOffset = 4
536 // VarOffsets = { %j -> element_size(<2 x i32>) }
537 //
538 // That lets us emit a single buffer_load directly into a VGPR, without ever
539 // allocating scratch memory for the intermediate pointer.
540 Value *CurPtr = GEP;
541 while (auto *CurGEP = dyn_cast<GetElementPtrInst>(CurPtr)) {
542 if (!CurGEP->collectOffset(DL, BW, VarOffsets, ConstOffset))
543 return {};
544
545 // Move to the next outer pointer.
546 CurPtr = CurGEP->getPointerOperand();
547 }
548
549 assert(CurPtr == Alloca && "GEP not based on alloca");
550
551 int64_t VecElemSize = DL.getTypeAllocSize(VecElemTy);
552 if (VarOffsets.size() > 1)
553 return {};
554
555 // We support vector indices of the form ((VarIndex * stride) >> shift) + B.
556 // IndexQuot represents B. Check that the constant offset is a multiple
557 // of the vector element size.
558 if (ConstOffset.srem(VecElemSize) != 0)
559 return {};
560 APInt IndexQuot = ConstOffset.sdiv(VecElemSize);
561
562 GEPToVectorIndex Result;
563
564 if (!ConstOffset.isZero())
565 Result.ConstIndex = ConstantInt::get(Ctx, IndexQuot.sextOrTrunc(BW));
566
567 // If there are no variable offsets, only a constant offset, then we're done.
568 if (VarOffsets.empty())
569 return Result;
570
571 // Scale is the stride in the (A * stride) part. Check that there is only one
572 // variable offset and extract the scale factor.
573 const auto &VarOffset = VarOffsets.front();
574 auto ScaleOpt = VarOffset.second.tryZExtValue();
575 if (!ScaleOpt || *ScaleOpt == 0)
576 return {};
577
578 uint64_t Scale = *ScaleOpt;
579 Result.VarIndex = VarOffset.first;
580 auto *OffsetType = dyn_cast<IntegerType>(Result.VarIndex->getType());
581 if (!OffsetType)
582 return {};
583
584 // The vector index for the variable part is: VarIndex * Scale / VecElemSize.
585 if (Scale >= (uint64_t)VecElemSize) {
586 if (Scale % VecElemSize != 0)
587 return {};
588
589 // Scale is a multiple of VecElemSize, so the index is just: VarIndex *
590 // (Scale / VecElemSize).
591 uint64_t VarMul = Scale / VecElemSize;
592 // Only the multiplier is needed.
593 if (VarMul != 1)
594 Result.VarMul = ConstantInt::get(Ctx, APInt(BW, VarMul));
595 } else {
596 if ((uint64_t)VecElemSize % Scale != 0)
597 return {};
598
599 // VecElemSize is a multiple of Scale, so the index is just: VarIndex /
600 // (VecElemSize / Scale).
601 uint64_t Divisor = VecElemSize / Scale;
602 // The divisor must be a power of 2 so we can use a right shift.
603 if (!isPowerOf2_64(Divisor))
604 return {};
605
606 // VarIndex must be known to be divisible by that divisor.
607 KnownBits KB = computeKnownBits(VarOffset.first, DL);
608 if (KB.countMinTrailingZeros() < Log2_64(Divisor))
609 return {};
610
611 Result.VarShift = ConstantInt::get(Ctx, APInt(BW, Log2_64(Divisor)));
612 }
613
614 return Result;
615}
616
617/// Promotes a single user of the alloca to a vector form.
618///
619/// \param Inst Instruction to be promoted.
620/// \param DL Module Data Layout.
621/// \param AA Alloca Analysis.
622/// \param VecStoreSize Size of \p VectorTy in bytes.
623/// \param ElementSize Size of \p VectorTy element type in bytes.
624/// \param CurVal Current value of the vector (e.g. last stored value)
625/// \param[out] DeferredLoads \p Inst is added to this vector if it can't
626/// be promoted now. This happens when promoting requires \p
627/// CurVal, but \p CurVal is nullptr.
628/// \return the stored value if \p Inst would have written to the alloca, or
629/// nullptr otherwise.
631 AllocaAnalysis &AA,
632 unsigned VecStoreSize,
633 unsigned ElementSize,
634 function_ref<Value *()> GetCurVal) {
635 // Note: we use InstSimplifyFolder because it can leverage the DataLayout
636 // to do more folding, especially in the case of vector splats.
639 Builder.SetInsertPoint(Inst);
640
641 Type *VecEltTy = AA.Vector.Ty->getElementType();
642
643 switch (Inst->getOpcode()) {
644 case Instruction::Load: {
645 Value *CurVal = GetCurVal();
646 Value *Index =
648
649 // We're loading the full vector.
650 Type *AccessTy = Inst->getType();
651 TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
652 if (Constant *CI = dyn_cast<Constant>(Index)) {
653 if (CI->isNullValue() && AccessSize == VecStoreSize) {
654 Inst->replaceAllUsesWith(
655 Builder.CreateBitPreservingCastChain(DL, CurVal, AccessTy));
656 return nullptr;
657 }
658 }
659
660 // Loading a subvector, or a scalar that spans several elements.
661 TypeSize EltSize = DL.getTypeStoreSize(VecEltTy);
662 assert(AccessSize.isKnownMultipleOf(EltSize) &&
663 "promotable access must cover a whole number of elements");
664 const unsigned NumLoadedElts = AccessSize / EltSize;
665 if (NumLoadedElts > 1) {
666 auto *SubVecTy = FixedVectorType::get(VecEltTy, NumLoadedElts);
667 assert(DL.getTypeStoreSize(SubVecTy) == DL.getTypeStoreSize(AccessTy));
668
669 // If idx is dynamic, then sandwich load with bitcasts.
670 // ie. VectorTy SubVecTy AccessTy
671 // <64 x i8> -> <16 x i8> <8 x i16>
672 // <64 x i8> -> <4 x i128> -> i128 -> <8 x i16>
673 // Extracting subvector with dynamic index has very large expansion in
674 // the amdgpu backend. Limit to pow2.
675 FixedVectorType *VectorTy = AA.Vector.Ty;
676 TypeSize NumBits = DL.getTypeStoreSize(SubVecTy) * 8u;
677 uint64_t LoadAlign = cast<LoadInst>(Inst)->getAlign().value();
678 bool IsAlignedLoad = NumBits <= (LoadAlign * 8u);
679 unsigned TotalNumElts = VectorTy->getNumElements();
680 bool IsProperlyDivisible = TotalNumElts % NumLoadedElts == 0;
681 if (!isa<ConstantInt>(Index) &&
682 llvm::isPowerOf2_32(SubVecTy->getNumElements()) &&
683 IsProperlyDivisible && IsAlignedLoad) {
684 IntegerType *NewElemTy = Builder.getIntNTy(NumBits);
685 const unsigned NewNumElts =
686 DL.getTypeStoreSize(VectorTy) * 8u / NumBits;
687 const unsigned LShrAmt = llvm::Log2_32(SubVecTy->getNumElements());
688 FixedVectorType *BitCastTy =
689 FixedVectorType::get(NewElemTy, NewNumElts);
690 Value *BCVal =
691 Builder.CreateBitPreservingCastChain(DL, CurVal, BitCastTy);
692 Value *NewIdx = Builder.CreateLShr(
693 Index, ConstantInt::get(Index->getType(), LShrAmt));
694 Value *ExtVal = Builder.CreateExtractElement(BCVal, NewIdx);
695 Value *BCOut =
696 Builder.CreateBitPreservingCastChain(DL, ExtVal, AccessTy);
697 Inst->replaceAllUsesWith(BCOut);
698 return nullptr;
699 }
700
701 Value *SubVec = PoisonValue::get(SubVecTy);
702 for (unsigned K = 0; K < NumLoadedElts; ++K) {
703 Value *CurIdx =
704 Builder.CreateAdd(Index, ConstantInt::get(Index->getType(), K));
705 SubVec = Builder.CreateInsertElement(
706 SubVec, Builder.CreateExtractElement(CurVal, CurIdx), K);
707 }
708
709 Inst->replaceAllUsesWith(
710 Builder.CreateBitPreservingCastChain(DL, SubVec, AccessTy));
711 return nullptr;
712 }
713
714 // We're loading one element.
715 Value *ExtractElement = Builder.CreateExtractElement(CurVal, Index);
716 if (AccessTy != VecEltTy)
717 ExtractElement = Builder.CreateBitOrPointerCast(ExtractElement, AccessTy);
718
719 Inst->replaceAllUsesWith(ExtractElement);
720 return nullptr;
721 }
722 case Instruction::Store: {
723 // For stores, it's a bit trickier and it depends on whether we're storing
724 // the full vector or not. If we're storing the full vector, we don't need
725 // to know the current value. If this is a store of a single element, we
726 // need to know the value.
728 Value *Index = calculateVectorIndex(SI->getPointerOperand(), AA);
729 Value *Val = SI->getValueOperand();
730
731 // We're storing the full vector, we can handle this without knowing CurVal.
732 Type *AccessTy = Val->getType();
733 TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
734 if (Constant *CI = dyn_cast<Constant>(Index)) {
735 if (CI->isNullValue() && AccessSize == VecStoreSize) {
736 Value *Result =
737 Builder.CreateBitPreservingCastChain(DL, Val, AA.Vector.Ty);
738 // If Result is a load from this alloca, it will later be RAUW'd and
739 // deleted. The SSAUpdater holds a raw Value* that RAUW doesn't update,
740 // leaving a dangling pointer. Wrap in a freeze to create a fresh value
741 // the SSAUpdater can safely hold; the freeze's operand is a proper IR
742 // use that RAUW does update.
743 if (isa<LoadInst>(Result))
744 Result = Builder.CreateFreeze(Result);
745 return Result;
746 }
747 }
748
749 // Storing a subvector, or a scalar that spans several elements.
750 TypeSize EltSize = DL.getTypeStoreSize(VecEltTy);
751 assert(AccessSize.isKnownMultipleOf(EltSize) &&
752 "promotable access must cover a whole number of elements");
753 const unsigned NumWrittenElts = AccessSize / EltSize;
754 if (NumWrittenElts > 1) {
755 const unsigned NumVecElts = AA.Vector.Ty->getNumElements();
756 auto *SubVecTy = FixedVectorType::get(VecEltTy, NumWrittenElts);
757 assert(DL.getTypeStoreSize(SubVecTy) == DL.getTypeStoreSize(AccessTy));
758
759 Val = Builder.CreateBitPreservingCastChain(DL, Val, SubVecTy);
760 Value *CurVec = GetCurVal();
761 for (unsigned K = 0, NumElts = std::min(NumWrittenElts, NumVecElts);
762 K < NumElts; ++K) {
763 Value *CurIdx =
764 Builder.CreateAdd(Index, ConstantInt::get(Index->getType(), K));
765 CurVec = Builder.CreateInsertElement(
766 CurVec, Builder.CreateExtractElement(Val, K), CurIdx);
767 }
768 return CurVec;
769 }
770
771 if (Val->getType() != VecEltTy)
772 Val = Builder.CreateBitOrPointerCast(Val, VecEltTy);
773 return Builder.CreateInsertElement(GetCurVal(), Val, Index);
774 }
775 case Instruction::Call: {
776 if (auto *MTI = dyn_cast<MemTransferInst>(Inst)) {
777 // For memcpy, we need to know curval.
778 ConstantInt *Length = cast<ConstantInt>(MTI->getLength());
779 unsigned NumCopied = Length->getZExtValue() / ElementSize;
780 MemTransferInfo *TI = &AA.Vector.TransferInfo[MTI];
781 unsigned SrcBegin = TI->SrcIndex->getZExtValue();
782 unsigned DestBegin = TI->DestIndex->getZExtValue();
783
784 SmallVector<int> Mask;
785 for (unsigned Idx = 0; Idx < AA.Vector.Ty->getNumElements(); ++Idx) {
786 if (Idx >= DestBegin && Idx < DestBegin + NumCopied) {
787 Mask.push_back(SrcBegin < AA.Vector.Ty->getNumElements()
788 ? SrcBegin++
790 } else {
791 Mask.push_back(Idx);
792 }
793 }
794
795 return Builder.CreateShuffleVector(GetCurVal(), Mask);
796 }
797
798 if (auto *MSI = dyn_cast<MemSetInst>(Inst)) {
799 // For memset, we don't need to know the previous value because we
800 // currently only allow memsets that cover the whole alloca.
801 Value *Elt = MSI->getOperand(1);
802 const unsigned BytesPerElt = DL.getTypeStoreSize(VecEltTy);
803 if (BytesPerElt > 1) {
804 Value *EltBytes = Builder.CreateVectorSplat(BytesPerElt, Elt);
805
806 // If the element type of the vector is a pointer, we need to first cast
807 // to an integer, then use a PtrCast.
808 if (VecEltTy->isPointerTy()) {
809 Type *PtrInt = Builder.getIntNTy(BytesPerElt * 8);
810 Elt = Builder.CreateBitCast(EltBytes, PtrInt);
811 Elt = Builder.CreateIntToPtr(Elt, VecEltTy);
812 } else
813 Elt = Builder.CreateBitCast(EltBytes, VecEltTy);
814 }
815
816 return Builder.CreateVectorSplat(AA.Vector.Ty->getElementCount(), Elt);
817 }
818
819 if (auto *Intr = dyn_cast<IntrinsicInst>(Inst)) {
820 if (Intr->getIntrinsicID() == Intrinsic::objectsize) {
821 Intr->replaceAllUsesWith(
822 Builder.getIntN(Intr->getType()->getIntegerBitWidth(),
823 DL.getTypeAllocSize(AA.Vector.Ty)));
824 return nullptr;
825 }
826 }
827
828 llvm_unreachable("Unsupported call when promoting alloca to vector");
829 }
830
831 default:
832 llvm_unreachable("Inconsistency in instructions promotable to vector");
833 }
834
835 llvm_unreachable("Did not return after promoting instruction!");
836}
837
838static bool isSupportedAccessType(FixedVectorType *VecTy, Type *AccessTy,
839 const DataLayout &DL) {
840 // An access that covers several elements can work if its size is a multiple
841 // of the size of the alloca's vector element type, since it can be split
842 // across consecutive elements. This covers accesses by a vector type, as well
843 // as scalar accesses that are wider than one element, which happens when an
844 // object is written one element at a time but read back in wider pieces.
845 //
846 // Examples:
847 // - VecTy = <8 x float>, AccessTy = <4 x float> -> OK
848 // - VecTy = <4 x double>, AccessTy = <2 x float> -> OK
849 // - VecTy = <4 x double>, AccessTy = <3 x float> -> NOT OK
850 // - 3*32 is not a multiple of 64
851 // - VecTy = <8 x i32>, AccessTy = i64 -> OK
852 //
853 // We could handle more complicated cases, but it'd make things a lot more
854 // complicated.
855 if (isa<FixedVectorType>(AccessTy) || AccessTy->isIntegerTy() ||
856 AccessTy->isFloatingPointTy()) {
857 TypeSize AccTS = DL.getTypeStoreSize(AccessTy);
858 TypeSize VecTS = DL.getTypeStoreSize(VecTy->getElementType());
859 // If the type size and the store size don't match, we would need to do more
860 // than just bitcast to translate between an extracted/insertable subvectors
861 // and the accessed value.
862 if (AccTS * 8 == DL.getTypeSizeInBits(AccessTy) && AccTS > VecTS &&
863 AccTS.isKnownMultipleOf(VecTS))
864 return true;
865 }
866
867 // An access that covers exactly one element only needs a cast.
869 DL);
870}
871
872/// Iterates over an instruction worklist that may contain multiple instructions
873/// from the same basic block, but in a different order.
874template <typename InstContainer>
875static void forEachWorkListItem(const InstContainer &WorkList,
876 std::function<void(Instruction *)> Fn) {
877 // Bucket up uses of the alloca by the block they occur in.
878 // This is important because we have to handle multiple defs/uses in a block
879 // ourselves: SSAUpdater is purely for cross-block references.
881 for (Instruction *User : WorkList)
882 UsesByBlock[User->getParent()].insert(User);
883
884 for (Instruction *User : WorkList) {
885 BasicBlock *BB = User->getParent();
886 auto &BlockUses = UsesByBlock[BB];
887
888 // Already processed, skip.
889 if (BlockUses.empty())
890 continue;
891
892 // Only user in the block, directly process it.
893 if (BlockUses.size() == 1) {
894 Fn(User);
895 continue;
896 }
897
898 // Multiple users in the block, do a linear scan to see users in order.
899 for (Instruction &Inst : *BB) {
900 if (!BlockUses.contains(&Inst))
901 continue;
902
903 Fn(&Inst);
904 }
905
906 // Clear the block so we know it's been processed.
907 BlockUses.clear();
908 }
909}
910
911/// Find an insert point after an alloca, after all other allocas clustered at
912/// the start of the block.
915 for (BasicBlock::iterator E = BB.end(); I != E && isa<AllocaInst>(*I); ++I)
916 ;
917 return I;
918}
919
920/// Peel nested aggregates down to a single uniform element type, multiplying
921/// NumElems by the element count of each layer peeled.
923 while (true) {
924 if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) {
925 NumElems *= ArrayTy->getNumElements();
926 Ty = ArrayTy->getElementType();
927 continue;
928 }
929
930 auto *StructTy = dyn_cast<StructType>(Ty);
931 if (!StructTy || !StructTy->containsHomogeneousTypes())
932 break;
933
934 NumElems *= StructTy->getNumElements();
935 Ty = StructTy->getElementType(0);
936 }
937
938 return Ty;
939}
940
942AMDGPUPromoteAllocaImpl::getVectorTypeForAlloca(Type *AllocaTy) const {
943 if (DisablePromoteAllocaToVector) {
944 LLVM_DEBUG(dbgs() << " Promote alloca to vectors is disabled\n");
945 return nullptr;
946 }
947
948 auto *VectorTy = dyn_cast<FixedVectorType>(AllocaTy);
949 if (AllocaTy->isAggregateType()) {
950 uint64_t NumElems = 1;
951 Type *ElemTy = peelAggregateToElementType(AllocaTy, NumElems);
952
953 // Check for array of vectors
954 auto *InnerVectorTy = dyn_cast<FixedVectorType>(ElemTy);
955 if (InnerVectorTy) {
956 NumElems *= InnerVectorTy->getNumElements();
957 ElemTy = InnerVectorTy->getElementType();
958 }
959
960 if (VectorType::isValidElementType(ElemTy) && NumElems > 0) {
961 unsigned ElementSize = DL.getTypeSizeInBits(ElemTy) / 8;
962 if (ElementSize > 0) {
963 unsigned AllocaSize = DL.getTypeStoreSize(AllocaTy);
964 // Expand vector if required to match padding of inner type,
965 // i.e. odd size subvectors.
966 // Storage size of new vector must match that of alloca for correct
967 // behaviour of byte offsets and GEP computation.
968 if (NumElems * ElementSize != AllocaSize)
969 NumElems = AllocaSize / ElementSize;
970 if (NumElems > 0 && (AllocaSize % ElementSize) == 0)
971 VectorTy = FixedVectorType::get(ElemTy, NumElems);
972 }
973 }
974 }
975 if (!VectorTy) {
976 LLVM_DEBUG(dbgs() << " Cannot convert type to vector\n");
977 return nullptr;
978 }
979
980 const unsigned MaxElements =
981 (MaxVectorRegs * 32) / DL.getTypeSizeInBits(VectorTy->getElementType());
982
983 if (VectorTy->getNumElements() > MaxElements ||
984 VectorTy->getNumElements() < 2) {
985 LLVM_DEBUG(dbgs() << " " << *VectorTy
986 << " has an unsupported number of elements\n");
987 return nullptr;
988 }
989
990 Type *VecEltTy = VectorTy->getElementType();
991 unsigned ElementSizeInBits = DL.getTypeSizeInBits(VecEltTy);
992 if (ElementSizeInBits != DL.getTypeAllocSizeInBits(VecEltTy)) {
993 LLVM_DEBUG(dbgs() << " Cannot convert to vector if the allocation size "
994 "does not match the type's size\n");
995 return nullptr;
996 }
997
998 return VectorTy;
999}
1000
1001void AMDGPUPromoteAllocaImpl::analyzePromoteToVector(AllocaAnalysis &AA) const {
1002 if (AA.HaveSelectOrPHI) {
1003 LLVM_DEBUG(dbgs() << " Cannot convert to vector due to select or phi\n");
1004 return;
1005 }
1006
1007 Type *AllocaTy = AA.Alloca->getAllocatedType();
1008 AA.Vector.Ty = getVectorTypeForAlloca(AllocaTy);
1009 if (!AA.Vector.Ty)
1010 return;
1011
1012 const auto RejectUser = [&](Instruction *Inst, Twine Msg) {
1013 LLVM_DEBUG(dbgs() << " Cannot promote alloca to vector: " << Msg << "\n"
1014 << " " << *Inst << "\n");
1015 AA.Vector.Ty = nullptr;
1016 };
1017
1018 Type *VecEltTy = AA.Vector.Ty->getElementType();
1019 unsigned ElementSize = DL.getTypeSizeInBits(VecEltTy) / 8;
1020 assert(ElementSize > 0);
1021 for (auto *U : AA.Uses) {
1022 Instruction *Inst = cast<Instruction>(U->getUser());
1023
1024 if (Value *Ptr = getLoadStorePointerOperand(Inst)) {
1025 assert(!isa<StoreInst>(Inst) ||
1026 U->getOperandNo() == StoreInst::getPointerOperandIndex());
1027
1028 Type *AccessTy = getLoadStoreType(Inst);
1029 if (AccessTy->isAggregateType())
1030 return RejectUser(Inst, "unsupported load/store as aggregate");
1031 assert(!AccessTy->isAggregateType() || AccessTy->isArrayTy());
1032
1033 // Check that this is a simple access of a vector element.
1034 bool IsSimple = isa<LoadInst>(Inst) ? cast<LoadInst>(Inst)->isSimple()
1035 : cast<StoreInst>(Inst)->isSimple();
1036 if (!IsSimple)
1037 return RejectUser(Inst, "not a simple load or store");
1038
1039 Ptr = Ptr->stripPointerCasts();
1040
1041 // Alloca already accessed as vector.
1042 if (Ptr == AA.Alloca &&
1043 DL.getTypeStoreSize(AA.Alloca->getAllocatedType()) ==
1044 DL.getTypeStoreSize(AccessTy)) {
1045 AA.Vector.Worklist.push_back(Inst);
1046 continue;
1047 }
1048
1049 if (!isSupportedAccessType(AA.Vector.Ty, AccessTy, DL))
1050 return RejectUser(Inst, "not a supported access type");
1051
1052 AA.Vector.Worklist.push_back(Inst);
1053 continue;
1054 }
1055
1056 if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
1057 // If we can't compute a vector index from this GEP, then we can't
1058 // promote this alloca to vector.
1059 auto Index = computeGEPToVectorIndex(GEP, AA.Alloca, VecEltTy, DL);
1060 if (!Index)
1061 return RejectUser(Inst, "cannot compute vector index for GEP");
1062
1063 AA.Vector.GEPVectorIdx[GEP] = std::move(Index.value());
1064 AA.Vector.UsersToRemove.push_back(Inst);
1065 continue;
1066 }
1067
1068 if (MemSetInst *MSI = dyn_cast<MemSetInst>(Inst);
1069 MSI && isSupportedMemset(MSI, AA.Alloca, DL)) {
1070 AA.Vector.Worklist.push_back(Inst);
1071 continue;
1072 }
1073
1074 if (MemTransferInst *TransferInst = dyn_cast<MemTransferInst>(Inst)) {
1075 if (TransferInst->isVolatile())
1076 return RejectUser(Inst, "mem transfer inst is volatile");
1077
1078 ConstantInt *Len = dyn_cast<ConstantInt>(TransferInst->getLength());
1079 if (!Len || (Len->getZExtValue() % ElementSize))
1080 return RejectUser(Inst, "mem transfer inst length is non-constant or "
1081 "not a multiple of the vector element size");
1082
1083 auto getConstIndexIntoAlloca = [&](Value *Ptr) -> ConstantInt * {
1084 if (Ptr == AA.Alloca)
1085 return ConstantInt::get(Ptr->getContext(), APInt(32, 0));
1086
1088 const auto &GEPI = AA.Vector.GEPVectorIdx.find(GEP)->second;
1089 if (GEPI.VarIndex)
1090 return nullptr;
1091 if (GEPI.ConstIndex)
1092 return GEPI.ConstIndex;
1093 return ConstantInt::get(Ptr->getContext(), APInt(32, 0));
1094 };
1095
1096 MemTransferInfo *TI =
1097 &AA.Vector.TransferInfo.try_emplace(TransferInst).first->second;
1098 unsigned OpNum = U->getOperandNo();
1099 if (OpNum == 0) {
1100 Value *Dest = TransferInst->getDest();
1101 ConstantInt *Index = getConstIndexIntoAlloca(Dest);
1102 if (!Index)
1103 return RejectUser(Inst, "could not calculate constant dest index");
1104 TI->DestIndex = Index;
1105 } else {
1106 assert(OpNum == 1);
1107 Value *Src = TransferInst->getSource();
1108 ConstantInt *Index = getConstIndexIntoAlloca(Src);
1109 if (!Index)
1110 return RejectUser(Inst, "could not calculate constant src index");
1111 TI->SrcIndex = Index;
1112 }
1113 continue;
1114 }
1115
1116 if (auto *Intr = dyn_cast<IntrinsicInst>(Inst)) {
1117 if (Intr->getIntrinsicID() == Intrinsic::objectsize) {
1118 AA.Vector.Worklist.push_back(Inst);
1119 continue;
1120 }
1121 }
1122
1123 // Ignore assume-like intrinsics and comparisons used in assumes.
1124 if (isAssumeLikeIntrinsic(Inst)) {
1125 if (!Inst->use_empty())
1126 return RejectUser(Inst, "assume-like intrinsic cannot have any users");
1127 AA.Vector.UsersToRemove.push_back(Inst);
1128 continue;
1129 }
1130
1131 if (isa<ICmpInst>(Inst) && all_of(Inst->users(), [](User *U) {
1132 return isAssumeLikeIntrinsic(cast<Instruction>(U));
1133 })) {
1134 AA.Vector.UsersToRemove.push_back(Inst);
1135 continue;
1136 }
1137
1138 return RejectUser(Inst, "unhandled alloca user");
1139 }
1140
1141 // Follow-up check to ensure we've seen both sides of all transfer insts.
1142 for (const auto &Entry : AA.Vector.TransferInfo) {
1143 const MemTransferInfo &TI = Entry.second;
1144 if (!TI.SrcIndex || !TI.DestIndex)
1145 return RejectUser(Entry.first,
1146 "mem transfer inst between different objects");
1147 AA.Vector.Worklist.push_back(Entry.first);
1148 }
1149}
1150
1151void AMDGPUPromoteAllocaImpl::promoteAllocaToVector(AllocaAnalysis &AA) {
1152 LLVM_DEBUG(dbgs() << "Promoting to vectors: " << *AA.Alloca << '\n');
1153 LLVM_DEBUG(dbgs() << " type conversion: " << *AA.Alloca->getAllocatedType()
1154 << " -> " << *AA.Vector.Ty << '\n');
1155 const unsigned VecStoreSize = DL.getTypeStoreSize(AA.Vector.Ty);
1156
1157 Type *VecEltTy = AA.Vector.Ty->getElementType();
1158 const unsigned ElementSize = DL.getTypeSizeInBits(VecEltTy) / 8;
1159
1160 // Alloca is uninitialized memory. Imitate that by making the first value
1161 // undef.
1162 SSAUpdater Updater;
1163 Updater.Initialize(AA.Vector.Ty, "promotealloca");
1164
1165 BasicBlock *EntryBB = AA.Alloca->getParent();
1166 BasicBlock::iterator InitInsertPos =
1167 skipToNonAllocaInsertPt(*EntryBB, AA.Alloca->getIterator());
1168 IRBuilder<> Builder(&*InitInsertPos);
1169 Value *AllocaInitValue = Builder.CreateFreeze(PoisonValue::get(AA.Vector.Ty));
1170 AllocaInitValue->takeName(AA.Alloca);
1171
1172 Updater.AddAvailableValue(AA.Alloca->getParent(), AllocaInitValue);
1173
1174 // First handle the initial worklist, in basic block order.
1175 //
1176 // Insert a placeholder whenever we need the vector value at the top of a
1177 // basic block.
1179 forEachWorkListItem(AA.Vector.Worklist, [&](Instruction *I) {
1180 BasicBlock *BB = I->getParent();
1181 auto GetCurVal = [&]() -> Value * {
1182 if (Value *CurVal = Updater.FindValueForBlock(BB))
1183 return CurVal;
1184
1185 if (!Placeholders.empty() && Placeholders.back()->getParent() == BB)
1186 return Placeholders.back();
1187
1188 // If the current value in the basic block is not yet known, insert a
1189 // placeholder that we will replace later.
1190 IRBuilder<> Builder(I);
1191 auto *Placeholder = cast<Instruction>(Builder.CreateFreeze(
1192 PoisonValue::get(AA.Vector.Ty), "promotealloca.placeholder"));
1193 Placeholders.insert(Placeholder);
1194 return Placeholders.back();
1195 };
1196
1197 Value *Result = promoteAllocaUserToVector(I, DL, AA, VecStoreSize,
1198 ElementSize, GetCurVal);
1199 // If the returned result is a placeholder, it means the instruction does
1200 // not really modify the alloca. So no need to make it being available value
1201 // to SSAUpdater.
1202 // This will stop placeholder being cached in SSAUpdater. The cached
1203 // placeholder may cause stale pointer being referenced when doing
1204 // placeholder replacement.
1205 if (Result && (!isa<Instruction>(Result) ||
1206 !Placeholders.contains(cast<Instruction>(Result))))
1207 Updater.AddAvailableValue(BB, Result);
1208 });
1209
1210 // Now fixup the placeholders.
1211 for (Instruction *Placeholder : Placeholders) {
1212 Placeholder->replaceAllUsesWith(
1213 Updater.GetValueInMiddleOfBlock(Placeholder->getParent()));
1214 Placeholder->eraseFromParent();
1215 }
1216
1217 // Delete all instructions.
1218 for (Instruction *I : AA.Vector.Worklist) {
1219 assert(I->use_empty());
1220 I->eraseFromParent();
1221 }
1222
1223 // Delete all the users that are known to be removeable.
1224 for (Instruction *I : reverse(AA.Vector.UsersToRemove)) {
1225 I->dropDroppableUses();
1226 assert(I->use_empty());
1227 I->eraseFromParent();
1228 }
1229
1230 // Alloca should now be dead too.
1231 assert(AA.Alloca->use_empty());
1232 AA.Alloca->eraseFromParent();
1233}
1234
1235std::pair<Value *, Value *>
1236AMDGPUPromoteAllocaImpl::getLocalSizeYZ(IRBuilder<> &Builder) {
1237 Function &F = *Builder.GetInsertBlock()->getParent();
1239
1240 if (!IsAMDHSA) {
1241 CallInst *LocalSizeY = Builder.CreateIntrinsicWithoutFolding(
1242 Intrinsic::r600_read_local_size_y, {});
1243 CallInst *LocalSizeZ = Builder.CreateIntrinsicWithoutFolding(
1244 Intrinsic::r600_read_local_size_z, {});
1245
1246 ST.makeLIDRangeMetadata(LocalSizeY);
1247 ST.makeLIDRangeMetadata(LocalSizeZ);
1248
1249 return std::pair(LocalSizeY, LocalSizeZ);
1250 }
1251
1252 // We must read the size out of the dispatch pointer.
1253 assert(IsAMDGCN);
1254
1255 // We are indexing into this struct, and want to extract the workgroup_size_*
1256 // fields.
1257 //
1258 // typedef struct hsa_kernel_dispatch_packet_s {
1259 // uint16_t header;
1260 // uint16_t setup;
1261 // uint16_t workgroup_size_x ;
1262 // uint16_t workgroup_size_y;
1263 // uint16_t workgroup_size_z;
1264 // uint16_t reserved0;
1265 // uint32_t grid_size_x ;
1266 // uint32_t grid_size_y ;
1267 // uint32_t grid_size_z;
1268 //
1269 // uint32_t private_segment_size;
1270 // uint32_t group_segment_size;
1271 // uint64_t kernel_object;
1272 //
1273 // #ifdef HSA_LARGE_MODEL
1274 // void *kernarg_address;
1275 // #elif defined HSA_LITTLE_ENDIAN
1276 // void *kernarg_address;
1277 // uint32_t reserved1;
1278 // #else
1279 // uint32_t reserved1;
1280 // void *kernarg_address;
1281 // #endif
1282 // uint64_t reserved2;
1283 // hsa_signal_t completion_signal; // uint64_t wrapper
1284 // } hsa_kernel_dispatch_packet_t
1285 //
1286 CallInst *DispatchPtr =
1287 Builder.CreateIntrinsicWithoutFolding(Intrinsic::amdgcn_dispatch_ptr, {});
1288 DispatchPtr->addRetAttr(Attribute::NoAlias);
1289 DispatchPtr->addRetAttr(Attribute::NonNull);
1290 F.removeFnAttr("amdgpu-no-dispatch-ptr");
1291
1292 // Size of the dispatch packet struct.
1293 DispatchPtr->addDereferenceableRetAttr(64);
1294
1295 Type *I32Ty = Type::getInt32Ty(Mod.getContext());
1296
1297 // We could do a single 64-bit load here, but it's likely that the basic
1298 // 32-bit and extract sequence is already present, and it is probably easier
1299 // to CSE this. The loads should be mergeable later anyway.
1300 Value *GEPXY = Builder.CreateConstInBoundsGEP1_64(I32Ty, DispatchPtr, 1);
1301 LoadInst *LoadXY = Builder.CreateAlignedLoad(I32Ty, GEPXY, Align(4));
1302
1303 Value *GEPZU = Builder.CreateConstInBoundsGEP1_64(I32Ty, DispatchPtr, 2);
1304 LoadInst *LoadZU = Builder.CreateAlignedLoad(I32Ty, GEPZU, Align(4));
1305
1306 MDNode *MD = MDNode::get(Mod.getContext(), {});
1307 LoadXY->setMetadata(LLVMContext::MD_invariant_load, MD);
1308 LoadZU->setMetadata(LLVMContext::MD_invariant_load, MD);
1309 ST.makeLIDRangeMetadata(LoadZU);
1310
1311 // Extract y component. Upper half of LoadZU should be zero already.
1312 Value *Y = Builder.CreateLShr(LoadXY, 16);
1313
1314 return std::pair(Y, LoadZU);
1315}
1316
1317Value *AMDGPUPromoteAllocaImpl::getWorkitemID(IRBuilder<> &Builder,
1318 unsigned N) {
1319 Function *F = Builder.GetInsertBlock()->getParent();
1322 StringRef AttrName;
1323
1324 switch (N) {
1325 case 0:
1326 IntrID = IsAMDGCN ? (Intrinsic::ID)Intrinsic::amdgcn_workitem_id_x
1327 : (Intrinsic::ID)Intrinsic::r600_read_tidig_x;
1328 AttrName = "amdgpu-no-workitem-id-x";
1329 break;
1330 case 1:
1331 IntrID = IsAMDGCN ? (Intrinsic::ID)Intrinsic::amdgcn_workitem_id_y
1332 : (Intrinsic::ID)Intrinsic::r600_read_tidig_y;
1333 AttrName = "amdgpu-no-workitem-id-y";
1334 break;
1335
1336 case 2:
1337 IntrID = IsAMDGCN ? (Intrinsic::ID)Intrinsic::amdgcn_workitem_id_z
1338 : (Intrinsic::ID)Intrinsic::r600_read_tidig_z;
1339 AttrName = "amdgpu-no-workitem-id-z";
1340 break;
1341 default:
1342 llvm_unreachable("invalid dimension");
1343 }
1344
1345 Function *WorkitemIdFn = Intrinsic::getOrInsertDeclaration(&Mod, IntrID);
1346 CallInst *CI = Builder.CreateCall(WorkitemIdFn);
1347 ST.makeLIDRangeMetadata(CI);
1348 F->removeFnAttr(AttrName);
1349
1350 return CI;
1351}
1352
1353static bool isCallPromotable(CallInst *CI) {
1355 if (!II)
1356 return false;
1357
1358 switch (II->getIntrinsicID()) {
1359 case Intrinsic::memcpy:
1360 case Intrinsic::memmove:
1361 case Intrinsic::memset:
1362 case Intrinsic::lifetime_start:
1363 case Intrinsic::lifetime_end:
1364 case Intrinsic::invariant_start:
1365 case Intrinsic::invariant_end:
1366 case Intrinsic::launder_invariant_group:
1367 case Intrinsic::objectsize:
1368 return true;
1369 default:
1370 return false;
1371 }
1372}
1373
1374bool AMDGPUPromoteAllocaImpl::binaryOpIsDerivedFromSameAlloca(
1375 Value *BaseAlloca, Value *Val, Instruction *Inst, int OpIdx0,
1376 int OpIdx1) const {
1377 // Figure out which operand is the one we might not be promoting.
1378 Value *OtherOp = Inst->getOperand(OpIdx0);
1379 if (Val == OtherOp)
1380 OtherOp = Inst->getOperand(OpIdx1);
1381
1383 return true;
1384
1385 // TODO: getUnderlyingObject will not work on a vector getelementptr
1386 Value *OtherObj = getUnderlyingObject(OtherOp);
1387 if (!isa<AllocaInst>(OtherObj))
1388 return false;
1389
1390 // TODO: We should be able to replace undefs with the right pointer type.
1391
1392 // TODO: If we know the other base object is another promotable
1393 // alloca, not necessarily this alloca, we can do this. The
1394 // important part is both must have the same address space at
1395 // the end.
1396 if (OtherObj != BaseAlloca) {
1397 LLVM_DEBUG(
1398 dbgs() << "Found a binary instruction with another alloca object\n");
1399 return false;
1400 }
1401
1402 return true;
1403}
1404
1405void AMDGPUPromoteAllocaImpl::analyzePromoteToLDS(AllocaAnalysis &AA) const {
1406 if (DisablePromoteAllocaToLDS) {
1407 LLVM_DEBUG(dbgs() << " Promote alloca to LDS is disabled\n");
1408 return;
1409 }
1410
1411 // Don't promote the alloca to LDS for shader calling conventions as the work
1412 // item ID intrinsics are not supported for these calling conventions.
1413 // Furthermore not all LDS is available for some of the stages.
1414 const Function &ContainingFunction = *AA.Alloca->getFunction();
1415 CallingConv::ID CC = ContainingFunction.getCallingConv();
1416
1417 switch (CC) {
1420 break;
1421 default:
1422 LLVM_DEBUG(
1423 dbgs()
1424 << " promote alloca to LDS not supported with calling convention.\n");
1425 return;
1426 }
1427
1428 for (Use *Use : AA.Uses) {
1429 auto *User = Use->getUser();
1430
1431 if (CallInst *CI = dyn_cast<CallInst>(User)) {
1432 if (!isCallPromotable(CI))
1433 return;
1434
1435 if (find(AA.LDS.Worklist, User) == AA.LDS.Worklist.end())
1436 AA.LDS.Worklist.push_back(User);
1437 continue;
1438 }
1439
1441 if (UseInst->getOpcode() == Instruction::PtrToInt)
1442 return;
1443
1444 if (LoadInst *LI = dyn_cast<LoadInst>(UseInst)) {
1445 if (LI->isVolatile())
1446 return;
1447 continue;
1448 }
1449
1450 if (StoreInst *SI = dyn_cast<StoreInst>(UseInst)) {
1451 if (SI->isVolatile())
1452 return;
1453 continue;
1454 }
1455
1456 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(UseInst)) {
1457 if (RMW->isVolatile())
1458 return;
1459 continue;
1460 }
1461
1462 if (AtomicCmpXchgInst *CAS = dyn_cast<AtomicCmpXchgInst>(UseInst)) {
1463 if (CAS->isVolatile())
1464 return;
1465 continue;
1466 }
1467
1468 // Only promote a select if we know that the other select operand
1469 // is from another pointer that will also be promoted.
1470 if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
1471 if (!binaryOpIsDerivedFromSameAlloca(AA.Alloca, Use->get(), ICmp, 0, 1))
1472 return;
1473
1474 // May need to rewrite constant operands.
1475 if (find(AA.LDS.Worklist, User) == AA.LDS.Worklist.end())
1476 AA.LDS.Worklist.push_back(ICmp);
1477 continue;
1478 }
1479
1481 // Be conservative if an address could be computed outside the bounds of
1482 // the alloca.
1483 if (!GEP->isInBounds())
1484 return;
1486 // Do not promote vector/aggregate type instructions. It is hard to track
1487 // their users.
1488
1489 // Do not promote addrspacecast.
1490 //
1491 // TODO: If we know the address is only observed through flat pointers, we
1492 // could still promote.
1493 return;
1494 }
1495
1496 if (find(AA.LDS.Worklist, User) == AA.LDS.Worklist.end())
1497 AA.LDS.Worklist.push_back(User);
1498 }
1499
1500 AA.LDS.Enable = true;
1501}
1502
1503bool AMDGPUPromoteAllocaImpl::hasSufficientLocalMem(const Function &F) {
1504
1505 FunctionType *FTy = F.getFunctionType();
1507
1508 // If the function has any arguments in the local address space, then it's
1509 // possible these arguments require the entire local memory space, so
1510 // we cannot use local memory in the pass.
1511 for (Type *ParamTy : FTy->params()) {
1512 PointerType *PtrTy = dyn_cast<PointerType>(ParamTy);
1513 if (PtrTy && PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
1514 LocalMemLimit = 0;
1515 LLVM_DEBUG(dbgs() << "Function has local memory argument. Promoting to "
1516 "local memory disabled.\n");
1517 return false;
1518 }
1519 }
1520
1521 LocalMemLimit = ST.getAddressableLocalMemorySize();
1522 if (LocalMemLimit == 0)
1523 return false;
1524
1526 SmallPtrSet<const Constant *, 8> VisitedConstants;
1528
1529 auto visitUsers = [&](const GlobalVariable *GV, const Constant *Val) -> bool {
1530 for (const User *U : Val->users()) {
1531 if (const Instruction *Use = dyn_cast<Instruction>(U)) {
1532 if (Use->getFunction() == &F)
1533 return true;
1534 } else {
1535 const Constant *C = cast<Constant>(U);
1536 if (VisitedConstants.insert(C).second)
1537 Stack.push_back(C);
1538 }
1539 }
1540
1541 return false;
1542 };
1543
1544 for (GlobalVariable &GV : Mod.globals()) {
1546 continue;
1547
1548 if (visitUsers(&GV, &GV)) {
1549 UsedLDS.insert(&GV);
1550 Stack.clear();
1551 continue;
1552 }
1553
1554 // For any ConstantExpr uses, we need to recursively search the users until
1555 // we see a function.
1556 while (!Stack.empty()) {
1557 const Constant *C = Stack.pop_back_val();
1558 if (visitUsers(&GV, C)) {
1559 UsedLDS.insert(&GV);
1560 Stack.clear();
1561 break;
1562 }
1563 }
1564 }
1565
1566 SmallVector<std::pair<uint64_t, Align>, 16> AllocatedSizes;
1567 AllocatedSizes.reserve(UsedLDS.size());
1568
1569 for (const GlobalVariable *GV : UsedLDS) {
1571 DL.getValueOrABITypeAlignment(GV->getAlign(), GV->getValueType());
1572 uint64_t AllocSize = GV->getGlobalSize(DL);
1573
1574 // HIP uses an extern unsized array in local address space for dynamically
1575 // allocated shared memory. In that case, we have to disable the promotion.
1576 if (GV->hasExternalLinkage() && AllocSize == 0) {
1577 LocalMemLimit = 0;
1578 LLVM_DEBUG(dbgs() << "Function has a reference to externally allocated "
1579 "local memory. Promoting to local memory "
1580 "disabled.\n");
1581 return false;
1582 }
1583
1584 AllocatedSizes.emplace_back(AllocSize, Alignment);
1585 }
1586
1587 // Sort to try to estimate the worst case alignment padding
1588 //
1589 // FIXME: We should really do something to fix the addresses to a more optimal
1590 // value instead
1591 llvm::sort(AllocatedSizes, llvm::less_second());
1592
1593 // Check how much local memory is being used by global objects
1594 CurrentLocalMemUsage = 0;
1595
1596 // FIXME: Try to account for padding here. The real padding and address is
1597 // currently determined from the inverse order of uses in the function when
1598 // legalizing, which could also potentially change. We try to estimate the
1599 // worst case here, but we probably should fix the addresses earlier.
1600 for (auto Alloc : AllocatedSizes) {
1601 CurrentLocalMemUsage = alignTo(CurrentLocalMemUsage, Alloc.second);
1602 CurrentLocalMemUsage += Alloc.first;
1603 }
1604
1605 unsigned MaxOccupancy =
1606 ST.getWavesPerEU(ST.getFlatWorkGroupSizes(F), CurrentLocalMemUsage, F)
1607 .second;
1608
1609 // Round up to the next tier of usage.
1610 unsigned MaxSizeWithWaveCount =
1611 ST.getMaxLocalMemSizeWithWaveCount(MaxOccupancy, F);
1612
1613 // Program may already use more LDS than is usable at maximum occupancy.
1614 if (CurrentLocalMemUsage > MaxSizeWithWaveCount)
1615 return false;
1616
1617 LocalMemLimit = MaxSizeWithWaveCount;
1618
1619 LLVM_DEBUG(dbgs() << F.getName() << " uses " << CurrentLocalMemUsage
1620 << " bytes of LDS\n"
1621 << " Rounding size to " << MaxSizeWithWaveCount
1622 << " with a maximum occupancy of " << MaxOccupancy << '\n'
1623 << " and " << (LocalMemLimit - CurrentLocalMemUsage)
1624 << " available for promotion\n");
1625
1626 return true;
1627}
1628
1629// FIXME: Should try to pick the most likely to be profitable allocas first.
1630bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToLDS(
1631 AllocaAnalysis &AA, bool SufficientLDS,
1632 SetVector<IntrinsicInst *> &DeferredIntrs) {
1633 LLVM_DEBUG(dbgs() << "Trying to promote to LDS: " << *AA.Alloca << '\n');
1634
1635 // Not likely to have sufficient local memory for promotion.
1636 if (!SufficientLDS)
1637 return false;
1638
1639 IRBuilder<> Builder(AA.Alloca);
1640
1641 const Function &ContainingFunction = *AA.Alloca->getParent()->getParent();
1642 const AMDGPUSubtarget &ST = AMDGPUSubtarget::get(TM, ContainingFunction);
1643 unsigned WorkGroupSize = ST.getFlatWorkGroupSizes(ContainingFunction).second;
1644
1645 Align Alignment = AA.Alloca->getAlign();
1646
1647 // FIXME: This computed padding is likely wrong since it depends on inverse
1648 // usage order.
1649 //
1650 // FIXME: It is also possible that if we're allowed to use all of the memory
1651 // could end up using more than the maximum due to alignment padding.
1652
1653 uint32_t NewSize = alignTo(CurrentLocalMemUsage, Alignment);
1654 std::optional<TypeSize> ElemSize = AA.Alloca->getAllocationSize(DL);
1655 if (!ElemSize || ElemSize->isScalable())
1656 return false;
1657 TypeSize AllocSize = WorkGroupSize * *ElemSize;
1658 NewSize += AllocSize.getFixedValue();
1659
1660 if (NewSize > LocalMemLimit) {
1661 LLVM_DEBUG(dbgs() << " " << AllocSize
1662 << " bytes of local memory not available to promote\n");
1663 return false;
1664 }
1665
1666 CurrentLocalMemUsage = NewSize;
1667
1668 LLVM_DEBUG(dbgs() << "Promoting alloca to local memory\n");
1669
1670 Function *F = AA.Alloca->getFunction();
1671
1672 Type *GVTy = ArrayType::get(AA.Alloca->getAllocatedType(), WorkGroupSize);
1675 Twine(F->getName()) + Twine('.') + AA.Alloca->getName(), nullptr,
1678 GV->setAlignment(AA.Alloca->getAlign());
1679
1680 Value *TCntY, *TCntZ;
1681
1682 std::tie(TCntY, TCntZ) = getLocalSizeYZ(Builder);
1683 Value *TIdX = getWorkitemID(Builder, 0);
1684 Value *TIdY = getWorkitemID(Builder, 1);
1685 Value *TIdZ = getWorkitemID(Builder, 2);
1686
1687 Value *Tmp0 = Builder.CreateMul(TCntY, TCntZ, "", true, true);
1688 Tmp0 = Builder.CreateMul(Tmp0, TIdX);
1689 Value *Tmp1 = Builder.CreateMul(TIdY, TCntZ, "", true, true);
1690 Value *TID = Builder.CreateAdd(Tmp0, Tmp1);
1691 TID = Builder.CreateAdd(TID, TIdZ);
1692
1693 LLVMContext &Context = Mod.getContext();
1695
1696 Value *Offset = Builder.CreateInBoundsGEP(GVTy, GV, Indices);
1697 AA.Alloca->mutateType(Offset->getType());
1698 AA.Alloca->replaceAllUsesWith(Offset);
1699 AA.Alloca->eraseFromParent();
1700
1702
1703 for (Value *V : AA.LDS.Worklist) {
1705 if (!Call) {
1706 if (ICmpInst *CI = dyn_cast<ICmpInst>(V)) {
1707 Value *LHS = CI->getOperand(0);
1708 Value *RHS = CI->getOperand(1);
1709
1710 Type *NewTy = LHS->getType()->getWithNewType(NewPtrTy);
1712 CI->setOperand(0, Constant::getNullValue(NewTy));
1713
1715 CI->setOperand(1, Constant::getNullValue(NewTy));
1716
1717 continue;
1718 }
1719
1720 // The operand's value should be corrected on its own and we don't want to
1721 // touch the users.
1723 continue;
1724
1725 assert(V->getType()->isPtrOrPtrVectorTy());
1726
1727 Type *NewTy = V->getType()->getWithNewType(NewPtrTy);
1728 V->mutateType(NewTy);
1729
1730 // Adjust the types of any constant operands.
1733 SI->setOperand(1, Constant::getNullValue(NewTy));
1734
1736 SI->setOperand(2, Constant::getNullValue(NewTy));
1737 } else if (PHINode *Phi = dyn_cast<PHINode>(V)) {
1738 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) {
1740 Phi->getIncomingValue(I)))
1741 Phi->setIncomingValue(I, Constant::getNullValue(NewTy));
1742 }
1743 }
1744
1745 continue;
1746 }
1747
1749 Builder.SetInsertPoint(Intr);
1750 switch (Intr->getIntrinsicID()) {
1751 case Intrinsic::lifetime_start:
1752 case Intrinsic::lifetime_end:
1753 // These intrinsics are for address space 0 only
1754 Intr->eraseFromParent();
1755 continue;
1756 case Intrinsic::memcpy:
1757 case Intrinsic::memmove:
1758 // These have 2 pointer operands. In case if second pointer also needs
1759 // to be replaced we defer processing of these intrinsics until all
1760 // other values are processed.
1761 DeferredIntrs.insert(Intr);
1762 continue;
1763 case Intrinsic::memset: {
1764 MemSetInst *MemSet = cast<MemSetInst>(Intr);
1765 Builder.CreateMemSet(MemSet->getRawDest(), MemSet->getValue(),
1766 MemSet->getLength(), MemSet->getDestAlign(),
1767 MemSet->isVolatile());
1768 Intr->eraseFromParent();
1769 continue;
1770 }
1771 case Intrinsic::invariant_start:
1772 case Intrinsic::invariant_end:
1773 case Intrinsic::launder_invariant_group: {
1774 assert(Intr->getArgOperand(Intr->arg_size() - 1)->getType() == NewPtrTy &&
1775 "pointer operand should already have been promoted");
1777 Intr->getModule(), Intr->getIntrinsicID(), NewPtrTy);
1778 Intr->mutateType(NewF->getReturnType());
1779 Intr->setCalledFunction(NewF);
1780 continue;
1781 }
1782 case Intrinsic::objectsize: {
1783 Value *Src = Intr->getOperand(0);
1784
1785 Value *NewCall = Builder.CreateIntrinsic(
1786 Intrinsic::objectsize,
1788 {Src, Intr->getOperand(1), Intr->getOperand(2), Intr->getOperand(3)});
1789 Intr->replaceAllUsesWith(NewCall);
1790 Intr->eraseFromParent();
1791 continue;
1792 }
1793 default:
1794 Intr->print(errs());
1795 llvm_unreachable("Don't know how to promote alloca intrinsic use.");
1796 }
1797 }
1798
1799 return true;
1800}
1801
1802void AMDGPUPromoteAllocaImpl::finishDeferredAllocaToLDSPromotion(
1803 SetVector<IntrinsicInst *> &DeferredIntrs) {
1804
1805 for (IntrinsicInst *Intr : DeferredIntrs) {
1806 IRBuilder<> Builder(Intr);
1807 Builder.SetInsertPoint(Intr);
1809 assert(ID == Intrinsic::memcpy || ID == Intrinsic::memmove);
1810
1812 auto *B = Builder.CreateMemTransferInst(
1813 ID, MI->getRawDest(), MI->getDestAlign(), MI->getRawSource(),
1814 MI->getSourceAlign(), MI->getLength(), MI->isVolatile());
1815
1816 for (unsigned I = 0; I != 2; ++I) {
1817 if (uint64_t Bytes = Intr->getParamDereferenceableBytes(I)) {
1818 B->addDereferenceableParamAttr(I, Bytes);
1819 }
1820 }
1821
1822 Intr->eraseFromParent();
1823 }
1824}
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.
static Type * peelAggregateToElementType(Type *Ty, uint64_t &NumElems)
Peel nested aggregates down to a single uniform element type, multiplying NumElems by the element cou...
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:376
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:843
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:1926
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1519
BasicBlock * GetInsertBlock() const
Definition IRBuilder.h:175
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Definition IRBuilder.h:2011
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:587
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:1409
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2553
Value * CreateConstInBoundsGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0, const Twine &Name="")
Definition IRBuilder.h:2053
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:1443
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2901
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:1081
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
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:712
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:2132
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:1781
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:1755
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.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=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...
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:408
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:1652
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
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
#define N
AMDGPUPromoteAllocaPass(TargetMachine &TM)
Definition AMDGPU.h:340
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:1464