LLVM 24.0.0git
NVPTXLowerAlloca.cpp
Go to the documentation of this file.
1//===-- NVPTXLowerAlloca.cpp - Make alloca to use local memory =====--===//
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// Replace each generic alloca with an equivalent alloca in the local address
10// space, followed by an addrspacecast back to generic for its users. For
11// example,
12//
13// %A = alloca i32
14// store i32 0, ptr %A ; emits st.u32
15//
16// is transformed to
17//
18// %A = alloca i32, addrspace(5)
19// %A.generic = addrspacecast ptr addrspace(5) %A to ptr
20// store i32 0, ptr %A.generic
21//
22// This gives the alloca a local frame index, which stack lowering addresses
23// through the local frame pointer (%SPL). When NVPTXInferAddressSpaces runs
24// after this pass, it propagates the local address space into the users and
25// folds the cast away where possible (so the store above becomes st.local.u32).
26//
27//===----------------------------------------------------------------------===//
28
30#include "NVPTX.h"
32#include "llvm/IR/DebugInfo.h"
33#include "llvm/IR/Function.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/Type.h"
38#include "llvm/Pass.h"
39
40using namespace llvm;
41
42// =============================================================================
43// Main function for this pass.
44// =============================================================================
45static bool lowerAllocas(Function &F) {
46 // Mandatory lowering: later stack lowering relies on local allocas, so run
47 // even for optnone functions (optnone is intentionally not honored).
48 SmallVector<AllocaInst *, 8> GenericAllocas;
49 for (auto &BB : F)
50 for (auto &I : BB)
51 if (auto *AI = dyn_cast<AllocaInst>(&I);
52 AI && AI->getAddressSpace() == ADDRESS_SPACE_GENERIC)
53 GenericAllocas.push_back(AI);
54
55 for (AllocaInst *AI : GenericAllocas) {
56 // Create an equivalent alloca in the local address space.
57 auto *LocalAlloca = new AllocaInst(AI->getAllocatedType(),
58 ADDRESS_SPACE_LOCAL, AI->getArraySize(),
59 AI->getAlign(), "", AI->getIterator());
60 LocalAlloca->setDebugLoc(AI->getDebugLoc());
61 LocalAlloca->copyMetadata(*AI);
62 LocalAlloca->setUsedWithInAlloca(AI->isUsedWithInAlloca());
63 LocalAlloca->setSwiftError(AI->isSwiftError());
64
65 // Debug records and lifetime markers have to reference the alloca itself,
66 // not a cast of it, so retarget them to the local alloca before rewriting
67 // the remaining users through a generic addrspacecast below:
68 // - the verifier requires an alloca operand for lifetime markers, and
69 // - pointing debug records at the alloca keeps the variable described by
70 // its (stable) stack slot rather than the cvta.local result.
72 findDbgUsers(AI, DbgUsers);
73 for (DbgVariableRecord *DVR : DbgUsers)
74 DVR->replaceVariableLocationOp(AI, LocalAlloca);
75
76 for (Use &U : llvm::make_early_inc_range(AI->uses())) {
77 auto *II = dyn_cast<IntrinsicInst>(U.getUser());
78 if (!II || !isLifetimeIntrinsic(II->getIntrinsicID()))
79 continue;
80 U.set(LocalAlloca);
82 II->getModule(), II->getIntrinsicID(), {LocalAlloca->getType()});
83 II->setCalledFunction(Decl);
84 }
85
86 // Everything else can go through a single generic addrspacecast.
87 // replaceAllUsesWith leaves the (already retargeted) lifetime markers and
88 // debug records untouched. NVPTXInferAddressSpaces folds the cast into the
89 // users that can operate on local memory directly.
90 auto *GenericPtr = new AddrSpaceCastInst(LocalAlloca, AI->getType(), "",
91 AI->getIterator());
92 GenericPtr->setDebugLoc(AI->getDebugLoc());
93 AI->replaceAllUsesWith(GenericPtr);
94 LocalAlloca->takeName(AI);
95 AI->eraseFromParent();
96 }
97
98 return !GenericAllocas.empty();
99}
100
101namespace {
102class NVPTXLowerAllocaLegacyPass : public FunctionPass {
103 bool runOnFunction(Function &F) override { return lowerAllocas(F); }
104
105public:
106 static char ID; // Pass identification, replacement for typeid
107 NVPTXLowerAllocaLegacyPass() : FunctionPass(ID) {}
108 StringRef getPassName() const override {
109 return "convert address space of alloca'ed memory to local";
110 }
111};
112} // namespace
113
114char NVPTXLowerAllocaLegacyPass::ID = 0;
115
116INITIALIZE_PASS(NVPTXLowerAllocaLegacyPass, "nvptx-lower-alloca",
117 "Lower Alloca", false, false)
118
120 return new NVPTXLowerAllocaLegacyPass();
121}
122
static bool runOnFunction(Function &F, bool PostInlining)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool lowerAllocas(Function &F)
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the SmallVector class.
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
Record of a variable value-assignment, aka a non instruction representation of the dbg....
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
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
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
static bool isLifetimeIntrinsic(Intrinsic::ID ID)
Check if ID corresponds to a lifetime intrinsic.
FunctionPass * createNVPTXLowerAllocaLegacyPass()
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void findDbgUsers(Value *V, SmallVectorImpl< DbgVariableRecord * > &DbgVariableRecords)
Finds the debug info records describing a value.