1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2017-2023 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "llvm/Config/llvm-config.h"
#include "AdaptorCommon/RayTracing/RayTracingAddressSpaceAliasAnalysis.h"
#include "Compiler/Optimizer/OpenCLPasses/AddressSpaceAliasAnalysis/AddressSpaceAliasAnalysis.h"
#include "Compiler/CodeGenPublic.h"
#include "Compiler/IGCPassSupport.h"
#include "Probe/Assertion.h"
#include "common/LLVMWarningsPush.hpp"
#include "llvmWrapper/Analysis/AliasAnalysis.h"
#include "common/LLVMWarningsPop.hpp"
using namespace llvm;
using namespace IGC;
namespace {
class AddressSpaceAAResult : public IGCLLVM::AAResultBaseWrapper<AddressSpaceAAResult> {
using BaseT = IGCLLVM::AAResultBaseWrapper<AddressSpaceAAResult>;
friend BaseT;
const TargetLibraryInfo &TLI;
const CodeGenContext &CGC;
public:
explicit AddressSpaceAAResult(const TargetLibraryInfo &TLI, const CodeGenContext &ctx)
: BaseT(), TLI(TLI), CGC(ctx) {}
AddressSpaceAAResult(AddressSpaceAAResult &&Arg) : BaseT(std::move(Arg)), TLI(Arg.TLI), CGC(Arg.CGC) {}
AddressSpaceAAResult(const AddressSpaceAAResult &) = delete;
AddressSpaceAAResult &operator=(const AddressSpaceAAResult &) = delete;
AddressSpaceAAResult &operator=(AddressSpaceAAResult &&) = delete;
IGCLLVM::AliasResultEnum alias(const MemoryLocation &LocA, const MemoryLocation &LocB, AAQueryInfo &AAQI,
#if LLVM_VERSION_MAJOR < 16
const llvm::Instruction *CtxI = nullptr
#else
const llvm::Instruction *CtxI
#endif
) {
// DO NOT strip any casting as the address space is encoded in pointer
// type. For `addrspacecast`, the current implementation in LLVM is too
// aggressive to strip them. With address space resolution, we should not
// have trivial cases where a non-generic pointer is cased into a generic
// one.
PointerType *PtrTy1 = dyn_cast<PointerType>(LocA.Ptr->getType());
PointerType *PtrTy2 = dyn_cast<PointerType>(LocB.Ptr->getType());
if (!PtrTy1 || !PtrTy2)
return IGCLLVM::AliasResultEnum::NoAlias;
unsigned AS1 = PtrTy1->getAddressSpace();
unsigned AS2 = PtrTy2->getAddressSpace();
// If LocA and LocB are pointers to different non-generic address spaces
// then they do not alias. This is not true in general, however, in OpenCL
// all address spaces except generic are disjoint.
//
// Address spaces greater than ADDRESS_SPACE_NUM_ADDRESSES are used for
// stateful accesses and may alias.
//
if (AS1 < ADDRESS_SPACE_NUM_ADDRESSES && AS2 < ADDRESS_SPACE_NUM_ADDRESSES && AS1 != ADDRESS_SPACE_GENERIC &&
AS2 != ADDRESS_SPACE_GENERIC && AS1 != AS2) {
bool isDisjointMemory = true;
if (CGC.allocatePrivateAsGlobalBuffer() && CGC.getModuleMetaData()->genericAccessesResolved) {
const bool isPrivateGlobal = (AS1 == ADDRESS_SPACE_PRIVATE && AS2 == ADDRESS_SPACE_GLOBAL) ||
(AS1 == ADDRESS_SPACE_GLOBAL && AS2 == ADDRESS_SPACE_PRIVATE);
isDisjointMemory = !isPrivateGlobal;
}
if (isDisjointMemory)
return IGCLLVM::AliasResultEnum::NoAlias;
}
// Shared local memory doesn't alias any stateful memory.
if ((AS1 == ADDRESS_SPACE_LOCAL && AS2 > ADDRESS_SPACE_NUM_ADDRESSES) ||
(AS1 > ADDRESS_SPACE_NUM_ADDRESSES && AS2 == ADDRESS_SPACE_LOCAL)) {
return IGCLLVM::AliasResultEnum::NoAlias;
}
// Private memory doesn't alias any stateful memory
if ((AS1 == ADDRESS_SPACE_PRIVATE && AS2 > ADDRESS_SPACE_NUM_ADDRESSES) ||
(AS1 > ADDRESS_SPACE_NUM_ADDRESSES && AS2 == ADDRESS_SPACE_PRIVATE)) {
return IGCLLVM::AliasResultEnum::NoAlias;
}
/// For some client APIs (e.g. vulkan) compiler is free to assume that
/// resources bound to two different bindings points never alias unless a
/// resource is explicitly marked as being aliased.
IGC_ASSERT(CGC.getModuleMetaData());
if (AS1 > ADDRESS_SPACE_NUM_ADDRESSES && AS2 > ADDRESS_SPACE_NUM_ADDRESSES &&
CGC.getModuleMetaData()->statefulResourcesNotAliased) {
bool isDirectAccess[2] = {false, false};
unsigned resourceIndex[2] = {0, 0};
BufferType resourceType[2] = {BUFFER_TYPE_UNKNOWN, BUFFER_TYPE_UNKNOWN};
resourceType[0] = DecodeAS4GFXResource(AS1, isDirectAccess[0], resourceIndex[0]);
resourceType[1] = DecodeAS4GFXResource(AS2, isDirectAccess[1], resourceIndex[1]);
/// Returns true if resource type is a texture, constant buffer or a storage buffer.
auto IsBufferOrTexture = [](BufferType type) {
return (type == BufferType::CONSTANT_BUFFER || type == BufferType::UAV || type == BufferType::RESOURCE);
};
if (IsBufferOrTexture(resourceType[0]) && IsBufferOrTexture(resourceType[1])) {
if ((resourceType[0] != resourceType[1]) || // different resource types
(isDirectAccess[0] && isDirectAccess[1] &&
resourceIndex[0] != resourceIndex[1])) // direct access to different BTIs
{
return IGCLLVM::AliasResultEnum::NoAlias;
}
}
}
return BaseT::alias(LocA, LocB, AAQI, CtxI);
}
bool pointsToConstantMemory(const llvm::MemoryLocation &Loc, AAQueryInfo &AAQI, bool OrLocal) {
// Pointers to constant address space memory, well, point to constant memory
PointerType *ptrType = dyn_cast<PointerType>(Loc.Ptr->getType());
if (ptrType) {
if (ptrType->getAddressSpace() == ADDRESS_SPACE_CONSTANT)
return true;
bool DirectIdx;
unsigned BufId;
BufferType BufTy = DecodeAS4GFXResource(ptrType->getAddressSpace(), DirectIdx, BufId);
if (BufTy == CONSTANT_BUFFER)
return true;
}
return BaseT::pointsToConstantMemory(Loc, AAQI, OrLocal);
}
};
class AddressSpaceAAWrapperPass : public ImmutablePass {
std::unique_ptr<AddressSpaceAAResult> Result;
public:
static char ID;
AddressSpaceAAWrapperPass();
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<TargetLibraryInfoWrapperPass>();
AU.addRequired<CodeGenContextWrapper>();
}
bool doInitialization(Module &M) override {
if (M.size() > 0) {
#if LLVM_VERSION_MAJOR >= 10
auto &F = *M.begin(); // see llvmWrapper/Analysis/TargetLibraryInfo.h
#endif
Result.reset(new AddressSpaceAAResult(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
*getAnalysis<CodeGenContextWrapper>().getCodeGenContext()));
}
return false;
}
bool doFinalization(Module &M) override {
Result.reset();
return false;
}
AddressSpaceAAResult &getResult() { return *Result; }
const AddressSpaceAAResult &getResult() const { return *Result; }
};
} // End anonymous namespace
#define PASS_FLAG "igc-address-space-alias-analysis"
#define PASS_DESC "Address space alias analysis"
#define PASS_CFG_ONLY false
#define PASS_ANALYSIS true
IGC_INITIALIZE_PASS_BEGIN(AddressSpaceAAWrapperPass, PASS_FLAG, PASS_DESC, PASS_CFG_ONLY, PASS_ANALYSIS)
IGC_INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
IGC_INITIALIZE_PASS_END(AddressSpaceAAWrapperPass, PASS_FLAG, PASS_DESC, PASS_CFG_ONLY, PASS_ANALYSIS)
char AddressSpaceAAWrapperPass::ID = 0;
AddressSpaceAAWrapperPass::AddressSpaceAAWrapperPass() : ImmutablePass(ID) {
initializeAddressSpaceAAWrapperPassPass(*PassRegistry::getPassRegistry());
}
ImmutablePass *IGC::createAddressSpaceAAWrapperPass() { return new AddressSpaceAAWrapperPass(); }
void IGC::addJointAddressSpaceAAResults(Pass &P, Function &F, AAResults &AAR) {
if (auto *WrapperPass = P.getAnalysisIfAvailable<AddressSpaceAAWrapperPass>())
AAR.addAAResult(WrapperPass->getResult());
addRayTracingAddressSpaceAAResult(P, F, AAR);
}
// Wrapper around LLVM's ExternalAAWrapperPass so that the default constructor
// gets the callback.
class IGCExternalAAWrapper : public ExternalAAWrapperPass {
public:
static char ID;
IGCExternalAAWrapper() : ExternalAAWrapperPass(&addJointAddressSpaceAAResults) {}
};
ImmutablePass *IGC::createIGCExternalAAWrapper() { return new IGCExternalAAWrapper(); }
char IGCExternalAAWrapper::ID = 0;
IGC_INITIALIZE_PASS_BEGIN(IGCExternalAAWrapper, "igc-aa-wrapper", "IGC Address space alias analysis Wrapper",
PASS_CFG_ONLY, PASS_ANALYSIS)
IGC_INITIALIZE_PASS_END(IGCExternalAAWrapper, "igc-aa-wrapper", "IGC Address space alias analysis Wrapper",
PASS_CFG_ONLY, PASS_ANALYSIS)
|