xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
10b57cec5SDimitry Andric //===- InferAddressSpace.cpp - --------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // CUDA C/C++ includes memory space designation as variable type qualifers (such
100b57cec5SDimitry Andric // as __global__ and __shared__). Knowing the space of a memory access allows
110b57cec5SDimitry Andric // CUDA compilers to emit faster PTX loads and stores. For example, a load from
120b57cec5SDimitry Andric // shared memory can be translated to `ld.shared` which is roughly 10% faster
130b57cec5SDimitry Andric // than a generic `ld` on an NVIDIA Tesla K40c.
140b57cec5SDimitry Andric //
150b57cec5SDimitry Andric // Unfortunately, type qualifiers only apply to variable declarations, so CUDA
160b57cec5SDimitry Andric // compilers must infer the memory space of an address expression from
170b57cec5SDimitry Andric // type-qualified variables.
180b57cec5SDimitry Andric //
190b57cec5SDimitry Andric // LLVM IR uses non-zero (so-called) specific address spaces to represent memory
200b57cec5SDimitry Andric // spaces (e.g. addrspace(3) means shared memory). The Clang frontend
210b57cec5SDimitry Andric // places only type-qualified variables in specific address spaces, and then
220b57cec5SDimitry Andric // conservatively `addrspacecast`s each type-qualified variable to addrspace(0)
230b57cec5SDimitry Andric // (so-called the generic address space) for other instructions to use.
240b57cec5SDimitry Andric //
250b57cec5SDimitry Andric // For example, the Clang translates the following CUDA code
260b57cec5SDimitry Andric //   __shared__ float a[10];
270b57cec5SDimitry Andric //   float v = a[i];
280b57cec5SDimitry Andric // to
290b57cec5SDimitry Andric //   %0 = addrspacecast [10 x float] addrspace(3)* @a to [10 x float]*
300b57cec5SDimitry Andric //   %1 = gep [10 x float], [10 x float]* %0, i64 0, i64 %i
310b57cec5SDimitry Andric //   %v = load float, float* %1 ; emits ld.f32
320b57cec5SDimitry Andric // @a is in addrspace(3) since it's type-qualified, but its use from %1 is
330b57cec5SDimitry Andric // redirected to %0 (the generic version of @a).
340b57cec5SDimitry Andric //
350b57cec5SDimitry Andric // The optimization implemented in this file propagates specific address spaces
360b57cec5SDimitry Andric // from type-qualified variable declarations to its users. For example, it
370b57cec5SDimitry Andric // optimizes the above IR to
380b57cec5SDimitry Andric //   %1 = gep [10 x float] addrspace(3)* @a, i64 0, i64 %i
390b57cec5SDimitry Andric //   %v = load float addrspace(3)* %1 ; emits ld.shared.f32
400b57cec5SDimitry Andric // propagating the addrspace(3) from @a to %1. As the result, the NVPTX
410b57cec5SDimitry Andric // codegen is able to emit ld.shared.f32 for %v.
420b57cec5SDimitry Andric //
430b57cec5SDimitry Andric // Address space inference works in two steps. First, it uses a data-flow
440b57cec5SDimitry Andric // analysis to infer as many generic pointers as possible to point to only one
450b57cec5SDimitry Andric // specific address space. In the above example, it can prove that %1 only
460b57cec5SDimitry Andric // points to addrspace(3). This algorithm was published in
470b57cec5SDimitry Andric //   CUDA: Compiling and optimizing for a GPU platform
480b57cec5SDimitry Andric //   Chakrabarti, Grover, Aarts, Kong, Kudlur, Lin, Marathe, Murphy, Wang
490b57cec5SDimitry Andric //   ICCS 2012
500b57cec5SDimitry Andric //
510b57cec5SDimitry Andric // Then, address space inference replaces all refinable generic pointers with
520b57cec5SDimitry Andric // equivalent specific pointers.
530b57cec5SDimitry Andric //
540b57cec5SDimitry Andric // The major challenge of implementing this optimization is handling PHINodes,
550b57cec5SDimitry Andric // which may create loops in the data flow graph. This brings two complications.
560b57cec5SDimitry Andric //
570b57cec5SDimitry Andric // First, the data flow analysis in Step 1 needs to be circular. For example,
580b57cec5SDimitry Andric //     %generic.input = addrspacecast float addrspace(3)* %input to float*
590b57cec5SDimitry Andric //   loop:
600b57cec5SDimitry Andric //     %y = phi [ %generic.input, %y2 ]
610b57cec5SDimitry Andric //     %y2 = getelementptr %y, 1
620b57cec5SDimitry Andric //     %v = load %y2
630b57cec5SDimitry Andric //     br ..., label %loop, ...
640b57cec5SDimitry Andric // proving %y specific requires proving both %generic.input and %y2 specific,
650b57cec5SDimitry Andric // but proving %y2 specific circles back to %y. To address this complication,
660b57cec5SDimitry Andric // the data flow analysis operates on a lattice:
670b57cec5SDimitry Andric //   uninitialized > specific address spaces > generic.
680b57cec5SDimitry Andric // All address expressions (our implementation only considers phi, bitcast,
690b57cec5SDimitry Andric // addrspacecast, and getelementptr) start with the uninitialized address space.
700b57cec5SDimitry Andric // The monotone transfer function moves the address space of a pointer down a
710b57cec5SDimitry Andric // lattice path from uninitialized to specific and then to generic. A join
720b57cec5SDimitry Andric // operation of two different specific address spaces pushes the expression down
730b57cec5SDimitry Andric // to the generic address space. The analysis completes once it reaches a fixed
740b57cec5SDimitry Andric // point.
750b57cec5SDimitry Andric //
760b57cec5SDimitry Andric // Second, IR rewriting in Step 2 also needs to be circular. For example,
770b57cec5SDimitry Andric // converting %y to addrspace(3) requires the compiler to know the converted
780b57cec5SDimitry Andric // %y2, but converting %y2 needs the converted %y. To address this complication,
7906c3fb27SDimitry Andric // we break these cycles using "poison" placeholders. When converting an
800b57cec5SDimitry Andric // instruction `I` to a new address space, if its operand `Op` is not converted
8106c3fb27SDimitry Andric // yet, we let `I` temporarily use `poison` and fix all the uses later.
820b57cec5SDimitry Andric // For instance, our algorithm first converts %y to
8306c3fb27SDimitry Andric //   %y' = phi float addrspace(3)* [ %input, poison ]
840b57cec5SDimitry Andric // Then, it converts %y2 to
850b57cec5SDimitry Andric //   %y2' = getelementptr %y', 1
8606c3fb27SDimitry Andric // Finally, it fixes the poison in %y' so that
870b57cec5SDimitry Andric //   %y' = phi float addrspace(3)* [ %input, %y2' ]
880b57cec5SDimitry Andric //
890b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
900b57cec5SDimitry Andric 
91e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/InferAddressSpaces.h"
920b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
930b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
940b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
950b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
960b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
97349cc55cSDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
980b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
99349cc55cSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
1000b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
1010b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
1020b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
103349cc55cSDimitry Andric #include "llvm/IR/Dominators.h"
1040b57cec5SDimitry Andric #include "llvm/IR/Function.h"
1050b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
1060b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h"
1070b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
1080b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
1090b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
1100b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
1110b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
1120b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
113e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h"
1140b57cec5SDimitry Andric #include "llvm/IR/Type.h"
1150b57cec5SDimitry Andric #include "llvm/IR/Use.h"
1160b57cec5SDimitry Andric #include "llvm/IR/User.h"
1170b57cec5SDimitry Andric #include "llvm/IR/Value.h"
1180b57cec5SDimitry Andric #include "llvm/IR/ValueHandle.h"
119349cc55cSDimitry Andric #include "llvm/InitializePasses.h"
1200b57cec5SDimitry Andric #include "llvm/Pass.h"
1210b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
1225ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
1230b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
1240b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
1250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
1270b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
1285ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/Local.h"
1290b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h"
1300b57cec5SDimitry Andric #include <cassert>
1310b57cec5SDimitry Andric #include <iterator>
1320b57cec5SDimitry Andric #include <limits>
1330b57cec5SDimitry Andric #include <utility>
1340b57cec5SDimitry Andric #include <vector>
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric #define DEBUG_TYPE "infer-address-spaces"
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric using namespace llvm;
1390b57cec5SDimitry Andric 
1405ffd83dbSDimitry Andric static cl::opt<bool> AssumeDefaultIsFlatAddressSpace(
1415ffd83dbSDimitry Andric     "assume-default-is-flat-addrspace", cl::init(false), cl::ReallyHidden,
1425ffd83dbSDimitry Andric     cl::desc("The default address space is assumed as the flat address space. "
1435ffd83dbSDimitry Andric              "This is mainly for test purpose."));
1445ffd83dbSDimitry Andric 
1450b57cec5SDimitry Andric static const unsigned UninitializedAddressSpace =
1460b57cec5SDimitry Andric     std::numeric_limits<unsigned>::max();
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric namespace {
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric using ValueToAddrSpaceMapTy = DenseMap<const Value *, unsigned>;
151349cc55cSDimitry Andric // Different from ValueToAddrSpaceMapTy, where a new addrspace is inferred on
152349cc55cSDimitry Andric // the *def* of a value, PredicatedAddrSpaceMapTy is map where a new
153349cc55cSDimitry Andric // addrspace is inferred on the *use* of a pointer. This map is introduced to
154349cc55cSDimitry Andric // infer addrspace from the addrspace predicate assumption built from assume
155349cc55cSDimitry Andric // intrinsic. In that scenario, only specific uses (under valid assumption
156349cc55cSDimitry Andric // context) could be inferred with a new addrspace.
157349cc55cSDimitry Andric using PredicatedAddrSpaceMapTy =
158349cc55cSDimitry Andric     DenseMap<std::pair<const Value *, const Value *>, unsigned>;
1595ffd83dbSDimitry Andric using PostorderStackTy = llvm::SmallVector<PointerIntPair<Value *, 1, bool>, 4>;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric class InferAddressSpaces : public FunctionPass {
162480093f4SDimitry Andric   unsigned FlatAddrSpace = 0;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric public:
1650b57cec5SDimitry Andric   static char ID;
1660b57cec5SDimitry Andric 
1675f757f3fSDimitry Andric   InferAddressSpaces()
1685f757f3fSDimitry Andric       : FunctionPass(ID), FlatAddrSpace(UninitializedAddressSpace) {
1695f757f3fSDimitry Andric     initializeInferAddressSpacesPass(*PassRegistry::getPassRegistry());
1705f757f3fSDimitry Andric   }
1715f757f3fSDimitry Andric   InferAddressSpaces(unsigned AS) : FunctionPass(ID), FlatAddrSpace(AS) {
1725f757f3fSDimitry Andric     initializeInferAddressSpacesPass(*PassRegistry::getPassRegistry());
1735f757f3fSDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
1760b57cec5SDimitry Andric     AU.setPreservesCFG();
177349cc55cSDimitry Andric     AU.addPreserved<DominatorTreeWrapperPass>();
178349cc55cSDimitry Andric     AU.addRequired<AssumptionCacheTracker>();
1790b57cec5SDimitry Andric     AU.addRequired<TargetTransformInfoWrapperPass>();
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   bool runOnFunction(Function &F) override;
183e8d8bef9SDimitry Andric };
1840b57cec5SDimitry Andric 
185e8d8bef9SDimitry Andric class InferAddressSpacesImpl {
186349cc55cSDimitry Andric   AssumptionCache &AC;
18781ad6265SDimitry Andric   const DominatorTree *DT = nullptr;
188e8d8bef9SDimitry Andric   const TargetTransformInfo *TTI = nullptr;
189e8d8bef9SDimitry Andric   const DataLayout *DL = nullptr;
190e8d8bef9SDimitry Andric 
191e8d8bef9SDimitry Andric   /// Target specific address space which uses of should be replaced if
192e8d8bef9SDimitry Andric   /// possible.
193e8d8bef9SDimitry Andric   unsigned FlatAddrSpace = 0;
194e8d8bef9SDimitry Andric 
195349cc55cSDimitry Andric   // Try to update the address space of V. If V is updated, returns true and
196349cc55cSDimitry Andric   // false otherwise.
197349cc55cSDimitry Andric   bool updateAddressSpace(const Value &V,
198349cc55cSDimitry Andric                           ValueToAddrSpaceMapTy &InferredAddrSpace,
199349cc55cSDimitry Andric                           PredicatedAddrSpaceMapTy &PredicatedAS) const;
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   // Tries to infer the specific address space of each address expression in
2020b57cec5SDimitry Andric   // Postorder.
2030b57cec5SDimitry Andric   void inferAddressSpaces(ArrayRef<WeakTrackingVH> Postorder,
204349cc55cSDimitry Andric                           ValueToAddrSpaceMapTy &InferredAddrSpace,
205349cc55cSDimitry Andric                           PredicatedAddrSpaceMapTy &PredicatedAS) const;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   bool isSafeToCastConstAddrSpace(Constant *C, unsigned NewAS) const;
2080b57cec5SDimitry Andric 
2095ffd83dbSDimitry Andric   Value *cloneInstructionWithNewAddressSpace(
2105ffd83dbSDimitry Andric       Instruction *I, unsigned NewAddrSpace,
2115ffd83dbSDimitry Andric       const ValueToValueMapTy &ValueWithNewAddrSpace,
212349cc55cSDimitry Andric       const PredicatedAddrSpaceMapTy &PredicatedAS,
21306c3fb27SDimitry Andric       SmallVectorImpl<const Use *> *PoisonUsesToFix) const;
2145ffd83dbSDimitry Andric 
2150b57cec5SDimitry Andric   // Changes the flat address expressions in function F to point to specific
2160b57cec5SDimitry Andric   // address spaces if InferredAddrSpace says so. Postorder is the postorder of
2170b57cec5SDimitry Andric   // all flat expressions in the use-def graph of function F.
21881ad6265SDimitry Andric   bool
21981ad6265SDimitry Andric   rewriteWithNewAddressSpaces(ArrayRef<WeakTrackingVH> Postorder,
220349cc55cSDimitry Andric                               const ValueToAddrSpaceMapTy &InferredAddrSpace,
22181ad6265SDimitry Andric                               const PredicatedAddrSpaceMapTy &PredicatedAS,
22281ad6265SDimitry Andric                               Function *F) const;
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   void appendsFlatAddressExpressionToPostorderStack(
2255ffd83dbSDimitry Andric       Value *V, PostorderStackTy &PostorderStack,
2260b57cec5SDimitry Andric       DenseSet<Value *> &Visited) const;
2270b57cec5SDimitry Andric 
2285f757f3fSDimitry Andric   bool rewriteIntrinsicOperands(IntrinsicInst *II, Value *OldV,
2295f757f3fSDimitry Andric                                 Value *NewV) const;
2305ffd83dbSDimitry Andric   void collectRewritableIntrinsicOperands(IntrinsicInst *II,
2315ffd83dbSDimitry Andric                                           PostorderStackTy &PostorderStack,
2320b57cec5SDimitry Andric                                           DenseSet<Value *> &Visited) const;
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   std::vector<WeakTrackingVH> collectFlatAddressExpressions(Function &F) const;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   Value *cloneValueWithNewAddressSpace(
2370b57cec5SDimitry Andric       Value *V, unsigned NewAddrSpace,
2380b57cec5SDimitry Andric       const ValueToValueMapTy &ValueWithNewAddrSpace,
239349cc55cSDimitry Andric       const PredicatedAddrSpaceMapTy &PredicatedAS,
24006c3fb27SDimitry Andric       SmallVectorImpl<const Use *> *PoisonUsesToFix) const;
2410b57cec5SDimitry Andric   unsigned joinAddressSpaces(unsigned AS1, unsigned AS2) const;
242e8d8bef9SDimitry Andric 
243349cc55cSDimitry Andric   unsigned getPredicatedAddrSpace(const Value &V, Value *Opnd) const;
244349cc55cSDimitry Andric 
245e8d8bef9SDimitry Andric public:
24681ad6265SDimitry Andric   InferAddressSpacesImpl(AssumptionCache &AC, const DominatorTree *DT,
247349cc55cSDimitry Andric                          const TargetTransformInfo *TTI, unsigned FlatAddrSpace)
248349cc55cSDimitry Andric       : AC(AC), DT(DT), TTI(TTI), FlatAddrSpace(FlatAddrSpace) {}
249e8d8bef9SDimitry Andric   bool run(Function &F);
2500b57cec5SDimitry Andric };
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric } // end anonymous namespace
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric char InferAddressSpaces::ID = 0;
2550b57cec5SDimitry Andric 
256349cc55cSDimitry Andric INITIALIZE_PASS_BEGIN(InferAddressSpaces, DEBUG_TYPE, "Infer address spaces",
257349cc55cSDimitry Andric                       false, false)
258349cc55cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
259349cc55cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
260349cc55cSDimitry Andric INITIALIZE_PASS_END(InferAddressSpaces, DEBUG_TYPE, "Infer address spaces",
2610b57cec5SDimitry Andric                     false, false)
2620b57cec5SDimitry Andric 
26306c3fb27SDimitry Andric static Type *getPtrOrVecOfPtrsWithNewAS(Type *Ty, unsigned NewAddrSpace) {
26406c3fb27SDimitry Andric   assert(Ty->isPtrOrPtrVectorTy());
26506c3fb27SDimitry Andric   PointerType *NPT = PointerType::get(Ty->getContext(), NewAddrSpace);
26606c3fb27SDimitry Andric   return Ty->getWithNewType(NPT);
26706c3fb27SDimitry Andric }
26806c3fb27SDimitry Andric 
2695ffd83dbSDimitry Andric // Check whether that's no-op pointer bicast using a pair of
2705ffd83dbSDimitry Andric // `ptrtoint`/`inttoptr` due to the missing no-op pointer bitcast over
2715ffd83dbSDimitry Andric // different address spaces.
2725ffd83dbSDimitry Andric static bool isNoopPtrIntCastPair(const Operator *I2P, const DataLayout &DL,
2735ffd83dbSDimitry Andric                                  const TargetTransformInfo *TTI) {
2745ffd83dbSDimitry Andric   assert(I2P->getOpcode() == Instruction::IntToPtr);
2755ffd83dbSDimitry Andric   auto *P2I = dyn_cast<Operator>(I2P->getOperand(0));
2765ffd83dbSDimitry Andric   if (!P2I || P2I->getOpcode() != Instruction::PtrToInt)
2775ffd83dbSDimitry Andric     return false;
2785ffd83dbSDimitry Andric   // Check it's really safe to treat that pair of `ptrtoint`/`inttoptr` as a
2795ffd83dbSDimitry Andric   // no-op cast. Besides checking both of them are no-op casts, as the
2805ffd83dbSDimitry Andric   // reinterpreted pointer may be used in other pointer arithmetic, we also
2815ffd83dbSDimitry Andric   // need to double-check that through the target-specific hook. That ensures
2825ffd83dbSDimitry Andric   // the underlying target also agrees that's a no-op address space cast and
2835ffd83dbSDimitry Andric   // pointer bits are preserved.
2845ffd83dbSDimitry Andric   // The current IR spec doesn't have clear rules on address space casts,
2855ffd83dbSDimitry Andric   // especially a clear definition for pointer bits in non-default address
2865ffd83dbSDimitry Andric   // spaces. It would be undefined if that pointer is dereferenced after an
2875ffd83dbSDimitry Andric   // invalid reinterpret cast. Also, due to the unclearness for the meaning of
2885ffd83dbSDimitry Andric   // bits in non-default address spaces in the current spec, the pointer
2895ffd83dbSDimitry Andric   // arithmetic may also be undefined after invalid pointer reinterpret cast.
2905ffd83dbSDimitry Andric   // However, as we confirm through the target hooks that it's a no-op
2915ffd83dbSDimitry Andric   // addrspacecast, it doesn't matter since the bits should be the same.
29281ad6265SDimitry Andric   unsigned P2IOp0AS = P2I->getOperand(0)->getType()->getPointerAddressSpace();
29381ad6265SDimitry Andric   unsigned I2PAS = I2P->getType()->getPointerAddressSpace();
2945ffd83dbSDimitry Andric   return CastInst::isNoopCast(Instruction::CastOps(I2P->getOpcode()),
2955ffd83dbSDimitry Andric                               I2P->getOperand(0)->getType(), I2P->getType(),
2965ffd83dbSDimitry Andric                               DL) &&
2975ffd83dbSDimitry Andric          CastInst::isNoopCast(Instruction::CastOps(P2I->getOpcode()),
2985ffd83dbSDimitry Andric                               P2I->getOperand(0)->getType(), P2I->getType(),
2995ffd83dbSDimitry Andric                               DL) &&
30081ad6265SDimitry Andric          (P2IOp0AS == I2PAS || TTI->isNoopAddrSpaceCast(P2IOp0AS, I2PAS));
3015ffd83dbSDimitry Andric }
3025ffd83dbSDimitry Andric 
3030b57cec5SDimitry Andric // Returns true if V is an address expression.
3040b57cec5SDimitry Andric // TODO: Currently, we consider only phi, bitcast, addrspacecast, and
3050b57cec5SDimitry Andric // getelementptr operators.
3065ffd83dbSDimitry Andric static bool isAddressExpression(const Value &V, const DataLayout &DL,
3075ffd83dbSDimitry Andric                                 const TargetTransformInfo *TTI) {
3085ffd83dbSDimitry Andric   const Operator *Op = dyn_cast<Operator>(&V);
3095ffd83dbSDimitry Andric   if (!Op)
3100b57cec5SDimitry Andric     return false;
3110b57cec5SDimitry Andric 
3125ffd83dbSDimitry Andric   switch (Op->getOpcode()) {
3130b57cec5SDimitry Andric   case Instruction::PHI:
31406c3fb27SDimitry Andric     assert(Op->getType()->isPtrOrPtrVectorTy());
3150b57cec5SDimitry Andric     return true;
3160b57cec5SDimitry Andric   case Instruction::BitCast:
3170b57cec5SDimitry Andric   case Instruction::AddrSpaceCast:
3180b57cec5SDimitry Andric   case Instruction::GetElementPtr:
3190b57cec5SDimitry Andric     return true;
3200b57cec5SDimitry Andric   case Instruction::Select:
32106c3fb27SDimitry Andric     return Op->getType()->isPtrOrPtrVectorTy();
3225ffd83dbSDimitry Andric   case Instruction::Call: {
3235ffd83dbSDimitry Andric     const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&V);
3245ffd83dbSDimitry Andric     return II && II->getIntrinsicID() == Intrinsic::ptrmask;
3255ffd83dbSDimitry Andric   }
3265ffd83dbSDimitry Andric   case Instruction::IntToPtr:
3275ffd83dbSDimitry Andric     return isNoopPtrIntCastPair(Op, DL, TTI);
3280b57cec5SDimitry Andric   default:
329e8d8bef9SDimitry Andric     // That value is an address expression if it has an assumed address space.
330e8d8bef9SDimitry Andric     return TTI->getAssumedAddrSpace(&V) != UninitializedAddressSpace;
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric // Returns the pointer operands of V.
3350b57cec5SDimitry Andric //
3360b57cec5SDimitry Andric // Precondition: V is an address expression.
3375ffd83dbSDimitry Andric static SmallVector<Value *, 2>
3385ffd83dbSDimitry Andric getPointerOperands(const Value &V, const DataLayout &DL,
3395ffd83dbSDimitry Andric                    const TargetTransformInfo *TTI) {
3400b57cec5SDimitry Andric   const Operator &Op = cast<Operator>(V);
3410b57cec5SDimitry Andric   switch (Op.getOpcode()) {
3420b57cec5SDimitry Andric   case Instruction::PHI: {
3430b57cec5SDimitry Andric     auto IncomingValues = cast<PHINode>(Op).incoming_values();
34481ad6265SDimitry Andric     return {IncomingValues.begin(), IncomingValues.end()};
3450b57cec5SDimitry Andric   }
3460b57cec5SDimitry Andric   case Instruction::BitCast:
3470b57cec5SDimitry Andric   case Instruction::AddrSpaceCast:
3480b57cec5SDimitry Andric   case Instruction::GetElementPtr:
3490b57cec5SDimitry Andric     return {Op.getOperand(0)};
3500b57cec5SDimitry Andric   case Instruction::Select:
3510b57cec5SDimitry Andric     return {Op.getOperand(1), Op.getOperand(2)};
3525ffd83dbSDimitry Andric   case Instruction::Call: {
3535ffd83dbSDimitry Andric     const IntrinsicInst &II = cast<IntrinsicInst>(Op);
3545ffd83dbSDimitry Andric     assert(II.getIntrinsicID() == Intrinsic::ptrmask &&
3555ffd83dbSDimitry Andric            "unexpected intrinsic call");
3565ffd83dbSDimitry Andric     return {II.getArgOperand(0)};
3575ffd83dbSDimitry Andric   }
3585ffd83dbSDimitry Andric   case Instruction::IntToPtr: {
3595ffd83dbSDimitry Andric     assert(isNoopPtrIntCastPair(&Op, DL, TTI));
3605ffd83dbSDimitry Andric     auto *P2I = cast<Operator>(Op.getOperand(0));
3615ffd83dbSDimitry Andric     return {P2I->getOperand(0)};
3625ffd83dbSDimitry Andric   }
3630b57cec5SDimitry Andric   default:
3640b57cec5SDimitry Andric     llvm_unreachable("Unexpected instruction type.");
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
368e8d8bef9SDimitry Andric bool InferAddressSpacesImpl::rewriteIntrinsicOperands(IntrinsicInst *II,
3690b57cec5SDimitry Andric                                                       Value *OldV,
3700b57cec5SDimitry Andric                                                       Value *NewV) const {
3710b57cec5SDimitry Andric   Module *M = II->getParent()->getParent()->getParent();
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric   switch (II->getIntrinsicID()) {
3740b57cec5SDimitry Andric   case Intrinsic::objectsize: {
3750b57cec5SDimitry Andric     Type *DestTy = II->getType();
3760b57cec5SDimitry Andric     Type *SrcTy = NewV->getType();
3770b57cec5SDimitry Andric     Function *NewDecl =
3780b57cec5SDimitry Andric         Intrinsic::getDeclaration(M, II->getIntrinsicID(), {DestTy, SrcTy});
3790b57cec5SDimitry Andric     II->setArgOperand(0, NewV);
3800b57cec5SDimitry Andric     II->setCalledFunction(NewDecl);
3810b57cec5SDimitry Andric     return true;
3820b57cec5SDimitry Andric   }
3835ffd83dbSDimitry Andric   case Intrinsic::ptrmask:
3845ffd83dbSDimitry Andric     // This is handled as an address expression, not as a use memory operation.
3855ffd83dbSDimitry Andric     return false;
38606c3fb27SDimitry Andric   case Intrinsic::masked_gather: {
38706c3fb27SDimitry Andric     Type *RetTy = II->getType();
38806c3fb27SDimitry Andric     Type *NewPtrTy = NewV->getType();
38906c3fb27SDimitry Andric     Function *NewDecl =
39006c3fb27SDimitry Andric         Intrinsic::getDeclaration(M, II->getIntrinsicID(), {RetTy, NewPtrTy});
39106c3fb27SDimitry Andric     II->setArgOperand(0, NewV);
39206c3fb27SDimitry Andric     II->setCalledFunction(NewDecl);
39306c3fb27SDimitry Andric     return true;
39406c3fb27SDimitry Andric   }
39506c3fb27SDimitry Andric   case Intrinsic::masked_scatter: {
39606c3fb27SDimitry Andric     Type *ValueTy = II->getOperand(0)->getType();
39706c3fb27SDimitry Andric     Type *NewPtrTy = NewV->getType();
39806c3fb27SDimitry Andric     Function *NewDecl =
39906c3fb27SDimitry Andric         Intrinsic::getDeclaration(M, II->getIntrinsicID(), {ValueTy, NewPtrTy});
40006c3fb27SDimitry Andric     II->setArgOperand(1, NewV);
40106c3fb27SDimitry Andric     II->setCalledFunction(NewDecl);
40206c3fb27SDimitry Andric     return true;
40306c3fb27SDimitry Andric   }
4045ffd83dbSDimitry Andric   default: {
4055ffd83dbSDimitry Andric     Value *Rewrite = TTI->rewriteIntrinsicWithAddressSpace(II, OldV, NewV);
4065ffd83dbSDimitry Andric     if (!Rewrite)
4075ffd83dbSDimitry Andric       return false;
4085ffd83dbSDimitry Andric     if (Rewrite != II)
4095ffd83dbSDimitry Andric       II->replaceAllUsesWith(Rewrite);
4105ffd83dbSDimitry Andric     return true;
4115ffd83dbSDimitry Andric   }
4120b57cec5SDimitry Andric   }
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
415e8d8bef9SDimitry Andric void InferAddressSpacesImpl::collectRewritableIntrinsicOperands(
4165ffd83dbSDimitry Andric     IntrinsicInst *II, PostorderStackTy &PostorderStack,
4170b57cec5SDimitry Andric     DenseSet<Value *> &Visited) const {
4188bcb0991SDimitry Andric   auto IID = II->getIntrinsicID();
4198bcb0991SDimitry Andric   switch (IID) {
4205ffd83dbSDimitry Andric   case Intrinsic::ptrmask:
4210b57cec5SDimitry Andric   case Intrinsic::objectsize:
4220b57cec5SDimitry Andric     appendsFlatAddressExpressionToPostorderStack(II->getArgOperand(0),
4230b57cec5SDimitry Andric                                                  PostorderStack, Visited);
4240b57cec5SDimitry Andric     break;
42506c3fb27SDimitry Andric   case Intrinsic::masked_gather:
42606c3fb27SDimitry Andric     appendsFlatAddressExpressionToPostorderStack(II->getArgOperand(0),
42706c3fb27SDimitry Andric                                                  PostorderStack, Visited);
42806c3fb27SDimitry Andric     break;
42906c3fb27SDimitry Andric   case Intrinsic::masked_scatter:
43006c3fb27SDimitry Andric     appendsFlatAddressExpressionToPostorderStack(II->getArgOperand(1),
43106c3fb27SDimitry Andric                                                  PostorderStack, Visited);
43206c3fb27SDimitry Andric     break;
4330b57cec5SDimitry Andric   default:
4348bcb0991SDimitry Andric     SmallVector<int, 2> OpIndexes;
4358bcb0991SDimitry Andric     if (TTI->collectFlatAddressOperands(OpIndexes, IID)) {
4368bcb0991SDimitry Andric       for (int Idx : OpIndexes) {
4378bcb0991SDimitry Andric         appendsFlatAddressExpressionToPostorderStack(II->getArgOperand(Idx),
4388bcb0991SDimitry Andric                                                      PostorderStack, Visited);
4398bcb0991SDimitry Andric       }
4408bcb0991SDimitry Andric     }
4410b57cec5SDimitry Andric     break;
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric // Returns all flat address expressions in function F. The elements are
4460b57cec5SDimitry Andric // If V is an unvisited flat address expression, appends V to PostorderStack
4470b57cec5SDimitry Andric // and marks it as visited.
448e8d8bef9SDimitry Andric void InferAddressSpacesImpl::appendsFlatAddressExpressionToPostorderStack(
4495ffd83dbSDimitry Andric     Value *V, PostorderStackTy &PostorderStack,
4500b57cec5SDimitry Andric     DenseSet<Value *> &Visited) const {
45106c3fb27SDimitry Andric   assert(V->getType()->isPtrOrPtrVectorTy());
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   // Generic addressing expressions may be hidden in nested constant
4540b57cec5SDimitry Andric   // expressions.
4550b57cec5SDimitry Andric   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
4560b57cec5SDimitry Andric     // TODO: Look in non-address parts, like icmp operands.
4575ffd83dbSDimitry Andric     if (isAddressExpression(*CE, *DL, TTI) && Visited.insert(CE).second)
4585ffd83dbSDimitry Andric       PostorderStack.emplace_back(CE, false);
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric     return;
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
463e8d8bef9SDimitry Andric   if (V->getType()->getPointerAddressSpace() == FlatAddrSpace &&
464e8d8bef9SDimitry Andric       isAddressExpression(*V, *DL, TTI)) {
4650b57cec5SDimitry Andric     if (Visited.insert(V).second) {
4665ffd83dbSDimitry Andric       PostorderStack.emplace_back(V, false);
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric       Operator *Op = cast<Operator>(V);
4690b57cec5SDimitry Andric       for (unsigned I = 0, E = Op->getNumOperands(); I != E; ++I) {
4700b57cec5SDimitry Andric         if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op->getOperand(I))) {
4715ffd83dbSDimitry Andric           if (isAddressExpression(*CE, *DL, TTI) && Visited.insert(CE).second)
4720b57cec5SDimitry Andric             PostorderStack.emplace_back(CE, false);
4730b57cec5SDimitry Andric         }
4740b57cec5SDimitry Andric       }
4750b57cec5SDimitry Andric     }
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric // Returns all flat address expressions in function F. The elements are ordered
4805f757f3fSDimitry Andric // in postorder.
4810b57cec5SDimitry Andric std::vector<WeakTrackingVH>
482e8d8bef9SDimitry Andric InferAddressSpacesImpl::collectFlatAddressExpressions(Function &F) const {
4830b57cec5SDimitry Andric   // This function implements a non-recursive postorder traversal of a partial
4840b57cec5SDimitry Andric   // use-def graph of function F.
4855ffd83dbSDimitry Andric   PostorderStackTy PostorderStack;
4860b57cec5SDimitry Andric   // The set of visited expressions.
4870b57cec5SDimitry Andric   DenseSet<Value *> Visited;
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   auto PushPtrOperand = [&](Value *Ptr) {
4905f757f3fSDimitry Andric     appendsFlatAddressExpressionToPostorderStack(Ptr, PostorderStack, Visited);
4910b57cec5SDimitry Andric   };
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   // Look at operations that may be interesting accelerate by moving to a known
4940b57cec5SDimitry Andric   // address space. We aim at generating after loads and stores, but pure
4950b57cec5SDimitry Andric   // addressing calculations may also be faster.
4960b57cec5SDimitry Andric   for (Instruction &I : instructions(F)) {
4970b57cec5SDimitry Andric     if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
4980b57cec5SDimitry Andric       PushPtrOperand(GEP->getPointerOperand());
4990b57cec5SDimitry Andric     } else if (auto *LI = dyn_cast<LoadInst>(&I))
5000b57cec5SDimitry Andric       PushPtrOperand(LI->getPointerOperand());
5010b57cec5SDimitry Andric     else if (auto *SI = dyn_cast<StoreInst>(&I))
5020b57cec5SDimitry Andric       PushPtrOperand(SI->getPointerOperand());
5030b57cec5SDimitry Andric     else if (auto *RMW = dyn_cast<AtomicRMWInst>(&I))
5040b57cec5SDimitry Andric       PushPtrOperand(RMW->getPointerOperand());
5050b57cec5SDimitry Andric     else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(&I))
5060b57cec5SDimitry Andric       PushPtrOperand(CmpX->getPointerOperand());
5070b57cec5SDimitry Andric     else if (auto *MI = dyn_cast<MemIntrinsic>(&I)) {
5080b57cec5SDimitry Andric       // For memset/memcpy/memmove, any pointer operand can be replaced.
5090b57cec5SDimitry Andric       PushPtrOperand(MI->getRawDest());
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric       // Handle 2nd operand for memcpy/memmove.
5120b57cec5SDimitry Andric       if (auto *MTI = dyn_cast<MemTransferInst>(MI))
5130b57cec5SDimitry Andric         PushPtrOperand(MTI->getRawSource());
5140b57cec5SDimitry Andric     } else if (auto *II = dyn_cast<IntrinsicInst>(&I))
5150b57cec5SDimitry Andric       collectRewritableIntrinsicOperands(II, PostorderStack, Visited);
5160b57cec5SDimitry Andric     else if (ICmpInst *Cmp = dyn_cast<ICmpInst>(&I)) {
51706c3fb27SDimitry Andric       if (Cmp->getOperand(0)->getType()->isPtrOrPtrVectorTy()) {
5180b57cec5SDimitry Andric         PushPtrOperand(Cmp->getOperand(0));
5190b57cec5SDimitry Andric         PushPtrOperand(Cmp->getOperand(1));
5200b57cec5SDimitry Andric       }
5210b57cec5SDimitry Andric     } else if (auto *ASC = dyn_cast<AddrSpaceCastInst>(&I)) {
5220b57cec5SDimitry Andric       PushPtrOperand(ASC->getPointerOperand());
5235ffd83dbSDimitry Andric     } else if (auto *I2P = dyn_cast<IntToPtrInst>(&I)) {
5245ffd83dbSDimitry Andric       if (isNoopPtrIntCastPair(cast<Operator>(I2P), *DL, TTI))
5255f757f3fSDimitry Andric         PushPtrOperand(cast<Operator>(I2P->getOperand(0))->getOperand(0));
5265f757f3fSDimitry Andric     } else if (auto *RI = dyn_cast<ReturnInst>(&I)) {
5275f757f3fSDimitry Andric       if (auto *RV = RI->getReturnValue();
5285f757f3fSDimitry Andric           RV && RV->getType()->isPtrOrPtrVectorTy())
5295f757f3fSDimitry Andric         PushPtrOperand(RV);
5300b57cec5SDimitry Andric     }
5310b57cec5SDimitry Andric   }
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   std::vector<WeakTrackingVH> Postorder; // The resultant postorder.
5340b57cec5SDimitry Andric   while (!PostorderStack.empty()) {
5355ffd83dbSDimitry Andric     Value *TopVal = PostorderStack.back().getPointer();
5360b57cec5SDimitry Andric     // If the operands of the expression on the top are already explored,
5370b57cec5SDimitry Andric     // adds that expression to the resultant postorder.
5385ffd83dbSDimitry Andric     if (PostorderStack.back().getInt()) {
5390b57cec5SDimitry Andric       if (TopVal->getType()->getPointerAddressSpace() == FlatAddrSpace)
5400b57cec5SDimitry Andric         Postorder.push_back(TopVal);
5410b57cec5SDimitry Andric       PostorderStack.pop_back();
5420b57cec5SDimitry Andric       continue;
5430b57cec5SDimitry Andric     }
5440b57cec5SDimitry Andric     // Otherwise, adds its operands to the stack and explores them.
5455ffd83dbSDimitry Andric     PostorderStack.back().setInt(true);
546e8d8bef9SDimitry Andric     // Skip values with an assumed address space.
547e8d8bef9SDimitry Andric     if (TTI->getAssumedAddrSpace(TopVal) == UninitializedAddressSpace) {
5485ffd83dbSDimitry Andric       for (Value *PtrOperand : getPointerOperands(*TopVal, *DL, TTI)) {
5490b57cec5SDimitry Andric         appendsFlatAddressExpressionToPostorderStack(PtrOperand, PostorderStack,
5500b57cec5SDimitry Andric                                                      Visited);
5510b57cec5SDimitry Andric       }
5520b57cec5SDimitry Andric     }
553e8d8bef9SDimitry Andric   }
5540b57cec5SDimitry Andric   return Postorder;
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric // A helper function for cloneInstructionWithNewAddressSpace. Returns the clone
5580b57cec5SDimitry Andric // of OperandUse.get() in the new address space. If the clone is not ready yet,
55906c3fb27SDimitry Andric // returns poison in the new address space as a placeholder.
56006c3fb27SDimitry Andric static Value *operandWithNewAddressSpaceOrCreatePoison(
5610b57cec5SDimitry Andric     const Use &OperandUse, unsigned NewAddrSpace,
5620b57cec5SDimitry Andric     const ValueToValueMapTy &ValueWithNewAddrSpace,
563349cc55cSDimitry Andric     const PredicatedAddrSpaceMapTy &PredicatedAS,
56406c3fb27SDimitry Andric     SmallVectorImpl<const Use *> *PoisonUsesToFix) {
5650b57cec5SDimitry Andric   Value *Operand = OperandUse.get();
5660b57cec5SDimitry Andric 
56706c3fb27SDimitry Andric   Type *NewPtrTy = getPtrOrVecOfPtrsWithNewAS(Operand->getType(), NewAddrSpace);
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   if (Constant *C = dyn_cast<Constant>(Operand))
5700b57cec5SDimitry Andric     return ConstantExpr::getAddrSpaceCast(C, NewPtrTy);
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   if (Value *NewOperand = ValueWithNewAddrSpace.lookup(Operand))
5730b57cec5SDimitry Andric     return NewOperand;
5740b57cec5SDimitry Andric 
575349cc55cSDimitry Andric   Instruction *Inst = cast<Instruction>(OperandUse.getUser());
576349cc55cSDimitry Andric   auto I = PredicatedAS.find(std::make_pair(Inst, Operand));
577349cc55cSDimitry Andric   if (I != PredicatedAS.end()) {
578349cc55cSDimitry Andric     // Insert an addrspacecast on that operand before the user.
579349cc55cSDimitry Andric     unsigned NewAS = I->second;
58006c3fb27SDimitry Andric     Type *NewPtrTy = getPtrOrVecOfPtrsWithNewAS(Operand->getType(), NewAS);
581349cc55cSDimitry Andric     auto *NewI = new AddrSpaceCastInst(Operand, NewPtrTy);
582349cc55cSDimitry Andric     NewI->insertBefore(Inst);
583bdd1243dSDimitry Andric     NewI->setDebugLoc(Inst->getDebugLoc());
584349cc55cSDimitry Andric     return NewI;
585349cc55cSDimitry Andric   }
586349cc55cSDimitry Andric 
58706c3fb27SDimitry Andric   PoisonUsesToFix->push_back(&OperandUse);
58806c3fb27SDimitry Andric   return PoisonValue::get(NewPtrTy);
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric // Returns a clone of `I` with its operands converted to those specified in
5920b57cec5SDimitry Andric // ValueWithNewAddrSpace. Due to potential cycles in the data flow graph, an
5930b57cec5SDimitry Andric // operand whose address space needs to be modified might not exist in
59406c3fb27SDimitry Andric // ValueWithNewAddrSpace. In that case, uses poison as a placeholder operand and
59506c3fb27SDimitry Andric // adds that operand use to PoisonUsesToFix so that caller can fix them later.
5960b57cec5SDimitry Andric //
5970b57cec5SDimitry Andric // Note that we do not necessarily clone `I`, e.g., if it is an addrspacecast
5980b57cec5SDimitry Andric // from a pointer whose type already matches. Therefore, this function returns a
5990b57cec5SDimitry Andric // Value* instead of an Instruction*.
6005ffd83dbSDimitry Andric //
6015ffd83dbSDimitry Andric // This may also return nullptr in the case the instruction could not be
6025ffd83dbSDimitry Andric // rewritten.
603e8d8bef9SDimitry Andric Value *InferAddressSpacesImpl::cloneInstructionWithNewAddressSpace(
6040b57cec5SDimitry Andric     Instruction *I, unsigned NewAddrSpace,
6050b57cec5SDimitry Andric     const ValueToValueMapTy &ValueWithNewAddrSpace,
606349cc55cSDimitry Andric     const PredicatedAddrSpaceMapTy &PredicatedAS,
60706c3fb27SDimitry Andric     SmallVectorImpl<const Use *> *PoisonUsesToFix) const {
60806c3fb27SDimitry Andric   Type *NewPtrType = getPtrOrVecOfPtrsWithNewAS(I->getType(), NewAddrSpace);
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   if (I->getOpcode() == Instruction::AddrSpaceCast) {
6110b57cec5SDimitry Andric     Value *Src = I->getOperand(0);
6120b57cec5SDimitry Andric     // Because `I` is flat, the source address space must be specific.
6130b57cec5SDimitry Andric     // Therefore, the inferred address space must be the source space, according
6140b57cec5SDimitry Andric     // to our algorithm.
6150b57cec5SDimitry Andric     assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace);
6160b57cec5SDimitry Andric     if (Src->getType() != NewPtrType)
6170b57cec5SDimitry Andric       return new BitCastInst(Src, NewPtrType);
6180b57cec5SDimitry Andric     return Src;
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric 
6215ffd83dbSDimitry Andric   if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
6225ffd83dbSDimitry Andric     // Technically the intrinsic ID is a pointer typed argument, so specially
6235ffd83dbSDimitry Andric     // handle calls early.
6245ffd83dbSDimitry Andric     assert(II->getIntrinsicID() == Intrinsic::ptrmask);
62506c3fb27SDimitry Andric     Value *NewPtr = operandWithNewAddressSpaceOrCreatePoison(
6265ffd83dbSDimitry Andric         II->getArgOperandUse(0), NewAddrSpace, ValueWithNewAddrSpace,
62706c3fb27SDimitry Andric         PredicatedAS, PoisonUsesToFix);
6285ffd83dbSDimitry Andric     Value *Rewrite =
6295ffd83dbSDimitry Andric         TTI->rewriteIntrinsicWithAddressSpace(II, II->getArgOperand(0), NewPtr);
6305ffd83dbSDimitry Andric     if (Rewrite) {
6315ffd83dbSDimitry Andric       assert(Rewrite != II && "cannot modify this pointer operation in place");
6325ffd83dbSDimitry Andric       return Rewrite;
6335ffd83dbSDimitry Andric     }
6345ffd83dbSDimitry Andric 
6355ffd83dbSDimitry Andric     return nullptr;
6365ffd83dbSDimitry Andric   }
6375ffd83dbSDimitry Andric 
638e8d8bef9SDimitry Andric   unsigned AS = TTI->getAssumedAddrSpace(I);
639e8d8bef9SDimitry Andric   if (AS != UninitializedAddressSpace) {
640e8d8bef9SDimitry Andric     // For the assumed address space, insert an `addrspacecast` to make that
641e8d8bef9SDimitry Andric     // explicit.
64206c3fb27SDimitry Andric     Type *NewPtrTy = getPtrOrVecOfPtrsWithNewAS(I->getType(), AS);
643e8d8bef9SDimitry Andric     auto *NewI = new AddrSpaceCastInst(I, NewPtrTy);
644e8d8bef9SDimitry Andric     NewI->insertAfter(I);
6450fca6ea1SDimitry Andric     NewI->setDebugLoc(I->getDebugLoc());
646e8d8bef9SDimitry Andric     return NewI;
647e8d8bef9SDimitry Andric   }
648e8d8bef9SDimitry Andric 
6490b57cec5SDimitry Andric   // Computes the converted pointer operands.
6500b57cec5SDimitry Andric   SmallVector<Value *, 4> NewPointerOperands;
6510b57cec5SDimitry Andric   for (const Use &OperandUse : I->operands()) {
65206c3fb27SDimitry Andric     if (!OperandUse.get()->getType()->isPtrOrPtrVectorTy())
6530b57cec5SDimitry Andric       NewPointerOperands.push_back(nullptr);
6540b57cec5SDimitry Andric     else
65506c3fb27SDimitry Andric       NewPointerOperands.push_back(operandWithNewAddressSpaceOrCreatePoison(
656349cc55cSDimitry Andric           OperandUse, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS,
65706c3fb27SDimitry Andric           PoisonUsesToFix));
6580b57cec5SDimitry Andric   }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric   switch (I->getOpcode()) {
6610b57cec5SDimitry Andric   case Instruction::BitCast:
6620b57cec5SDimitry Andric     return new BitCastInst(NewPointerOperands[0], NewPtrType);
6630b57cec5SDimitry Andric   case Instruction::PHI: {
66406c3fb27SDimitry Andric     assert(I->getType()->isPtrOrPtrVectorTy());
6650b57cec5SDimitry Andric     PHINode *PHI = cast<PHINode>(I);
6660b57cec5SDimitry Andric     PHINode *NewPHI = PHINode::Create(NewPtrType, PHI->getNumIncomingValues());
6670b57cec5SDimitry Andric     for (unsigned Index = 0; Index < PHI->getNumIncomingValues(); ++Index) {
6680b57cec5SDimitry Andric       unsigned OperandNo = PHINode::getOperandNumForIncomingValue(Index);
6690b57cec5SDimitry Andric       NewPHI->addIncoming(NewPointerOperands[OperandNo],
6700b57cec5SDimitry Andric                           PHI->getIncomingBlock(Index));
6710b57cec5SDimitry Andric     }
6720b57cec5SDimitry Andric     return NewPHI;
6730b57cec5SDimitry Andric   }
6740b57cec5SDimitry Andric   case Instruction::GetElementPtr: {
6750b57cec5SDimitry Andric     GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
6760b57cec5SDimitry Andric     GetElementPtrInst *NewGEP = GetElementPtrInst::Create(
6770b57cec5SDimitry Andric         GEP->getSourceElementType(), NewPointerOperands[0],
678e8d8bef9SDimitry Andric         SmallVector<Value *, 4>(GEP->indices()));
6790b57cec5SDimitry Andric     NewGEP->setIsInBounds(GEP->isInBounds());
6800b57cec5SDimitry Andric     return NewGEP;
6810b57cec5SDimitry Andric   }
6820b57cec5SDimitry Andric   case Instruction::Select:
68306c3fb27SDimitry Andric     assert(I->getType()->isPtrOrPtrVectorTy());
6840b57cec5SDimitry Andric     return SelectInst::Create(I->getOperand(0), NewPointerOperands[1],
6850b57cec5SDimitry Andric                               NewPointerOperands[2], "", nullptr, I);
6865ffd83dbSDimitry Andric   case Instruction::IntToPtr: {
6875ffd83dbSDimitry Andric     assert(isNoopPtrIntCastPair(cast<Operator>(I), *DL, TTI));
6885ffd83dbSDimitry Andric     Value *Src = cast<Operator>(I->getOperand(0))->getOperand(0);
689d56accc7SDimitry Andric     if (Src->getType() == NewPtrType)
6905ffd83dbSDimitry Andric       return Src;
691d56accc7SDimitry Andric 
692d56accc7SDimitry Andric     // If we had a no-op inttoptr/ptrtoint pair, we may still have inferred a
693d56accc7SDimitry Andric     // source address space from a generic pointer source need to insert a cast
694d56accc7SDimitry Andric     // back.
695d56accc7SDimitry Andric     return CastInst::CreatePointerBitCastOrAddrSpaceCast(Src, NewPtrType);
6965ffd83dbSDimitry Andric   }
6970b57cec5SDimitry Andric   default:
6980b57cec5SDimitry Andric     llvm_unreachable("Unexpected opcode");
6990b57cec5SDimitry Andric   }
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric // Similar to cloneInstructionWithNewAddressSpace, returns a clone of the
7030b57cec5SDimitry Andric // constant expression `CE` with its operands replaced as specified in
7040b57cec5SDimitry Andric // ValueWithNewAddrSpace.
7050b57cec5SDimitry Andric static Value *cloneConstantExprWithNewAddressSpace(
7060b57cec5SDimitry Andric     ConstantExpr *CE, unsigned NewAddrSpace,
7075ffd83dbSDimitry Andric     const ValueToValueMapTy &ValueWithNewAddrSpace, const DataLayout *DL,
7085ffd83dbSDimitry Andric     const TargetTransformInfo *TTI) {
70906c3fb27SDimitry Andric   Type *TargetType =
71006c3fb27SDimitry Andric       CE->getType()->isPtrOrPtrVectorTy()
71106c3fb27SDimitry Andric           ? getPtrOrVecOfPtrsWithNewAS(CE->getType(), NewAddrSpace)
712fe6060f1SDimitry Andric           : CE->getType();
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   if (CE->getOpcode() == Instruction::AddrSpaceCast) {
7150b57cec5SDimitry Andric     // Because CE is flat, the source address space must be specific.
7160b57cec5SDimitry Andric     // Therefore, the inferred address space must be the source space according
7170b57cec5SDimitry Andric     // to our algorithm.
7180b57cec5SDimitry Andric     assert(CE->getOperand(0)->getType()->getPointerAddressSpace() ==
7190b57cec5SDimitry Andric            NewAddrSpace);
7200b57cec5SDimitry Andric     return ConstantExpr::getBitCast(CE->getOperand(0), TargetType);
7210b57cec5SDimitry Andric   }
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric   if (CE->getOpcode() == Instruction::BitCast) {
7240b57cec5SDimitry Andric     if (Value *NewOperand = ValueWithNewAddrSpace.lookup(CE->getOperand(0)))
7250b57cec5SDimitry Andric       return ConstantExpr::getBitCast(cast<Constant>(NewOperand), TargetType);
7260b57cec5SDimitry Andric     return ConstantExpr::getAddrSpaceCast(CE, TargetType);
7270b57cec5SDimitry Andric   }
7280b57cec5SDimitry Andric 
7295ffd83dbSDimitry Andric   if (CE->getOpcode() == Instruction::IntToPtr) {
7305ffd83dbSDimitry Andric     assert(isNoopPtrIntCastPair(cast<Operator>(CE), *DL, TTI));
7315ffd83dbSDimitry Andric     Constant *Src = cast<ConstantExpr>(CE->getOperand(0))->getOperand(0);
7325ffd83dbSDimitry Andric     assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace);
7335ffd83dbSDimitry Andric     return ConstantExpr::getBitCast(Src, TargetType);
7345ffd83dbSDimitry Andric   }
7355ffd83dbSDimitry Andric 
7360b57cec5SDimitry Andric   // Computes the operands of the new constant expression.
7370b57cec5SDimitry Andric   bool IsNew = false;
7380b57cec5SDimitry Andric   SmallVector<Constant *, 4> NewOperands;
7390b57cec5SDimitry Andric   for (unsigned Index = 0; Index < CE->getNumOperands(); ++Index) {
7400b57cec5SDimitry Andric     Constant *Operand = CE->getOperand(Index);
7410b57cec5SDimitry Andric     // If the address space of `Operand` needs to be modified, the new operand
7420b57cec5SDimitry Andric     // with the new address space should already be in ValueWithNewAddrSpace
7430b57cec5SDimitry Andric     // because (1) the constant expressions we consider (i.e. addrspacecast,
7440b57cec5SDimitry Andric     // bitcast, and getelementptr) do not incur cycles in the data flow graph
7450b57cec5SDimitry Andric     // and (2) this function is called on constant expressions in postorder.
7460b57cec5SDimitry Andric     if (Value *NewOperand = ValueWithNewAddrSpace.lookup(Operand)) {
7470b57cec5SDimitry Andric       IsNew = true;
7480b57cec5SDimitry Andric       NewOperands.push_back(cast<Constant>(NewOperand));
7490b57cec5SDimitry Andric       continue;
7500b57cec5SDimitry Andric     }
75181ad6265SDimitry Andric     if (auto *CExpr = dyn_cast<ConstantExpr>(Operand))
7520b57cec5SDimitry Andric       if (Value *NewOperand = cloneConstantExprWithNewAddressSpace(
7535ffd83dbSDimitry Andric               CExpr, NewAddrSpace, ValueWithNewAddrSpace, DL, TTI)) {
7540b57cec5SDimitry Andric         IsNew = true;
7550b57cec5SDimitry Andric         NewOperands.push_back(cast<Constant>(NewOperand));
7560b57cec5SDimitry Andric         continue;
7570b57cec5SDimitry Andric       }
7580b57cec5SDimitry Andric     // Otherwise, reuses the old operand.
7590b57cec5SDimitry Andric     NewOperands.push_back(Operand);
7600b57cec5SDimitry Andric   }
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   // If !IsNew, we will replace the Value with itself. However, replaced values
76381ad6265SDimitry Andric   // are assumed to wrapped in an addrspacecast cast later so drop it now.
7640b57cec5SDimitry Andric   if (!IsNew)
7650b57cec5SDimitry Andric     return nullptr;
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric   if (CE->getOpcode() == Instruction::GetElementPtr) {
7680b57cec5SDimitry Andric     // Needs to specify the source type while constructing a getelementptr
7690b57cec5SDimitry Andric     // constant expression.
770349cc55cSDimitry Andric     return CE->getWithOperands(NewOperands, TargetType, /*OnlyIfReduced=*/false,
771349cc55cSDimitry Andric                                cast<GEPOperator>(CE)->getSourceElementType());
7720b57cec5SDimitry Andric   }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric   return CE->getWithOperands(NewOperands, TargetType);
7750b57cec5SDimitry Andric }
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric // Returns a clone of the value `V`, with its operands replaced as specified in
7780b57cec5SDimitry Andric // ValueWithNewAddrSpace. This function is called on every flat address
7790b57cec5SDimitry Andric // expression whose address space needs to be modified, in postorder.
7800b57cec5SDimitry Andric //
78106c3fb27SDimitry Andric // See cloneInstructionWithNewAddressSpace for the meaning of PoisonUsesToFix.
782e8d8bef9SDimitry Andric Value *InferAddressSpacesImpl::cloneValueWithNewAddressSpace(
7830b57cec5SDimitry Andric     Value *V, unsigned NewAddrSpace,
7840b57cec5SDimitry Andric     const ValueToValueMapTy &ValueWithNewAddrSpace,
785349cc55cSDimitry Andric     const PredicatedAddrSpaceMapTy &PredicatedAS,
78606c3fb27SDimitry Andric     SmallVectorImpl<const Use *> *PoisonUsesToFix) const {
7870b57cec5SDimitry Andric   // All values in Postorder are flat address expressions.
788e8d8bef9SDimitry Andric   assert(V->getType()->getPointerAddressSpace() == FlatAddrSpace &&
789e8d8bef9SDimitry Andric          isAddressExpression(*V, *DL, TTI));
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   if (Instruction *I = dyn_cast<Instruction>(V)) {
7920b57cec5SDimitry Andric     Value *NewV = cloneInstructionWithNewAddressSpace(
79306c3fb27SDimitry Andric         I, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix);
7945ffd83dbSDimitry Andric     if (Instruction *NewI = dyn_cast_or_null<Instruction>(NewV)) {
7950b57cec5SDimitry Andric       if (NewI->getParent() == nullptr) {
7960b57cec5SDimitry Andric         NewI->insertBefore(I);
7970b57cec5SDimitry Andric         NewI->takeName(I);
798bdd1243dSDimitry Andric         NewI->setDebugLoc(I->getDebugLoc());
7990b57cec5SDimitry Andric       }
8000b57cec5SDimitry Andric     }
8010b57cec5SDimitry Andric     return NewV;
8020b57cec5SDimitry Andric   }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric   return cloneConstantExprWithNewAddressSpace(
8055ffd83dbSDimitry Andric       cast<ConstantExpr>(V), NewAddrSpace, ValueWithNewAddrSpace, DL, TTI);
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric // Defines the join operation on the address space lattice (see the file header
8090b57cec5SDimitry Andric // comments).
810e8d8bef9SDimitry Andric unsigned InferAddressSpacesImpl::joinAddressSpaces(unsigned AS1,
8110b57cec5SDimitry Andric                                                    unsigned AS2) const {
8120b57cec5SDimitry Andric   if (AS1 == FlatAddrSpace || AS2 == FlatAddrSpace)
8130b57cec5SDimitry Andric     return FlatAddrSpace;
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric   if (AS1 == UninitializedAddressSpace)
8160b57cec5SDimitry Andric     return AS2;
8170b57cec5SDimitry Andric   if (AS2 == UninitializedAddressSpace)
8180b57cec5SDimitry Andric     return AS1;
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric   // The join of two different specific address spaces is flat.
8210b57cec5SDimitry Andric   return (AS1 == AS2) ? AS1 : FlatAddrSpace;
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric 
824e8d8bef9SDimitry Andric bool InferAddressSpacesImpl::run(Function &F) {
8250fca6ea1SDimitry Andric   DL = &F.getDataLayout();
8265ffd83dbSDimitry Andric 
8275ffd83dbSDimitry Andric   if (AssumeDefaultIsFlatAddressSpace)
8285ffd83dbSDimitry Andric     FlatAddrSpace = 0;
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric   if (FlatAddrSpace == UninitializedAddressSpace) {
8318bcb0991SDimitry Andric     FlatAddrSpace = TTI->getFlatAddressSpace();
8320b57cec5SDimitry Andric     if (FlatAddrSpace == UninitializedAddressSpace)
8330b57cec5SDimitry Andric       return false;
8340b57cec5SDimitry Andric   }
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric   // Collects all flat address expressions in postorder.
8370b57cec5SDimitry Andric   std::vector<WeakTrackingVH> Postorder = collectFlatAddressExpressions(F);
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric   // Runs a data-flow analysis to refine the address spaces of every expression
8400b57cec5SDimitry Andric   // in Postorder.
8410b57cec5SDimitry Andric   ValueToAddrSpaceMapTy InferredAddrSpace;
842349cc55cSDimitry Andric   PredicatedAddrSpaceMapTy PredicatedAS;
843349cc55cSDimitry Andric   inferAddressSpaces(Postorder, InferredAddrSpace, PredicatedAS);
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric   // Changes the address spaces of the flat address expressions who are inferred
8460b57cec5SDimitry Andric   // to point to a specific address space.
84781ad6265SDimitry Andric   return rewriteWithNewAddressSpaces(Postorder, InferredAddrSpace, PredicatedAS,
84881ad6265SDimitry Andric                                      &F);
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric 
8510b57cec5SDimitry Andric // Constants need to be tracked through RAUW to handle cases with nested
8520b57cec5SDimitry Andric // constant expressions, so wrap values in WeakTrackingVH.
853e8d8bef9SDimitry Andric void InferAddressSpacesImpl::inferAddressSpaces(
8540b57cec5SDimitry Andric     ArrayRef<WeakTrackingVH> Postorder,
855349cc55cSDimitry Andric     ValueToAddrSpaceMapTy &InferredAddrSpace,
856349cc55cSDimitry Andric     PredicatedAddrSpaceMapTy &PredicatedAS) const {
8570b57cec5SDimitry Andric   SetVector<Value *> Worklist(Postorder.begin(), Postorder.end());
8580b57cec5SDimitry Andric   // Initially, all expressions are in the uninitialized address space.
8590b57cec5SDimitry Andric   for (Value *V : Postorder)
860349cc55cSDimitry Andric     InferredAddrSpace[V] = UninitializedAddressSpace;
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   while (!Worklist.empty()) {
8630b57cec5SDimitry Andric     Value *V = Worklist.pop_back_val();
8640b57cec5SDimitry Andric 
865349cc55cSDimitry Andric     // Try to update the address space of the stack top according to the
8660b57cec5SDimitry Andric     // address spaces of its operands.
867349cc55cSDimitry Andric     if (!updateAddressSpace(*V, InferredAddrSpace, PredicatedAS))
8680b57cec5SDimitry Andric       continue;
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric     for (Value *User : V->users()) {
8710b57cec5SDimitry Andric       // Skip if User is already in the worklist.
8720b57cec5SDimitry Andric       if (Worklist.count(User))
8730b57cec5SDimitry Andric         continue;
8740b57cec5SDimitry Andric 
875349cc55cSDimitry Andric       auto Pos = InferredAddrSpace.find(User);
8760b57cec5SDimitry Andric       // Our algorithm only updates the address spaces of flat address
8770b57cec5SDimitry Andric       // expressions, which are those in InferredAddrSpace.
878349cc55cSDimitry Andric       if (Pos == InferredAddrSpace.end())
8790b57cec5SDimitry Andric         continue;
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric       // Function updateAddressSpace moves the address space down a lattice
8820b57cec5SDimitry Andric       // path. Therefore, nothing to do if User is already inferred as flat (the
8830b57cec5SDimitry Andric       // bottom element in the lattice).
8840b57cec5SDimitry Andric       if (Pos->second == FlatAddrSpace)
8850b57cec5SDimitry Andric         continue;
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric       Worklist.insert(User);
8880b57cec5SDimitry Andric     }
8890b57cec5SDimitry Andric   }
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric 
892349cc55cSDimitry Andric unsigned InferAddressSpacesImpl::getPredicatedAddrSpace(const Value &V,
893349cc55cSDimitry Andric                                                         Value *Opnd) const {
894349cc55cSDimitry Andric   const Instruction *I = dyn_cast<Instruction>(&V);
895349cc55cSDimitry Andric   if (!I)
896349cc55cSDimitry Andric     return UninitializedAddressSpace;
897349cc55cSDimitry Andric 
898349cc55cSDimitry Andric   Opnd = Opnd->stripInBoundsOffsets();
899349cc55cSDimitry Andric   for (auto &AssumeVH : AC.assumptionsFor(Opnd)) {
900349cc55cSDimitry Andric     if (!AssumeVH)
901349cc55cSDimitry Andric       continue;
902349cc55cSDimitry Andric     CallInst *CI = cast<CallInst>(AssumeVH);
903349cc55cSDimitry Andric     if (!isValidAssumeForContext(CI, I, DT))
904349cc55cSDimitry Andric       continue;
905349cc55cSDimitry Andric 
906349cc55cSDimitry Andric     const Value *Ptr;
907349cc55cSDimitry Andric     unsigned AS;
908349cc55cSDimitry Andric     std::tie(Ptr, AS) = TTI->getPredicatedAddrSpace(CI->getArgOperand(0));
909349cc55cSDimitry Andric     if (Ptr)
910349cc55cSDimitry Andric       return AS;
911349cc55cSDimitry Andric   }
912349cc55cSDimitry Andric 
913349cc55cSDimitry Andric   return UninitializedAddressSpace;
914349cc55cSDimitry Andric }
915349cc55cSDimitry Andric 
916349cc55cSDimitry Andric bool InferAddressSpacesImpl::updateAddressSpace(
917349cc55cSDimitry Andric     const Value &V, ValueToAddrSpaceMapTy &InferredAddrSpace,
918349cc55cSDimitry Andric     PredicatedAddrSpaceMapTy &PredicatedAS) const {
9190b57cec5SDimitry Andric   assert(InferredAddrSpace.count(&V));
9200b57cec5SDimitry Andric 
921349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Updating the address space of\n  " << V << '\n');
922349cc55cSDimitry Andric 
9230b57cec5SDimitry Andric   // The new inferred address space equals the join of the address spaces
9240b57cec5SDimitry Andric   // of all its pointer operands.
9250b57cec5SDimitry Andric   unsigned NewAS = UninitializedAddressSpace;
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   const Operator &Op = cast<Operator>(V);
9280b57cec5SDimitry Andric   if (Op.getOpcode() == Instruction::Select) {
9290b57cec5SDimitry Andric     Value *Src0 = Op.getOperand(1);
9300b57cec5SDimitry Andric     Value *Src1 = Op.getOperand(2);
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric     auto I = InferredAddrSpace.find(Src0);
9335f757f3fSDimitry Andric     unsigned Src0AS = (I != InferredAddrSpace.end())
9345f757f3fSDimitry Andric                           ? I->second
9355f757f3fSDimitry Andric                           : Src0->getType()->getPointerAddressSpace();
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric     auto J = InferredAddrSpace.find(Src1);
9385f757f3fSDimitry Andric     unsigned Src1AS = (J != InferredAddrSpace.end())
9395f757f3fSDimitry Andric                           ? J->second
9405f757f3fSDimitry Andric                           : Src1->getType()->getPointerAddressSpace();
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric     auto *C0 = dyn_cast<Constant>(Src0);
9430b57cec5SDimitry Andric     auto *C1 = dyn_cast<Constant>(Src1);
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric     // If one of the inputs is a constant, we may be able to do a constant
9460b57cec5SDimitry Andric     // addrspacecast of it. Defer inferring the address space until the input
9470b57cec5SDimitry Andric     // address space is known.
9480b57cec5SDimitry Andric     if ((C1 && Src0AS == UninitializedAddressSpace) ||
9490b57cec5SDimitry Andric         (C0 && Src1AS == UninitializedAddressSpace))
950349cc55cSDimitry Andric       return false;
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric     if (C0 && isSafeToCastConstAddrSpace(C0, Src1AS))
9530b57cec5SDimitry Andric       NewAS = Src1AS;
9540b57cec5SDimitry Andric     else if (C1 && isSafeToCastConstAddrSpace(C1, Src0AS))
9550b57cec5SDimitry Andric       NewAS = Src0AS;
9560b57cec5SDimitry Andric     else
9570b57cec5SDimitry Andric       NewAS = joinAddressSpaces(Src0AS, Src1AS);
9580b57cec5SDimitry Andric   } else {
959e8d8bef9SDimitry Andric     unsigned AS = TTI->getAssumedAddrSpace(&V);
960e8d8bef9SDimitry Andric     if (AS != UninitializedAddressSpace) {
961e8d8bef9SDimitry Andric       // Use the assumed address space directly.
962e8d8bef9SDimitry Andric       NewAS = AS;
963e8d8bef9SDimitry Andric     } else {
964e8d8bef9SDimitry Andric       // Otherwise, infer the address space from its pointer operands.
9655ffd83dbSDimitry Andric       for (Value *PtrOperand : getPointerOperands(V, *DL, TTI)) {
9660b57cec5SDimitry Andric         auto I = InferredAddrSpace.find(PtrOperand);
967349cc55cSDimitry Andric         unsigned OperandAS;
968349cc55cSDimitry Andric         if (I == InferredAddrSpace.end()) {
969349cc55cSDimitry Andric           OperandAS = PtrOperand->getType()->getPointerAddressSpace();
970349cc55cSDimitry Andric           if (OperandAS == FlatAddrSpace) {
971349cc55cSDimitry Andric             // Check AC for assumption dominating V.
972349cc55cSDimitry Andric             unsigned AS = getPredicatedAddrSpace(V, PtrOperand);
973349cc55cSDimitry Andric             if (AS != UninitializedAddressSpace) {
974349cc55cSDimitry Andric               LLVM_DEBUG(dbgs()
975349cc55cSDimitry Andric                          << "  deduce operand AS from the predicate addrspace "
976349cc55cSDimitry Andric                          << AS << '\n');
977349cc55cSDimitry Andric               OperandAS = AS;
978349cc55cSDimitry Andric               // Record this use with the predicated AS.
979349cc55cSDimitry Andric               PredicatedAS[std::make_pair(&V, PtrOperand)] = OperandAS;
980349cc55cSDimitry Andric             }
981349cc55cSDimitry Andric           }
982349cc55cSDimitry Andric         } else
983349cc55cSDimitry Andric           OperandAS = I->second;
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric         // join(flat, *) = flat. So we can break if NewAS is already flat.
9860b57cec5SDimitry Andric         NewAS = joinAddressSpaces(NewAS, OperandAS);
9870b57cec5SDimitry Andric         if (NewAS == FlatAddrSpace)
9880b57cec5SDimitry Andric           break;
9890b57cec5SDimitry Andric       }
9900b57cec5SDimitry Andric     }
991e8d8bef9SDimitry Andric   }
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric   unsigned OldAS = InferredAddrSpace.lookup(&V);
9940b57cec5SDimitry Andric   assert(OldAS != FlatAddrSpace);
9950b57cec5SDimitry Andric   if (OldAS == NewAS)
996349cc55cSDimitry Andric     return false;
997349cc55cSDimitry Andric 
998349cc55cSDimitry Andric   // If any updates are made, grabs its users to the worklist because
999349cc55cSDimitry Andric   // their address spaces can also be possibly updated.
1000349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "  to " << NewAS << '\n');
1001349cc55cSDimitry Andric   InferredAddrSpace[&V] = NewAS;
1002349cc55cSDimitry Andric   return true;
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric /// \p returns true if \p U is the pointer operand of a memory instruction with
10060b57cec5SDimitry Andric /// a single pointer operand that can have its address space changed by simply
10070b57cec5SDimitry Andric /// mutating the use to a new value. If the memory instruction is volatile,
10080b57cec5SDimitry Andric /// return true only if the target allows the memory instruction to be volatile
10090b57cec5SDimitry Andric /// in the new address space.
10100b57cec5SDimitry Andric static bool isSimplePointerUseValidToReplace(const TargetTransformInfo &TTI,
10110b57cec5SDimitry Andric                                              Use &U, unsigned AddrSpace) {
10120b57cec5SDimitry Andric   User *Inst = U.getUser();
10130b57cec5SDimitry Andric   unsigned OpNo = U.getOperandNo();
10140b57cec5SDimitry Andric   bool VolatileIsAllowed = false;
10150b57cec5SDimitry Andric   if (auto *I = dyn_cast<Instruction>(Inst))
10160b57cec5SDimitry Andric     VolatileIsAllowed = TTI.hasVolatileVariant(I, AddrSpace);
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   if (auto *LI = dyn_cast<LoadInst>(Inst))
10190b57cec5SDimitry Andric     return OpNo == LoadInst::getPointerOperandIndex() &&
10200b57cec5SDimitry Andric            (VolatileIsAllowed || !LI->isVolatile());
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   if (auto *SI = dyn_cast<StoreInst>(Inst))
10230b57cec5SDimitry Andric     return OpNo == StoreInst::getPointerOperandIndex() &&
10240b57cec5SDimitry Andric            (VolatileIsAllowed || !SI->isVolatile());
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric   if (auto *RMW = dyn_cast<AtomicRMWInst>(Inst))
10270b57cec5SDimitry Andric     return OpNo == AtomicRMWInst::getPointerOperandIndex() &&
10280b57cec5SDimitry Andric            (VolatileIsAllowed || !RMW->isVolatile());
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Inst))
10310b57cec5SDimitry Andric     return OpNo == AtomicCmpXchgInst::getPointerOperandIndex() &&
10320b57cec5SDimitry Andric            (VolatileIsAllowed || !CmpX->isVolatile());
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   return false;
10350b57cec5SDimitry Andric }
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric /// Update memory intrinsic uses that require more complex processing than
103881ad6265SDimitry Andric /// simple memory instructions. These require re-mangling and may have multiple
10390b57cec5SDimitry Andric /// pointer operands.
10400b57cec5SDimitry Andric static bool handleMemIntrinsicPtrUse(MemIntrinsic *MI, Value *OldV,
10410b57cec5SDimitry Andric                                      Value *NewV) {
10420b57cec5SDimitry Andric   IRBuilder<> B(MI);
10430b57cec5SDimitry Andric   MDNode *TBAA = MI->getMetadata(LLVMContext::MD_tbaa);
10440b57cec5SDimitry Andric   MDNode *ScopeMD = MI->getMetadata(LLVMContext::MD_alias_scope);
10450b57cec5SDimitry Andric   MDNode *NoAliasMD = MI->getMetadata(LLVMContext::MD_noalias);
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   if (auto *MSI = dyn_cast<MemSetInst>(MI)) {
104881ad6265SDimitry Andric     B.CreateMemSet(NewV, MSI->getValue(), MSI->getLength(), MSI->getDestAlign(),
10490b57cec5SDimitry Andric                    false, // isVolatile
10500b57cec5SDimitry Andric                    TBAA, ScopeMD, NoAliasMD);
10510b57cec5SDimitry Andric   } else if (auto *MTI = dyn_cast<MemTransferInst>(MI)) {
10520b57cec5SDimitry Andric     Value *Src = MTI->getRawSource();
10530b57cec5SDimitry Andric     Value *Dest = MTI->getRawDest();
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric     // Be careful in case this is a self-to-self copy.
10560b57cec5SDimitry Andric     if (Src == OldV)
10570b57cec5SDimitry Andric       Src = NewV;
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric     if (Dest == OldV)
10600b57cec5SDimitry Andric       Dest = NewV;
10610b57cec5SDimitry Andric 
1062fe6060f1SDimitry Andric     if (isa<MemCpyInlineInst>(MTI)) {
1063fe6060f1SDimitry Andric       MDNode *TBAAStruct = MTI->getMetadata(LLVMContext::MD_tbaa_struct);
1064fe6060f1SDimitry Andric       B.CreateMemCpyInline(Dest, MTI->getDestAlign(), Src,
1065fe6060f1SDimitry Andric                            MTI->getSourceAlign(), MTI->getLength(),
1066fe6060f1SDimitry Andric                            false, // isVolatile
1067fe6060f1SDimitry Andric                            TBAA, TBAAStruct, ScopeMD, NoAliasMD);
1068fe6060f1SDimitry Andric     } else if (isa<MemCpyInst>(MTI)) {
10690b57cec5SDimitry Andric       MDNode *TBAAStruct = MTI->getMetadata(LLVMContext::MD_tbaa_struct);
1070480093f4SDimitry Andric       B.CreateMemCpy(Dest, MTI->getDestAlign(), Src, MTI->getSourceAlign(),
10710b57cec5SDimitry Andric                      MTI->getLength(),
10720b57cec5SDimitry Andric                      false, // isVolatile
10730b57cec5SDimitry Andric                      TBAA, TBAAStruct, ScopeMD, NoAliasMD);
10740b57cec5SDimitry Andric     } else {
10750b57cec5SDimitry Andric       assert(isa<MemMoveInst>(MTI));
1076480093f4SDimitry Andric       B.CreateMemMove(Dest, MTI->getDestAlign(), Src, MTI->getSourceAlign(),
10770b57cec5SDimitry Andric                       MTI->getLength(),
10780b57cec5SDimitry Andric                       false, // isVolatile
10790b57cec5SDimitry Andric                       TBAA, ScopeMD, NoAliasMD);
10800b57cec5SDimitry Andric     }
10810b57cec5SDimitry Andric   } else
10820b57cec5SDimitry Andric     llvm_unreachable("unhandled MemIntrinsic");
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric   MI->eraseFromParent();
10850b57cec5SDimitry Andric   return true;
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric // \p returns true if it is OK to change the address space of constant \p C with
10890b57cec5SDimitry Andric // a ConstantExpr addrspacecast.
1090e8d8bef9SDimitry Andric bool InferAddressSpacesImpl::isSafeToCastConstAddrSpace(Constant *C,
1091e8d8bef9SDimitry Andric                                                         unsigned NewAS) const {
10920b57cec5SDimitry Andric   assert(NewAS != UninitializedAddressSpace);
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric   unsigned SrcAS = C->getType()->getPointerAddressSpace();
10950b57cec5SDimitry Andric   if (SrcAS == NewAS || isa<UndefValue>(C))
10960b57cec5SDimitry Andric     return true;
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric   // Prevent illegal casts between different non-flat address spaces.
10990b57cec5SDimitry Andric   if (SrcAS != FlatAddrSpace && NewAS != FlatAddrSpace)
11000b57cec5SDimitry Andric     return false;
11010b57cec5SDimitry Andric 
11020b57cec5SDimitry Andric   if (isa<ConstantPointerNull>(C))
11030b57cec5SDimitry Andric     return true;
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   if (auto *Op = dyn_cast<Operator>(C)) {
11060b57cec5SDimitry Andric     // If we already have a constant addrspacecast, it should be safe to cast it
11070b57cec5SDimitry Andric     // off.
11080b57cec5SDimitry Andric     if (Op->getOpcode() == Instruction::AddrSpaceCast)
11095f757f3fSDimitry Andric       return isSafeToCastConstAddrSpace(cast<Constant>(Op->getOperand(0)),
11105f757f3fSDimitry Andric                                         NewAS);
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric     if (Op->getOpcode() == Instruction::IntToPtr &&
11130b57cec5SDimitry Andric         Op->getType()->getPointerAddressSpace() == FlatAddrSpace)
11140b57cec5SDimitry Andric       return true;
11150b57cec5SDimitry Andric   }
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric   return false;
11180b57cec5SDimitry Andric }
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric static Value::use_iterator skipToNextUser(Value::use_iterator I,
11210b57cec5SDimitry Andric                                           Value::use_iterator End) {
11220b57cec5SDimitry Andric   User *CurUser = I->getUser();
11230b57cec5SDimitry Andric   ++I;
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric   while (I != End && I->getUser() == CurUser)
11260b57cec5SDimitry Andric     ++I;
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric   return I;
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric 
1131e8d8bef9SDimitry Andric bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
113281ad6265SDimitry Andric     ArrayRef<WeakTrackingVH> Postorder,
1133349cc55cSDimitry Andric     const ValueToAddrSpaceMapTy &InferredAddrSpace,
1134349cc55cSDimitry Andric     const PredicatedAddrSpaceMapTy &PredicatedAS, Function *F) const {
11350b57cec5SDimitry Andric   // For each address expression to be modified, creates a clone of it with its
11360b57cec5SDimitry Andric   // pointer operands converted to the new address space. Since the pointer
11370b57cec5SDimitry Andric   // operands are converted, the clone is naturally in the new address space by
11380b57cec5SDimitry Andric   // construction.
11390b57cec5SDimitry Andric   ValueToValueMapTy ValueWithNewAddrSpace;
114006c3fb27SDimitry Andric   SmallVector<const Use *, 32> PoisonUsesToFix;
11410b57cec5SDimitry Andric   for (Value *V : Postorder) {
11420b57cec5SDimitry Andric     unsigned NewAddrSpace = InferredAddrSpace.lookup(V);
1143e8d8bef9SDimitry Andric 
1144e8d8bef9SDimitry Andric     // In some degenerate cases (e.g. invalid IR in unreachable code), we may
1145e8d8bef9SDimitry Andric     // not even infer the value to have its original address space.
1146e8d8bef9SDimitry Andric     if (NewAddrSpace == UninitializedAddressSpace)
1147e8d8bef9SDimitry Andric       continue;
1148e8d8bef9SDimitry Andric 
11490b57cec5SDimitry Andric     if (V->getType()->getPointerAddressSpace() != NewAddrSpace) {
1150349cc55cSDimitry Andric       Value *New =
1151349cc55cSDimitry Andric           cloneValueWithNewAddressSpace(V, NewAddrSpace, ValueWithNewAddrSpace,
115206c3fb27SDimitry Andric                                         PredicatedAS, &PoisonUsesToFix);
11535ffd83dbSDimitry Andric       if (New)
11545ffd83dbSDimitry Andric         ValueWithNewAddrSpace[V] = New;
11550b57cec5SDimitry Andric     }
11560b57cec5SDimitry Andric   }
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric   if (ValueWithNewAddrSpace.empty())
11590b57cec5SDimitry Andric     return false;
11600b57cec5SDimitry Andric 
116106c3fb27SDimitry Andric   // Fixes all the poison uses generated by cloneInstructionWithNewAddressSpace.
116206c3fb27SDimitry Andric   for (const Use *PoisonUse : PoisonUsesToFix) {
116306c3fb27SDimitry Andric     User *V = PoisonUse->getUser();
11645ffd83dbSDimitry Andric     User *NewV = cast_or_null<User>(ValueWithNewAddrSpace.lookup(V));
11655ffd83dbSDimitry Andric     if (!NewV)
11665ffd83dbSDimitry Andric       continue;
11675ffd83dbSDimitry Andric 
116806c3fb27SDimitry Andric     unsigned OperandNo = PoisonUse->getOperandNo();
116906c3fb27SDimitry Andric     assert(isa<PoisonValue>(NewV->getOperand(OperandNo)));
117006c3fb27SDimitry Andric     NewV->setOperand(OperandNo, ValueWithNewAddrSpace.lookup(PoisonUse->get()));
11710b57cec5SDimitry Andric   }
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric   SmallVector<Instruction *, 16> DeadInstructions;
11745f757f3fSDimitry Andric   ValueToValueMapTy VMap;
11755f757f3fSDimitry Andric   ValueMapper VMapper(VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   // Replaces the uses of the old address expressions with the new ones.
11780b57cec5SDimitry Andric   for (const WeakTrackingVH &WVH : Postorder) {
11790b57cec5SDimitry Andric     assert(WVH && "value was unexpectedly deleted");
11800b57cec5SDimitry Andric     Value *V = WVH;
11810b57cec5SDimitry Andric     Value *NewV = ValueWithNewAddrSpace.lookup(V);
11820b57cec5SDimitry Andric     if (NewV == nullptr)
11830b57cec5SDimitry Andric       continue;
11840b57cec5SDimitry Andric 
11850b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Replacing the uses of " << *V << "\n  with\n  "
11860b57cec5SDimitry Andric                       << *NewV << '\n');
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric     if (Constant *C = dyn_cast<Constant>(V)) {
11895f757f3fSDimitry Andric       Constant *Replace =
11905f757f3fSDimitry Andric           ConstantExpr::getAddrSpaceCast(cast<Constant>(NewV), C->getType());
11910b57cec5SDimitry Andric       if (C != Replace) {
11920b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Inserting replacement const cast: " << Replace
11930b57cec5SDimitry Andric                           << ": " << *Replace << '\n');
11945f757f3fSDimitry Andric         SmallVector<User *, 16> WorkList;
11955f757f3fSDimitry Andric         for (User *U : make_early_inc_range(C->users())) {
11965f757f3fSDimitry Andric           if (auto *I = dyn_cast<Instruction>(U)) {
11975f757f3fSDimitry Andric             if (I->getFunction() == F)
11985f757f3fSDimitry Andric               I->replaceUsesOfWith(C, Replace);
11995f757f3fSDimitry Andric           } else {
12005f757f3fSDimitry Andric             WorkList.append(U->user_begin(), U->user_end());
12015f757f3fSDimitry Andric           }
12025f757f3fSDimitry Andric         }
12035f757f3fSDimitry Andric         if (!WorkList.empty()) {
12045f757f3fSDimitry Andric           VMap[C] = Replace;
12055f757f3fSDimitry Andric           DenseSet<User *> Visited{WorkList.begin(), WorkList.end()};
12065f757f3fSDimitry Andric           while (!WorkList.empty()) {
12075f757f3fSDimitry Andric             User *U = WorkList.pop_back_val();
12085f757f3fSDimitry Andric             if (auto *I = dyn_cast<Instruction>(U)) {
12095f757f3fSDimitry Andric               if (I->getFunction() == F)
12105f757f3fSDimitry Andric                 VMapper.remapInstruction(*I);
12115f757f3fSDimitry Andric               continue;
12125f757f3fSDimitry Andric             }
12135f757f3fSDimitry Andric             for (User *U2 : U->users())
12145f757f3fSDimitry Andric               if (Visited.insert(U2).second)
12155f757f3fSDimitry Andric                 WorkList.push_back(U2);
12165f757f3fSDimitry Andric           }
12175f757f3fSDimitry Andric         }
12180b57cec5SDimitry Andric         V = Replace;
12190b57cec5SDimitry Andric       }
12200b57cec5SDimitry Andric     }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric     Value::use_iterator I, E, Next;
12230b57cec5SDimitry Andric     for (I = V->use_begin(), E = V->use_end(); I != E;) {
12240b57cec5SDimitry Andric       Use &U = *I;
12250fca6ea1SDimitry Andric       User *CurUser = U.getUser();
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric       // Some users may see the same pointer operand in multiple operands. Skip
12280b57cec5SDimitry Andric       // to the next instruction.
12290b57cec5SDimitry Andric       I = skipToNextUser(I, E);
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric       if (isSimplePointerUseValidToReplace(
123281ad6265SDimitry Andric               *TTI, U, V->getType()->getPointerAddressSpace())) {
12330b57cec5SDimitry Andric         // If V is used as the pointer operand of a compatible memory operation,
12340b57cec5SDimitry Andric         // sets the pointer operand to NewV. This replacement does not change
12350b57cec5SDimitry Andric         // the element type, so the resultant load/store is still valid.
1236*52418fc2SDimitry Andric         U.set(NewV);
12370b57cec5SDimitry Andric         continue;
12380b57cec5SDimitry Andric       }
12390b57cec5SDimitry Andric 
1240e8d8bef9SDimitry Andric       // Skip if the current user is the new value itself.
1241e8d8bef9SDimitry Andric       if (CurUser == NewV)
1242e8d8bef9SDimitry Andric         continue;
12435f757f3fSDimitry Andric 
12445f757f3fSDimitry Andric       if (auto *CurUserI = dyn_cast<Instruction>(CurUser);
12455f757f3fSDimitry Andric           CurUserI && CurUserI->getFunction() != F)
12465f757f3fSDimitry Andric         continue;
12475f757f3fSDimitry Andric 
12480b57cec5SDimitry Andric       // Handle more complex cases like intrinsic that need to be remangled.
12490b57cec5SDimitry Andric       if (auto *MI = dyn_cast<MemIntrinsic>(CurUser)) {
12500b57cec5SDimitry Andric         if (!MI->isVolatile() && handleMemIntrinsicPtrUse(MI, V, NewV))
12510b57cec5SDimitry Andric           continue;
12520b57cec5SDimitry Andric       }
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric       if (auto *II = dyn_cast<IntrinsicInst>(CurUser)) {
12550b57cec5SDimitry Andric         if (rewriteIntrinsicOperands(II, V, NewV))
12560b57cec5SDimitry Andric           continue;
12570b57cec5SDimitry Andric       }
12580b57cec5SDimitry Andric 
12590b57cec5SDimitry Andric       if (isa<Instruction>(CurUser)) {
12600b57cec5SDimitry Andric         if (ICmpInst *Cmp = dyn_cast<ICmpInst>(CurUser)) {
12610b57cec5SDimitry Andric           // If we can infer that both pointers are in the same addrspace,
12620b57cec5SDimitry Andric           // transform e.g.
12630b57cec5SDimitry Andric           //   %cmp = icmp eq float* %p, %q
12640b57cec5SDimitry Andric           // into
12650b57cec5SDimitry Andric           //   %cmp = icmp eq float addrspace(3)* %new_p, %new_q
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric           unsigned NewAS = NewV->getType()->getPointerAddressSpace();
12680b57cec5SDimitry Andric           int SrcIdx = U.getOperandNo();
12690b57cec5SDimitry Andric           int OtherIdx = (SrcIdx == 0) ? 1 : 0;
12700b57cec5SDimitry Andric           Value *OtherSrc = Cmp->getOperand(OtherIdx);
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric           if (Value *OtherNewV = ValueWithNewAddrSpace.lookup(OtherSrc)) {
12730b57cec5SDimitry Andric             if (OtherNewV->getType()->getPointerAddressSpace() == NewAS) {
12740b57cec5SDimitry Andric               Cmp->setOperand(OtherIdx, OtherNewV);
12750b57cec5SDimitry Andric               Cmp->setOperand(SrcIdx, NewV);
12760b57cec5SDimitry Andric               continue;
12770b57cec5SDimitry Andric             }
12780b57cec5SDimitry Andric           }
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric           // Even if the type mismatches, we can cast the constant.
12810b57cec5SDimitry Andric           if (auto *KOtherSrc = dyn_cast<Constant>(OtherSrc)) {
12820b57cec5SDimitry Andric             if (isSafeToCastConstAddrSpace(KOtherSrc, NewAS)) {
12830b57cec5SDimitry Andric               Cmp->setOperand(SrcIdx, NewV);
12845f757f3fSDimitry Andric               Cmp->setOperand(OtherIdx, ConstantExpr::getAddrSpaceCast(
12855f757f3fSDimitry Andric                                             KOtherSrc, NewV->getType()));
12860b57cec5SDimitry Andric               continue;
12870b57cec5SDimitry Andric             }
12880b57cec5SDimitry Andric           }
12890b57cec5SDimitry Andric         }
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric         if (AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(CurUser)) {
12920b57cec5SDimitry Andric           unsigned NewAS = NewV->getType()->getPointerAddressSpace();
12930b57cec5SDimitry Andric           if (ASC->getDestAddressSpace() == NewAS) {
12940b57cec5SDimitry Andric             ASC->replaceAllUsesWith(NewV);
12950b57cec5SDimitry Andric             DeadInstructions.push_back(ASC);
12960b57cec5SDimitry Andric             continue;
12970b57cec5SDimitry Andric           }
12980b57cec5SDimitry Andric         }
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric         // Otherwise, replaces the use with flat(NewV).
130181ad6265SDimitry Andric         if (Instruction *VInst = dyn_cast<Instruction>(V)) {
13020b57cec5SDimitry Andric           // Don't create a copy of the original addrspacecast.
13030b57cec5SDimitry Andric           if (U == V && isa<AddrSpaceCastInst>(V))
13040b57cec5SDimitry Andric             continue;
13050b57cec5SDimitry Andric 
130681ad6265SDimitry Andric           // Insert the addrspacecast after NewV.
130781ad6265SDimitry Andric           BasicBlock::iterator InsertPos;
130881ad6265SDimitry Andric           if (Instruction *NewVInst = dyn_cast<Instruction>(NewV))
130981ad6265SDimitry Andric             InsertPos = std::next(NewVInst->getIterator());
131081ad6265SDimitry Andric           else
131181ad6265SDimitry Andric             InsertPos = std::next(VInst->getIterator());
131281ad6265SDimitry Andric 
13130b57cec5SDimitry Andric           while (isa<PHINode>(InsertPos))
13140b57cec5SDimitry Andric             ++InsertPos;
13150fca6ea1SDimitry Andric           // This instruction may contain multiple uses of V, update them all.
13160fca6ea1SDimitry Andric           CurUser->replaceUsesOfWith(
13170fca6ea1SDimitry Andric               V, new AddrSpaceCastInst(NewV, V->getType(), "", InsertPos));
13180b57cec5SDimitry Andric         } else {
13190fca6ea1SDimitry Andric           CurUser->replaceUsesOfWith(
13200fca6ea1SDimitry Andric               V, ConstantExpr::getAddrSpaceCast(cast<Constant>(NewV),
13210b57cec5SDimitry Andric                                                 V->getType()));
13220b57cec5SDimitry Andric         }
13230b57cec5SDimitry Andric       }
13240b57cec5SDimitry Andric     }
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric     if (V->use_empty()) {
13270b57cec5SDimitry Andric       if (Instruction *I = dyn_cast<Instruction>(V))
13280b57cec5SDimitry Andric         DeadInstructions.push_back(I);
13290b57cec5SDimitry Andric     }
13300b57cec5SDimitry Andric   }
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric   for (Instruction *I : DeadInstructions)
13330b57cec5SDimitry Andric     RecursivelyDeleteTriviallyDeadInstructions(I);
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   return true;
13360b57cec5SDimitry Andric }
13370b57cec5SDimitry Andric 
1338e8d8bef9SDimitry Andric bool InferAddressSpaces::runOnFunction(Function &F) {
1339e8d8bef9SDimitry Andric   if (skipFunction(F))
1340e8d8bef9SDimitry Andric     return false;
1341e8d8bef9SDimitry Andric 
1342349cc55cSDimitry Andric   auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1343349cc55cSDimitry Andric   DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr;
1344e8d8bef9SDimitry Andric   return InferAddressSpacesImpl(
1345349cc55cSDimitry Andric              getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F), DT,
1346e8d8bef9SDimitry Andric              &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F),
1347e8d8bef9SDimitry Andric              FlatAddrSpace)
1348e8d8bef9SDimitry Andric       .run(F);
1349e8d8bef9SDimitry Andric }
1350e8d8bef9SDimitry Andric 
13510b57cec5SDimitry Andric FunctionPass *llvm::createInferAddressSpacesPass(unsigned AddressSpace) {
13520b57cec5SDimitry Andric   return new InferAddressSpaces(AddressSpace);
13530b57cec5SDimitry Andric }
1354e8d8bef9SDimitry Andric 
1355e8d8bef9SDimitry Andric InferAddressSpacesPass::InferAddressSpacesPass()
1356e8d8bef9SDimitry Andric     : FlatAddrSpace(UninitializedAddressSpace) {}
1357e8d8bef9SDimitry Andric InferAddressSpacesPass::InferAddressSpacesPass(unsigned AddressSpace)
1358e8d8bef9SDimitry Andric     : FlatAddrSpace(AddressSpace) {}
1359e8d8bef9SDimitry Andric 
1360e8d8bef9SDimitry Andric PreservedAnalyses InferAddressSpacesPass::run(Function &F,
1361e8d8bef9SDimitry Andric                                               FunctionAnalysisManager &AM) {
1362e8d8bef9SDimitry Andric   bool Changed =
1363349cc55cSDimitry Andric       InferAddressSpacesImpl(AM.getResult<AssumptionAnalysis>(F),
1364349cc55cSDimitry Andric                              AM.getCachedResult<DominatorTreeAnalysis>(F),
1365349cc55cSDimitry Andric                              &AM.getResult<TargetIRAnalysis>(F), FlatAddrSpace)
1366e8d8bef9SDimitry Andric           .run(F);
1367e8d8bef9SDimitry Andric   if (Changed) {
1368e8d8bef9SDimitry Andric     PreservedAnalyses PA;
1369e8d8bef9SDimitry Andric     PA.preserveSet<CFGAnalyses>();
1370349cc55cSDimitry Andric     PA.preserve<DominatorTreeAnalysis>();
1371e8d8bef9SDimitry Andric     return PA;
1372e8d8bef9SDimitry Andric   }
1373e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
1374e8d8bef9SDimitry Andric }
1375