1*9880d681SAndroid Build Coastguard Worker //===-- NVPTXInferAddressSpace.cpp - ---------------------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // CUDA C/C++ includes memory space designation as variable type qualifers (such
11*9880d681SAndroid Build Coastguard Worker // as __global__ and __shared__). Knowing the space of a memory access allows
12*9880d681SAndroid Build Coastguard Worker // CUDA compilers to emit faster PTX loads and stores. For example, a load from
13*9880d681SAndroid Build Coastguard Worker // shared memory can be translated to `ld.shared` which is roughly 10% faster
14*9880d681SAndroid Build Coastguard Worker // than a generic `ld` on an NVIDIA Tesla K40c.
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker // Unfortunately, type qualifiers only apply to variable declarations, so CUDA
17*9880d681SAndroid Build Coastguard Worker // compilers must infer the memory space of an address expression from
18*9880d681SAndroid Build Coastguard Worker // type-qualified variables.
19*9880d681SAndroid Build Coastguard Worker //
20*9880d681SAndroid Build Coastguard Worker // LLVM IR uses non-zero (so-called) specific address spaces to represent memory
21*9880d681SAndroid Build Coastguard Worker // spaces (e.g. addrspace(3) means shared memory). The Clang frontend
22*9880d681SAndroid Build Coastguard Worker // places only type-qualified variables in specific address spaces, and then
23*9880d681SAndroid Build Coastguard Worker // conservatively `addrspacecast`s each type-qualified variable to addrspace(0)
24*9880d681SAndroid Build Coastguard Worker // (so-called the generic address space) for other instructions to use.
25*9880d681SAndroid Build Coastguard Worker //
26*9880d681SAndroid Build Coastguard Worker // For example, the Clang translates the following CUDA code
27*9880d681SAndroid Build Coastguard Worker // __shared__ float a[10];
28*9880d681SAndroid Build Coastguard Worker // float v = a[i];
29*9880d681SAndroid Build Coastguard Worker // to
30*9880d681SAndroid Build Coastguard Worker // %0 = addrspacecast [10 x float] addrspace(3)* @a to [10 x float]*
31*9880d681SAndroid Build Coastguard Worker // %1 = gep [10 x float], [10 x float]* %0, i64 0, i64 %i
32*9880d681SAndroid Build Coastguard Worker // %v = load float, float* %1 ; emits ld.f32
33*9880d681SAndroid Build Coastguard Worker // @a is in addrspace(3) since it's type-qualified, but its use from %1 is
34*9880d681SAndroid Build Coastguard Worker // redirected to %0 (the generic version of @a).
35*9880d681SAndroid Build Coastguard Worker //
36*9880d681SAndroid Build Coastguard Worker // The optimization implemented in this file propagates specific address spaces
37*9880d681SAndroid Build Coastguard Worker // from type-qualified variable declarations to its users. For example, it
38*9880d681SAndroid Build Coastguard Worker // optimizes the above IR to
39*9880d681SAndroid Build Coastguard Worker // %1 = gep [10 x float] addrspace(3)* @a, i64 0, i64 %i
40*9880d681SAndroid Build Coastguard Worker // %v = load float addrspace(3)* %1 ; emits ld.shared.f32
41*9880d681SAndroid Build Coastguard Worker // propagating the addrspace(3) from @a to %1. As the result, the NVPTX
42*9880d681SAndroid Build Coastguard Worker // codegen is able to emit ld.shared.f32 for %v.
43*9880d681SAndroid Build Coastguard Worker //
44*9880d681SAndroid Build Coastguard Worker // Address space inference works in two steps. First, it uses a data-flow
45*9880d681SAndroid Build Coastguard Worker // analysis to infer as many generic pointers as possible to point to only one
46*9880d681SAndroid Build Coastguard Worker // specific address space. In the above example, it can prove that %1 only
47*9880d681SAndroid Build Coastguard Worker // points to addrspace(3). This algorithm was published in
48*9880d681SAndroid Build Coastguard Worker // CUDA: Compiling and optimizing for a GPU platform
49*9880d681SAndroid Build Coastguard Worker // Chakrabarti, Grover, Aarts, Kong, Kudlur, Lin, Marathe, Murphy, Wang
50*9880d681SAndroid Build Coastguard Worker // ICCS 2012
51*9880d681SAndroid Build Coastguard Worker //
52*9880d681SAndroid Build Coastguard Worker // Then, address space inference replaces all refinable generic pointers with
53*9880d681SAndroid Build Coastguard Worker // equivalent specific pointers.
54*9880d681SAndroid Build Coastguard Worker //
55*9880d681SAndroid Build Coastguard Worker // The major challenge of implementing this optimization is handling PHINodes,
56*9880d681SAndroid Build Coastguard Worker // which may create loops in the data flow graph. This brings two complications.
57*9880d681SAndroid Build Coastguard Worker //
58*9880d681SAndroid Build Coastguard Worker // First, the data flow analysis in Step 1 needs to be circular. For example,
59*9880d681SAndroid Build Coastguard Worker // %generic.input = addrspacecast float addrspace(3)* %input to float*
60*9880d681SAndroid Build Coastguard Worker // loop:
61*9880d681SAndroid Build Coastguard Worker // %y = phi [ %generic.input, %y2 ]
62*9880d681SAndroid Build Coastguard Worker // %y2 = getelementptr %y, 1
63*9880d681SAndroid Build Coastguard Worker // %v = load %y2
64*9880d681SAndroid Build Coastguard Worker // br ..., label %loop, ...
65*9880d681SAndroid Build Coastguard Worker // proving %y specific requires proving both %generic.input and %y2 specific,
66*9880d681SAndroid Build Coastguard Worker // but proving %y2 specific circles back to %y. To address this complication,
67*9880d681SAndroid Build Coastguard Worker // the data flow analysis operates on a lattice:
68*9880d681SAndroid Build Coastguard Worker // uninitialized > specific address spaces > generic.
69*9880d681SAndroid Build Coastguard Worker // All address expressions (our implementation only considers phi, bitcast,
70*9880d681SAndroid Build Coastguard Worker // addrspacecast, and getelementptr) start with the uninitialized address space.
71*9880d681SAndroid Build Coastguard Worker // The monotone transfer function moves the address space of a pointer down a
72*9880d681SAndroid Build Coastguard Worker // lattice path from uninitialized to specific and then to generic. A join
73*9880d681SAndroid Build Coastguard Worker // operation of two different specific address spaces pushes the expression down
74*9880d681SAndroid Build Coastguard Worker // to the generic address space. The analysis completes once it reaches a fixed
75*9880d681SAndroid Build Coastguard Worker // point.
76*9880d681SAndroid Build Coastguard Worker //
77*9880d681SAndroid Build Coastguard Worker // Second, IR rewriting in Step 2 also needs to be circular. For example,
78*9880d681SAndroid Build Coastguard Worker // converting %y to addrspace(3) requires the compiler to know the converted
79*9880d681SAndroid Build Coastguard Worker // %y2, but converting %y2 needs the converted %y. To address this complication,
80*9880d681SAndroid Build Coastguard Worker // we break these cycles using "undef" placeholders. When converting an
81*9880d681SAndroid Build Coastguard Worker // instruction `I` to a new address space, if its operand `Op` is not converted
82*9880d681SAndroid Build Coastguard Worker // yet, we let `I` temporarily use `undef` and fix all the uses of undef later.
83*9880d681SAndroid Build Coastguard Worker // For instance, our algorithm first converts %y to
84*9880d681SAndroid Build Coastguard Worker // %y' = phi float addrspace(3)* [ %input, undef ]
85*9880d681SAndroid Build Coastguard Worker // Then, it converts %y2 to
86*9880d681SAndroid Build Coastguard Worker // %y2' = getelementptr %y', 1
87*9880d681SAndroid Build Coastguard Worker // Finally, it fixes the undef in %y' so that
88*9880d681SAndroid Build Coastguard Worker // %y' = phi float addrspace(3)* [ %input, %y2' ]
89*9880d681SAndroid Build Coastguard Worker //
90*9880d681SAndroid Build Coastguard Worker // TODO: This pass is experimental and not enabled by default. Users can turn it
91*9880d681SAndroid Build Coastguard Worker // on by setting the -nvptx-use-infer-addrspace flag of llc. We plan to replace
92*9880d681SAndroid Build Coastguard Worker // NVPTXNonFavorGenericAddrSpaces with this pass shortly.
93*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "nvptx-infer-addrspace"
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker #include "NVPTX.h"
98*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/NVPTXBaseInfo.h"
99*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseSet.h"
100*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Optional.h"
101*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SetVector.h"
102*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
103*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstIterator.h"
104*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
105*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Operator.h"
106*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
107*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
108*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/Local.h"
109*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/ValueMapper.h"
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker using namespace llvm;
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker namespace {
114*9880d681SAndroid Build Coastguard Worker const unsigned ADDRESS_SPACE_UNINITIALIZED = (unsigned)-1;
115*9880d681SAndroid Build Coastguard Worker
116*9880d681SAndroid Build Coastguard Worker using ValueToAddrSpaceMapTy = DenseMap<const Value *, unsigned>;
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker /// \brief NVPTXInferAddressSpaces
119*9880d681SAndroid Build Coastguard Worker class NVPTXInferAddressSpaces: public FunctionPass {
120*9880d681SAndroid Build Coastguard Worker public:
121*9880d681SAndroid Build Coastguard Worker static char ID;
122*9880d681SAndroid Build Coastguard Worker
NVPTXInferAddressSpaces()123*9880d681SAndroid Build Coastguard Worker NVPTXInferAddressSpaces() : FunctionPass(ID) {}
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override;
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker private:
128*9880d681SAndroid Build Coastguard Worker // Returns the new address space of V if updated; otherwise, returns None.
129*9880d681SAndroid Build Coastguard Worker Optional<unsigned>
130*9880d681SAndroid Build Coastguard Worker updateAddressSpace(const Value &V,
131*9880d681SAndroid Build Coastguard Worker const ValueToAddrSpaceMapTy &InferredAddrSpace);
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker // Tries to infer the specific address space of each address expression in
134*9880d681SAndroid Build Coastguard Worker // Postorder.
135*9880d681SAndroid Build Coastguard Worker void inferAddressSpaces(const std::vector<Value *> &Postorder,
136*9880d681SAndroid Build Coastguard Worker ValueToAddrSpaceMapTy *InferredAddrSpace);
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker // Changes the generic address expressions in function F to point to specific
139*9880d681SAndroid Build Coastguard Worker // address spaces if InferredAddrSpace says so. Postorder is the postorder of
140*9880d681SAndroid Build Coastguard Worker // all generic address expressions in the use-def graph of function F.
141*9880d681SAndroid Build Coastguard Worker bool
142*9880d681SAndroid Build Coastguard Worker rewriteWithNewAddressSpaces(const std::vector<Value *> &Postorder,
143*9880d681SAndroid Build Coastguard Worker const ValueToAddrSpaceMapTy &InferredAddrSpace,
144*9880d681SAndroid Build Coastguard Worker Function *F);
145*9880d681SAndroid Build Coastguard Worker };
146*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker char NVPTXInferAddressSpaces::ID = 0;
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker namespace llvm {
151*9880d681SAndroid Build Coastguard Worker void initializeNVPTXInferAddressSpacesPass(PassRegistry &);
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(NVPTXInferAddressSpaces, "nvptx-infer-addrspace",
154*9880d681SAndroid Build Coastguard Worker "Infer address spaces",
155*9880d681SAndroid Build Coastguard Worker false, false)
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker // Returns true if V is an address expression.
158*9880d681SAndroid Build Coastguard Worker // TODO: Currently, we consider only phi, bitcast, addrspacecast, and
159*9880d681SAndroid Build Coastguard Worker // getelementptr operators.
isAddressExpression(const Value & V)160*9880d681SAndroid Build Coastguard Worker static bool isAddressExpression(const Value &V) {
161*9880d681SAndroid Build Coastguard Worker if (!isa<Operator>(V))
162*9880d681SAndroid Build Coastguard Worker return false;
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker switch (cast<Operator>(V).getOpcode()) {
165*9880d681SAndroid Build Coastguard Worker case Instruction::PHI:
166*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
167*9880d681SAndroid Build Coastguard Worker case Instruction::AddrSpaceCast:
168*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr:
169*9880d681SAndroid Build Coastguard Worker return true;
170*9880d681SAndroid Build Coastguard Worker default:
171*9880d681SAndroid Build Coastguard Worker return false;
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker }
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Worker // Returns the pointer operands of V.
176*9880d681SAndroid Build Coastguard Worker //
177*9880d681SAndroid Build Coastguard Worker // Precondition: V is an address expression.
getPointerOperands(const Value & V)178*9880d681SAndroid Build Coastguard Worker static SmallVector<Value *, 2> getPointerOperands(const Value &V) {
179*9880d681SAndroid Build Coastguard Worker assert(isAddressExpression(V));
180*9880d681SAndroid Build Coastguard Worker const Operator& Op = cast<Operator>(V);
181*9880d681SAndroid Build Coastguard Worker switch (Op.getOpcode()) {
182*9880d681SAndroid Build Coastguard Worker case Instruction::PHI: {
183*9880d681SAndroid Build Coastguard Worker auto IncomingValues = cast<PHINode>(Op).incoming_values();
184*9880d681SAndroid Build Coastguard Worker return SmallVector<Value *, 2>(IncomingValues.begin(),
185*9880d681SAndroid Build Coastguard Worker IncomingValues.end());
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
188*9880d681SAndroid Build Coastguard Worker case Instruction::AddrSpaceCast:
189*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr:
190*9880d681SAndroid Build Coastguard Worker return {Op.getOperand(0)};
191*9880d681SAndroid Build Coastguard Worker default:
192*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected instruction type.");
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker // If V is an unvisited generic address expression, appends V to PostorderStack
197*9880d681SAndroid Build Coastguard Worker // and marks it as visited.
appendsGenericAddressExpressionToPostorderStack(Value * V,std::vector<std::pair<Value *,bool>> * PostorderStack,DenseSet<Value * > * Visited)198*9880d681SAndroid Build Coastguard Worker static void appendsGenericAddressExpressionToPostorderStack(
199*9880d681SAndroid Build Coastguard Worker Value *V, std::vector<std::pair<Value *, bool>> *PostorderStack,
200*9880d681SAndroid Build Coastguard Worker DenseSet<Value *> *Visited) {
201*9880d681SAndroid Build Coastguard Worker assert(V->getType()->isPointerTy());
202*9880d681SAndroid Build Coastguard Worker if (isAddressExpression(*V) &&
203*9880d681SAndroid Build Coastguard Worker V->getType()->getPointerAddressSpace() ==
204*9880d681SAndroid Build Coastguard Worker AddressSpace::ADDRESS_SPACE_GENERIC) {
205*9880d681SAndroid Build Coastguard Worker if (Visited->insert(V).second)
206*9880d681SAndroid Build Coastguard Worker PostorderStack->push_back(std::make_pair(V, false));
207*9880d681SAndroid Build Coastguard Worker }
208*9880d681SAndroid Build Coastguard Worker }
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker // Returns all generic address expressions in function F. The elements are
211*9880d681SAndroid Build Coastguard Worker // ordered in postorder.
collectGenericAddressExpressions(Function & F)212*9880d681SAndroid Build Coastguard Worker static std::vector<Value *> collectGenericAddressExpressions(Function &F) {
213*9880d681SAndroid Build Coastguard Worker // This function implements a non-recursive postorder traversal of a partial
214*9880d681SAndroid Build Coastguard Worker // use-def graph of function F.
215*9880d681SAndroid Build Coastguard Worker std::vector<std::pair<Value*, bool>> PostorderStack;
216*9880d681SAndroid Build Coastguard Worker // The set of visited expressions.
217*9880d681SAndroid Build Coastguard Worker DenseSet<Value*> Visited;
218*9880d681SAndroid Build Coastguard Worker // We only explore address expressions that are reachable from loads and
219*9880d681SAndroid Build Coastguard Worker // stores for now because we aim at generating faster loads and stores.
220*9880d681SAndroid Build Coastguard Worker for (Instruction &I : instructions(F)) {
221*9880d681SAndroid Build Coastguard Worker if (isa<LoadInst>(I)) {
222*9880d681SAndroid Build Coastguard Worker appendsGenericAddressExpressionToPostorderStack(
223*9880d681SAndroid Build Coastguard Worker I.getOperand(0), &PostorderStack, &Visited);
224*9880d681SAndroid Build Coastguard Worker } else if (isa<StoreInst>(I)) {
225*9880d681SAndroid Build Coastguard Worker appendsGenericAddressExpressionToPostorderStack(
226*9880d681SAndroid Build Coastguard Worker I.getOperand(1), &PostorderStack, &Visited);
227*9880d681SAndroid Build Coastguard Worker }
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker
230*9880d681SAndroid Build Coastguard Worker std::vector<Value *> Postorder; // The resultant postorder.
231*9880d681SAndroid Build Coastguard Worker while (!PostorderStack.empty()) {
232*9880d681SAndroid Build Coastguard Worker // If the operands of the expression on the top are already explored,
233*9880d681SAndroid Build Coastguard Worker // adds that expression to the resultant postorder.
234*9880d681SAndroid Build Coastguard Worker if (PostorderStack.back().second) {
235*9880d681SAndroid Build Coastguard Worker Postorder.push_back(PostorderStack.back().first);
236*9880d681SAndroid Build Coastguard Worker PostorderStack.pop_back();
237*9880d681SAndroid Build Coastguard Worker continue;
238*9880d681SAndroid Build Coastguard Worker }
239*9880d681SAndroid Build Coastguard Worker // Otherwise, adds its operands to the stack and explores them.
240*9880d681SAndroid Build Coastguard Worker PostorderStack.back().second = true;
241*9880d681SAndroid Build Coastguard Worker for (Value *PtrOperand : getPointerOperands(*PostorderStack.back().first)) {
242*9880d681SAndroid Build Coastguard Worker appendsGenericAddressExpressionToPostorderStack(
243*9880d681SAndroid Build Coastguard Worker PtrOperand, &PostorderStack, &Visited);
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker }
246*9880d681SAndroid Build Coastguard Worker return Postorder;
247*9880d681SAndroid Build Coastguard Worker }
248*9880d681SAndroid Build Coastguard Worker
249*9880d681SAndroid Build Coastguard Worker // A helper function for cloneInstructionWithNewAddressSpace. Returns the clone
250*9880d681SAndroid Build Coastguard Worker // of OperandUse.get() in the new address space. If the clone is not ready yet,
251*9880d681SAndroid Build Coastguard Worker // returns an undef in the new address space as a placeholder.
operandWithNewAddressSpaceOrCreateUndef(const Use & OperandUse,unsigned NewAddrSpace,const ValueToValueMapTy & ValueWithNewAddrSpace,SmallVectorImpl<const Use * > * UndefUsesToFix)252*9880d681SAndroid Build Coastguard Worker static Value *operandWithNewAddressSpaceOrCreateUndef(
253*9880d681SAndroid Build Coastguard Worker const Use &OperandUse, unsigned NewAddrSpace,
254*9880d681SAndroid Build Coastguard Worker const ValueToValueMapTy &ValueWithNewAddrSpace,
255*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<const Use *> *UndefUsesToFix) {
256*9880d681SAndroid Build Coastguard Worker Value *Operand = OperandUse.get();
257*9880d681SAndroid Build Coastguard Worker if (Value *NewOperand = ValueWithNewAddrSpace.lookup(Operand))
258*9880d681SAndroid Build Coastguard Worker return NewOperand;
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker UndefUsesToFix->push_back(&OperandUse);
261*9880d681SAndroid Build Coastguard Worker return UndefValue::get(
262*9880d681SAndroid Build Coastguard Worker Operand->getType()->getPointerElementType()->getPointerTo(NewAddrSpace));
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker // Returns a clone of `I` with its operands converted to those specified in
266*9880d681SAndroid Build Coastguard Worker // ValueWithNewAddrSpace. Due to potential cycles in the data flow graph, an
267*9880d681SAndroid Build Coastguard Worker // operand whose address space needs to be modified might not exist in
268*9880d681SAndroid Build Coastguard Worker // ValueWithNewAddrSpace. In that case, uses undef as a placeholder operand and
269*9880d681SAndroid Build Coastguard Worker // adds that operand use to UndefUsesToFix so that caller can fix them later.
270*9880d681SAndroid Build Coastguard Worker //
271*9880d681SAndroid Build Coastguard Worker // Note that we do not necessarily clone `I`, e.g., if it is an addrspacecast
272*9880d681SAndroid Build Coastguard Worker // from a pointer whose type already matches. Therefore, this function returns a
273*9880d681SAndroid Build Coastguard Worker // Value* instead of an Instruction*.
cloneInstructionWithNewAddressSpace(Instruction * I,unsigned NewAddrSpace,const ValueToValueMapTy & ValueWithNewAddrSpace,SmallVectorImpl<const Use * > * UndefUsesToFix)274*9880d681SAndroid Build Coastguard Worker static Value *cloneInstructionWithNewAddressSpace(
275*9880d681SAndroid Build Coastguard Worker Instruction *I, unsigned NewAddrSpace,
276*9880d681SAndroid Build Coastguard Worker const ValueToValueMapTy &ValueWithNewAddrSpace,
277*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<const Use *> *UndefUsesToFix) {
278*9880d681SAndroid Build Coastguard Worker Type *NewPtrType =
279*9880d681SAndroid Build Coastguard Worker I->getType()->getPointerElementType()->getPointerTo(NewAddrSpace);
280*9880d681SAndroid Build Coastguard Worker
281*9880d681SAndroid Build Coastguard Worker if (I->getOpcode() == Instruction::AddrSpaceCast) {
282*9880d681SAndroid Build Coastguard Worker Value *Src = I->getOperand(0);
283*9880d681SAndroid Build Coastguard Worker // Because `I` is generic, the source address space must be specific.
284*9880d681SAndroid Build Coastguard Worker // Therefore, the inferred address space must be the source space, according
285*9880d681SAndroid Build Coastguard Worker // to our algorithm.
286*9880d681SAndroid Build Coastguard Worker assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace);
287*9880d681SAndroid Build Coastguard Worker if (Src->getType() != NewPtrType)
288*9880d681SAndroid Build Coastguard Worker return new BitCastInst(Src, NewPtrType);
289*9880d681SAndroid Build Coastguard Worker return Src;
290*9880d681SAndroid Build Coastguard Worker }
291*9880d681SAndroid Build Coastguard Worker
292*9880d681SAndroid Build Coastguard Worker // Computes the converted pointer operands.
293*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 4> NewPointerOperands;
294*9880d681SAndroid Build Coastguard Worker for (const Use &OperandUse : I->operands()) {
295*9880d681SAndroid Build Coastguard Worker if (!OperandUse.get()->getType()->isPointerTy())
296*9880d681SAndroid Build Coastguard Worker NewPointerOperands.push_back(nullptr);
297*9880d681SAndroid Build Coastguard Worker else
298*9880d681SAndroid Build Coastguard Worker NewPointerOperands.push_back(operandWithNewAddressSpaceOrCreateUndef(
299*9880d681SAndroid Build Coastguard Worker OperandUse, NewAddrSpace, ValueWithNewAddrSpace, UndefUsesToFix));
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker
302*9880d681SAndroid Build Coastguard Worker switch (I->getOpcode()) {
303*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
304*9880d681SAndroid Build Coastguard Worker return new BitCastInst(NewPointerOperands[0], NewPtrType);
305*9880d681SAndroid Build Coastguard Worker case Instruction::PHI: {
306*9880d681SAndroid Build Coastguard Worker assert(I->getType()->isPointerTy());
307*9880d681SAndroid Build Coastguard Worker PHINode *PHI = cast<PHINode>(I);
308*9880d681SAndroid Build Coastguard Worker PHINode *NewPHI = PHINode::Create(NewPtrType, PHI->getNumIncomingValues());
309*9880d681SAndroid Build Coastguard Worker for (unsigned Index = 0; Index < PHI->getNumIncomingValues(); ++Index) {
310*9880d681SAndroid Build Coastguard Worker unsigned OperandNo = PHINode::getOperandNumForIncomingValue(Index);
311*9880d681SAndroid Build Coastguard Worker NewPHI->addIncoming(NewPointerOperands[OperandNo],
312*9880d681SAndroid Build Coastguard Worker PHI->getIncomingBlock(Index));
313*9880d681SAndroid Build Coastguard Worker }
314*9880d681SAndroid Build Coastguard Worker return NewPHI;
315*9880d681SAndroid Build Coastguard Worker }
316*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr: {
317*9880d681SAndroid Build Coastguard Worker GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
318*9880d681SAndroid Build Coastguard Worker GetElementPtrInst *NewGEP = GetElementPtrInst::Create(
319*9880d681SAndroid Build Coastguard Worker GEP->getSourceElementType(), NewPointerOperands[0],
320*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 4>(GEP->idx_begin(), GEP->idx_end()));
321*9880d681SAndroid Build Coastguard Worker NewGEP->setIsInBounds(GEP->isInBounds());
322*9880d681SAndroid Build Coastguard Worker return NewGEP;
323*9880d681SAndroid Build Coastguard Worker }
324*9880d681SAndroid Build Coastguard Worker default:
325*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected opcode");
326*9880d681SAndroid Build Coastguard Worker }
327*9880d681SAndroid Build Coastguard Worker }
328*9880d681SAndroid Build Coastguard Worker
329*9880d681SAndroid Build Coastguard Worker // Similar to cloneInstructionWithNewAddressSpace, returns a clone of the
330*9880d681SAndroid Build Coastguard Worker // constant expression `CE` with its operands replaced as specified in
331*9880d681SAndroid Build Coastguard Worker // ValueWithNewAddrSpace.
cloneConstantExprWithNewAddressSpace(ConstantExpr * CE,unsigned NewAddrSpace,const ValueToValueMapTy & ValueWithNewAddrSpace)332*9880d681SAndroid Build Coastguard Worker static Value *cloneConstantExprWithNewAddressSpace(
333*9880d681SAndroid Build Coastguard Worker ConstantExpr *CE, unsigned NewAddrSpace,
334*9880d681SAndroid Build Coastguard Worker const ValueToValueMapTy &ValueWithNewAddrSpace) {
335*9880d681SAndroid Build Coastguard Worker Type *TargetType =
336*9880d681SAndroid Build Coastguard Worker CE->getType()->getPointerElementType()->getPointerTo(NewAddrSpace);
337*9880d681SAndroid Build Coastguard Worker
338*9880d681SAndroid Build Coastguard Worker if (CE->getOpcode() == Instruction::AddrSpaceCast) {
339*9880d681SAndroid Build Coastguard Worker // Because CE is generic, the source address space must be specific.
340*9880d681SAndroid Build Coastguard Worker // Therefore, the inferred address space must be the source space according
341*9880d681SAndroid Build Coastguard Worker // to our algorithm.
342*9880d681SAndroid Build Coastguard Worker assert(CE->getOperand(0)->getType()->getPointerAddressSpace() ==
343*9880d681SAndroid Build Coastguard Worker NewAddrSpace);
344*9880d681SAndroid Build Coastguard Worker return ConstantExpr::getBitCast(CE->getOperand(0), TargetType);
345*9880d681SAndroid Build Coastguard Worker }
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Worker // Computes the operands of the new constant expression.
348*9880d681SAndroid Build Coastguard Worker SmallVector<Constant *, 4> NewOperands;
349*9880d681SAndroid Build Coastguard Worker for (unsigned Index = 0; Index < CE->getNumOperands(); ++Index) {
350*9880d681SAndroid Build Coastguard Worker Constant *Operand = CE->getOperand(Index);
351*9880d681SAndroid Build Coastguard Worker // If the address space of `Operand` needs to be modified, the new operand
352*9880d681SAndroid Build Coastguard Worker // with the new address space should already be in ValueWithNewAddrSpace
353*9880d681SAndroid Build Coastguard Worker // because (1) the constant expressions we consider (i.e. addrspacecast,
354*9880d681SAndroid Build Coastguard Worker // bitcast, and getelementptr) do not incur cycles in the data flow graph
355*9880d681SAndroid Build Coastguard Worker // and (2) this function is called on constant expressions in postorder.
356*9880d681SAndroid Build Coastguard Worker if (Value *NewOperand = ValueWithNewAddrSpace.lookup(Operand)) {
357*9880d681SAndroid Build Coastguard Worker NewOperands.push_back(cast<Constant>(NewOperand));
358*9880d681SAndroid Build Coastguard Worker } else {
359*9880d681SAndroid Build Coastguard Worker // Otherwise, reuses the old operand.
360*9880d681SAndroid Build Coastguard Worker NewOperands.push_back(Operand);
361*9880d681SAndroid Build Coastguard Worker }
362*9880d681SAndroid Build Coastguard Worker }
363*9880d681SAndroid Build Coastguard Worker
364*9880d681SAndroid Build Coastguard Worker if (CE->getOpcode() == Instruction::GetElementPtr) {
365*9880d681SAndroid Build Coastguard Worker // Needs to specify the source type while constructing a getelementptr
366*9880d681SAndroid Build Coastguard Worker // constant expression.
367*9880d681SAndroid Build Coastguard Worker return CE->getWithOperands(
368*9880d681SAndroid Build Coastguard Worker NewOperands, TargetType, /*OnlyIfReduced=*/false,
369*9880d681SAndroid Build Coastguard Worker NewOperands[0]->getType()->getPointerElementType());
370*9880d681SAndroid Build Coastguard Worker }
371*9880d681SAndroid Build Coastguard Worker
372*9880d681SAndroid Build Coastguard Worker return CE->getWithOperands(NewOperands, TargetType);
373*9880d681SAndroid Build Coastguard Worker }
374*9880d681SAndroid Build Coastguard Worker
375*9880d681SAndroid Build Coastguard Worker // Returns a clone of the value `V`, with its operands replaced as specified in
376*9880d681SAndroid Build Coastguard Worker // ValueWithNewAddrSpace. This function is called on every generic address
377*9880d681SAndroid Build Coastguard Worker // expression whose address space needs to be modified, in postorder.
378*9880d681SAndroid Build Coastguard Worker //
379*9880d681SAndroid Build Coastguard Worker // See cloneInstructionWithNewAddressSpace for the meaning of UndefUsesToFix.
380*9880d681SAndroid Build Coastguard Worker static Value *
cloneValueWithNewAddressSpace(Value * V,unsigned NewAddrSpace,const ValueToValueMapTy & ValueWithNewAddrSpace,SmallVectorImpl<const Use * > * UndefUsesToFix)381*9880d681SAndroid Build Coastguard Worker cloneValueWithNewAddressSpace(Value *V, unsigned NewAddrSpace,
382*9880d681SAndroid Build Coastguard Worker const ValueToValueMapTy &ValueWithNewAddrSpace,
383*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<const Use *> *UndefUsesToFix) {
384*9880d681SAndroid Build Coastguard Worker // All values in Postorder are generic address expressions.
385*9880d681SAndroid Build Coastguard Worker assert(isAddressExpression(*V) &&
386*9880d681SAndroid Build Coastguard Worker V->getType()->getPointerAddressSpace() ==
387*9880d681SAndroid Build Coastguard Worker AddressSpace::ADDRESS_SPACE_GENERIC);
388*9880d681SAndroid Build Coastguard Worker
389*9880d681SAndroid Build Coastguard Worker if (Instruction *I = dyn_cast<Instruction>(V)) {
390*9880d681SAndroid Build Coastguard Worker Value *NewV = cloneInstructionWithNewAddressSpace(
391*9880d681SAndroid Build Coastguard Worker I, NewAddrSpace, ValueWithNewAddrSpace, UndefUsesToFix);
392*9880d681SAndroid Build Coastguard Worker if (Instruction *NewI = dyn_cast<Instruction>(NewV)) {
393*9880d681SAndroid Build Coastguard Worker if (NewI->getParent() == nullptr) {
394*9880d681SAndroid Build Coastguard Worker NewI->insertBefore(I);
395*9880d681SAndroid Build Coastguard Worker NewI->takeName(I);
396*9880d681SAndroid Build Coastguard Worker }
397*9880d681SAndroid Build Coastguard Worker }
398*9880d681SAndroid Build Coastguard Worker return NewV;
399*9880d681SAndroid Build Coastguard Worker }
400*9880d681SAndroid Build Coastguard Worker
401*9880d681SAndroid Build Coastguard Worker return cloneConstantExprWithNewAddressSpace(
402*9880d681SAndroid Build Coastguard Worker cast<ConstantExpr>(V), NewAddrSpace, ValueWithNewAddrSpace);
403*9880d681SAndroid Build Coastguard Worker }
404*9880d681SAndroid Build Coastguard Worker
405*9880d681SAndroid Build Coastguard Worker // Defines the join operation on the address space lattice (see the file header
406*9880d681SAndroid Build Coastguard Worker // comments).
joinAddressSpaces(unsigned AS1,unsigned AS2)407*9880d681SAndroid Build Coastguard Worker static unsigned joinAddressSpaces(unsigned AS1, unsigned AS2) {
408*9880d681SAndroid Build Coastguard Worker if (AS1 == AddressSpace::ADDRESS_SPACE_GENERIC ||
409*9880d681SAndroid Build Coastguard Worker AS2 == AddressSpace::ADDRESS_SPACE_GENERIC)
410*9880d681SAndroid Build Coastguard Worker return AddressSpace::ADDRESS_SPACE_GENERIC;
411*9880d681SAndroid Build Coastguard Worker
412*9880d681SAndroid Build Coastguard Worker if (AS1 == ADDRESS_SPACE_UNINITIALIZED)
413*9880d681SAndroid Build Coastguard Worker return AS2;
414*9880d681SAndroid Build Coastguard Worker if (AS2 == ADDRESS_SPACE_UNINITIALIZED)
415*9880d681SAndroid Build Coastguard Worker return AS1;
416*9880d681SAndroid Build Coastguard Worker
417*9880d681SAndroid Build Coastguard Worker // The join of two different specific address spaces is generic.
418*9880d681SAndroid Build Coastguard Worker return AS1 == AS2 ? AS1 : (unsigned)AddressSpace::ADDRESS_SPACE_GENERIC;
419*9880d681SAndroid Build Coastguard Worker }
420*9880d681SAndroid Build Coastguard Worker
runOnFunction(Function & F)421*9880d681SAndroid Build Coastguard Worker bool NVPTXInferAddressSpaces::runOnFunction(Function &F) {
422*9880d681SAndroid Build Coastguard Worker if (skipFunction(F))
423*9880d681SAndroid Build Coastguard Worker return false;
424*9880d681SAndroid Build Coastguard Worker
425*9880d681SAndroid Build Coastguard Worker // Collects all generic address expressions in postorder.
426*9880d681SAndroid Build Coastguard Worker std::vector<Value *> Postorder = collectGenericAddressExpressions(F);
427*9880d681SAndroid Build Coastguard Worker
428*9880d681SAndroid Build Coastguard Worker // Runs a data-flow analysis to refine the address spaces of every expression
429*9880d681SAndroid Build Coastguard Worker // in Postorder.
430*9880d681SAndroid Build Coastguard Worker ValueToAddrSpaceMapTy InferredAddrSpace;
431*9880d681SAndroid Build Coastguard Worker inferAddressSpaces(Postorder, &InferredAddrSpace);
432*9880d681SAndroid Build Coastguard Worker
433*9880d681SAndroid Build Coastguard Worker // Changes the address spaces of the generic address expressions who are
434*9880d681SAndroid Build Coastguard Worker // inferred to point to a specific address space.
435*9880d681SAndroid Build Coastguard Worker return rewriteWithNewAddressSpaces(Postorder, InferredAddrSpace, &F);
436*9880d681SAndroid Build Coastguard Worker }
437*9880d681SAndroid Build Coastguard Worker
inferAddressSpaces(const std::vector<Value * > & Postorder,ValueToAddrSpaceMapTy * InferredAddrSpace)438*9880d681SAndroid Build Coastguard Worker void NVPTXInferAddressSpaces::inferAddressSpaces(
439*9880d681SAndroid Build Coastguard Worker const std::vector<Value *> &Postorder,
440*9880d681SAndroid Build Coastguard Worker ValueToAddrSpaceMapTy *InferredAddrSpace) {
441*9880d681SAndroid Build Coastguard Worker SetVector<Value *> Worklist(Postorder.begin(), Postorder.end());
442*9880d681SAndroid Build Coastguard Worker // Initially, all expressions are in the uninitialized address space.
443*9880d681SAndroid Build Coastguard Worker for (Value *V : Postorder)
444*9880d681SAndroid Build Coastguard Worker (*InferredAddrSpace)[V] = ADDRESS_SPACE_UNINITIALIZED;
445*9880d681SAndroid Build Coastguard Worker
446*9880d681SAndroid Build Coastguard Worker while (!Worklist.empty()) {
447*9880d681SAndroid Build Coastguard Worker Value* V = Worklist.pop_back_val();
448*9880d681SAndroid Build Coastguard Worker
449*9880d681SAndroid Build Coastguard Worker // Tries to update the address space of the stack top according to the
450*9880d681SAndroid Build Coastguard Worker // address spaces of its operands.
451*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Updating the address space of\n"
452*9880d681SAndroid Build Coastguard Worker << " " << *V << "\n");
453*9880d681SAndroid Build Coastguard Worker Optional<unsigned> NewAS = updateAddressSpace(*V, *InferredAddrSpace);
454*9880d681SAndroid Build Coastguard Worker if (!NewAS.hasValue())
455*9880d681SAndroid Build Coastguard Worker continue;
456*9880d681SAndroid Build Coastguard Worker // If any updates are made, grabs its users to the worklist because
457*9880d681SAndroid Build Coastguard Worker // their address spaces can also be possibly updated.
458*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " to " << NewAS.getValue() << "\n");
459*9880d681SAndroid Build Coastguard Worker (*InferredAddrSpace)[V] = NewAS.getValue();
460*9880d681SAndroid Build Coastguard Worker
461*9880d681SAndroid Build Coastguard Worker for (Value *User : V->users()) {
462*9880d681SAndroid Build Coastguard Worker // Skip if User is already in the worklist.
463*9880d681SAndroid Build Coastguard Worker if (Worklist.count(User))
464*9880d681SAndroid Build Coastguard Worker continue;
465*9880d681SAndroid Build Coastguard Worker
466*9880d681SAndroid Build Coastguard Worker auto Pos = InferredAddrSpace->find(User);
467*9880d681SAndroid Build Coastguard Worker // Our algorithm only updates the address spaces of generic address
468*9880d681SAndroid Build Coastguard Worker // expressions, which are those in InferredAddrSpace.
469*9880d681SAndroid Build Coastguard Worker if (Pos == InferredAddrSpace->end())
470*9880d681SAndroid Build Coastguard Worker continue;
471*9880d681SAndroid Build Coastguard Worker
472*9880d681SAndroid Build Coastguard Worker // Function updateAddressSpace moves the address space down a lattice
473*9880d681SAndroid Build Coastguard Worker // path. Therefore, nothing to do if User is already inferred as
474*9880d681SAndroid Build Coastguard Worker // generic (the bottom element in the lattice).
475*9880d681SAndroid Build Coastguard Worker if (Pos->second == AddressSpace::ADDRESS_SPACE_GENERIC)
476*9880d681SAndroid Build Coastguard Worker continue;
477*9880d681SAndroid Build Coastguard Worker
478*9880d681SAndroid Build Coastguard Worker Worklist.insert(User);
479*9880d681SAndroid Build Coastguard Worker }
480*9880d681SAndroid Build Coastguard Worker }
481*9880d681SAndroid Build Coastguard Worker }
482*9880d681SAndroid Build Coastguard Worker
updateAddressSpace(const Value & V,const ValueToAddrSpaceMapTy & InferredAddrSpace)483*9880d681SAndroid Build Coastguard Worker Optional<unsigned> NVPTXInferAddressSpaces::updateAddressSpace(
484*9880d681SAndroid Build Coastguard Worker const Value &V, const ValueToAddrSpaceMapTy &InferredAddrSpace) {
485*9880d681SAndroid Build Coastguard Worker assert(InferredAddrSpace.count(&V));
486*9880d681SAndroid Build Coastguard Worker
487*9880d681SAndroid Build Coastguard Worker // The new inferred address space equals the join of the address spaces
488*9880d681SAndroid Build Coastguard Worker // of all its pointer operands.
489*9880d681SAndroid Build Coastguard Worker unsigned NewAS = ADDRESS_SPACE_UNINITIALIZED;
490*9880d681SAndroid Build Coastguard Worker for (Value *PtrOperand : getPointerOperands(V)) {
491*9880d681SAndroid Build Coastguard Worker unsigned OperandAS;
492*9880d681SAndroid Build Coastguard Worker if (InferredAddrSpace.count(PtrOperand))
493*9880d681SAndroid Build Coastguard Worker OperandAS = InferredAddrSpace.lookup(PtrOperand);
494*9880d681SAndroid Build Coastguard Worker else
495*9880d681SAndroid Build Coastguard Worker OperandAS = PtrOperand->getType()->getPointerAddressSpace();
496*9880d681SAndroid Build Coastguard Worker NewAS = joinAddressSpaces(NewAS, OperandAS);
497*9880d681SAndroid Build Coastguard Worker // join(generic, *) = generic. So we can break if NewAS is already generic.
498*9880d681SAndroid Build Coastguard Worker if (NewAS == AddressSpace::ADDRESS_SPACE_GENERIC)
499*9880d681SAndroid Build Coastguard Worker break;
500*9880d681SAndroid Build Coastguard Worker }
501*9880d681SAndroid Build Coastguard Worker
502*9880d681SAndroid Build Coastguard Worker unsigned OldAS = InferredAddrSpace.lookup(&V);
503*9880d681SAndroid Build Coastguard Worker assert(OldAS != AddressSpace::ADDRESS_SPACE_GENERIC);
504*9880d681SAndroid Build Coastguard Worker if (OldAS == NewAS)
505*9880d681SAndroid Build Coastguard Worker return None;
506*9880d681SAndroid Build Coastguard Worker return NewAS;
507*9880d681SAndroid Build Coastguard Worker }
508*9880d681SAndroid Build Coastguard Worker
rewriteWithNewAddressSpaces(const std::vector<Value * > & Postorder,const ValueToAddrSpaceMapTy & InferredAddrSpace,Function * F)509*9880d681SAndroid Build Coastguard Worker bool NVPTXInferAddressSpaces::rewriteWithNewAddressSpaces(
510*9880d681SAndroid Build Coastguard Worker const std::vector<Value *> &Postorder,
511*9880d681SAndroid Build Coastguard Worker const ValueToAddrSpaceMapTy &InferredAddrSpace, Function *F) {
512*9880d681SAndroid Build Coastguard Worker // For each address expression to be modified, creates a clone of it with its
513*9880d681SAndroid Build Coastguard Worker // pointer operands converted to the new address space. Since the pointer
514*9880d681SAndroid Build Coastguard Worker // operands are converted, the clone is naturally in the new address space by
515*9880d681SAndroid Build Coastguard Worker // construction.
516*9880d681SAndroid Build Coastguard Worker ValueToValueMapTy ValueWithNewAddrSpace;
517*9880d681SAndroid Build Coastguard Worker SmallVector<const Use *, 32> UndefUsesToFix;
518*9880d681SAndroid Build Coastguard Worker for (Value* V : Postorder) {
519*9880d681SAndroid Build Coastguard Worker unsigned NewAddrSpace = InferredAddrSpace.lookup(V);
520*9880d681SAndroid Build Coastguard Worker if (V->getType()->getPointerAddressSpace() != NewAddrSpace) {
521*9880d681SAndroid Build Coastguard Worker ValueWithNewAddrSpace[V] = cloneValueWithNewAddressSpace(
522*9880d681SAndroid Build Coastguard Worker V, NewAddrSpace, ValueWithNewAddrSpace, &UndefUsesToFix);
523*9880d681SAndroid Build Coastguard Worker }
524*9880d681SAndroid Build Coastguard Worker }
525*9880d681SAndroid Build Coastguard Worker
526*9880d681SAndroid Build Coastguard Worker if (ValueWithNewAddrSpace.empty())
527*9880d681SAndroid Build Coastguard Worker return false;
528*9880d681SAndroid Build Coastguard Worker
529*9880d681SAndroid Build Coastguard Worker // Fixes all the undef uses generated by cloneInstructionWithNewAddressSpace.
530*9880d681SAndroid Build Coastguard Worker for (const Use* UndefUse : UndefUsesToFix) {
531*9880d681SAndroid Build Coastguard Worker User *V = UndefUse->getUser();
532*9880d681SAndroid Build Coastguard Worker User *NewV = cast<User>(ValueWithNewAddrSpace.lookup(V));
533*9880d681SAndroid Build Coastguard Worker unsigned OperandNo = UndefUse->getOperandNo();
534*9880d681SAndroid Build Coastguard Worker assert(isa<UndefValue>(NewV->getOperand(OperandNo)));
535*9880d681SAndroid Build Coastguard Worker NewV->setOperand(OperandNo, ValueWithNewAddrSpace.lookup(UndefUse->get()));
536*9880d681SAndroid Build Coastguard Worker }
537*9880d681SAndroid Build Coastguard Worker
538*9880d681SAndroid Build Coastguard Worker // Replaces the uses of the old address expressions with the new ones.
539*9880d681SAndroid Build Coastguard Worker for (Value *V : Postorder) {
540*9880d681SAndroid Build Coastguard Worker Value *NewV = ValueWithNewAddrSpace.lookup(V);
541*9880d681SAndroid Build Coastguard Worker if (NewV == nullptr)
542*9880d681SAndroid Build Coastguard Worker continue;
543*9880d681SAndroid Build Coastguard Worker
544*9880d681SAndroid Build Coastguard Worker SmallVector<Use *, 4> Uses;
545*9880d681SAndroid Build Coastguard Worker for (Use &U : V->uses())
546*9880d681SAndroid Build Coastguard Worker Uses.push_back(&U);
547*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Replacing the uses of " << *V << "\n to\n " << *NewV
548*9880d681SAndroid Build Coastguard Worker << "\n");
549*9880d681SAndroid Build Coastguard Worker for (Use *U : Uses) {
550*9880d681SAndroid Build Coastguard Worker if (isa<LoadInst>(U->getUser()) ||
551*9880d681SAndroid Build Coastguard Worker (isa<StoreInst>(U->getUser()) && U->getOperandNo() == 1)) {
552*9880d681SAndroid Build Coastguard Worker // If V is used as the pointer operand of a load/store, sets the pointer
553*9880d681SAndroid Build Coastguard Worker // operand to NewV. This replacement does not change the element type,
554*9880d681SAndroid Build Coastguard Worker // so the resultant load/store is still valid.
555*9880d681SAndroid Build Coastguard Worker U->set(NewV);
556*9880d681SAndroid Build Coastguard Worker } else if (isa<Instruction>(U->getUser())) {
557*9880d681SAndroid Build Coastguard Worker // Otherwise, replaces the use with generic(NewV).
558*9880d681SAndroid Build Coastguard Worker // TODO: Some optimization opportunities are missed. For example, in
559*9880d681SAndroid Build Coastguard Worker // %0 = icmp eq float* %p, %q
560*9880d681SAndroid Build Coastguard Worker // if both p and q are inferred to be shared, we can rewrite %0 as
561*9880d681SAndroid Build Coastguard Worker // %0 = icmp eq float addrspace(3)* %new_p, %new_q
562*9880d681SAndroid Build Coastguard Worker // instead of currently
563*9880d681SAndroid Build Coastguard Worker // %generic_p = addrspacecast float addrspace(3)* %new_p to float*
564*9880d681SAndroid Build Coastguard Worker // %generic_q = addrspacecast float addrspace(3)* %new_q to float*
565*9880d681SAndroid Build Coastguard Worker // %0 = icmp eq float* %generic_p, %generic_q
566*9880d681SAndroid Build Coastguard Worker if (Instruction *I = dyn_cast<Instruction>(V)) {
567*9880d681SAndroid Build Coastguard Worker BasicBlock::iterator InsertPos = std::next(I->getIterator());
568*9880d681SAndroid Build Coastguard Worker while (isa<PHINode>(InsertPos))
569*9880d681SAndroid Build Coastguard Worker ++InsertPos;
570*9880d681SAndroid Build Coastguard Worker U->set(new AddrSpaceCastInst(NewV, V->getType(), "", &*InsertPos));
571*9880d681SAndroid Build Coastguard Worker } else {
572*9880d681SAndroid Build Coastguard Worker U->set(ConstantExpr::getAddrSpaceCast(cast<Constant>(NewV),
573*9880d681SAndroid Build Coastguard Worker V->getType()));
574*9880d681SAndroid Build Coastguard Worker }
575*9880d681SAndroid Build Coastguard Worker }
576*9880d681SAndroid Build Coastguard Worker }
577*9880d681SAndroid Build Coastguard Worker if (V->use_empty())
578*9880d681SAndroid Build Coastguard Worker RecursivelyDeleteTriviallyDeadInstructions(V);
579*9880d681SAndroid Build Coastguard Worker }
580*9880d681SAndroid Build Coastguard Worker
581*9880d681SAndroid Build Coastguard Worker return true;
582*9880d681SAndroid Build Coastguard Worker }
583*9880d681SAndroid Build Coastguard Worker
createNVPTXInferAddressSpacesPass()584*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createNVPTXInferAddressSpacesPass() {
585*9880d681SAndroid Build Coastguard Worker return new NVPTXInferAddressSpaces();
586*9880d681SAndroid Build Coastguard Worker }
587