1//===- AMDGPUAliasAnalysis ------------------------------------------------===//
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/// \file
9/// This is the AMGPU address space based alias analysis pass.
10//===----------------------------------------------------------------------===//
11
12#include "AMDGPUAliasAnalysis.h"
13#include "AMDGPU.h"
14#include "llvm/Analysis/ValueTracking.h"
15#include "llvm/IR/Instructions.h"
16
17using namespace llvm;
18
19#define DEBUG_TYPE "amdgpu-aa"
20
21AnalysisKey AMDGPUAA::Key;
22
23// Register this pass...
24char AMDGPUAAWrapperPass::ID = 0;
25char AMDGPUExternalAAWrapper::ID = 0;
26
27INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
28 "AMDGPU Address space based Alias Analysis", false, true)
29
30INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
31 "AMDGPU Address space based Alias Analysis Wrapper", false, true)
32
33ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
34 return new AMDGPUAAWrapperPass();
35}
36
37ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
38 return new AMDGPUExternalAAWrapper();
39}
40
41AMDGPUAAWrapperPass::AMDGPUAAWrapperPass() : ImmutablePass(ID) {}
42
43void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
44 AU.setPreservesAll();
45}
46
47AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
48 const MemoryLocation &LocB, AAQueryInfo &AAQI,
49 const Instruction *) {
50 unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
51 unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
52
53 if (!AMDGPU::addrspacesMayAlias(AS1: asA, AS2: asB))
54 return AliasResult::NoAlias;
55
56 // In general, FLAT (generic) pointers could be aliased to LOCAL or PRIVATE
57 // pointers. However, as LOCAL or PRIVATE pointers point to local objects, in
58 // certain cases, it's still viable to check whether a FLAT pointer won't
59 // alias to a LOCAL or PRIVATE pointer.
60 MemoryLocation A = LocA;
61 MemoryLocation B = LocB;
62 // Canonicalize the location order to simplify the following alias check.
63 if (asA != AMDGPUAS::FLAT_ADDRESS) {
64 std::swap(a&: asA, b&: asB);
65 std::swap(a&: A, b&: B);
66 }
67 if (asA == AMDGPUAS::FLAT_ADDRESS &&
68 (asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) {
69 const auto *ObjA =
70 getUnderlyingObject(V: A.Ptr->stripPointerCastsForAliasAnalysis());
71 if (const LoadInst *LI = dyn_cast<LoadInst>(Val: ObjA)) {
72 // If a generic pointer is loaded from the constant address space, it
73 // could only be a GLOBAL or CONSTANT one as that address space is solely
74 // prepared on the host side, where only GLOBAL or CONSTANT variables are
75 // visible. Note that this even holds for regular functions.
76 if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)
77 return AliasResult::NoAlias;
78 } else if (const Argument *Arg = dyn_cast<Argument>(Val: ObjA)) {
79 const Function *F = Arg->getParent();
80 switch (F->getCallingConv()) {
81 case CallingConv::AMDGPU_KERNEL: {
82 // In the kernel function, kernel arguments won't alias to (local)
83 // variables in shared or private address space.
84 const auto *ObjB =
85 getUnderlyingObject(V: B.Ptr->stripPointerCastsForAliasAnalysis());
86 return ObjA != ObjB && isIdentifiedObject(V: ObjB) ? AliasResult::NoAlias
87 : AliasResult::MayAlias;
88 }
89 default:
90 // TODO: In the regular function, if that local variable in the
91 // location B is not captured, that argument pointer won't alias to it
92 // as well.
93 break;
94 }
95 }
96 }
97
98 return AliasResult::MayAlias;
99}
100
101ModRefInfo AMDGPUAAResult::getModRefInfoMask(const MemoryLocation &Loc,
102 AAQueryInfo &AAQI,
103 bool IgnoreLocals) {
104 unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace();
105 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
106 AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
107 return ModRefInfo::NoModRef;
108
109 const Value *Base = getUnderlyingObject(V: Loc.Ptr);
110 AS = Base->getType()->getPointerAddressSpace();
111 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
112 AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
113 return ModRefInfo::NoModRef;
114
115 return ModRefInfo::ModRef;
116}
117