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
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
//
/// GenXVisitor
/// -----------
///
/// GenXVisitor is a wrapper over llvm::InstVisitor, that supports GenX-specific
/// routines: iteration over function groups and GenX intrinsics. All visitors
/// are organized hierarchically, i.e. default non-overrided callbacks delegate
/// control to the next higher level, until the most specific overrided callback
/// for this intrinsic will be reached.
///
/// It's expected that support for the majority of GenX intrinsics will be added
/// here over time.
///
//===----------------------------------------------------------------------===//
#ifndef GENX_VISITOR_H
#define GENX_VISITOR_H
#include "FunctionGroup.h"
#include "llvm/GenXIntrinsics/GenXIntrinsicInst.h"
#include "llvm/IR/InstVisitor.h"
namespace llvm {
namespace genx {
#define DELEGATE(CLASS_TO_VISIT) \
return static_cast<SubClass*>(this)-> \
visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT&>(I))
#define GENX_DELEGATE(CLASS_TO_VISIT) \
return static_cast<SubClass*>(this)->visit##CLASS_TO_VISIT(I)
template<typename SubClass, typename RetTy=void>
class GenXVisitor : public InstVisitor<SubClass, RetTy> {
public:
using InstVisitor<SubClass, RetTy>::visit;
// Visitor for FunctionGroup.
void visit(FunctionGroup &FG) {
static_cast<SubClass*>(this)->visitFunctionGroup(FG);
visit(FG.begin(), FG.end());
};
// Forwarding function so that user can visit with pointer.
void visit(FunctionGroup *FG) {
visit(*FG);
}
// Default fallback for visiting FunctionGroup.
void visitFunctionGroup(FunctionGroup &FG) {}
// Redefine callback for Instruction::Call opcode: if it's GenX intrinsic,
// delegate it to appropriate callback, otherwise use standard call delegate.
RetTy visitCall(CallInst &I) {
return GenXIntrinsic::isGenXIntrinsic(&I) ?
delegateGenXIntrinsic(cast<GenXIntrinsicInst>(I)) :
InstVisitor<SubClass, RetTy>::visitCall(I);
}
// Implementation of default callbacks for GenX intrisnics: propagate calls
// to next level of their hierarchy.
RetTy visitGenXIntrinsicInst(GenXIntrinsicInst &I) {
DELEGATE(CallInst);
}
RetTy visitWrRegion(GenXIntrinsicInst &I) {
GENX_DELEGATE(GenXIntrinsicInst);
}
RetTy visitRdRegion(GenXIntrinsicInst &I) {
GENX_DELEGATE(GenXIntrinsicInst);
}
RetTy visitReadWritePredefReg(GenXIntrinsicInst &I) {
GENX_DELEGATE(GenXIntrinsicInst);
}
RetTy visitReadPredefReg(GenXIntrinsicInst &I) {
GENX_DELEGATE(ReadWritePredefReg);
}
RetTy visitWritePredefReg(GenXIntrinsicInst &I) {
GENX_DELEGATE(ReadWritePredefReg);
}
private:
RetTy delegateGenXIntrinsic(GenXIntrinsicInst &I) {
auto ID = I.getIntrinsicID();
if (ID == GenXIntrinsic::not_genx_intrinsic)
DELEGATE(CallInst);
else if (GenXIntrinsic::isWrRegion(ID))
GENX_DELEGATE(WrRegion);
else if (GenXIntrinsic::isRdRegion(ID))
GENX_DELEGATE(RdRegion);
else if (GenXIntrinsic::isReadPredefReg(ID))
GENX_DELEGATE(ReadPredefReg);
else if (GenXIntrinsic::isWritePredefReg(ID))
GENX_DELEGATE(WritePredefReg);
else
GENX_DELEGATE(GenXIntrinsicInst);
}
};
#undef DELEGATE
#undef GENX_DELEGATE
} // namespace genx
} // namespace llvm
#endif
|