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
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2024 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "vc/GenXOpts/GenXOpts.h"
#include "vc/Utils/GenX/IntrinsicsWrapper.h"
#include "vc/Utils/GenX/Region.h"
#include "llvmWrapper/IR/DerivedTypes.h"
#include <llvm/GenXIntrinsics/GenXIntrinsics.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/Pass.h>
using namespace llvm;
namespace {
class GenXStatePointerFence final : public FunctionPass {
public:
static char ID;
GenXStatePointerFence() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
}
StringRef getPassName() const override { return "GenX State Pointer Fence"; }
bool runOnFunction(Function &F) override;
private:
bool processStatePointer(Value *V);
};
} // namespace
char GenXStatePointerFence::ID = 0;
INITIALIZE_PASS_BEGIN(GenXStatePointerFence, "GenXStatePointerFence",
"GenXStatePointerFence", false, false);
INITIALIZE_PASS_END(GenXStatePointerFence, "GenXStatePointerFence",
"GenXStatePointerFence", false, false);
namespace llvm {
FunctionPass *createGenXStatePointerFencePass() {
initializeGenXStatePointerFencePass(*PassRegistry::getPassRegistry());
return new GenXStatePointerFence();
}
} // namespace llvm
#if LLVM_VERSION_MAJOR >= 16
PreservedAnalyses GenXStatePointerFencePass::run(Function &F,
FunctionAnalysisManager &AM) {
GenXStatePointerFence GenXPoinerFence;
if (GenXPoinerFence.runOnFunction(F))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
#endif
bool GenXStatePointerFence::runOnFunction(Function &F) {
using namespace vc::InternalIntrinsic;
bool Changed = false;
for (auto &I : instructions(F)) {
auto IID = vc::getAnyIntrinsicID(&I);
auto SurfaceOperand = getMemorySurfaceOperandIndex(IID);
if (SurfaceOperand < 0)
continue;
Changed |= processStatePointer(I.getOperand(SurfaceOperand));
auto SamplerOperand = getMemorySamplerOperandIndex(IID);
if (SamplerOperand < 0)
continue;
Changed |= processStatePointer(I.getOperand(SamplerOperand));
}
return Changed;
}
bool GenXStatePointerFence::processStatePointer(Value *V) {
constexpr unsigned FenceIID = vc::InternalIntrinsic::optimization_fence;
auto *Trunc = dyn_cast<TruncInst>(V);
if (!Trunc)
return false;
auto *SrcTy = Trunc->getSrcTy();
auto *DstTy = Trunc->getDestTy();
if (!SrcTy->isIntegerTy(64) || !DstTy->isIntegerTy(32))
return false;
IRBuilder<> Builder(Trunc);
auto *Src = Trunc->getOperand(0);
if (vc::getAnyIntrinsicID(Src) == FenceIID)
return false;
auto *F = vc::getAnyDeclaration(Trunc->getModule(), FenceIID, {SrcTy});
auto *Fence = Builder.CreateCall(F, {Src});
Trunc->setOperand(0, Fence);
return true;
}
|