Home | History | Annotate | Download | only in AMDGPU
      1 //===- AMDGPUAliasAnalysis ------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 /// \file
     10 /// This is the AMGPU address space based alias analysis pass.
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "AMDGPUAliasAnalysis.h"
     14 #include "AMDGPU.h"
     15 #include "llvm/ADT/Triple.h"
     16 #include "llvm/Analysis/AliasAnalysis.h"
     17 #include "llvm/Analysis/MemoryLocation.h"
     18 #include "llvm/Analysis/ValueTracking.h"
     19 #include "llvm/IR/Argument.h"
     20 #include "llvm/IR/Attributes.h"
     21 #include "llvm/IR/CallingConv.h"
     22 #include "llvm/IR/Function.h"
     23 #include "llvm/IR/GlobalVariable.h"
     24 #include "llvm/IR/Type.h"
     25 #include "llvm/IR/Value.h"
     26 #include "llvm/Pass.h"
     27 #include "llvm/Support/Casting.h"
     28 #include "llvm/Support/ErrorHandling.h"
     29 #include <cassert>
     30 
     31 using namespace llvm;
     32 
     33 #define DEBUG_TYPE "amdgpu-aa"
     34 
     35 // Register this pass...
     36 char AMDGPUAAWrapperPass::ID = 0;
     37 
     38 INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
     39                 "AMDGPU Address space based Alias Analysis", false, true)
     40 
     41 ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
     42   return new AMDGPUAAWrapperPass();
     43 }
     44 
     45 void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
     46   AU.setPreservesAll();
     47 }
     48 
     49 // Must match the table in getAliasResult.
     50 AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_, Triple::ArchType Arch_)
     51   : Arch(Arch_), AS(AS_) {
     52   // These arrarys are indexed by address space value
     53   // enum elements 0 ... to 6
     54   static const AliasResult ASAliasRulesPrivIsZero[7][7] = {
     55   /*                    Private    Global    Constant  Group     Flat      Region    Constant 32-bit */
     56   /* Private  */        {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias , NoAlias},
     57   /* Global   */        {NoAlias , MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , MayAlias},
     58   /* Constant */        {NoAlias , MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , MayAlias},
     59   /* Group    */        {NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias , NoAlias},
     60   /* Flat     */        {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
     61   /* Region   */        {NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias},
     62   /* Constant 32-bit */ {NoAlias , MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , MayAlias}
     63   };
     64   static const AliasResult ASAliasRulesGenIsZero[7][7] = {
     65   /*                    Flat       Global    Region    Group     Constant  Private   Constant 32-bit */
     66   /* Flat     */        {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
     67   /* Global   */        {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias},
     68   /* Region   */        {MayAlias, NoAlias , NoAlias , NoAlias,  MayAlias, NoAlias , MayAlias},
     69   /* Group    */        {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias , NoAlias},
     70   /* Constant */        {MayAlias, MayAlias, MayAlias, NoAlias , NoAlias,  NoAlias , MayAlias},
     71   /* Private  */        {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, NoAlias},
     72   /* Constant 32-bit */ {MayAlias, MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , NoAlias}
     73   };
     74   static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 6, "Addr space out of range");
     75   if (AS.FLAT_ADDRESS == 0) {
     76     assert(AS.GLOBAL_ADDRESS         == 1 &&
     77            AS.REGION_ADDRESS         == 2 &&
     78            AS.LOCAL_ADDRESS          == 3 &&
     79            AS.CONSTANT_ADDRESS       == 4 &&
     80            AS.PRIVATE_ADDRESS        == 5 &&
     81            AS.CONSTANT_ADDRESS_32BIT == 6);
     82     ASAliasRules = &ASAliasRulesGenIsZero;
     83   } else {
     84     assert(AS.PRIVATE_ADDRESS        == 0 &&
     85            AS.GLOBAL_ADDRESS         == 1 &&
     86            AS.CONSTANT_ADDRESS       == 2 &&
     87            AS.LOCAL_ADDRESS          == 3 &&
     88            AS.FLAT_ADDRESS           == 4 &&
     89            AS.REGION_ADDRESS         == 5 &&
     90            AS.CONSTANT_ADDRESS_32BIT == 6);
     91     ASAliasRules = &ASAliasRulesPrivIsZero;
     92   }
     93 }
     94 
     95 AliasResult AMDGPUAAResult::ASAliasRulesTy::getAliasResult(unsigned AS1,
     96     unsigned AS2) const {
     97   if (AS1 > AS.MAX_AMDGPU_ADDRESS || AS2 > AS.MAX_AMDGPU_ADDRESS) {
     98     if (Arch == Triple::amdgcn)
     99       report_fatal_error("Pointer address space out of range");
    100     return AS1 == AS2 ? MayAlias : NoAlias;
    101   }
    102 
    103   return (*ASAliasRules)[AS1][AS2];
    104 }
    105 
    106 AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
    107                                   const MemoryLocation &LocB) {
    108   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
    109   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
    110 
    111   AliasResult Result = ASAliasRules.getAliasResult(asA, asB);
    112   if (Result == NoAlias) return Result;
    113 
    114   // Forward the query to the next alias analysis.
    115   return AAResultBase::alias(LocA, LocB);
    116 }
    117 
    118 bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
    119                                             bool OrLocal) {
    120   const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
    121 
    122   if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS ||
    123       Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS_32BIT) {
    124     return true;
    125   }
    126 
    127   if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
    128     if (GV->isConstant())
    129       return true;
    130   } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
    131     const Function *F = Arg->getParent();
    132 
    133     // Only assume constant memory for arguments on kernels.
    134     switch (F->getCallingConv()) {
    135     default:
    136       return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
    137     case CallingConv::AMDGPU_LS:
    138     case CallingConv::AMDGPU_HS:
    139     case CallingConv::AMDGPU_ES:
    140     case CallingConv::AMDGPU_GS:
    141     case CallingConv::AMDGPU_VS:
    142     case CallingConv::AMDGPU_PS:
    143     case CallingConv::AMDGPU_CS:
    144     case CallingConv::AMDGPU_KERNEL:
    145     case CallingConv::SPIR_KERNEL:
    146       break;
    147     }
    148 
    149     unsigned ArgNo = Arg->getArgNo();
    150     /* On an argument, ReadOnly attribute indicates that the function does
    151        not write through this pointer argument, even though it may write
    152        to the memory that the pointer points to.
    153        On an argument, ReadNone attribute indicates that the function does
    154        not dereference that pointer argument, even though it may read or write
    155        the memory that the pointer points to if accessed through other pointers.
    156      */
    157     if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
    158         (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
    159          F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
    160       return true;
    161     }
    162   }
    163   return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
    164 }
    165