File: PatternMatchPass.hpp

package info (click to toggle)
intel-graphics-compiler 1.0.12504.6-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 83,912 kB
  • sloc: cpp: 910,147; lisp: 202,655; ansic: 15,197; python: 4,025; yacc: 2,241; lex: 1,570; pascal: 244; sh: 104; makefile: 25
file content (349 lines) | stat: -rw-r--r-- 13,581 bytes parent folder | download
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
/*========================== begin_copyright_notice ============================

Copyright (C) 2017-2021 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

#pragma once
#include "Compiler/CISACodeGen/CISACodeGen.h"
#include "Compiler/CISACodeGen/helper.h"
#include "Compiler/CISACodeGen/LiveVars.hpp"
#include "Compiler/MetaDataUtilsWrapper.h"
#include "Compiler/CISACodeGen/WIAnalysis.hpp"
#include "Compiler/CISACodeGen/PositionDepAnalysis.hpp"

#include "common/LLVMWarningsPush.hpp"
#include <llvm/IR/InstVisitor.h>
#include <llvm/ADT/DenseSet.h>
#include <llvm/ADT/MapVector.h>
#include <llvm/Analysis/LoopInfo.h>
#include <llvm/IR/DataLayout.h>
#include "common/LLVMWarningsPop.hpp"
#include "llvmWrapper/IR/Instructions.h"

namespace llvm
{
    class Value;
    class PHINode;
    class Function;
    class BasicBlock;
    class GenIntrinsicInst;
}

namespace IGC
{

    struct SSource
    {
        llvm::Value* value;
        VISA_Type type;      // Set if source needs to be bit-casted to different type.
        e_modifier mod;
        int elementOffset;
        int SIMDOffset;
        unsigned char region[3];
        bool region_set;
        e_instance instance;
        bool fromConstantPool;

        SSource() : value(nullptr), type(VISA_Type::ISA_TYPE_NUM), mod(EMOD_NONE), elementOffset(0), SIMDOffset(0), region_set(false), instance(EINSTANCE_UNSPECIFIED), fromConstantPool(false)
        {
        }
    };

    struct DstModifier
    {
        SSource* flag;
        bool invertFlag;
        bool sat;
        e_predMode predMode;
        DstModifier() :
            flag(nullptr), invertFlag(false)
            , sat(false), predMode(EPRED_NORMAL)
        {
        }
    };
    class EmitPass;
    class CShader;

    struct Pattern
    {
        virtual void Emit(EmitPass* pass, const DstModifier& modifier) = 0;
        virtual ~Pattern() {}

        // Does the pattern allow destination saturation?
        virtual bool supportsSaturate() { return true; }
    };

    struct SDAG
    {
        SDAG(Pattern* pattern, llvm::Instruction* root) : m_pattern(pattern), m_root(root)
        {

        }
        Pattern* m_pattern;
        llvm::Instruction* m_root;
    };

    struct SDestination
    {
        llvm::Instruction* inst;
        llvm::Value* predicate;
        e_modifier mod;
        bool inversePredicate;
        bool uniform;
    };

    struct SBasicBlock
    {
        using reverse_iterator = std::vector<SDAG>::reverse_iterator;

        ~SBasicBlock() {}
        uint id;
        llvm::BasicBlock* bb;
        std::vector<SDAG> m_dags;

        //
        // Caching some variables for re-use, mostly within the same BB.
        //
        // caches the active lane mask (a flag variable) for the current instance in this BB
        // this is currently set only when we enable the A64 WA
        CVariable* m_activeMask = nullptr;   // flag var
        CVariable* m_numActiveLanes = nullptr;  // general var, #lanes for the entire dispatch size.
        void clearCaching() {
            m_activeMask = nullptr;
            m_numActiveLanes = nullptr;
        }
    };

    class CodeGenPatternMatch : public llvm::FunctionPass, public llvm::InstVisitor<CodeGenPatternMatch>
    {
    private:
        CodeGenPatternMatch(CodeGenPatternMatch&) = delete;
        CodeGenPatternMatch& operator =(CodeGenPatternMatch&) = delete;

    public:

        CodeGenPatternMatch();

        ~CodeGenPatternMatch();

        virtual void getAnalysisUsage(llvm::AnalysisUsage& AU) const override
        {
            AU.addRequired<llvm::DominatorTreeWrapperPass>();
            AU.addRequired<llvm::LoopInfoWrapperPass>();
            AU.addRequired<WIAnalysis>();
            AU.addRequired<LiveVarsAnalysis>();
            AU.addRequired<MetaDataUtilsWrapper>();
            AU.addRequired<PositionDepAnalysis>();
            AU.addRequired<CodeGenContextWrapper>();
            AU.setPreservesAll();
        }

        virtual bool runOnFunction(llvm::Function& F) override;

        virtual llvm::StringRef getPassName() const override {
            return "CodeGenPatternMatchPass";
        }

        void visitCastInst(llvm::CastInst& I);
        void visitBinaryOperator(llvm::BinaryOperator& I);
        void visitCmpInst(llvm::CmpInst& I);
        void visitPHINode(llvm::PHINode& I);
        void visitUnaryInstruction(llvm::UnaryInstruction& I);
        void visitCallInst(llvm::CallInst& I);
        void visitIntrinsicInst(llvm::IntrinsicInst& I);
        void visitSelectInst(llvm::SelectInst& I);
        void visitBitCastInst(llvm::BitCastInst& I);
        void visitIntToPtrInst(llvm::IntToPtrInst& I);
        void visitPtrToIntInst(llvm::PtrToIntInst& I);
        void visitAddrSpaceCast(llvm::AddrSpaceCastInst& I);
        void visitInstruction(llvm::Instruction& I);
        void visitExtractElementInst(llvm::ExtractElementInst& I);
        void visitLoadInst(llvm::LoadInst& I);
        void visitStoreInst(llvm::StoreInst& I);
        void visitFPToSIInst(llvm::FPToSIInst& I);
        void visitFPToUIInst(llvm::FPToUIInst& I);
        void visitDbgInfoIntrinsic(llvm::DbgInfoIntrinsic& I);
        void visitExtractValueInst(llvm::ExtractValueInst& I);
        void visitInsertValueInst(llvm::InsertValueInst& I);
        void visitBranchInst(llvm::BranchInst& I);

    public:
        void CodeGenBlock(llvm::BasicBlock* bb);
        void CodeGenNode(llvm::DomTreeNode* node);

        void ForceIsolate(llvm::Value* val) { m_forceIsolates.insert(val); }
        bool IsForceIsolated(llvm::Value* val) { return (m_forceIsolates.count(val) > 0) ? true : false; }

        SSource GetSource(llvm::Value* v, bool modifier, bool regioning);
        SSource GetSource(llvm::Value* value, e_modifier mod, bool regioning);
        bool GetRegionModifier(SSource& mod, llvm::Value*& source, bool regioning);
        bool BitcastSearch(SSource& mod, llvm::Value*& source, bool broadcast);

        void MarkAsSource(llvm::Value* v);

        bool MatchFMA(llvm::IntrinsicInst& I);
        bool MatchFrc(llvm::BinaryOperator& I);
        bool MatchFloor(llvm::BinaryOperator& I);
        bool MatchPredAdd(llvm::BinaryOperator& I);
        bool MatchSimpleAdd(llvm::BinaryOperator& I);
        bool MatchMad(llvm::BinaryOperator& I);
        bool MatchLrp(llvm::BinaryOperator& I);
        bool MatchCmpSext(llvm::Instruction& I);
        bool MatchModifier(llvm::Instruction& I, bool SupportSrc0Mod = true);
        bool MatchSingleInstruction(llvm::Instruction& I);
        bool MatchCanonicalizeInstruction(llvm::Instruction& I);
        bool MatchBranch(llvm::BranchInst& I);
        bool MatchShuffleBroadCast(llvm::GenIntrinsicInst& I);
        bool MatchWaveShuffleIndex(llvm::GenIntrinsicInst& I);
        bool MatchWaveInstruction(llvm::GenIntrinsicInst& I);
        bool MatchRegisterRegion(llvm::GenIntrinsicInst& I);

        Pattern* Match(llvm::Instruction& inst);
        bool MatchAbsNeg(llvm::Instruction& I);
        bool MatchFloatingPointSatModifier(llvm::Instruction& I);
        bool MatchIntegerSatModifier(llvm::Instruction& I);
        bool MatchPredicate(llvm::SelectInst& I);
        bool MatchSelectModifier(llvm::SelectInst& I);
        bool MatchPow(llvm::IntrinsicInst& I);
        bool MatchGenericPointersCmp(llvm::CmpInst& I);
        bool MatchCondModifier(llvm::CmpInst& I);
        bool MatchBoolOp(llvm::BinaryOperator& I);
        bool MatchFunnelShiftRotate(llvm::IntrinsicInst& I);
        bool MatchImmOffsetLSC(llvm::Instruction& I);
        bool MatchBfn(llvm::Instruction& I);
        bool MatchCmpSelect(llvm::SelectInst& I);
        bool MatchAdd3(llvm::Instruction& I);
        bool MatchDpas(llvm::GenIntrinsicInst& I);
        bool MatchDp4a(llvm::GenIntrinsicInst& I);
        bool MatchLogicAlu(llvm::BinaryOperator& I);
        bool MatchRsqrt(llvm::BinaryOperator& I);
        bool MatchLoadStorePointer(llvm::Instruction& I, llvm::Value& ptrVal);
        bool MatchBlockReadWritePointer(llvm::GenIntrinsicInst& I);
        bool MatchGradient(llvm::GenIntrinsicInst& I);
        bool MatchSampleDerivative(llvm::GenIntrinsicInst& I);
        bool MatchDbgInstruction(llvm::DbgInfoIntrinsic& I);
        bool MatchAvg(llvm::Instruction& I);

        bool MatchMinMax(llvm::SelectInst& I);
        bool MatchFullMul32(llvm::Instruction& I);
        bool MatchMulAdd16(llvm::Instruction& I);
        bool MatchFPToIntegerWithSaturation(llvm::Instruction& I);
        std::tuple<llvm::Value*, unsigned, VISA_Type> isFPToIntegerSatWithExactConstant(llvm::CastInst* I);
        std::tuple<llvm::Value*, unsigned, VISA_Type> isFPToSignedIntSatWithInexactConstant(llvm::SelectInst* I);
        std::tuple<llvm::Value*, unsigned, VISA_Type> isFPToUnsignedIntSatWithInexactConstant(llvm::SelectInst* I);
        bool MatchIntegerTruncSatModifier(llvm::SelectInst& I);
        std::tuple<llvm::Value*, bool, bool> isIntegerSatTrunc(llvm::SelectInst*);

        bool MatchSIToFPZExt(llvm::SIToFPInst* S2FI);

        bool matchAddPair(llvm::ExtractValueInst*);
        bool matchSubPair(llvm::ExtractValueInst*);
        bool matchMulPair(llvm::ExtractValueInst*);
        bool matchPtrToPair(llvm::ExtractValueInst*);

        bool MatchUnmaskedRegionBoundary(llvm::Instruction& I, bool start);

        bool MatchInsertToStruct(llvm::InsertValueInst*);
        bool MatchExtractFromStruct(llvm::ExtractValueInst*);

        void AddPattern(Pattern* P)
        {
            m_currentPattern = P;
        }

        void SetSrcModifier(unsigned int sourceIndex, e_modifier mod);
        void SetPatternRoot(llvm::Instruction& inst);
        void CreateBasicBlocks(llvm::Function* pLLVMFunc);
        uint GetBlockId(llvm::BasicBlock* bb);
        void HandleSubspanUse(llvm::Value* v);
        void HandleSampleDerivative(llvm::GenIntrinsicInst& I);
        bool IsSubspanUse(llvm::Value* v);
        bool HasUseOutsideLoop(llvm::Value* v);
        bool NeedVMask();

        //helper function
        bool NeedInstruction(llvm::Instruction& I);
        bool SIMDConstExpr(llvm::Instruction* v);
        bool IsConstOrSimdConstExpr(llvm::Value* C);
        bool FlushesDenormsOnOutput(llvm::Instruction& I);
        bool FlushesDenormsOnInput(llvm::Instruction& I);
        bool ContractionAllowed(llvm::Instruction& I) const;

        // Place a constant Val into the constant pool. This constant should be
        // available in basic block UseBlock.
        void AddToConstantPool(llvm::BasicBlock* UseBlock, llvm::Value* Val);

        bool canEmitAsUniformBool(const llvm::Value* Val) const
        {
            return UniformBools.count(Val) > 0;
        }

        bool isUniform(const llvm::Value* V) const
        {
            return m_WI && (m_WI->isUniform(V));
        };

    public:
        llvm::DenseSet<llvm::Instruction*>       m_usedInstructions;
        bool                  m_rootIsSubspanUse;
        llvm::DenseSet<llvm::Value*>             m_subSpanUse;
        llvm::SmallPtrSet<llvm::Value*, 8>       m_forceIsolates;
        std::map<llvm::BasicBlock*, SBasicBlock*> m_blockMap;
        SBasicBlock* m_blocks;
        uint                  m_numBlocks;
        llvm::DenseMap<llvm::Instruction*, bool> m_IsSIMDConstExpr;

        // Where we put the constant initialization.
        llvm::MapVector<llvm::Constant*, llvm::BasicBlock*> ConstantPlacement;

        typedef std::pair<llvm::ExtractValueInst*, llvm::ExtractValueInst*> PairOutputTy;
        typedef llvm::DenseMap<llvm::Value*, PairOutputTy> PairOutputMapTy;
        PairOutputMapTy PairOutputMap;

        llvm::Instruction* m_root;
        Pattern* m_currentPattern;

        CPlatform             m_Platform;
        bool                  m_AllowContractions;
        bool                  m_NeedVMask;
        bool                  m_samplertoRenderTargetEnable;
    public:
        static char ID;

    private:
        CodeGenContext* m_ctx; // Caching codegen context, valid only within runOnFunction().
        llvm::DominatorTree* DT;
        llvm::LoopInfo* LI;
        const llvm::DataLayout* m_DL;
        WIAnalysis* m_WI;
        LiveVars* m_LivenessInfo;
        PositionDepAnalysis* m_PosDep;
        llvm::BumpPtrAllocator m_allocator;
        // The set of boolean values stored as predicates of a single element.
        // Otherwise, they are expanded to the SIMD size.
        llvm::DenseSet<const llvm::Value*> UniformBools;

        // Find bool values that will be emitted as uniform variables.
        // Otherwise they will be expanded to the SIMD size, by default.
        void gatherUniformBools(llvm::Value* Val);

        // Return true if it is dbg related instruction
        bool IsDbgInst(llvm::Instruction& inst) const;
    };

    //helper
    bool GetModifier(llvm::Instruction& modifier, e_modifier& mod, llvm::Value*& source);
    bool GetModifier(llvm::Value& modifier, e_modifier& mod, llvm::Value*& source);
    bool IsNegate(llvm::Instruction* modifier, llvm::Value*& negateSource);
    bool IsZero(llvm::Value* v);
    bool isAbs(llvm::Value* abs, e_modifier& mod, llvm::Value*& source);
    bool isSat(llvm::Instruction* sat, llvm::Value*& source, bool& isUnsigned);
    bool isOne(llvm::Value* zero);
    bool isMinOrMax(llvm::Value* inst, llvm::Value*& source0, llvm::Value*& source1, bool& isMin, bool& isUnsigned);
    bool isCandidateForConstantPool(llvm::Value * val);
    e_modifier CombineModifier(e_modifier mod1, e_modifier mod2);

} // namespace IGC