#include "AMDGPUAliasAnalysis.h"
#include "AMDGPU.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Instructions.h"
using namespace llvm;
#define DEBUG_TYPE "amdgpu-aa"
AnalysisKey AMDGPUAA::Key;
char AMDGPUAAWrapperPass::ID = 0;
char AMDGPUExternalAAWrapper::ID = 0;
INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
"AMDGPU Address space based Alias Analysis", false, true)
INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
"AMDGPU Address space based Alias Analysis Wrapper", false, true)
ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
return new AMDGPUAAWrapperPass();
}
ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
return new AMDGPUExternalAAWrapper();
}
AMDGPUAAWrapperPass::AMDGPUAAWrapperPass() : ImmutablePass(ID) {
initializeAMDGPUAAWrapperPassPass(*PassRegistry::getPassRegistry());
}
void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
static AliasResult getAliasResult(unsigned AS1, unsigned AS2) {
static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 7, "Addr space out of range");
if (AS1 > AMDGPUAS::MAX_AMDGPU_ADDRESS || AS2 > AMDGPUAS::MAX_AMDGPU_ADDRESS)
return AliasResult::MayAlias;
#define ASMay AliasResult::MayAlias
#define ASNo AliasResult::NoAlias
static const AliasResult ASAliasRules[8][8] = {
{ASMay, ASMay, ASNo, ASMay, ASMay, ASMay, ASMay, ASMay},
{ASMay, ASMay, ASNo, ASNo, ASMay, ASNo, ASMay, ASMay},
{ASNo, ASNo, ASMay, ASNo, ASNo, ASNo, ASNo, ASNo},
{ASMay, ASNo, ASNo, ASMay, ASNo, ASNo, ASNo, ASNo},
{ASMay, ASMay, ASNo, ASNo, ASNo, ASNo, ASMay, ASMay},
{ASMay, ASNo, ASNo, ASNo, ASNo, ASMay, ASNo, ASNo},
{ASMay, ASMay, ASNo, ASNo, ASMay, ASNo, ASNo, ASMay},
{ASMay, ASMay, ASNo, ASNo, ASMay, ASNo, ASMay, ASMay}
};
#undef ASMay
#undef ASNo
return ASAliasRules[AS1][AS2];
}
AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
const MemoryLocation &LocB,
AAQueryInfo &AAQI) {
unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
AliasResult Result = getAliasResult(asA, asB);
if (Result == AliasResult::NoAlias)
return Result;
MemoryLocation A = LocA;
MemoryLocation B = LocB;
if (asA != AMDGPUAS::FLAT_ADDRESS) {
std::swap(asA, asB);
std::swap(A, B);
}
if (asA == AMDGPUAS::FLAT_ADDRESS &&
(asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) {
const auto *ObjA =
getUnderlyingObject(A.Ptr->stripPointerCastsForAliasAnalysis());
if (const LoadInst *LI = dyn_cast<LoadInst>(ObjA)) {
if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)
return AliasResult::NoAlias;
} else if (const Argument *Arg = dyn_cast<Argument>(ObjA)) {
const Function *F = Arg->getParent();
switch (F->getCallingConv()) {
case CallingConv::AMDGPU_KERNEL:
return AliasResult::NoAlias;
default:
break;
}
}
}
return AAResultBase::alias(LocA, LocB, AAQI);
}
bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
AAQueryInfo &AAQI, bool OrLocal) {
unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace();
if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
return true;
const Value *Base = getUnderlyingObject(Loc.Ptr);
AS = Base->getType()->getPointerAddressSpace();
if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
return true;
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
if (GV->isConstant())
return true;
} else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
const Function *F = Arg->getParent();
switch (F->getCallingConv()) {
default:
return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
case CallingConv::AMDGPU_LS:
case CallingConv::AMDGPU_HS:
case CallingConv::AMDGPU_ES:
case CallingConv::AMDGPU_GS:
case CallingConv::AMDGPU_VS:
case CallingConv::AMDGPU_PS:
case CallingConv::AMDGPU_CS:
case CallingConv::AMDGPU_KERNEL:
case CallingConv::SPIR_KERNEL:
break;
}
unsigned ArgNo = Arg->getArgNo();
if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
(F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
return true;
}
}
return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
}