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
42namespace {
43class NVPTXLowerAlloca : public FunctionPass {
44 bool runOnFunction(Function &F) override;
45
46public:
47 static char ID; // Pass identification, replacement for typeid
48 NVPTXLowerAlloca() : FunctionPass(ID) {}
49 StringRef getPassName() const override {
50 return "convert address space of alloca'ed memory to local";
51 }
52};
53} // namespace
54
55char NVPTXLowerAlloca::ID = 0;
56
57INITIALIZE_PASS(NVPTXLowerAlloca, "nvptx-lower-alloca", "Lower Alloca", false,
58 false)
59
60// =============================================================================
61// Main function for this pass.
62// =============================================================================
63bool NVPTXLowerAlloca::runOnFunction(Function &F) {
64 // Mandatory lowering: later stack lowering relies on local allocas, so run
65 // even for optnone functions (skipFunction is intentionally not called).
66 SmallVector<AllocaInst *, 8> GenericAllocas;
67 for (auto &BB : F)
68 for (auto &I : BB)
69 if (auto *AI = dyn_cast<AllocaInst>(&I);
70 AI && AI->getAddressSpace() == ADDRESS_SPACE_GENERIC)
71 GenericAllocas.push_back(AI);
72
73 for (AllocaInst *AI : GenericAllocas) {
74 // Create an equivalent alloca in the local address space.
75 auto *LocalAlloca = new AllocaInst(AI->getAllocatedType(),
76 ADDRESS_SPACE_LOCAL, AI->getArraySize(),
77 AI->getAlign(), "", AI->getIterator());
78 LocalAlloca->setDebugLoc(AI->getDebugLoc());
79 LocalAlloca->copyMetadata(*AI);
80 LocalAlloca->setUsedWithInAlloca(AI->isUsedWithInAlloca());
81 LocalAlloca->setSwiftError(AI->isSwiftError());
82
83 // Debug records and lifetime markers have to reference the alloca itself,
84 // not a cast of it, so retarget them to the local alloca before rewriting
85 // the remaining users through a generic addrspacecast below:
86 // - the verifier requires an alloca operand for lifetime markers, and
87 // - pointing debug records at the alloca keeps the variable described by
88 // its (stable) stack slot rather than the cvta.local result.
90 findDbgUsers(AI, DbgUsers);
91 for (DbgVariableRecord *DVR : DbgUsers)
92 DVR->replaceVariableLocationOp(AI, LocalAlloca);
93
94 for (Use &U : llvm::make_early_inc_range(AI->uses())) {
95 auto *II = dyn_cast<IntrinsicInst>(U.getUser());
96 if (!II || !isLifetimeIntrinsic(II->getIntrinsicID()))
97 continue;
98 U.set(LocalAlloca);
100 II->getModule(), II->getIntrinsicID(), {LocalAlloca->getType()});
101 II->setCalledFunction(Decl);
102 }
103
104 // Everything else can go through a single generic addrspacecast.
105 // replaceAllUsesWith leaves the (already retargeted) lifetime markers and
106 // debug records untouched. NVPTXInferAddressSpaces folds the cast into the
107 // users that can operate on local memory directly.
108 auto *GenericPtr = new AddrSpaceCastInst(LocalAlloca, AI->getType(), "",
109 AI->getIterator());
110 GenericPtr->setDebugLoc(AI->getDebugLoc());
111 AI->replaceAllUsesWith(GenericPtr);
112 LocalAlloca->takeName(AI);
113 AI->eraseFromParent();
114 }
115
116 return !GenericAllocas.empty();
117}
118
120 return new NVPTXLowerAlloca();
121}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
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
uint64_t IntrinsicInst * II
#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
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
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 * createNVPTXLowerAllocaPass()
LLVM_ABI void findDbgUsers(Value *V, SmallVectorImpl< DbgVariableRecord * > &DbgVariableRecords)
Finds the debug info records describing a value.