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