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