xref: /aosp_15_r20/external/llvm/lib/Target/NVPTX/NVPTXInferAddressSpaces.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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