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
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "Compiler/Optimizer/OpenCLPasses/GenericAddressResolution/GenericNullPtrPropagation.hpp"
#include "Compiler/CodeGenPublic.h"
#include "IGCPassSupport.h"
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Pass.h>
#include <llvmWrapper/IR/IRBuilder.h>
#include <llvm/IR/InstVisitor.h>
using namespace llvm;
using namespace IGC;
namespace {
class GenericNullPtrPropagation : public FunctionPass, public InstVisitor<GenericNullPtrPropagation> {
public:
static char ID;
GenericNullPtrPropagation() : FunctionPass(ID) {}
~GenericNullPtrPropagation() = default;
StringRef getPassName() const override { return "GenericNullPtrPropagation"; }
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<CodeGenContextWrapper>();
AU.addRequired<llvm::DominatorTreeWrapperPass>();
}
bool runOnFunction(Function &F) override;
void visitAddrSpaceCastInst(AddrSpaceCastInst &I);
private:
bool m_modified = false;
DominatorTree *dt = nullptr;
CodeGenContext *m_ctx = nullptr;
};
} // namespace
#define PASS_FLAG "igc-generic-null-ptr-propagation"
#define PASS_DESCRIPTION "Propagates null pointers through addrespace casts."
#define PASS_CFG_ONLY false
#define PASS_ANALYSIS false
IGC_INITIALIZE_PASS_BEGIN(GenericNullPtrPropagation, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
IGC_INITIALIZE_PASS_DEPENDENCY(CodeGenContextWrapper)
IGC_INITIALIZE_PASS_END(GenericNullPtrPropagation, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
char GenericNullPtrPropagation::ID = 0;
bool GenericNullPtrPropagation::runOnFunction(Function &F) {
m_ctx = getAnalysis<CodeGenContextWrapper>().getCodeGenContext();
dt = &getAnalysis<llvm::DominatorTreeWrapperPass>().getDomTree();
visit(F);
return m_modified;
}
static void updateAddrSpaceCastLocation(AddrSpaceCastInst &I, DominatorTree *dt) {
if (!I.hasOneUser()) {
return;
}
// If we can move addrspace cast closer to use we do it, to enable PrivateMemoryResolution to
// optimize alloca location better.
auto *user = llvm::dyn_cast<llvm::Instruction>(*I.user_begin());
if (!user) {
return;
}
if (llvm::isa<llvm::PHINode>(user)) {
return;
}
auto *addrSpaceCastParent = I.getParent();
auto *userParent = user->getParent();
if (addrSpaceCastParent != userParent && dt->dominates(addrSpaceCastParent, userParent)) {
auto firstInsertPt = userParent->getFirstInsertionPt();
if (firstInsertPt == userParent->end() || user->comesBefore(&*firstInsertPt)) {
return;
}
I.moveBefore(user);
}
}
void GenericNullPtrPropagation::visitAddrSpaceCastInst(AddrSpaceCastInst &I) {
if ((I.getSrcAddressSpace() == ADDRESS_SPACE_LOCAL ||
(I.getSrcAddressSpace() == ADDRESS_SPACE_PRIVATE && m_ctx->mustDistinguishBetweenPrivateAndGlobalPtr())) &&
I.getDestAddressSpace() == ADDRESS_SPACE_GENERIC) {
updateAddrSpaceCastLocation(I, dt);
Value *src = I.getPointerOperand();
Value *srcNull = ConstantPointerNull::get(cast<PointerType>(src->getType()));
Value *dstNull = ConstantPointerNull::get(cast<PointerType>(I.getType()));
IGCLLVM::IRBuilder<> builder(&I);
auto *AddrSpaceCastCpy = builder.CreateAddrSpaceCast(src, I.getType(), I.getName());
auto *isNotNull = builder.CreateICmpNE(src, srcNull);
auto *select = builder.CreateSelect(isNotNull, AddrSpaceCastCpy, dstNull);
I.replaceAllUsesWith(select);
I.eraseFromParent();
m_modified = true;
}
}
namespace IGC {
FunctionPass *createGenericNullPtrPropagationPass() { return new GenericNullPtrPropagation; }
} // namespace IGC
|