xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===- AMDGPUAliasAnalysis ------------------------------------------------===//
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 /// \file
90b57cec5SDimitry Andric /// This is the AMGPU address space based alias analysis pass.
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "AMDGPUAliasAnalysis.h"
130b57cec5SDimitry Andric #include "AMDGPU.h"
140b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
150b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
160b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h"
170b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
180b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
190b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
200b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h"
210b57cec5SDimitry Andric #include "llvm/IR/Function.h"
220b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
230b57cec5SDimitry Andric #include "llvm/IR/Type.h"
240b57cec5SDimitry Andric #include "llvm/IR/Value.h"
250b57cec5SDimitry Andric #include "llvm/Pass.h"
260b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
280b57cec5SDimitry Andric #include <cassert>
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-aa"
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric // Register this pass...
350b57cec5SDimitry Andric char AMDGPUAAWrapperPass::ID = 0;
360b57cec5SDimitry Andric char AMDGPUExternalAAWrapper::ID = 0;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
390b57cec5SDimitry Andric                 "AMDGPU Address space based Alias Analysis", false, true)
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
420b57cec5SDimitry Andric                 "AMDGPU Address space based Alias Analysis Wrapper", false, true)
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
450b57cec5SDimitry Andric   return new AMDGPUAAWrapperPass();
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
490b57cec5SDimitry Andric   return new AMDGPUExternalAAWrapper();
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
530b57cec5SDimitry Andric   AU.setPreservesAll();
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric // These arrays are indexed by address space value enum elements 0 ... to 7
570b57cec5SDimitry Andric static const AliasResult ASAliasRules[8][8] = {
580b57cec5SDimitry Andric   /*                    Flat       Global    Region    Group     Constant  Private   Constant 32-bit  Buffer Fat Ptr */
590b57cec5SDimitry Andric   /* Flat     */        {MayAlias, MayAlias, NoAlias,  MayAlias, MayAlias, MayAlias, MayAlias,        MayAlias},
600b57cec5SDimitry Andric   /* Global   */        {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias,        MayAlias},
610b57cec5SDimitry Andric   /* Region   */        {NoAlias,  NoAlias , MayAlias, NoAlias , NoAlias,  NoAlias , NoAlias,         NoAlias},
620b57cec5SDimitry Andric   /* Group    */        {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias , NoAlias ,        NoAlias},
630b57cec5SDimitry Andric   /* Constant */        {MayAlias, MayAlias, NoAlias,  NoAlias , NoAlias , NoAlias , MayAlias,        MayAlias},
640b57cec5SDimitry Andric   /* Private  */        {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, NoAlias ,        NoAlias},
650b57cec5SDimitry Andric   /* Constant 32-bit */ {MayAlias, MayAlias, NoAlias,  NoAlias , MayAlias, NoAlias , NoAlias ,        MayAlias},
660b57cec5SDimitry Andric   /* Buffer Fat Ptr  */ {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias,        MayAlias}
670b57cec5SDimitry Andric };
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric static AliasResult getAliasResult(unsigned AS1, unsigned AS2) {
700b57cec5SDimitry Andric   static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 7, "Addr space out of range");
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   if (AS1 > AMDGPUAS::MAX_AMDGPU_ADDRESS || AS2 > AMDGPUAS::MAX_AMDGPU_ADDRESS)
730b57cec5SDimitry Andric     return MayAlias;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   return ASAliasRules[AS1][AS2];
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
790b57cec5SDimitry Andric                                   const MemoryLocation &LocB,
800b57cec5SDimitry Andric                                   AAQueryInfo &AAQI) {
810b57cec5SDimitry Andric   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
820b57cec5SDimitry Andric   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   AliasResult Result = getAliasResult(asA, asB);
850b57cec5SDimitry Andric   if (Result == NoAlias)
860b57cec5SDimitry Andric     return Result;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   // Forward the query to the next alias analysis.
890b57cec5SDimitry Andric   return AAResultBase::alias(LocA, LocB, AAQI);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
930b57cec5SDimitry Andric                                             AAQueryInfo &AAQI, bool OrLocal) {
94*5ffd83dbSDimitry Andric   unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace();
950b57cec5SDimitry Andric   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
96*5ffd83dbSDimitry Andric       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
970b57cec5SDimitry Andric     return true;
98*5ffd83dbSDimitry Andric 
99*5ffd83dbSDimitry Andric   const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
100*5ffd83dbSDimitry Andric   AS = Base->getType()->getPointerAddressSpace();
101*5ffd83dbSDimitry Andric   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
102*5ffd83dbSDimitry Andric       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
103*5ffd83dbSDimitry Andric     return true;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
1060b57cec5SDimitry Andric     if (GV->isConstant())
1070b57cec5SDimitry Andric       return true;
1080b57cec5SDimitry Andric   } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
1090b57cec5SDimitry Andric     const Function *F = Arg->getParent();
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     // Only assume constant memory for arguments on kernels.
1120b57cec5SDimitry Andric     switch (F->getCallingConv()) {
1130b57cec5SDimitry Andric     default:
1140b57cec5SDimitry Andric       return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
1150b57cec5SDimitry Andric     case CallingConv::AMDGPU_LS:
1160b57cec5SDimitry Andric     case CallingConv::AMDGPU_HS:
1170b57cec5SDimitry Andric     case CallingConv::AMDGPU_ES:
1180b57cec5SDimitry Andric     case CallingConv::AMDGPU_GS:
1190b57cec5SDimitry Andric     case CallingConv::AMDGPU_VS:
1200b57cec5SDimitry Andric     case CallingConv::AMDGPU_PS:
1210b57cec5SDimitry Andric     case CallingConv::AMDGPU_CS:
1220b57cec5SDimitry Andric     case CallingConv::AMDGPU_KERNEL:
1230b57cec5SDimitry Andric     case CallingConv::SPIR_KERNEL:
1240b57cec5SDimitry Andric       break;
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     unsigned ArgNo = Arg->getArgNo();
1280b57cec5SDimitry Andric     /* On an argument, ReadOnly attribute indicates that the function does
1290b57cec5SDimitry Andric        not write through this pointer argument, even though it may write
1300b57cec5SDimitry Andric        to the memory that the pointer points to.
1310b57cec5SDimitry Andric        On an argument, ReadNone attribute indicates that the function does
1320b57cec5SDimitry Andric        not dereference that pointer argument, even though it may read or write
1330b57cec5SDimitry Andric        the memory that the pointer points to if accessed through other pointers.
1340b57cec5SDimitry Andric      */
1350b57cec5SDimitry Andric     if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
1360b57cec5SDimitry Andric         (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
1370b57cec5SDimitry Andric          F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
1380b57cec5SDimitry Andric       return true;
1390b57cec5SDimitry Andric     }
1400b57cec5SDimitry Andric   }
1410b57cec5SDimitry Andric   return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
1420b57cec5SDimitry Andric }
143