| 1 | //===- InferAddressSpace.cpp - --------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // CUDA C/C++ includes memory space designation as variable type qualifers (such |
| 10 | // as __global__ and __shared__). Knowing the space of a memory access allows |
| 11 | // CUDA compilers to emit faster PTX loads and stores. For example, a load from |
| 12 | // shared memory can be translated to `ld.shared` which is roughly 10% faster |
| 13 | // than a generic `ld` on an NVIDIA Tesla K40c. |
| 14 | // |
| 15 | // Unfortunately, type qualifiers only apply to variable declarations, so CUDA |
| 16 | // compilers must infer the memory space of an address expression from |
| 17 | // type-qualified variables. |
| 18 | // |
| 19 | // LLVM IR uses non-zero (so-called) specific address spaces to represent memory |
| 20 | // spaces (e.g. addrspace(3) means shared memory). The Clang frontend |
| 21 | // places only type-qualified variables in specific address spaces, and then |
| 22 | // conservatively `addrspacecast`s each type-qualified variable to addrspace(0) |
| 23 | // (so-called the generic address space) for other instructions to use. |
| 24 | // |
| 25 | // For example, the Clang translates the following CUDA code |
| 26 | // __shared__ float a[10]; |
| 27 | // float v = a[i]; |
| 28 | // to |
| 29 | // %0 = addrspacecast [10 x float] addrspace(3)* @a to [10 x float]* |
| 30 | // %1 = gep [10 x float], [10 x float]* %0, i64 0, i64 %i |
| 31 | // %v = load float, float* %1 ; emits ld.f32 |
| 32 | // @a is in addrspace(3) since it's type-qualified, but its use from %1 is |
| 33 | // redirected to %0 (the generic version of @a). |
| 34 | // |
| 35 | // The optimization implemented in this file propagates specific address spaces |
| 36 | // from type-qualified variable declarations to its users. For example, it |
| 37 | // optimizes the above IR to |
| 38 | // %1 = gep [10 x float] addrspace(3)* @a, i64 0, i64 %i |
| 39 | // %v = load float addrspace(3)* %1 ; emits ld.shared.f32 |
| 40 | // propagating the addrspace(3) from @a to %1. As the result, the NVPTX |
| 41 | // codegen is able to emit ld.shared.f32 for %v. |
| 42 | // |
| 43 | // Address space inference works in two steps. First, it uses a data-flow |
| 44 | // analysis to infer as many generic pointers as possible to point to only one |
| 45 | // specific address space. In the above example, it can prove that %1 only |
| 46 | // points to addrspace(3). This algorithm was published in |
| 47 | // CUDA: Compiling and optimizing for a GPU platform |
| 48 | // Chakrabarti, Grover, Aarts, Kong, Kudlur, Lin, Marathe, Murphy, Wang |
| 49 | // ICCS 2012 |
| 50 | // |
| 51 | // Then, address space inference replaces all refinable generic pointers with |
| 52 | // equivalent specific pointers. |
| 53 | // |
| 54 | // The major challenge of implementing this optimization is handling PHINodes, |
| 55 | // which may create loops in the data flow graph. This brings two complications. |
| 56 | // |
| 57 | // First, the data flow analysis in Step 1 needs to be circular. For example, |
| 58 | // %generic.input = addrspacecast float addrspace(3)* %input to float* |
| 59 | // loop: |
| 60 | // %y = phi [ %generic.input, %y2 ] |
| 61 | // %y2 = getelementptr %y, 1 |
| 62 | // %v = load %y2 |
| 63 | // br ..., label %loop, ... |
| 64 | // proving %y specific requires proving both %generic.input and %y2 specific, |
| 65 | // but proving %y2 specific circles back to %y. To address this complication, |
| 66 | // the data flow analysis operates on a lattice: |
| 67 | // uninitialized > specific address spaces > generic. |
| 68 | // All address expressions (our implementation only considers phi, bitcast, |
| 69 | // addrspacecast, and getelementptr) start with the uninitialized address space. |
| 70 | // The monotone transfer function moves the address space of a pointer down a |
| 71 | // lattice path from uninitialized to specific and then to generic. A join |
| 72 | // operation of two different specific address spaces pushes the expression down |
| 73 | // to their common address space. The analysis completes once it reaches a fixed |
| 74 | // point. |
| 75 | // |
| 76 | // Second, IR rewriting in Step 2 also needs to be circular. For example, |
| 77 | // converting %y to addrspace(3) requires the compiler to know the converted |
| 78 | // %y2, but converting %y2 needs the converted %y. To address this complication, |
| 79 | // we break these cycles using "poison" placeholders. When converting an |
| 80 | // instruction `I` to a new address space, if its operand `Op` is not converted |
| 81 | // yet, we let `I` temporarily use `poison` and fix all the uses later. |
| 82 | // For instance, our algorithm first converts %y to |
| 83 | // %y' = phi float addrspace(3)* [ %input, poison ] |
| 84 | // Then, it converts %y2 to |
| 85 | // %y2' = getelementptr %y', 1 |
| 86 | // Finally, it fixes the poison in %y' so that |
| 87 | // %y' = phi float addrspace(3)* [ %input, %y2' ] |
| 88 | // |
| 89 | //===----------------------------------------------------------------------===// |
| 90 | |
| 91 | #include "llvm/Transforms/Scalar/InferAddressSpaces.h" |
| 92 | #include "llvm/ADT/ArrayRef.h" |
| 93 | #include "llvm/ADT/DenseMap.h" |
| 94 | #include "llvm/ADT/DenseSet.h" |
| 95 | #include "llvm/ADT/SetVector.h" |
| 96 | #include "llvm/ADT/SmallVector.h" |
| 97 | #include "llvm/Analysis/AssumptionCache.h" |
| 98 | #include "llvm/Analysis/TargetTransformInfo.h" |
| 99 | #include "llvm/Analysis/ValueTracking.h" |
| 100 | #include "llvm/IR/Argument.h" |
| 101 | #include "llvm/IR/BasicBlock.h" |
| 102 | #include "llvm/IR/Constant.h" |
| 103 | #include "llvm/IR/Constants.h" |
| 104 | #include "llvm/IR/Dominators.h" |
| 105 | #include "llvm/IR/Function.h" |
| 106 | #include "llvm/IR/IRBuilder.h" |
| 107 | #include "llvm/IR/InstIterator.h" |
| 108 | #include "llvm/IR/Instruction.h" |
| 109 | #include "llvm/IR/Instructions.h" |
| 110 | #include "llvm/IR/IntrinsicInst.h" |
| 111 | #include "llvm/IR/Intrinsics.h" |
| 112 | #include "llvm/IR/LLVMContext.h" |
| 113 | #include "llvm/IR/Operator.h" |
| 114 | #include "llvm/IR/PassManager.h" |
| 115 | #include "llvm/IR/PatternMatch.h" |
| 116 | #include "llvm/IR/Type.h" |
| 117 | #include "llvm/IR/Use.h" |
| 118 | #include "llvm/IR/User.h" |
| 119 | #include "llvm/IR/Value.h" |
| 120 | #include "llvm/IR/ValueHandle.h" |
| 121 | #include "llvm/InitializePasses.h" |
| 122 | #include "llvm/Pass.h" |
| 123 | #include "llvm/Support/Casting.h" |
| 124 | #include "llvm/Support/Debug.h" |
| 125 | #include "llvm/Support/ErrorHandling.h" |
| 126 | #include "llvm/Support/KnownBits.h" |
| 127 | #include "llvm/Support/raw_ostream.h" |
| 128 | #include "llvm/Transforms/Scalar.h" |
| 129 | #include "llvm/Transforms/Utils/Local.h" |
| 130 | #include "llvm/Transforms/Utils/ValueMapper.h" |
| 131 | #include <cassert> |
| 132 | #include <iterator> |
| 133 | #include <limits> |
| 134 | #include <optional> |
| 135 | #include <utility> |
| 136 | #include <vector> |
| 137 | |
| 138 | #define DEBUG_TYPE "infer-address-spaces" |
| 139 | |
| 140 | using namespace llvm; |
| 141 | using namespace llvm::PatternMatch; |
| 142 | |
| 143 | static const unsigned UninitializedAddressSpace = |
| 144 | std::numeric_limits<unsigned>::max(); |
| 145 | |
| 146 | namespace { |
| 147 | |
| 148 | using ValueToAddrSpaceMapTy = DenseMap<const Value *, unsigned>; |
| 149 | // Different from ValueToAddrSpaceMapTy, where a new addrspace is inferred on |
| 150 | // the *def* of a value, PredicatedAddrSpaceMapTy is map where a new |
| 151 | // addrspace is inferred on the *use* of a pointer. This map is introduced to |
| 152 | // infer addrspace from the addrspace predicate assumption built from assume |
| 153 | // intrinsic. In that scenario, only specific uses (under valid assumption |
| 154 | // context) could be inferred with a new addrspace. |
| 155 | using PredicatedAddrSpaceMapTy = |
| 156 | DenseMap<std::pair<const Value *, const Value *>, unsigned>; |
| 157 | using PostorderStackTy = llvm::SmallVector<PointerIntPair<Value *, 1, bool>, 4>; |
| 158 | |
| 159 | class InferAddressSpaces : public FunctionPass { |
| 160 | unsigned FlatAddrSpace = 0; |
| 161 | |
| 162 | public: |
| 163 | static char ID; |
| 164 | |
| 165 | InferAddressSpaces() |
| 166 | : FunctionPass(ID), FlatAddrSpace(UninitializedAddressSpace) { |
| 167 | initializeInferAddressSpacesPass(*PassRegistry::getPassRegistry()); |
| 168 | } |
| 169 | InferAddressSpaces(unsigned AS) : FunctionPass(ID), FlatAddrSpace(AS) { |
| 170 | initializeInferAddressSpacesPass(*PassRegistry::getPassRegistry()); |
| 171 | } |
| 172 | |
| 173 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
| 174 | AU.setPreservesCFG(); |
| 175 | AU.addRequired<AssumptionCacheTracker>(); |
| 176 | AU.addRequired<TargetTransformInfoWrapperPass>(); |
| 177 | } |
| 178 | |
| 179 | bool runOnFunction(Function &F) override; |
| 180 | }; |
| 181 | |
| 182 | class InferAddressSpacesImpl { |
| 183 | AssumptionCache &AC; |
| 184 | Function *F = nullptr; |
| 185 | const DominatorTree *DT = nullptr; |
| 186 | const TargetTransformInfo *TTI = nullptr; |
| 187 | const DataLayout *DL = nullptr; |
| 188 | |
| 189 | /// Target specific address space which uses of should be replaced if |
| 190 | /// possible. |
| 191 | unsigned FlatAddrSpace = 0; |
| 192 | |
| 193 | /// The default address space is assumed as the flat address space. This is |
| 194 | /// mainly for test purpose. |
| 195 | const bool AssumeDefaultIsFlatAddressSpace = false; |
| 196 | |
| 197 | DenseMap<const Value *, Value *> PtrIntCastPairs; |
| 198 | |
| 199 | // Tries to find if the inttoptr instruction is derived from an pointer have |
| 200 | // specific address space, and is safe to propagate the address space to the |
| 201 | // new pointer that inttoptr produces. |
| 202 | Value *getIntToPtrPointerOperand(const Operator *I2P) const; |
| 203 | // Tries to find if the inttoptr instruction is derived from an pointer have |
| 204 | // specific address space, and is safe to propagate the address space to the |
| 205 | // new pointer that inttoptr produces. If the old pointer is found, cache the |
| 206 | // <OldPtr, inttoptr> pairs to a map. |
| 207 | void collectIntToPtrPointerOperand(); |
| 208 | // Check if an old pointer is found ahead of time. The safety has been checked |
| 209 | // when collecting the inttoptr original pointer and the result is cached in |
| 210 | // PtrIntCastPairs. |
| 211 | bool isSafeToCastIntToPtrAddrSpace(const Operator *I2P) const { |
| 212 | return PtrIntCastPairs.contains(Val: I2P); |
| 213 | } |
| 214 | bool isAddressExpression(const Value &V, const DataLayout &DL, |
| 215 | const TargetTransformInfo *TTI) const; |
| 216 | Value *cloneConstantExprWithNewAddressSpace( |
| 217 | ConstantExpr *CE, unsigned NewAddrSpace, |
| 218 | const ValueToValueMapTy &ValueWithNewAddrSpace, const DataLayout *DL, |
| 219 | const TargetTransformInfo *TTI) const; |
| 220 | |
| 221 | SmallVector<Value *, 2> |
| 222 | getPointerOperands(const Value &V, const DataLayout &DL, |
| 223 | const TargetTransformInfo *TTI) const; |
| 224 | |
| 225 | // Try to update the address space of V. If V is updated, returns true and |
| 226 | // false otherwise. |
| 227 | bool updateAddressSpace(const Value &V, |
| 228 | ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 229 | PredicatedAddrSpaceMapTy &PredicatedAS) const; |
| 230 | |
| 231 | // Adds the users of V whose address space may still change to Worklist. |
| 232 | void enqueueUsers(Value &V, const ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 233 | SetVector<Value *> &Worklist) const; |
| 234 | |
| 235 | // Propagates address spaces out of Worklist until nothing changes. |
| 236 | void runToFixPoint(SetVector<Value *> &Worklist, |
| 237 | ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 238 | PredicatedAddrSpaceMapTy &PredicatedAS) const; |
| 239 | |
| 240 | // Tries to infer the specific address space of each address expression in |
| 241 | // Postorder. |
| 242 | void inferAddressSpaces(ArrayRef<WeakTrackingVH> Postorder, |
| 243 | ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 244 | PredicatedAddrSpaceMapTy &PredicatedAS) const; |
| 245 | |
| 246 | bool isSafeToCastConstAddrSpace(Constant *C, unsigned NewAS) const; |
| 247 | |
| 248 | Value *clonePtrMaskWithNewAddressSpace( |
| 249 | IntrinsicInst *I, unsigned NewAddrSpace, |
| 250 | const ValueToValueMapTy &ValueWithNewAddrSpace, |
| 251 | const PredicatedAddrSpaceMapTy &PredicatedAS, |
| 252 | SmallVectorImpl<const Use *> *PoisonUsesToFix) const; |
| 253 | |
| 254 | Value *cloneInstructionWithNewAddressSpace( |
| 255 | Instruction *I, unsigned NewAddrSpace, |
| 256 | const ValueToValueMapTy &ValueWithNewAddrSpace, |
| 257 | const PredicatedAddrSpaceMapTy &PredicatedAS, |
| 258 | SmallVectorImpl<const Use *> *PoisonUsesToFix) const; |
| 259 | |
| 260 | void performPointerReplacement( |
| 261 | Value *V, Value *NewV, Use &U, ValueToValueMapTy &ValueWithNewAddrSpace, |
| 262 | SmallVectorImpl<Instruction *> &DeadInstructions) const; |
| 263 | |
| 264 | // Changes the flat address expressions in function F to point to specific |
| 265 | // address spaces if InferredAddrSpace says so. Postorder is the postorder of |
| 266 | // all flat expressions in the use-def graph of function F. |
| 267 | bool rewriteWithNewAddressSpaces( |
| 268 | ArrayRef<WeakTrackingVH> Postorder, |
| 269 | const ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 270 | const PredicatedAddrSpaceMapTy &PredicatedAS) const; |
| 271 | |
| 272 | void appendsFlatAddressExpressionToPostorderStack( |
| 273 | Value *V, PostorderStackTy &PostorderStack, |
| 274 | DenseSet<Value *> &Visited) const; |
| 275 | |
| 276 | bool rewriteIntrinsicOperands(IntrinsicInst *II, Value *OldV, |
| 277 | Value *NewV) const; |
| 278 | void collectRewritableIntrinsicOperands(IntrinsicInst *II, |
| 279 | PostorderStackTy &PostorderStack, |
| 280 | DenseSet<Value *> &Visited) const; |
| 281 | |
| 282 | std::vector<WeakTrackingVH> collectFlatAddressExpressions(Function &F) const; |
| 283 | |
| 284 | Value *cloneValueWithNewAddressSpace( |
| 285 | Value *V, unsigned NewAddrSpace, |
| 286 | const ValueToValueMapTy &ValueWithNewAddrSpace, |
| 287 | const PredicatedAddrSpaceMapTy &PredicatedAS, |
| 288 | SmallVectorImpl<const Use *> *PoisonUsesToFix) const; |
| 289 | unsigned joinAddressSpaces(unsigned AS1, unsigned AS2) const; |
| 290 | |
| 291 | unsigned getPredicatedAddrSpace(const Value &PtrV, |
| 292 | const Value *UserCtx) const; |
| 293 | |
| 294 | public: |
| 295 | InferAddressSpacesImpl(AssumptionCache &AC, const DominatorTree *DT, |
| 296 | const TargetTransformInfo *TTI, unsigned FlatAddrSpace, |
| 297 | bool AssumeDefaultIsFlatAddressSpace) |
| 298 | : AC(AC), DT(DT), TTI(TTI), FlatAddrSpace(FlatAddrSpace), |
| 299 | AssumeDefaultIsFlatAddressSpace(AssumeDefaultIsFlatAddressSpace) {} |
| 300 | bool run(Function &F); |
| 301 | }; |
| 302 | |
| 303 | } // end anonymous namespace |
| 304 | |
| 305 | char InferAddressSpaces::ID = 0; |
| 306 | |
| 307 | INITIALIZE_PASS_BEGIN(InferAddressSpaces, DEBUG_TYPE, "Infer address spaces" , |
| 308 | false, false) |
| 309 | INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) |
| 310 | INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) |
| 311 | INITIALIZE_PASS_END(InferAddressSpaces, DEBUG_TYPE, "Infer address spaces" , |
| 312 | false, false) |
| 313 | |
| 314 | static Type *getPtrOrVecOfPtrsWithNewAS(Type *Ty, unsigned NewAddrSpace) { |
| 315 | assert(Ty->isPtrOrPtrVectorTy()); |
| 316 | PointerType *NPT = PointerType::get(C&: Ty->getContext(), AddressSpace: NewAddrSpace); |
| 317 | return Ty->getWithNewType(EltTy: NPT); |
| 318 | } |
| 319 | |
| 320 | // Check whether that's no-op pointer bitcast using a pair of |
| 321 | // `ptrtoint`/`inttoptr` due to the missing no-op pointer bitcast over |
| 322 | // different address spaces. |
| 323 | static bool isNoopPtrIntCastPair(const Operator *I2P, const DataLayout &DL, |
| 324 | const TargetTransformInfo *TTI) { |
| 325 | assert(I2P->getOpcode() == Instruction::IntToPtr); |
| 326 | auto *P2I = dyn_cast<Operator>(Val: I2P->getOperand(i: 0)); |
| 327 | if (!P2I || P2I->getOpcode() != Instruction::PtrToInt) |
| 328 | return false; |
| 329 | // Check it's really safe to treat that pair of `ptrtoint`/`inttoptr` as a |
| 330 | // no-op cast. Besides checking both of them are no-op casts, as the |
| 331 | // reinterpreted pointer may be used in other pointer arithmetic, we also |
| 332 | // need to double-check that through the target-specific hook. That ensures |
| 333 | // the underlying target also agrees that's a no-op address space cast and |
| 334 | // pointer bits are preserved. |
| 335 | // The current IR spec doesn't have clear rules on address space casts, |
| 336 | // especially a clear definition for pointer bits in non-default address |
| 337 | // spaces. It would be undefined if that pointer is dereferenced after an |
| 338 | // invalid reinterpret cast. Also, due to the unclearness for the meaning of |
| 339 | // bits in non-default address spaces in the current spec, the pointer |
| 340 | // arithmetic may also be undefined after invalid pointer reinterpret cast. |
| 341 | // However, as we confirm through the target hooks that it's a no-op |
| 342 | // addrspacecast, it doesn't matter since the bits should be the same. |
| 343 | unsigned P2IOp0AS = P2I->getOperand(i: 0)->getType()->getPointerAddressSpace(); |
| 344 | unsigned I2PAS = I2P->getType()->getPointerAddressSpace(); |
| 345 | return CastInst::isNoopCast(Opcode: Instruction::CastOps(I2P->getOpcode()), |
| 346 | SrcTy: I2P->getOperand(i: 0)->getType(), DstTy: I2P->getType(), |
| 347 | DL) && |
| 348 | CastInst::isNoopCast(Opcode: Instruction::CastOps(P2I->getOpcode()), |
| 349 | SrcTy: P2I->getOperand(i: 0)->getType(), DstTy: P2I->getType(), |
| 350 | DL) && |
| 351 | (P2IOp0AS == I2PAS || TTI->isNoopAddrSpaceCast(FromAS: P2IOp0AS, ToAS: I2PAS)); |
| 352 | } |
| 353 | |
| 354 | // Returns true if V is an address expression. |
| 355 | // TODO: Currently, we only consider: |
| 356 | // - arguments |
| 357 | // - phi, bitcast, addrspacecast, and getelementptr operators |
| 358 | bool InferAddressSpacesImpl::isAddressExpression( |
| 359 | const Value &V, const DataLayout &DL, |
| 360 | const TargetTransformInfo *TTI) const { |
| 361 | |
| 362 | if (const Argument *Arg = dyn_cast<Argument>(Val: &V)) |
| 363 | return Arg->getType()->isPointerTy() && |
| 364 | TTI->getAssumedAddrSpace(V: &V) != UninitializedAddressSpace; |
| 365 | |
| 366 | const Operator *Op = dyn_cast<Operator>(Val: &V); |
| 367 | if (!Op) |
| 368 | return false; |
| 369 | |
| 370 | switch (Op->getOpcode()) { |
| 371 | case Instruction::PHI: |
| 372 | assert(Op->getType()->isPtrOrPtrVectorTy()); |
| 373 | return true; |
| 374 | case Instruction::BitCast: |
| 375 | case Instruction::AddrSpaceCast: |
| 376 | case Instruction::GetElementPtr: |
| 377 | return true; |
| 378 | case Instruction::Select: |
| 379 | return Op->getType()->isPtrOrPtrVectorTy(); |
| 380 | case Instruction::Call: { |
| 381 | const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Val: &V); |
| 382 | return II && II->getIntrinsicID() == Intrinsic::ptrmask; |
| 383 | } |
| 384 | case Instruction::IntToPtr: |
| 385 | return isNoopPtrIntCastPair(I2P: Op, DL, TTI) || |
| 386 | isSafeToCastIntToPtrAddrSpace(I2P: Op); |
| 387 | default: |
| 388 | // That value is an address expression if it has an assumed address space. |
| 389 | return TTI->getAssumedAddrSpace(V: &V) != UninitializedAddressSpace; |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | // Returns the pointer operands of V. |
| 394 | // |
| 395 | // Precondition: V is an address expression. |
| 396 | SmallVector<Value *, 2> InferAddressSpacesImpl::getPointerOperands( |
| 397 | const Value &V, const DataLayout &DL, |
| 398 | const TargetTransformInfo *TTI) const { |
| 399 | if (isa<Argument>(Val: &V)) |
| 400 | return {}; |
| 401 | |
| 402 | const Operator &Op = cast<Operator>(Val: V); |
| 403 | switch (Op.getOpcode()) { |
| 404 | case Instruction::PHI: { |
| 405 | auto IncomingValues = cast<PHINode>(Val: Op).incoming_values(); |
| 406 | return {IncomingValues.begin(), IncomingValues.end()}; |
| 407 | } |
| 408 | case Instruction::BitCast: |
| 409 | case Instruction::AddrSpaceCast: |
| 410 | case Instruction::GetElementPtr: |
| 411 | return {Op.getOperand(i: 0)}; |
| 412 | case Instruction::Select: |
| 413 | return {Op.getOperand(i: 1), Op.getOperand(i: 2)}; |
| 414 | case Instruction::Call: { |
| 415 | const IntrinsicInst &II = cast<IntrinsicInst>(Val: Op); |
| 416 | assert(II.getIntrinsicID() == Intrinsic::ptrmask && |
| 417 | "unexpected intrinsic call" ); |
| 418 | return {II.getArgOperand(i: 0)}; |
| 419 | } |
| 420 | case Instruction::IntToPtr: { |
| 421 | if (isNoopPtrIntCastPair(I2P: &Op, DL, TTI)) { |
| 422 | auto *P2I = cast<Operator>(Val: Op.getOperand(i: 0)); |
| 423 | return {P2I->getOperand(i: 0)}; |
| 424 | } |
| 425 | assert(isSafeToCastIntToPtrAddrSpace(&Op)); |
| 426 | return {getIntToPtrPointerOperand(I2P: &Op)}; |
| 427 | } |
| 428 | default: |
| 429 | llvm_unreachable("Unexpected instruction type." ); |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | // Return mask. The 1 in mask indicate the bit is changed. |
| 434 | // This helper function is to compute the max know changed bits for ptr1 and |
| 435 | // ptr2 after the operation `ptr2 = ptr1 Op Mask`. |
| 436 | static APInt computeMaxChangedPtrBits(const Operator *Op, const Value *Mask, |
| 437 | const DataLayout &DL, AssumptionCache *AC, |
| 438 | const DominatorTree *DT) { |
| 439 | KnownBits Known = computeKnownBits(V: Mask, DL, AC, CtxI: nullptr, DT); |
| 440 | switch (Op->getOpcode()) { |
| 441 | case Instruction::Xor: |
| 442 | case Instruction::Or: |
| 443 | return ~Known.Zero; |
| 444 | case Instruction::And: |
| 445 | return ~Known.One; |
| 446 | default: |
| 447 | return APInt::getAllOnes(numBits: Known.getBitWidth()); |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | Value * |
| 452 | InferAddressSpacesImpl::getIntToPtrPointerOperand(const Operator *I2P) const { |
| 453 | assert(I2P->getOpcode() == Instruction::IntToPtr); |
| 454 | if (I2P->getType()->isVectorTy()) |
| 455 | return nullptr; |
| 456 | |
| 457 | // If I2P has been accessed and has the corresponding old pointer value, just |
| 458 | // return true. |
| 459 | if (auto *OldPtr = PtrIntCastPairs.lookup(Val: I2P)) |
| 460 | return OldPtr; |
| 461 | |
| 462 | Value *LogicalOp = I2P->getOperand(i: 0); |
| 463 | Value *OldPtr, *Mask; |
| 464 | if (!match(V: LogicalOp, |
| 465 | P: m_c_BitwiseLogic(L: m_PtrToInt(Op: m_Value(V&: OldPtr)), R: m_Value(V&: Mask)))) |
| 466 | return nullptr; |
| 467 | |
| 468 | Operator *AsCast = dyn_cast<AddrSpaceCastOperator>(Val: OldPtr); |
| 469 | if (!AsCast) |
| 470 | return nullptr; |
| 471 | |
| 472 | unsigned SrcAS = I2P->getType()->getPointerAddressSpace(); |
| 473 | unsigned DstAS = AsCast->getOperand(i: 0)->getType()->getPointerAddressSpace(); |
| 474 | APInt PreservedPtrMask = TTI->getAddrSpaceCastPreservedPtrMask(SrcAS, DstAS); |
| 475 | if (PreservedPtrMask.isZero()) |
| 476 | return nullptr; |
| 477 | APInt ChangedPtrBits = |
| 478 | computeMaxChangedPtrBits(Op: cast<Operator>(Val: LogicalOp), Mask, DL: *DL, AC: &AC, DT); |
| 479 | // Check if the address bits change is within the preserved mask. If the bits |
| 480 | // change is not preserved, it is not safe to perform address space cast. |
| 481 | // The following pattern is not safe to cast address space. |
| 482 | // %1 = ptrtoint ptr addrspace(3) %sp to i32 |
| 483 | // %2 = zext i32 %1 to i64 |
| 484 | // %gp = inttoptr i64 %2 to ptr |
| 485 | assert(ChangedPtrBits.getBitWidth() == PreservedPtrMask.getBitWidth()); |
| 486 | if (ChangedPtrBits.isSubsetOf(RHS: PreservedPtrMask)) |
| 487 | return OldPtr; |
| 488 | |
| 489 | return nullptr; |
| 490 | } |
| 491 | |
| 492 | void InferAddressSpacesImpl::collectIntToPtrPointerOperand() { |
| 493 | // Only collect inttoptr instruction. |
| 494 | // TODO: We need to collect inttoptr constant expression as well. |
| 495 | for (Instruction &I : instructions(F)) { |
| 496 | if (!dyn_cast<IntToPtrInst>(Val: &I)) |
| 497 | continue; |
| 498 | if (auto *OldPtr = getIntToPtrPointerOperand(I2P: cast<Operator>(Val: &I))) |
| 499 | PtrIntCastPairs.insert(KV: {&I, OldPtr}); |
| 500 | } |
| 501 | } |
| 502 | |
| 503 | bool InferAddressSpacesImpl::rewriteIntrinsicOperands(IntrinsicInst *II, |
| 504 | Value *OldV, |
| 505 | Value *NewV) const { |
| 506 | Module *M = II->getParent()->getParent()->getParent(); |
| 507 | Intrinsic::ID IID = II->getIntrinsicID(); |
| 508 | switch (IID) { |
| 509 | case Intrinsic::objectsize: |
| 510 | case Intrinsic::masked_load: { |
| 511 | Type *DestTy = II->getType(); |
| 512 | Type *SrcTy = NewV->getType(); |
| 513 | Function *NewDecl = |
| 514 | Intrinsic::getOrInsertDeclaration(M, id: IID, OverloadTys: {DestTy, SrcTy}); |
| 515 | II->setArgOperand(i: 0, v: NewV); |
| 516 | II->setCalledFunction(NewDecl); |
| 517 | return true; |
| 518 | } |
| 519 | case Intrinsic::ptrmask: |
| 520 | // This is handled as an address expression, not as a use memory operation. |
| 521 | return false; |
| 522 | case Intrinsic::masked_gather: { |
| 523 | Type *RetTy = II->getType(); |
| 524 | Type *NewPtrTy = NewV->getType(); |
| 525 | Function *NewDecl = |
| 526 | Intrinsic::getOrInsertDeclaration(M, id: IID, OverloadTys: {RetTy, NewPtrTy}); |
| 527 | II->setArgOperand(i: 0, v: NewV); |
| 528 | II->setCalledFunction(NewDecl); |
| 529 | return true; |
| 530 | } |
| 531 | case Intrinsic::masked_store: |
| 532 | case Intrinsic::masked_scatter: { |
| 533 | Type *ValueTy = II->getOperand(i_nocapture: 0)->getType(); |
| 534 | Type *NewPtrTy = NewV->getType(); |
| 535 | Function *NewDecl = Intrinsic::getOrInsertDeclaration( |
| 536 | M, id: II->getIntrinsicID(), OverloadTys: {ValueTy, NewPtrTy}); |
| 537 | II->setArgOperand(i: 1, v: NewV); |
| 538 | II->setCalledFunction(NewDecl); |
| 539 | return true; |
| 540 | } |
| 541 | case Intrinsic::prefetch: |
| 542 | case Intrinsic::is_constant: { |
| 543 | Function *NewDecl = Intrinsic::getOrInsertDeclaration( |
| 544 | M, id: II->getIntrinsicID(), OverloadTys: {NewV->getType()}); |
| 545 | II->setArgOperand(i: 0, v: NewV); |
| 546 | II->setCalledFunction(NewDecl); |
| 547 | return true; |
| 548 | } |
| 549 | case Intrinsic::fake_use: { |
| 550 | II->replaceUsesOfWith(From: OldV, To: NewV); |
| 551 | return true; |
| 552 | } |
| 553 | case Intrinsic::lifetime_start: |
| 554 | case Intrinsic::lifetime_end: { |
| 555 | // Always force lifetime markers to work directly on the alloca. |
| 556 | NewV = NewV->stripPointerCasts(); |
| 557 | Function *NewDecl = Intrinsic::getOrInsertDeclaration( |
| 558 | M, id: II->getIntrinsicID(), OverloadTys: {NewV->getType()}); |
| 559 | II->setArgOperand(i: 0, v: NewV); |
| 560 | II->setCalledFunction(NewDecl); |
| 561 | return true; |
| 562 | } |
| 563 | default: { |
| 564 | Value *Rewrite = TTI->rewriteIntrinsicWithAddressSpace(II, OldV, NewV); |
| 565 | if (!Rewrite) |
| 566 | return false; |
| 567 | if (Rewrite != II) { |
| 568 | II->replaceAllUsesWith(V: Rewrite); |
| 569 | II->eraseFromParent(); |
| 570 | } |
| 571 | return true; |
| 572 | } |
| 573 | } |
| 574 | } |
| 575 | |
| 576 | void InferAddressSpacesImpl::collectRewritableIntrinsicOperands( |
| 577 | IntrinsicInst *II, PostorderStackTy &PostorderStack, |
| 578 | DenseSet<Value *> &Visited) const { |
| 579 | auto IID = II->getIntrinsicID(); |
| 580 | switch (IID) { |
| 581 | case Intrinsic::ptrmask: |
| 582 | case Intrinsic::objectsize: |
| 583 | appendsFlatAddressExpressionToPostorderStack(V: II->getArgOperand(i: 0), |
| 584 | PostorderStack, Visited); |
| 585 | break; |
| 586 | case Intrinsic::is_constant: { |
| 587 | Value *Ptr = II->getArgOperand(i: 0); |
| 588 | if (Ptr->getType()->isPtrOrPtrVectorTy()) { |
| 589 | appendsFlatAddressExpressionToPostorderStack(V: Ptr, PostorderStack, |
| 590 | Visited); |
| 591 | } |
| 592 | |
| 593 | break; |
| 594 | } |
| 595 | case Intrinsic::masked_load: |
| 596 | case Intrinsic::masked_gather: |
| 597 | case Intrinsic::prefetch: |
| 598 | appendsFlatAddressExpressionToPostorderStack(V: II->getArgOperand(i: 0), |
| 599 | PostorderStack, Visited); |
| 600 | break; |
| 601 | case Intrinsic::masked_store: |
| 602 | case Intrinsic::masked_scatter: |
| 603 | appendsFlatAddressExpressionToPostorderStack(V: II->getArgOperand(i: 1), |
| 604 | PostorderStack, Visited); |
| 605 | break; |
| 606 | case Intrinsic::fake_use: { |
| 607 | for (Value *Op : II->operands()) { |
| 608 | if (Op->getType()->isPtrOrPtrVectorTy()) { |
| 609 | appendsFlatAddressExpressionToPostorderStack(V: Op, PostorderStack, |
| 610 | Visited); |
| 611 | } |
| 612 | } |
| 613 | |
| 614 | break; |
| 615 | } |
| 616 | case Intrinsic::lifetime_start: |
| 617 | case Intrinsic::lifetime_end: { |
| 618 | appendsFlatAddressExpressionToPostorderStack(V: II->getArgOperand(i: 0), |
| 619 | PostorderStack, Visited); |
| 620 | break; |
| 621 | } |
| 622 | default: |
| 623 | SmallVector<int, 2> OpIndexes; |
| 624 | if (TTI->collectFlatAddressOperands(OpIndexes, IID)) { |
| 625 | for (int Idx : OpIndexes) { |
| 626 | appendsFlatAddressExpressionToPostorderStack(V: II->getArgOperand(i: Idx), |
| 627 | PostorderStack, Visited); |
| 628 | } |
| 629 | } |
| 630 | break; |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | // Returns all flat address expressions in function F. The elements are |
| 635 | // If V is an unvisited flat address expression, appends V to PostorderStack |
| 636 | // and marks it as visited. |
| 637 | void InferAddressSpacesImpl::appendsFlatAddressExpressionToPostorderStack( |
| 638 | Value *V, PostorderStackTy &PostorderStack, |
| 639 | DenseSet<Value *> &Visited) const { |
| 640 | assert(V->getType()->isPtrOrPtrVectorTy()); |
| 641 | |
| 642 | // Generic addressing expressions may be hidden in nested constant |
| 643 | // expressions. |
| 644 | if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Val: V)) { |
| 645 | // TODO: Look in non-address parts, like icmp operands. |
| 646 | if (isAddressExpression(V: *CE, DL: *DL, TTI) && Visited.insert(V: CE).second) |
| 647 | PostorderStack.emplace_back(Args&: CE, Args: false); |
| 648 | |
| 649 | return; |
| 650 | } |
| 651 | |
| 652 | if (V->getType()->getPointerAddressSpace() == FlatAddrSpace && |
| 653 | isAddressExpression(V: *V, DL: *DL, TTI)) { |
| 654 | if (Visited.insert(V).second) { |
| 655 | PostorderStack.emplace_back(Args&: V, Args: false); |
| 656 | |
| 657 | if (auto *Op = dyn_cast<Operator>(Val: V)) |
| 658 | for (auto &O : Op->operands()) |
| 659 | if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Val&: O)) |
| 660 | if (isAddressExpression(V: *CE, DL: *DL, TTI) && Visited.insert(V: CE).second) |
| 661 | PostorderStack.emplace_back(Args&: CE, Args: false); |
| 662 | } |
| 663 | } |
| 664 | } |
| 665 | |
| 666 | // Returns all flat address expressions in function F. The elements are ordered |
| 667 | // in postorder. |
| 668 | std::vector<WeakTrackingVH> |
| 669 | InferAddressSpacesImpl::collectFlatAddressExpressions(Function &F) const { |
| 670 | // This function implements a non-recursive postorder traversal of a partial |
| 671 | // use-def graph of function F. |
| 672 | PostorderStackTy PostorderStack; |
| 673 | // The set of visited expressions. |
| 674 | DenseSet<Value *> Visited; |
| 675 | |
| 676 | auto PushPtrOperand = [&](Value *Ptr) { |
| 677 | appendsFlatAddressExpressionToPostorderStack(V: Ptr, PostorderStack, Visited); |
| 678 | }; |
| 679 | |
| 680 | // Look at operations that may be interesting accelerate by moving to a known |
| 681 | // address space. We aim at generating after loads and stores, but pure |
| 682 | // addressing calculations may also be faster. |
| 683 | for (Instruction &I : instructions(F)) { |
| 684 | if (auto *GEP = dyn_cast<GetElementPtrInst>(Val: &I)) { |
| 685 | PushPtrOperand(GEP->getPointerOperand()); |
| 686 | } else if (auto *LI = dyn_cast<LoadInst>(Val: &I)) |
| 687 | PushPtrOperand(LI->getPointerOperand()); |
| 688 | else if (auto *SI = dyn_cast<StoreInst>(Val: &I)) |
| 689 | PushPtrOperand(SI->getPointerOperand()); |
| 690 | else if (auto *RMW = dyn_cast<AtomicRMWInst>(Val: &I)) |
| 691 | PushPtrOperand(RMW->getPointerOperand()); |
| 692 | else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Val: &I)) |
| 693 | PushPtrOperand(CmpX->getPointerOperand()); |
| 694 | else if (auto *MI = dyn_cast<MemIntrinsic>(Val: &I)) { |
| 695 | // For memset/memcpy/memmove, any pointer operand can be replaced. |
| 696 | PushPtrOperand(MI->getRawDest()); |
| 697 | |
| 698 | // Handle 2nd operand for memcpy/memmove. |
| 699 | if (auto *MTI = dyn_cast<MemTransferInst>(Val: MI)) |
| 700 | PushPtrOperand(MTI->getRawSource()); |
| 701 | } else if (auto *II = dyn_cast<IntrinsicInst>(Val: &I)) |
| 702 | collectRewritableIntrinsicOperands(II, PostorderStack, Visited); |
| 703 | else if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Val: &I)) { |
| 704 | if (Cmp->getOperand(i_nocapture: 0)->getType()->isPtrOrPtrVectorTy()) { |
| 705 | PushPtrOperand(Cmp->getOperand(i_nocapture: 0)); |
| 706 | PushPtrOperand(Cmp->getOperand(i_nocapture: 1)); |
| 707 | } |
| 708 | } else if (auto *ASC = dyn_cast<AddrSpaceCastInst>(Val: &I)) { |
| 709 | PushPtrOperand(ASC->getPointerOperand()); |
| 710 | } else if (auto *I2P = dyn_cast<IntToPtrInst>(Val: &I)) { |
| 711 | if (isNoopPtrIntCastPair(I2P: cast<Operator>(Val: I2P), DL: *DL, TTI)) |
| 712 | PushPtrOperand(cast<Operator>(Val: I2P->getOperand(i_nocapture: 0))->getOperand(i: 0)); |
| 713 | else if (isSafeToCastIntToPtrAddrSpace(I2P: cast<Operator>(Val: I2P))) |
| 714 | PushPtrOperand(getIntToPtrPointerOperand(I2P: cast<Operator>(Val: I2P))); |
| 715 | } else if (auto *RI = dyn_cast<ReturnInst>(Val: &I)) { |
| 716 | if (auto *RV = RI->getReturnValue(); |
| 717 | RV && RV->getType()->isPtrOrPtrVectorTy()) |
| 718 | PushPtrOperand(RV); |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | std::vector<WeakTrackingVH> Postorder; // The resultant postorder. |
| 723 | while (!PostorderStack.empty()) { |
| 724 | Value *TopVal = PostorderStack.back().getPointer(); |
| 725 | // If the operands of the expression on the top are already explored, |
| 726 | // adds that expression to the resultant postorder. |
| 727 | if (PostorderStack.back().getInt()) { |
| 728 | if (TopVal->getType()->getPointerAddressSpace() == FlatAddrSpace) |
| 729 | Postorder.push_back(x: TopVal); |
| 730 | PostorderStack.pop_back(); |
| 731 | continue; |
| 732 | } |
| 733 | // Otherwise, adds its operands to the stack and explores them. |
| 734 | PostorderStack.back().setInt(true); |
| 735 | // Skip values with an assumed address space. |
| 736 | if (TTI->getAssumedAddrSpace(V: TopVal) == UninitializedAddressSpace) { |
| 737 | for (Value *PtrOperand : getPointerOperands(V: *TopVal, DL: *DL, TTI)) { |
| 738 | appendsFlatAddressExpressionToPostorderStack(V: PtrOperand, PostorderStack, |
| 739 | Visited); |
| 740 | } |
| 741 | } |
| 742 | } |
| 743 | return Postorder; |
| 744 | } |
| 745 | |
| 746 | // Inserts an addrspacecast for a phi node operand, handling the proper |
| 747 | // insertion position based on the operand type. |
| 748 | static Value *phiNodeOperandWithNewAddressSpace(AddrSpaceCastInst *NewI, |
| 749 | Value *Operand) { |
| 750 | auto InsertBefore = [NewI](auto It) { |
| 751 | NewI->insertBefore(It); |
| 752 | NewI->setDebugLoc(It->getDebugLoc()); |
| 753 | return NewI; |
| 754 | }; |
| 755 | |
| 756 | if (auto *Arg = dyn_cast<Argument>(Val: Operand)) { |
| 757 | // For arguments, insert the cast at the beginning of entry block. |
| 758 | // Consider inserting at the dominating block for better placement. |
| 759 | Function *F = Arg->getParent(); |
| 760 | auto InsertI = F->getEntryBlock().getFirstNonPHIIt(); |
| 761 | return InsertBefore(InsertI); |
| 762 | } |
| 763 | |
| 764 | // No check for Constant here, as constants are already handled. |
| 765 | assert(isa<Instruction>(Operand)); |
| 766 | |
| 767 | Instruction *OpInst = cast<Instruction>(Val: Operand); |
| 768 | if (LLVM_UNLIKELY(OpInst->getOpcode() == Instruction::PHI)) { |
| 769 | // If the operand is defined by another PHI node, insert after the first |
| 770 | // non-PHI instruction at the corresponding basic block. |
| 771 | auto InsertI = OpInst->getParent()->getFirstNonPHIIt(); |
| 772 | return InsertBefore(InsertI); |
| 773 | } |
| 774 | |
| 775 | // Otherwise, insert immediately after the operand definition. |
| 776 | NewI->insertAfter(InsertPos: OpInst->getIterator()); |
| 777 | NewI->setDebugLoc(OpInst->getDebugLoc()); |
| 778 | return NewI; |
| 779 | } |
| 780 | |
| 781 | // A helper function for cloneInstructionWithNewAddressSpace. Returns the clone |
| 782 | // of OperandUse.get() in the new address space. If the clone is not ready yet, |
| 783 | // returns poison in the new address space as a placeholder. |
| 784 | static Value *operandWithNewAddressSpaceOrCreatePoison( |
| 785 | const Use &OperandUse, unsigned NewAddrSpace, |
| 786 | const ValueToValueMapTy &ValueWithNewAddrSpace, |
| 787 | const PredicatedAddrSpaceMapTy &PredicatedAS, |
| 788 | SmallVectorImpl<const Use *> *PoisonUsesToFix) { |
| 789 | Value *Operand = OperandUse.get(); |
| 790 | |
| 791 | Type *NewPtrTy = getPtrOrVecOfPtrsWithNewAS(Ty: Operand->getType(), NewAddrSpace); |
| 792 | |
| 793 | if (Constant *C = dyn_cast<Constant>(Val: Operand)) |
| 794 | return ConstantExpr::getAddrSpaceCast(C, Ty: NewPtrTy); |
| 795 | |
| 796 | Instruction *Inst = cast<Instruction>(Val: OperandUse.getUser()); |
| 797 | if (Value *NewOperand = ValueWithNewAddrSpace.lookup(Val: Operand)) { |
| 798 | Operand = NewOperand; |
| 799 | } else if (!PredicatedAS.contains(Val: std::make_pair(x&: Inst, y&: Operand))) { |
| 800 | assert(PoisonUsesToFix && "missing inferred operand replacement" ); |
| 801 | PoisonUsesToFix->push_back(Elt: &OperandUse); |
| 802 | return PoisonValue::get(T: NewPtrTy); |
| 803 | } |
| 804 | |
| 805 | if (Operand->getType() == NewPtrTy) |
| 806 | return Operand; |
| 807 | |
| 808 | auto *NewI = new AddrSpaceCastInst(Operand, NewPtrTy); |
| 809 | if (LLVM_UNLIKELY(Inst->getOpcode() == Instruction::PHI)) |
| 810 | return phiNodeOperandWithNewAddressSpace(NewI, Operand: OperandUse.get()); |
| 811 | |
| 812 | // During cloning phase, the cast is placed before the original flat |
| 813 | // instruction, as its clone in the new address space has not been inserted |
| 814 | // yet. During poison fixup phase, the clone already exists, thus make sure |
| 815 | // the cast is inserted before it. |
| 816 | Instruction *InsertPt = Inst; |
| 817 | if (Value *NewUser = ValueWithNewAddrSpace.lookup(Val: Inst)) |
| 818 | InsertPt = cast<Instruction>(Val: NewUser); |
| 819 | NewI->insertBefore(InsertPos: InsertPt->getIterator()); |
| 820 | NewI->setDebugLoc(Inst->getDebugLoc()); |
| 821 | return NewI; |
| 822 | } |
| 823 | |
| 824 | // A helper function for cloneInstructionWithNewAddressSpace. Handles the |
| 825 | // conversion of a ptrmask intrinsic instruction. |
| 826 | Value *InferAddressSpacesImpl::clonePtrMaskWithNewAddressSpace( |
| 827 | IntrinsicInst *I, unsigned NewAddrSpace, |
| 828 | const ValueToValueMapTy &ValueWithNewAddrSpace, |
| 829 | const PredicatedAddrSpaceMapTy &PredicatedAS, |
| 830 | SmallVectorImpl<const Use *> *PoisonUsesToFix) const { |
| 831 | const Use &PtrOpUse = I->getArgOperandUse(i: 0); |
| 832 | unsigned OldAddrSpace = PtrOpUse->getType()->getPointerAddressSpace(); |
| 833 | Value *MaskOp = I->getArgOperand(i: 1); |
| 834 | Type *MaskTy = MaskOp->getType(); |
| 835 | |
| 836 | KnownBits OldPtrBits{DL->getPointerSizeInBits(AS: OldAddrSpace)}; |
| 837 | KnownBits NewPtrBits{DL->getPointerSizeInBits(AS: NewAddrSpace)}; |
| 838 | if (!TTI->isNoopAddrSpaceCast(FromAS: OldAddrSpace, ToAS: NewAddrSpace)) { |
| 839 | std::tie(args&: OldPtrBits, args&: NewPtrBits) = |
| 840 | TTI->computeKnownBitsAddrSpaceCast(ToAS: NewAddrSpace, PtrOp: *PtrOpUse.get()); |
| 841 | } |
| 842 | |
| 843 | // If the pointers in both addrspaces have a bitwise representation and if the |
| 844 | // representation of the new pointer is smaller (fewer bits) than the old one, |
| 845 | // check if the mask is applicable to the ptr in the new addrspace. Any |
| 846 | // masking only clearing the low bits will also apply in the new addrspace |
| 847 | // Note: checking if the mask clears high bits is not sufficient as those |
| 848 | // might have already been 0 in the old ptr. |
| 849 | if (OldPtrBits.getBitWidth() > NewPtrBits.getBitWidth()) { |
| 850 | KnownBits MaskBits = |
| 851 | computeKnownBits(V: MaskOp, DL: *DL, /*AssumptionCache=*/AC: nullptr, CtxI: I); |
| 852 | // Set all unknown bits of the old ptr to 1, so that we are conservative in |
| 853 | // checking which bits are cleared by the mask. |
| 854 | OldPtrBits.One |= ~OldPtrBits.Zero; |
| 855 | // Check which bits are cleared by the mask in the old ptr. |
| 856 | KnownBits ClearedBits = KnownBits::sub(LHS: OldPtrBits, RHS: OldPtrBits & MaskBits); |
| 857 | |
| 858 | // If the mask isn't applicable to the new ptr, leave the ptrmask as-is and |
| 859 | // insert an addrspacecast after it. |
| 860 | if (ClearedBits.countMaxActiveBits() > NewPtrBits.countMaxActiveBits()) { |
| 861 | std::optional<BasicBlock::iterator> InsertPoint = |
| 862 | I->getInsertionPointAfterDef(); |
| 863 | assert(InsertPoint && "insertion after ptrmask should be possible" ); |
| 864 | Type *NewPtrType = getPtrOrVecOfPtrsWithNewAS(Ty: I->getType(), NewAddrSpace); |
| 865 | Instruction *AddrSpaceCast = |
| 866 | new AddrSpaceCastInst(I, NewPtrType, "" , *InsertPoint); |
| 867 | AddrSpaceCast->setDebugLoc(I->getDebugLoc()); |
| 868 | return AddrSpaceCast; |
| 869 | } |
| 870 | } |
| 871 | |
| 872 | IRBuilder<> B(I); |
| 873 | if (NewPtrBits.getBitWidth() < MaskTy->getScalarSizeInBits()) { |
| 874 | MaskTy = MaskTy->getWithNewBitWidth(NewBitWidth: NewPtrBits.getBitWidth()); |
| 875 | MaskOp = B.CreateTrunc(V: MaskOp, DestTy: MaskTy); |
| 876 | } |
| 877 | Value *NewPtr = operandWithNewAddressSpaceOrCreatePoison( |
| 878 | OperandUse: PtrOpUse, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, |
| 879 | PoisonUsesToFix); |
| 880 | return B.CreateIntrinsic(ID: Intrinsic::ptrmask, OverloadTypes: {NewPtr->getType(), MaskTy}, |
| 881 | Args: {NewPtr, MaskOp}); |
| 882 | } |
| 883 | |
| 884 | // Returns a clone of `I` with its operands converted to those specified in |
| 885 | // ValueWithNewAddrSpace. Due to potential cycles in the data flow graph, an |
| 886 | // operand whose address space needs to be modified might not exist in |
| 887 | // ValueWithNewAddrSpace. In that case, uses poison as a placeholder operand and |
| 888 | // adds that operand use to PoisonUsesToFix so that caller can fix them later. |
| 889 | // |
| 890 | // Note that we do not necessarily clone `I`, e.g., if it is an addrspacecast |
| 891 | // from a pointer whose type already matches. Therefore, this function returns a |
| 892 | // Value* instead of an Instruction*. |
| 893 | Value *InferAddressSpacesImpl::cloneInstructionWithNewAddressSpace( |
| 894 | Instruction *I, unsigned NewAddrSpace, |
| 895 | const ValueToValueMapTy &ValueWithNewAddrSpace, |
| 896 | const PredicatedAddrSpaceMapTy &PredicatedAS, |
| 897 | SmallVectorImpl<const Use *> *PoisonUsesToFix) const { |
| 898 | Type *NewPtrType = getPtrOrVecOfPtrsWithNewAS(Ty: I->getType(), NewAddrSpace); |
| 899 | |
| 900 | if (I->getOpcode() == Instruction::AddrSpaceCast) { |
| 901 | Value *Src = I->getOperand(i: 0); |
| 902 | // Because `I` is flat, the source address space must be specific. |
| 903 | // Therefore, the inferred address space must be the source space, according |
| 904 | // to our algorithm. |
| 905 | assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace); |
| 906 | return Src; |
| 907 | } |
| 908 | |
| 909 | if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Val: I)) { |
| 910 | // Technically the intrinsic ID is a pointer typed argument, so specially |
| 911 | // handle calls early. |
| 912 | assert(II->getIntrinsicID() == Intrinsic::ptrmask); |
| 913 | return clonePtrMaskWithNewAddressSpace( |
| 914 | I: II, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix); |
| 915 | } |
| 916 | |
| 917 | unsigned AS = TTI->getAssumedAddrSpace(V: I); |
| 918 | if (AS != UninitializedAddressSpace) { |
| 919 | // For the assumed address space, insert an `addrspacecast` to make that |
| 920 | // explicit. |
| 921 | Type *NewPtrTy = getPtrOrVecOfPtrsWithNewAS(Ty: I->getType(), NewAddrSpace: AS); |
| 922 | auto *NewI = new AddrSpaceCastInst(I, NewPtrTy); |
| 923 | NewI->insertAfter(InsertPos: I->getIterator()); |
| 924 | NewI->setDebugLoc(I->getDebugLoc()); |
| 925 | return NewI; |
| 926 | } |
| 927 | |
| 928 | // Computes the converted pointer operands. |
| 929 | SmallVector<Value *, 4> NewPointerOperands; |
| 930 | for (const Use &OperandUse : I->operands()) { |
| 931 | if (!OperandUse.get()->getType()->isPtrOrPtrVectorTy()) |
| 932 | NewPointerOperands.push_back(Elt: nullptr); |
| 933 | else |
| 934 | NewPointerOperands.push_back(Elt: operandWithNewAddressSpaceOrCreatePoison( |
| 935 | OperandUse, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, |
| 936 | PoisonUsesToFix)); |
| 937 | } |
| 938 | |
| 939 | switch (I->getOpcode()) { |
| 940 | case Instruction::BitCast: |
| 941 | return new BitCastInst(NewPointerOperands[0], NewPtrType); |
| 942 | case Instruction::PHI: { |
| 943 | assert(I->getType()->isPtrOrPtrVectorTy()); |
| 944 | PHINode *PHI = cast<PHINode>(Val: I); |
| 945 | PHINode *NewPHI = PHINode::Create(Ty: NewPtrType, NumReservedValues: PHI->getNumIncomingValues()); |
| 946 | for (unsigned Index = 0; Index < PHI->getNumIncomingValues(); ++Index) { |
| 947 | unsigned OperandNo = PHINode::getOperandNumForIncomingValue(i: Index); |
| 948 | NewPHI->addIncoming(V: NewPointerOperands[OperandNo], |
| 949 | BB: PHI->getIncomingBlock(i: Index)); |
| 950 | } |
| 951 | return NewPHI; |
| 952 | } |
| 953 | case Instruction::GetElementPtr: { |
| 954 | GetElementPtrInst *GEP = cast<GetElementPtrInst>(Val: I); |
| 955 | GetElementPtrInst *NewGEP = GetElementPtrInst::Create( |
| 956 | PointeeType: GEP->getSourceElementType(), Ptr: NewPointerOperands[0], |
| 957 | IdxList: SmallVector<Value *, 4>(GEP->indices())); |
| 958 | NewGEP->setIsInBounds(GEP->isInBounds()); |
| 959 | return NewGEP; |
| 960 | } |
| 961 | case Instruction::Select: |
| 962 | assert(I->getType()->isPtrOrPtrVectorTy()); |
| 963 | return SelectInst::Create(C: I->getOperand(i: 0), S1: NewPointerOperands[1], |
| 964 | S2: NewPointerOperands[2], NameStr: "" , InsertBefore: nullptr, MDFrom: I); |
| 965 | case Instruction::IntToPtr: { |
| 966 | if (isNoopPtrIntCastPair(I2P: cast<Operator>(Val: I), DL: *DL, TTI)) { |
| 967 | Value *Src = cast<Operator>(Val: I->getOperand(i: 0))->getOperand(i: 0); |
| 968 | if (Src->getType() == NewPtrType) |
| 969 | return Src; |
| 970 | |
| 971 | // If we had a no-op inttoptr/ptrtoint pair, we may still have inferred a |
| 972 | // source address space from a generic pointer source need to insert a |
| 973 | // cast back. |
| 974 | return new AddrSpaceCastInst(Src, NewPtrType); |
| 975 | } |
| 976 | assert(isSafeToCastIntToPtrAddrSpace(cast<Operator>(I))); |
| 977 | AddrSpaceCastInst *AsCast = new AddrSpaceCastInst(I, NewPtrType); |
| 978 | AsCast->insertAfter(InsertPos: I); |
| 979 | return AsCast; |
| 980 | } |
| 981 | default: |
| 982 | llvm_unreachable("Unexpected opcode" ); |
| 983 | } |
| 984 | } |
| 985 | |
| 986 | // Similar to cloneInstructionWithNewAddressSpace, returns a clone of the |
| 987 | // constant expression `CE` with its operands replaced as specified in |
| 988 | // ValueWithNewAddrSpace. |
| 989 | Value *InferAddressSpacesImpl::cloneConstantExprWithNewAddressSpace( |
| 990 | ConstantExpr *CE, unsigned NewAddrSpace, |
| 991 | const ValueToValueMapTy &ValueWithNewAddrSpace, const DataLayout *DL, |
| 992 | const TargetTransformInfo *TTI) const { |
| 993 | Type *TargetType = |
| 994 | CE->getType()->isPtrOrPtrVectorTy() |
| 995 | ? getPtrOrVecOfPtrsWithNewAS(Ty: CE->getType(), NewAddrSpace) |
| 996 | : CE->getType(); |
| 997 | |
| 998 | switch (CE->getOpcode()) { |
| 999 | case Instruction::AddrSpaceCast: |
| 1000 | // Because CE is flat, the source address space must be specific. |
| 1001 | // Therefore, the inferred address space must be the source space according |
| 1002 | // to our algorithm. |
| 1003 | assert(CE->getOperand(0)->getType()->getPointerAddressSpace() == |
| 1004 | NewAddrSpace); |
| 1005 | return CE->getOperand(i_nocapture: 0); |
| 1006 | |
| 1007 | case Instruction::BitCast: |
| 1008 | if (Value *NewOperand = ValueWithNewAddrSpace.lookup(Val: CE->getOperand(i_nocapture: 0))) |
| 1009 | return ConstantExpr::getBitCast(C: cast<Constant>(Val: NewOperand), Ty: TargetType); |
| 1010 | return ConstantExpr::getAddrSpaceCast(C: CE, Ty: TargetType); |
| 1011 | |
| 1012 | case Instruction::IntToPtr: |
| 1013 | if (isNoopPtrIntCastPair(I2P: cast<Operator>(Val: CE), DL: *DL, TTI)) { |
| 1014 | Constant *Src = cast<ConstantExpr>(Val: CE->getOperand(i_nocapture: 0))->getOperand(i_nocapture: 0); |
| 1015 | assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace); |
| 1016 | return Src; |
| 1017 | } |
| 1018 | assert(isSafeToCastIntToPtrAddrSpace(cast<Operator>(CE))); |
| 1019 | return ConstantExpr::getAddrSpaceCast(C: CE, Ty: TargetType); |
| 1020 | |
| 1021 | case Instruction::GetElementPtr: { |
| 1022 | // Only the pointer operand is rewritten: the indices are not related to |
| 1023 | // the pointer and NewAddrSpace may not be valid for them. The pointer |
| 1024 | // operand is an address expression, but it is not guaranteed to have been |
| 1025 | // cloned already, so clone it here if needed. |
| 1026 | Constant *Base = CE->getOperand(i_nocapture: 0); |
| 1027 | Value *NewBase = ValueWithNewAddrSpace.lookup(Val: Base); |
| 1028 | if (!NewBase) |
| 1029 | NewBase = cloneConstantExprWithNewAddressSpace( |
| 1030 | CE: cast<ConstantExpr>(Val: Base), NewAddrSpace, ValueWithNewAddrSpace, DL, |
| 1031 | TTI); |
| 1032 | assert(NewBase && "pointer operand of a rewritten GEP was not rewritten" ); |
| 1033 | |
| 1034 | SmallVector<Constant *, 4> NewOperands; |
| 1035 | NewOperands.push_back(Elt: cast<Constant>(Val: NewBase)); |
| 1036 | for (unsigned Index = 1; Index < CE->getNumOperands(); ++Index) |
| 1037 | NewOperands.push_back(Elt: CE->getOperand(i_nocapture: Index)); |
| 1038 | // Needs to specify the source type while constructing a getelementptr |
| 1039 | // constant expression. |
| 1040 | return CE->getWithOperands(Ops: NewOperands, Ty: TargetType, /*OnlyIfReduced=*/false, |
| 1041 | SrcTy: cast<GEPOperator>(Val: CE)->getSourceElementType()); |
| 1042 | } |
| 1043 | |
| 1044 | default: |
| 1045 | llvm_unreachable("unexpected constant expression" ); |
| 1046 | } |
| 1047 | } |
| 1048 | |
| 1049 | // Returns a clone of the value `V`, with its operands replaced as specified in |
| 1050 | // ValueWithNewAddrSpace. This function is called on every flat address |
| 1051 | // expression whose address space needs to be modified, in postorder. |
| 1052 | // |
| 1053 | // See cloneInstructionWithNewAddressSpace for the meaning of PoisonUsesToFix. |
| 1054 | Value *InferAddressSpacesImpl::cloneValueWithNewAddressSpace( |
| 1055 | Value *V, unsigned NewAddrSpace, |
| 1056 | const ValueToValueMapTy &ValueWithNewAddrSpace, |
| 1057 | const PredicatedAddrSpaceMapTy &PredicatedAS, |
| 1058 | SmallVectorImpl<const Use *> *PoisonUsesToFix) const { |
| 1059 | // All values in Postorder are flat address expressions. |
| 1060 | assert(V->getType()->getPointerAddressSpace() == FlatAddrSpace && |
| 1061 | isAddressExpression(*V, *DL, TTI)); |
| 1062 | |
| 1063 | if (auto *Arg = dyn_cast<Argument>(Val: V)) { |
| 1064 | // Arguments are address space casted in the function body, as we do not |
| 1065 | // want to change the function signature. |
| 1066 | Function *F = Arg->getParent(); |
| 1067 | BasicBlock::iterator Insert = F->getEntryBlock().getFirstNonPHIIt(); |
| 1068 | |
| 1069 | Type *NewPtrTy = PointerType::get(C&: Arg->getContext(), AddressSpace: NewAddrSpace); |
| 1070 | auto *NewI = new AddrSpaceCastInst(Arg, NewPtrTy); |
| 1071 | NewI->insertBefore(InsertPos: Insert); |
| 1072 | return NewI; |
| 1073 | } |
| 1074 | |
| 1075 | if (Instruction *I = dyn_cast<Instruction>(Val: V)) { |
| 1076 | Value *NewV = cloneInstructionWithNewAddressSpace( |
| 1077 | I, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix); |
| 1078 | if (Instruction *NewI = dyn_cast_or_null<Instruction>(Val: NewV)) { |
| 1079 | if (NewI->getParent() == nullptr) { |
| 1080 | NewI->insertBefore(InsertPos: I->getIterator()); |
| 1081 | NewI->takeName(V: I); |
| 1082 | NewI->setDebugLoc(I->getDebugLoc()); |
| 1083 | } |
| 1084 | } |
| 1085 | return NewV; |
| 1086 | } |
| 1087 | |
| 1088 | return cloneConstantExprWithNewAddressSpace( |
| 1089 | CE: cast<ConstantExpr>(Val: V), NewAddrSpace, ValueWithNewAddrSpace, DL, TTI); |
| 1090 | } |
| 1091 | |
| 1092 | // Defines the join operation on the address space lattice (see the file header |
| 1093 | // comments). |
| 1094 | unsigned InferAddressSpacesImpl::joinAddressSpaces(unsigned AS1, |
| 1095 | unsigned AS2) const { |
| 1096 | if (AS1 == AS2) |
| 1097 | return AS1; |
| 1098 | |
| 1099 | if (AS1 == FlatAddrSpace || AS2 == FlatAddrSpace) |
| 1100 | return FlatAddrSpace; |
| 1101 | |
| 1102 | if (AS1 == UninitializedAddressSpace) |
| 1103 | return AS2; |
| 1104 | if (AS2 == UninitializedAddressSpace) |
| 1105 | return AS1; |
| 1106 | |
| 1107 | return TTI->getAddressSpaceJoin(AS1, AS2); |
| 1108 | } |
| 1109 | |
| 1110 | bool InferAddressSpacesImpl::run(Function &CurFn) { |
| 1111 | F = &CurFn; |
| 1112 | DL = &F->getDataLayout(); |
| 1113 | PtrIntCastPairs.clear(); |
| 1114 | |
| 1115 | if (AssumeDefaultIsFlatAddressSpace) |
| 1116 | FlatAddrSpace = 0; |
| 1117 | |
| 1118 | if (FlatAddrSpace == UninitializedAddressSpace) { |
| 1119 | FlatAddrSpace = TTI->getFlatAddressSpace(); |
| 1120 | if (FlatAddrSpace == UninitializedAddressSpace) |
| 1121 | return false; |
| 1122 | } |
| 1123 | |
| 1124 | collectIntToPtrPointerOperand(); |
| 1125 | // Collects all flat address expressions in postorder. |
| 1126 | std::vector<WeakTrackingVH> Postorder = collectFlatAddressExpressions(F&: *F); |
| 1127 | |
| 1128 | // Runs a data-flow analysis to refine the address spaces of every expression |
| 1129 | // in Postorder. |
| 1130 | ValueToAddrSpaceMapTy InferredAddrSpace; |
| 1131 | PredicatedAddrSpaceMapTy PredicatedAS; |
| 1132 | inferAddressSpaces(Postorder, InferredAddrSpace, PredicatedAS); |
| 1133 | |
| 1134 | // Changes the address spaces of the flat address expressions who are inferred |
| 1135 | // to point to a specific address space. |
| 1136 | return rewriteWithNewAddressSpaces(Postorder, InferredAddrSpace, |
| 1137 | PredicatedAS); |
| 1138 | } |
| 1139 | |
| 1140 | void InferAddressSpacesImpl::enqueueUsers( |
| 1141 | Value &V, const ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 1142 | SetVector<Value *> &Worklist) const { |
| 1143 | for (Value *User : V.users()) { |
| 1144 | // Skip if User is already in the worklist. |
| 1145 | if (Worklist.count(key: User)) |
| 1146 | continue; |
| 1147 | |
| 1148 | ValueToAddrSpaceMapTy::const_iterator Pos = InferredAddrSpace.find(Val: User); |
| 1149 | // Our algorithm only updates the address spaces of flat address |
| 1150 | // expressions, which are those in InferredAddrSpace. |
| 1151 | if (Pos == InferredAddrSpace.end()) |
| 1152 | continue; |
| 1153 | |
| 1154 | // Function updateAddressSpace moves the address space down a lattice path. |
| 1155 | // Therefore, nothing to do if User is already inferred as flat (the bottom |
| 1156 | // element in the lattice). |
| 1157 | if (Pos->second == FlatAddrSpace) |
| 1158 | continue; |
| 1159 | |
| 1160 | Worklist.insert(X: User); |
| 1161 | } |
| 1162 | } |
| 1163 | |
| 1164 | void InferAddressSpacesImpl::runToFixPoint( |
| 1165 | SetVector<Value *> &Worklist, ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 1166 | PredicatedAddrSpaceMapTy &PredicatedAS) const { |
| 1167 | while (!Worklist.empty()) { |
| 1168 | Value *V = Worklist.pop_back_val(); |
| 1169 | |
| 1170 | // Try to update the address space of the stack top according to the |
| 1171 | // address spaces of its operands. |
| 1172 | if (!updateAddressSpace(V: *V, InferredAddrSpace, PredicatedAS)) |
| 1173 | continue; |
| 1174 | |
| 1175 | enqueueUsers(V&: *V, InferredAddrSpace, Worklist); |
| 1176 | } |
| 1177 | } |
| 1178 | |
| 1179 | // Constants need to be tracked through RAUW to handle cases with nested |
| 1180 | // constant expressions, so wrap values in WeakTrackingVH. |
| 1181 | void InferAddressSpacesImpl::inferAddressSpaces( |
| 1182 | ArrayRef<WeakTrackingVH> Postorder, |
| 1183 | ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 1184 | PredicatedAddrSpaceMapTy &PredicatedAS) const { |
| 1185 | SetVector<Value *> Worklist(llvm::from_range, Postorder); |
| 1186 | // Initially, all expressions are in the uninitialized address space. |
| 1187 | for (Value *V : Postorder) |
| 1188 | InferredAddrSpace[V] = UninitializedAddressSpace; |
| 1189 | |
| 1190 | runToFixPoint(Worklist, InferredAddrSpace, PredicatedAS); |
| 1191 | |
| 1192 | // A value still uninitialized here is stuck in a cycle of uninitialized |
| 1193 | // values and carries no address space information. Lower it to flat so its |
| 1194 | // users join to flat, instead of being rewritten to reference an operand |
| 1195 | // that rewriteWithNewAddressSpaces() never converts. |
| 1196 | SmallVector<Value *, 4> Lowered; |
| 1197 | for (Value *V : Postorder) { |
| 1198 | ValueToAddrSpaceMapTy::iterator I = InferredAddrSpace.find(Val: V); |
| 1199 | if (I->second == UninitializedAddressSpace) { |
| 1200 | I->second = FlatAddrSpace; |
| 1201 | Lowered.push_back(Elt: V); |
| 1202 | } |
| 1203 | } |
| 1204 | |
| 1205 | for (Value *V : Lowered) |
| 1206 | enqueueUsers(V&: *V, InferredAddrSpace, Worklist); |
| 1207 | |
| 1208 | runToFixPoint(Worklist, InferredAddrSpace, PredicatedAS); |
| 1209 | } |
| 1210 | |
| 1211 | unsigned |
| 1212 | InferAddressSpacesImpl::getPredicatedAddrSpace(const Value &Ptr, |
| 1213 | const Value *UserCtx) const { |
| 1214 | const Instruction *UserCtxI = dyn_cast<Instruction>(Val: UserCtx); |
| 1215 | if (!UserCtxI) |
| 1216 | return UninitializedAddressSpace; |
| 1217 | |
| 1218 | const Value *StrippedPtr = Ptr.stripInBoundsOffsets(); |
| 1219 | for (auto &AssumeVH : AC.assumptionsFor(V: StrippedPtr)) { |
| 1220 | if (!AssumeVH) |
| 1221 | continue; |
| 1222 | CallInst *CI = cast<CallInst>(Val&: AssumeVH); |
| 1223 | if (!isValidAssumeForContext(I: CI, CtxI: UserCtxI, DT)) |
| 1224 | continue; |
| 1225 | |
| 1226 | const Value *Ptr; |
| 1227 | unsigned AS; |
| 1228 | std::tie(args&: Ptr, args&: AS) = TTI->getPredicatedAddrSpace(V: CI->getArgOperand(i: 0)); |
| 1229 | if (Ptr) |
| 1230 | return AS; |
| 1231 | } |
| 1232 | |
| 1233 | return UninitializedAddressSpace; |
| 1234 | } |
| 1235 | |
| 1236 | bool InferAddressSpacesImpl::updateAddressSpace( |
| 1237 | const Value &V, ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 1238 | PredicatedAddrSpaceMapTy &PredicatedAS) const { |
| 1239 | assert(InferredAddrSpace.count(&V)); |
| 1240 | |
| 1241 | LLVM_DEBUG(dbgs() << "Updating the address space of\n " << V << '\n'); |
| 1242 | |
| 1243 | // The new inferred address space equals the join of the address spaces |
| 1244 | // of all its pointer operands. |
| 1245 | unsigned NewAS = UninitializedAddressSpace; |
| 1246 | |
| 1247 | // isAddressExpression should guarantee that V is an operator or an argument. |
| 1248 | assert(isa<Operator>(V) || isa<Argument>(V)); |
| 1249 | |
| 1250 | unsigned AS = TTI->getAssumedAddrSpace(V: &V); |
| 1251 | if (AS != UninitializedAddressSpace) { |
| 1252 | // Use the assumed address space directly. |
| 1253 | NewAS = AS; |
| 1254 | } else { |
| 1255 | // Otherwise, infer the address space from its pointer operands. |
| 1256 | SmallVector<Constant *, 2> ConstantPtrOps; |
| 1257 | SmallVector<Value *, 2> PtrOps = getPointerOperands(V, DL: *DL, TTI); |
| 1258 | for (Value *PtrOperand : PtrOps) { |
| 1259 | auto I = InferredAddrSpace.find(Val: PtrOperand); |
| 1260 | unsigned OperandAS; |
| 1261 | if (I == InferredAddrSpace.end()) { |
| 1262 | OperandAS = PtrOperand->getType()->getPointerAddressSpace(); |
| 1263 | if (auto *C = dyn_cast<Constant>(Val: PtrOperand); |
| 1264 | C && OperandAS == FlatAddrSpace) { |
| 1265 | // Defer joining the address space of constant pointer operands. |
| 1266 | ConstantPtrOps.push_back(Elt: C); |
| 1267 | continue; |
| 1268 | } |
| 1269 | if (OperandAS == FlatAddrSpace) { |
| 1270 | // Check AC for assumption dominating V. |
| 1271 | unsigned AS = getPredicatedAddrSpace(Ptr: *PtrOperand, UserCtx: &V); |
| 1272 | if (AS != UninitializedAddressSpace) { |
| 1273 | LLVM_DEBUG(dbgs() |
| 1274 | << " deduce operand AS from the predicate addrspace " |
| 1275 | << AS << '\n'); |
| 1276 | OperandAS = AS; |
| 1277 | // Record this use with the predicated AS. |
| 1278 | PredicatedAS[std::make_pair(x: &V, y&: PtrOperand)] = OperandAS; |
| 1279 | } |
| 1280 | } |
| 1281 | } else |
| 1282 | OperandAS = I->second; |
| 1283 | |
| 1284 | // join(flat, *) = flat. So we can break if NewAS is already flat. |
| 1285 | NewAS = joinAddressSpaces(AS1: NewAS, AS2: OperandAS); |
| 1286 | if (NewAS == FlatAddrSpace) |
| 1287 | break; |
| 1288 | } |
| 1289 | |
| 1290 | if (NewAS != FlatAddrSpace && NewAS != UninitializedAddressSpace) { |
| 1291 | if (any_of(Range&: ConstantPtrOps, P: [=](Constant *C) { |
| 1292 | return !isSafeToCastConstAddrSpace(C, NewAS); |
| 1293 | })) |
| 1294 | NewAS = FlatAddrSpace; |
| 1295 | } |
| 1296 | |
| 1297 | // operator(flat const, flat const, ...) -> flat |
| 1298 | if (NewAS == UninitializedAddressSpace && |
| 1299 | PtrOps.size() == ConstantPtrOps.size()) |
| 1300 | NewAS = FlatAddrSpace; |
| 1301 | } |
| 1302 | |
| 1303 | unsigned OldAS = InferredAddrSpace.lookup(Val: &V); |
| 1304 | assert(OldAS != FlatAddrSpace); |
| 1305 | if (OldAS == NewAS) |
| 1306 | return false; |
| 1307 | |
| 1308 | // If any updates are made, grabs its users to the worklist because |
| 1309 | // their address spaces can also be possibly updated. |
| 1310 | LLVM_DEBUG(dbgs() << " to " << NewAS << '\n'); |
| 1311 | InferredAddrSpace[&V] = NewAS; |
| 1312 | return true; |
| 1313 | } |
| 1314 | |
| 1315 | /// Replace operand \p OpIdx in \p Inst, if the value is the same as \p OldVal |
| 1316 | /// with \p NewVal. |
| 1317 | static bool replaceOperandIfSame(Instruction *Inst, unsigned OpIdx, |
| 1318 | Value *OldVal, Value *NewVal) { |
| 1319 | Use &U = Inst->getOperandUse(i: OpIdx); |
| 1320 | if (U.get() == OldVal) { |
| 1321 | U.set(NewVal); |
| 1322 | return true; |
| 1323 | } |
| 1324 | |
| 1325 | return false; |
| 1326 | } |
| 1327 | |
| 1328 | template <typename InstrType> |
| 1329 | static bool replaceSimplePointerUse(const TargetTransformInfo &TTI, |
| 1330 | InstrType *MemInstr, Value *OldV, |
| 1331 | Value *NewV) { |
| 1332 | unsigned AddrSpace = NewV->getType()->getPointerAddressSpace(); |
| 1333 | if (!MemInstr->isVolatile() || TTI.hasVolatileVariant(I: MemInstr, AddrSpace)) { |
| 1334 | return replaceOperandIfSame(MemInstr, InstrType::getPointerOperandIndex(), |
| 1335 | OldV, NewV); |
| 1336 | } |
| 1337 | |
| 1338 | return false; |
| 1339 | } |
| 1340 | |
| 1341 | /// If \p OldV is used as the pointer operand of a compatible memory operation |
| 1342 | /// \p Inst, replaces the pointer operand with NewV. |
| 1343 | /// |
| 1344 | /// This covers memory instructions with a single pointer operand that can have |
| 1345 | /// its address space changed by simply mutating the use to a new value. |
| 1346 | /// |
| 1347 | /// \p returns true the user replacement was made. |
| 1348 | static bool replaceIfSimplePointerUse(const TargetTransformInfo &TTI, |
| 1349 | User *Inst, Value *OldV, Value *NewV) { |
| 1350 | if (auto *LI = dyn_cast<LoadInst>(Val: Inst)) |
| 1351 | return replaceSimplePointerUse(TTI, MemInstr: LI, OldV, NewV); |
| 1352 | |
| 1353 | if (auto *SI = dyn_cast<StoreInst>(Val: Inst)) |
| 1354 | return replaceSimplePointerUse(TTI, MemInstr: SI, OldV, NewV); |
| 1355 | |
| 1356 | if (auto *RMW = dyn_cast<AtomicRMWInst>(Val: Inst)) |
| 1357 | return replaceSimplePointerUse(TTI, MemInstr: RMW, OldV, NewV); |
| 1358 | |
| 1359 | if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Val: Inst)) |
| 1360 | return replaceSimplePointerUse(TTI, MemInstr: CmpX, OldV, NewV); |
| 1361 | |
| 1362 | return false; |
| 1363 | } |
| 1364 | |
| 1365 | /// Update memory intrinsic uses that require more complex processing than |
| 1366 | /// simple memory instructions. These require re-mangling and may have multiple |
| 1367 | /// pointer operands. |
| 1368 | static bool handleMemIntrinsicPtrUse(MemIntrinsic *MI, Value *OldV, |
| 1369 | Value *NewV) { |
| 1370 | IRBuilder<> B(MI); |
| 1371 | if (auto *MSI = dyn_cast<MemSetInst>(Val: MI)) { |
| 1372 | B.CreateMemSet(Ptr: NewV, Val: MSI->getValue(), Size: MSI->getLength(), Align: MSI->getDestAlign(), |
| 1373 | isVolatile: false, // isVolatile |
| 1374 | AAInfo: MI->getAAMetadata()); |
| 1375 | } else if (auto *MTI = dyn_cast<MemTransferInst>(Val: MI)) { |
| 1376 | Value *Src = MTI->getRawSource(); |
| 1377 | Value *Dest = MTI->getRawDest(); |
| 1378 | |
| 1379 | // Be careful in case this is a self-to-self copy. |
| 1380 | if (Src == OldV) |
| 1381 | Src = NewV; |
| 1382 | |
| 1383 | if (Dest == OldV) |
| 1384 | Dest = NewV; |
| 1385 | |
| 1386 | if (auto *MCI = dyn_cast<MemCpyInst>(Val: MTI)) { |
| 1387 | if (MCI->isForceInlined()) |
| 1388 | B.CreateMemCpyInline(Dst: Dest, DstAlign: MTI->getDestAlign(), Src, |
| 1389 | SrcAlign: MTI->getSourceAlign(), Size: MTI->getLength(), |
| 1390 | isVolatile: false, // isVolatile |
| 1391 | AAInfo: MI->getAAMetadata()); |
| 1392 | else |
| 1393 | B.CreateMemCpy(Dst: Dest, DstAlign: MTI->getDestAlign(), Src, SrcAlign: MTI->getSourceAlign(), |
| 1394 | Size: MTI->getLength(), |
| 1395 | isVolatile: false, // isVolatile |
| 1396 | AAInfo: MI->getAAMetadata()); |
| 1397 | } else { |
| 1398 | assert(isa<MemMoveInst>(MTI)); |
| 1399 | B.CreateMemMove(Dst: Dest, DstAlign: MTI->getDestAlign(), Src, SrcAlign: MTI->getSourceAlign(), |
| 1400 | Size: MTI->getLength(), |
| 1401 | isVolatile: false, // isVolatile |
| 1402 | AAInfo: MI->getAAMetadata()); |
| 1403 | } |
| 1404 | } else |
| 1405 | llvm_unreachable("unhandled MemIntrinsic" ); |
| 1406 | |
| 1407 | MI->eraseFromParent(); |
| 1408 | return true; |
| 1409 | } |
| 1410 | |
| 1411 | // \p returns true if it is OK to change the address space of constant \p C with |
| 1412 | // a ConstantExpr addrspacecast. |
| 1413 | bool InferAddressSpacesImpl::isSafeToCastConstAddrSpace(Constant *C, |
| 1414 | unsigned NewAS) const { |
| 1415 | assert(NewAS != UninitializedAddressSpace); |
| 1416 | |
| 1417 | unsigned SrcAS = C->getType()->getPointerAddressSpace(); |
| 1418 | if (SrcAS == NewAS || isa<UndefValue>(Val: C)) |
| 1419 | return true; |
| 1420 | |
| 1421 | // Prevent illegal casts between different non-flat address spaces. |
| 1422 | if (SrcAS != FlatAddrSpace && NewAS != FlatAddrSpace) |
| 1423 | return false; |
| 1424 | |
| 1425 | if (isa<ConstantPointerNull>(Val: C) || isa<ConstantAggregateZero>(Val: C)) |
| 1426 | return true; |
| 1427 | |
| 1428 | if (auto *Op = dyn_cast<Operator>(Val: C)) { |
| 1429 | // If we already have a constant addrspacecast, it should be safe to cast it |
| 1430 | // off. |
| 1431 | if (Op->getOpcode() == Instruction::AddrSpaceCast) |
| 1432 | return isSafeToCastConstAddrSpace(C: cast<Constant>(Val: Op->getOperand(i: 0)), |
| 1433 | NewAS); |
| 1434 | |
| 1435 | if (Op->getOpcode() == Instruction::IntToPtr && |
| 1436 | Op->getType()->getPointerAddressSpace() == FlatAddrSpace) |
| 1437 | return true; |
| 1438 | } |
| 1439 | |
| 1440 | return false; |
| 1441 | } |
| 1442 | |
| 1443 | static Value::use_iterator skipToNextUser(Value::use_iterator I, |
| 1444 | Value::use_iterator End) { |
| 1445 | User *CurUser = I->getUser(); |
| 1446 | ++I; |
| 1447 | |
| 1448 | while (I != End && I->getUser() == CurUser) |
| 1449 | ++I; |
| 1450 | |
| 1451 | return I; |
| 1452 | } |
| 1453 | |
| 1454 | void InferAddressSpacesImpl::performPointerReplacement( |
| 1455 | Value *V, Value *NewV, Use &U, ValueToValueMapTy &ValueWithNewAddrSpace, |
| 1456 | SmallVectorImpl<Instruction *> &DeadInstructions) const { |
| 1457 | |
| 1458 | User *CurUser = U.getUser(); |
| 1459 | |
| 1460 | if (replaceIfSimplePointerUse(TTI: *TTI, Inst: CurUser, OldV: V, NewV)) |
| 1461 | return; |
| 1462 | |
| 1463 | // Skip if the current user is the new value itself. |
| 1464 | if (CurUser == NewV) |
| 1465 | return; |
| 1466 | |
| 1467 | auto *CurUserI = dyn_cast<Instruction>(Val: CurUser); |
| 1468 | if (!CurUserI || CurUserI->getFunction() != F) |
| 1469 | return; |
| 1470 | |
| 1471 | // Handle more complex cases like intrinsic that need to be remangled. |
| 1472 | if (auto *MI = dyn_cast<MemIntrinsic>(Val: CurUser)) { |
| 1473 | if (!MI->isVolatile() && handleMemIntrinsicPtrUse(MI, OldV: V, NewV)) |
| 1474 | return; |
| 1475 | } |
| 1476 | |
| 1477 | if (auto *II = dyn_cast<IntrinsicInst>(Val: CurUser)) { |
| 1478 | if (rewriteIntrinsicOperands(II, OldV: V, NewV)) |
| 1479 | return; |
| 1480 | } |
| 1481 | |
| 1482 | if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Val: CurUserI)) { |
| 1483 | // If we can infer that both pointers are in the same addrspace, |
| 1484 | // transform e.g. |
| 1485 | // %cmp = icmp eq float* %p, %q |
| 1486 | // into |
| 1487 | // %cmp = icmp eq float addrspace(3)* %new_p, %new_q |
| 1488 | |
| 1489 | unsigned NewAS = NewV->getType()->getPointerAddressSpace(); |
| 1490 | int SrcIdx = U.getOperandNo(); |
| 1491 | int OtherIdx = (SrcIdx == 0) ? 1 : 0; |
| 1492 | Value *OtherSrc = Cmp->getOperand(i_nocapture: OtherIdx); |
| 1493 | |
| 1494 | if (Value *OtherNewV = ValueWithNewAddrSpace.lookup(Val: OtherSrc)) { |
| 1495 | if (OtherNewV->getType()->getPointerAddressSpace() == NewAS) { |
| 1496 | Cmp->setOperand(i_nocapture: OtherIdx, Val_nocapture: OtherNewV); |
| 1497 | Cmp->setOperand(i_nocapture: SrcIdx, Val_nocapture: NewV); |
| 1498 | return; |
| 1499 | } |
| 1500 | } |
| 1501 | |
| 1502 | // Even if the type mismatches, we can cast the constant. |
| 1503 | if (auto *KOtherSrc = dyn_cast<Constant>(Val: OtherSrc)) { |
| 1504 | if (isSafeToCastConstAddrSpace(C: KOtherSrc, NewAS)) { |
| 1505 | Cmp->setOperand(i_nocapture: SrcIdx, Val_nocapture: NewV); |
| 1506 | Cmp->setOperand(i_nocapture: OtherIdx, Val_nocapture: ConstantExpr::getAddrSpaceCast( |
| 1507 | C: KOtherSrc, Ty: NewV->getType())); |
| 1508 | return; |
| 1509 | } |
| 1510 | } |
| 1511 | } |
| 1512 | |
| 1513 | if (AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(Val: CurUserI)) { |
| 1514 | unsigned NewAS = NewV->getType()->getPointerAddressSpace(); |
| 1515 | if (ASC->getDestAddressSpace() == NewAS) { |
| 1516 | ASC->replaceAllUsesWith(V: NewV); |
| 1517 | DeadInstructions.push_back(Elt: ASC); |
| 1518 | return; |
| 1519 | } |
| 1520 | } |
| 1521 | |
| 1522 | // Otherwise, replaces the use with flat(NewV). |
| 1523 | if (isa<Instruction>(Val: V) || isa<Instruction>(Val: NewV)) { |
| 1524 | // Don't create a copy of the original addrspacecast. |
| 1525 | if (U == V && isa<AddrSpaceCastInst>(Val: V)) |
| 1526 | return; |
| 1527 | |
| 1528 | // Insert the addrspacecast after NewV. |
| 1529 | BasicBlock::iterator InsertPos; |
| 1530 | if (Instruction *NewVInst = dyn_cast<Instruction>(Val: NewV)) |
| 1531 | InsertPos = std::next(x: NewVInst->getIterator()); |
| 1532 | else |
| 1533 | InsertPos = std::next(x: cast<Instruction>(Val: V)->getIterator()); |
| 1534 | |
| 1535 | while (isa<PHINode>(Val: InsertPos)) |
| 1536 | ++InsertPos; |
| 1537 | // This instruction may contain multiple uses of V, update them all. |
| 1538 | CurUser->replaceUsesOfWith( |
| 1539 | From: V, To: new AddrSpaceCastInst(NewV, V->getType(), "" , InsertPos)); |
| 1540 | } else { |
| 1541 | CurUserI->replaceUsesOfWith( |
| 1542 | From: V, To: ConstantExpr::getAddrSpaceCast(C: cast<Constant>(Val: NewV), Ty: V->getType())); |
| 1543 | } |
| 1544 | } |
| 1545 | |
| 1546 | bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces( |
| 1547 | ArrayRef<WeakTrackingVH> Postorder, |
| 1548 | const ValueToAddrSpaceMapTy &InferredAddrSpace, |
| 1549 | const PredicatedAddrSpaceMapTy &PredicatedAS) const { |
| 1550 | // For each address expression to be modified, creates a clone of it with its |
| 1551 | // pointer operands converted to the new address space. Since the pointer |
| 1552 | // operands are converted, the clone is naturally in the new address space by |
| 1553 | // construction. |
| 1554 | ValueToValueMapTy ValueWithNewAddrSpace; |
| 1555 | SmallVector<const Use *, 32> PoisonUsesToFix; |
| 1556 | for (Value *V : Postorder) { |
| 1557 | unsigned NewAddrSpace = InferredAddrSpace.lookup(Val: V); |
| 1558 | |
| 1559 | // In some degenerate cases (e.g. invalid IR in unreachable code), we may |
| 1560 | // not even infer the value to have its original address space. |
| 1561 | if (NewAddrSpace == UninitializedAddressSpace) |
| 1562 | continue; |
| 1563 | |
| 1564 | if (V->getType()->getPointerAddressSpace() != NewAddrSpace) { |
| 1565 | Value *New = |
| 1566 | cloneValueWithNewAddressSpace(V, NewAddrSpace, ValueWithNewAddrSpace, |
| 1567 | PredicatedAS, PoisonUsesToFix: &PoisonUsesToFix); |
| 1568 | if (New) |
| 1569 | ValueWithNewAddrSpace[V] = New; |
| 1570 | } |
| 1571 | } |
| 1572 | |
| 1573 | if (ValueWithNewAddrSpace.empty()) |
| 1574 | return false; |
| 1575 | |
| 1576 | // Fixes all the poison uses generated by cloneInstructionWithNewAddressSpace. |
| 1577 | for (const Use *PoisonUse : PoisonUsesToFix) { |
| 1578 | User *V = PoisonUse->getUser(); |
| 1579 | User *NewV = cast_or_null<User>(Val: ValueWithNewAddrSpace.lookup(Val: V)); |
| 1580 | if (!NewV) |
| 1581 | continue; |
| 1582 | |
| 1583 | unsigned OperandNo = PoisonUse->getOperandNo(); |
| 1584 | assert(isa<PoisonValue>(NewV->getOperand(OperandNo))); |
| 1585 | unsigned NewAS = |
| 1586 | NewV->getOperand(i: OperandNo)->getType()->getPointerAddressSpace(); |
| 1587 | Value *NewOp = operandWithNewAddressSpaceOrCreatePoison( |
| 1588 | OperandUse: *PoisonUse, NewAddrSpace: NewAS, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix: nullptr); |
| 1589 | NewV->setOperand(i: OperandNo, Val: NewOp); |
| 1590 | } |
| 1591 | |
| 1592 | SmallVector<Instruction *, 16> DeadInstructions; |
| 1593 | ValueToValueMapTy VMap; |
| 1594 | ValueMapper VMapper(VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); |
| 1595 | |
| 1596 | // Replaces the uses of the old address expressions with the new ones. |
| 1597 | for (const WeakTrackingVH &WVH : Postorder) { |
| 1598 | assert(WVH && "value was unexpectedly deleted" ); |
| 1599 | Value *V = WVH; |
| 1600 | Value *NewV = ValueWithNewAddrSpace.lookup(Val: V); |
| 1601 | if (NewV == nullptr) |
| 1602 | continue; |
| 1603 | |
| 1604 | LLVM_DEBUG(dbgs() << "Replacing the uses of " << *V << "\n with\n " |
| 1605 | << *NewV << '\n'); |
| 1606 | |
| 1607 | if (Constant *C = dyn_cast<Constant>(Val: V)) { |
| 1608 | Constant *Replace = |
| 1609 | ConstantExpr::getAddrSpaceCast(C: cast<Constant>(Val: NewV), Ty: C->getType()); |
| 1610 | if (C != Replace) { |
| 1611 | LLVM_DEBUG(dbgs() << "Inserting replacement const cast: " << Replace |
| 1612 | << ": " << *Replace << '\n'); |
| 1613 | SmallVector<User *, 16> WorkList; |
| 1614 | for (User *U : make_early_inc_range(Range: C->users())) { |
| 1615 | if (auto *I = dyn_cast<Instruction>(Val: U)) { |
| 1616 | if (I->getFunction() == F) |
| 1617 | I->replaceUsesOfWith(From: C, To: Replace); |
| 1618 | } else { |
| 1619 | WorkList.append(in_start: U->user_begin(), in_end: U->user_end()); |
| 1620 | } |
| 1621 | } |
| 1622 | if (!WorkList.empty()) { |
| 1623 | VMap[C] = Replace; |
| 1624 | DenseSet<User *> Visited{WorkList.begin(), WorkList.end()}; |
| 1625 | while (!WorkList.empty()) { |
| 1626 | User *U = WorkList.pop_back_val(); |
| 1627 | if (auto *I = dyn_cast<Instruction>(Val: U)) { |
| 1628 | if (I->getFunction() == F) |
| 1629 | VMapper.remapInstruction(I&: *I); |
| 1630 | continue; |
| 1631 | } |
| 1632 | for (User *U2 : U->users()) |
| 1633 | if (Visited.insert(V: U2).second) |
| 1634 | WorkList.push_back(Elt: U2); |
| 1635 | } |
| 1636 | } |
| 1637 | V = Replace; |
| 1638 | } |
| 1639 | } |
| 1640 | |
| 1641 | Value::use_iterator I, E, Next; |
| 1642 | for (I = V->use_begin(), E = V->use_end(); I != E;) { |
| 1643 | Use &U = *I; |
| 1644 | |
| 1645 | // Some users may see the same pointer operand in multiple operands. Skip |
| 1646 | // to the next instruction. |
| 1647 | I = skipToNextUser(I, End: E); |
| 1648 | |
| 1649 | performPointerReplacement(V, NewV, U, ValueWithNewAddrSpace, |
| 1650 | DeadInstructions); |
| 1651 | } |
| 1652 | |
| 1653 | if (V->use_empty()) { |
| 1654 | if (Instruction *I = dyn_cast<Instruction>(Val: V)) |
| 1655 | DeadInstructions.push_back(Elt: I); |
| 1656 | } |
| 1657 | } |
| 1658 | |
| 1659 | // Deleting one instruction may recursively delete another queued |
| 1660 | // instruction. Create handles before the first deletion so overlapping |
| 1661 | // entries are nulled instead of leaving dangling pointers. |
| 1662 | auto DeadInstructionHandles = |
| 1663 | to_vector_of<WeakTrackingVH, 16>(Range&: DeadInstructions); |
| 1664 | RecursivelyDeleteTriviallyDeadInstructions(DeadInsts&: DeadInstructionHandles); |
| 1665 | |
| 1666 | return true; |
| 1667 | } |
| 1668 | |
| 1669 | bool InferAddressSpaces::runOnFunction(Function &F) { |
| 1670 | if (skipFunction(F)) |
| 1671 | return false; |
| 1672 | |
| 1673 | auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>(); |
| 1674 | DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr; |
| 1675 | return InferAddressSpacesImpl( |
| 1676 | getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F), DT, |
| 1677 | &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F), |
| 1678 | FlatAddrSpace, /*AssumeDefaultIsFlatAddressSpace=*/false) |
| 1679 | .run(CurFn&: F); |
| 1680 | } |
| 1681 | |
| 1682 | FunctionPass *llvm::createInferAddressSpacesPass(unsigned AddressSpace) { |
| 1683 | return new InferAddressSpaces(AddressSpace); |
| 1684 | } |
| 1685 | |
| 1686 | InferAddressSpacesPass::InferAddressSpacesPass( |
| 1687 | bool AssumeDefaultIsFlatAddressSpace) |
| 1688 | : FlatAddrSpace(UninitializedAddressSpace), |
| 1689 | AssumeDefaultIsFlatAddressSpace(AssumeDefaultIsFlatAddressSpace) {} |
| 1690 | InferAddressSpacesPass::InferAddressSpacesPass( |
| 1691 | unsigned AddressSpace, bool AssumeDefaultIsFlatAddressSpace) |
| 1692 | : FlatAddrSpace(AddressSpace), |
| 1693 | AssumeDefaultIsFlatAddressSpace(AssumeDefaultIsFlatAddressSpace) {} |
| 1694 | |
| 1695 | PreservedAnalyses InferAddressSpacesPass::run(Function &F, |
| 1696 | FunctionAnalysisManager &AM) { |
| 1697 | bool Changed = |
| 1698 | InferAddressSpacesImpl(AM.getResult<AssumptionAnalysis>(IR&: F), |
| 1699 | AM.getCachedResult<DominatorTreeAnalysis>(IR&: F), |
| 1700 | &AM.getResult<TargetIRAnalysis>(IR&: F), FlatAddrSpace, |
| 1701 | AssumeDefaultIsFlatAddressSpace) |
| 1702 | .run(CurFn&: F); |
| 1703 | if (Changed) { |
| 1704 | PreservedAnalyses PA; |
| 1705 | PA.preserveSet<CFGAnalyses>(); |
| 1706 | return PA; |
| 1707 | } |
| 1708 | return PreservedAnalyses::all(); |
| 1709 | } |
| 1710 | |
| 1711 | void InferAddressSpacesPass::printPipeline( |
| 1712 | raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { |
| 1713 | static_cast<PassInfoMixin<InferAddressSpacesPass> *>(this)->printPipeline( |
| 1714 | OS, MapClassName2PassName); |
| 1715 | if (AssumeDefaultIsFlatAddressSpace) |
| 1716 | OS << "<assume-default-is-flat-addrspace>" ; |
| 1717 | } |
| 1718 | |