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
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2024 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#pragma once
#include "Compiler/IGCPassSupport.h"
#include "DebugInfo/VISAIDebugEmitter.hpp"
#include "DebugInfo/VISAModule.hpp"
#include "Probe/Assertion.h"
#include "ShaderCodeGen.hpp"
#include "common/LLVMWarningsPush.hpp"
#include "llvm/Config/llvm-config.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/IR/DIBuilder.h"
#include "common/LLVMWarningsPop.hpp"
#include <fstream>
using namespace IGC;
namespace IGC {
class IGCVectorizer : public llvm::FunctionPass {
typedef llvm::SmallPtrSet<Instruction *, 8> ValueSet;
typedef llvm::SmallVector<Instruction *, 8> VecArr;
typedef llvm::SmallVector<Constant *, 8> VecConst;
typedef llvm::SmallVector<Value *, 8> VecVal;
typedef llvm::SmallVector<VecArr, 8> VectorSliceChain;
struct Slice {
unsigned int OpNum;
VecArr Vector;
unsigned ParentIndex;
};
typedef llvm::SmallVector<Slice, 32> VecOfSlices;
typedef llvm::SmallVector<VecOfSlices, 3> Tree;
typedef std::unordered_map<Instruction *, VecArr *> InstructionToSliceMap;
struct InsertStruct {
Instruction *Final = nullptr;
// contains insert elements
VecArr Vec;
// contains slices of vector tree
VecOfSlices SlChain;
};
CodeGenContext *CGCtx = nullptr;
IGCMD::MetaDataUtils *MDUtils = nullptr;
WIAnalysis *WI = nullptr;
// when we vectorize, we build a new vector chain,
// this map contains associations between scalar and vector
// basically every element inside scalarSlice should point to the same
// vectorized element which contains all of them
std::unordered_map<Value *, Value *> ScalarToVector;
// contains information about instruction position inside BB
// with relation to other instrucitons
std::unordered_map<Value *, unsigned> PositionMap;
// all vector instructions that were produced for chain will be stored
// in this array, used for clean up if we bail
VecArr CreatedVectorInstructions;
// logging
std::unique_ptr<std::ofstream> OutputLogFile;
std::string LogStr;
llvm::raw_string_ostream OutputLogStream = raw_string_ostream(LogStr);
Module *M = nullptr;
bool checkIfSIMD16(llvm::Function &F);
void initializeLogFile(Function &F);
void writeLog();
void findInsertElementsInDataFlow(llvm::Instruction *I, VecArr &Chain);
bool checkSlice(VecArr &Slice, InsertStruct &InSt);
bool processChain(InsertStruct &InSt);
void clusterInsertElement(InsertStruct &InSt);
void collectInstructionToProcess(VecArr &ToProcess, Function &F);
void buildTree(VecArr &V, VecOfSlices &Chain);
void printSlice(Slice *S);
bool checkDependencyAndTryToEliminate(VecArr &Slice);
unsigned getPositionInsideBB(llvm::Instruction *Inst);
void collectPositionInsideBB(llvm::Instruction *Inst);
Instruction *getMaxPoint(VecArr &Slice);
Instruction *getMinPoint(VecArr &Slice);
Instruction *getInsertPointForVector(VecArr &Arr);
Instruction *getInsertPointForCreatedInstruction(VecVal &Arr, VecArr &Slice);
bool checkPHI(Instruction *Compare, VecArr &Slice);
bool handleStub(VecArr &Slice);
bool handlePHI(VecArr &Slice);
bool checkInsertElement(Instruction *First, VecArr &Slice);
bool handleInsertElement(VecArr &Slice, Instruction *Final);
bool checkExtractElement(Instruction *Compare, VecArr &Slice);
bool handleExtractElement(VecArr &Slice);
bool handleCastInstruction(VecArr &Slice);
bool handleSelectInstruction(VecArr &Slice);
bool handleBinaryInstruction(VecArr &Slice);
bool handleCMPInstruction(VecArr &Slice);
bool handleIntrinsic(VecArr &Slice);
bool checkBinaryOperator(VecArr &Slice);
bool checkPrevVectorization(VecArr& Slice, Value*& PrevVectorization);
bool collectOperandsForVectorization(unsigned OperNumToStart, unsigned OperNumToStop, Instruction* First, VecArr& Slice, VecVal& Operands);
bool handleIntrinsicInstruction(VecArr &Slice);
Value *checkOperandsToBeVectorized(Instruction *First, unsigned int OperNum, VecArr &Slice);
Value *vectorizeSlice(VecArr &Slice, unsigned int OperNum);
bool compareOperands(Value *A, Value *B);
InsertElementInst *createVector(VecArr &Slice, Instruction *InsertPoint);
void replaceSliceInstructionsWithExtract(VecArr &Slice, Instruction *CreatedInst);
public:
llvm::StringRef getPassName() const override { return "IGCVectorizer"; }
virtual ~IGCVectorizer() { ScalarToVector.clear(); }
IGCVectorizer(const IGCVectorizer &) = delete;
IGCVectorizer &operator=(const IGCVectorizer &) = delete;
virtual bool runOnFunction(llvm::Function &F) override;
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
AU.addRequired<CodeGenContextWrapper>();
AU.addRequired<MetaDataUtilsWrapper>();
AU.addRequired<WIAnalysis>();
}
IGCVectorizer();
IGCVectorizer(const std::string &FileName);
static char ID;
};
}; // namespace IGC
|