1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #ifndef __SPILLMANAGERGMRF_H__
10 #define __SPILLMANAGERGMRF_H__
11 
12 #include "Mem_Manager.h"
13 #include "G4_Opcode.h"
14 #include "BuildIR.h"
15 
16 #include <list>
17 #include <utility>
18 
19 // Forward declarations
20 namespace vISA
21 {
22 class G4_Kernel;
23 class G4_Declare;
24 class G4_Operand;
25 class G4_RegVar;
26 class G4_RegVarTransient;
27 class G4_DstRegRegion;
28 class G4_SrcRegRegion;
29 class G4_Imm;
30 class G4_Predicate;
31 class G4_INST;
32 class IR_Builder;
33 class LivenessAnalysis;
34 class Interference;
35 class LiveRange;
36 class LSLiveRange;
37 class PointsToAnalysis;
38 class GlobalRA;
39 class GraphColor;
40 }
41 struct RegionDesc;
42 // Class definitions
43 namespace vISA
44 {
45 
46 class SpillManagerGRF
47 {
48 public:
49 
50     using DECLARE_LIST = std::list<G4_Declare *> ;
51     using LR_LIST = std::list<LiveRange *>;
52     using LSLR_LIST = std::list<LSLiveRange *>;
53     using INST_LIST = std::list<G4_INST *,INST_LIST_NODE_ALLOCATOR>;
54     typedef struct Edge
55     {
56         unsigned first;
57         unsigned second;
58     } EDGE;
59     using INTF_LIST = std::list<EDGE>;
60 
61     // Methods
62 
63     SpillManagerGRF(
64         GlobalRA&                g,
65         unsigned                 spillAreaOffset,
66         unsigned                 varIdCount,
67         const LivenessAnalysis * lvInfo,
68         LiveRange **             lrInfo,
69         const Interference *     intf,
70         const LR_LIST *          spilledLRs,
71         unsigned                 iterationNo,
72         bool                     useSpillReg,
73         unsigned                 spillRegSize,
74         unsigned                 indrSpillRegSize,
75         bool                     enableSpillSpaceCompression,
76         bool                     useScratchMsg,
77         bool                     avoidDstSrcOverlap
78     );
79 
80     SpillManagerGRF(
81         GlobalRA& g,
82         unsigned spillAreaOffset,
83         unsigned varIdCount,
84         const LivenessAnalysis* lvInfo,
85         LSLR_LIST* spilledLSLRs,
86         bool enableSpillSpaceCompression,
87         bool useScratchMsg,
88         bool avoidDstSrcOverlap
89     );
90 
~SpillManagerGRF()91     ~SpillManagerGRF() {}
92 
93 
94     bool insertSpillFillCode(
95         G4_Kernel*         kernel,
96         PointsToAnalysis& pointsToAnalysis
97     );
98 
99     void expireRanges(unsigned int idx, std::list<LSLiveRange*>* liveList);
100 
101     void updateActiveList(LSLiveRange* lr, std::list<LSLiveRange*>* liveList);
102 
103     bool spillLiveRanges(G4_Kernel* kernel);
104 
getNumGRFSpill()105     unsigned getNumGRFSpill() const { return numGRFSpill; }
getNumGRFFill()106     unsigned getNumGRFFill() const { return numGRFFill; }
getNumGRFMove()107     unsigned getNumGRFMove() const { return numGRFMove; }
108     // return the next cumulative logical offset. This does not non-spilled stuff like
109     // private variables placed by IGC (marked by spill_mem_offset)
110     // this should only be called after insertSpillFillCode()
getNextOffset()111     uint32_t getNextOffset() const { return nextSpillOffset_; }
112     // return the cumulative scratch space offset for the next spilled variable.
113     // This adjusts for scratch space reserved for file scope vars and IGC/GT-pin
getNextScratchOffset()114     uint32_t getNextScratchOffset() const
115     {
116         int offset = nextSpillOffset_;
117         getSpillOffset(offset);
118         return offset;
119     }
120 
121     // convert zero-based logical offset into the scratch space offset.
getSpillOffset(int & logicalOffset)122     void getSpillOffset(int& logicalOffset) const
123     {
124         logicalOffset += globalScratchOffset;
125     }
126 
127     static std::tuple<uint32_t, G4_ExecSize> createSpillSendMsgDescOWord(
128         unsigned int height);
129 
130 private:
131     G4_Declare* getOrCreateAddrSpillFillDcl(G4_Declare* spilledAddrTakenDcl, G4_Kernel* kernel);
132     bool handleAddrTakenSpills(G4_Kernel * kernel, PointsToAnalysis& pointsToAnalysis);
133     unsigned int handleAddrTakenLSSpills(G4_Kernel* kernel, PointsToAnalysis& pointsToAnalysis);
134     void insertAddrTakenSpillFill(G4_Kernel * kernel, PointsToAnalysis& pointsToAnalysis);
135     void insertAddrTakenLSSpillFill(G4_Kernel* kernel, PointsToAnalysis& pointsToAnalysis);
136     void insertAddrTakenSpillAndFillCode(
137         G4_Kernel* kernel, G4_BB* bb, INST_LIST::iterator inst_it,
138         G4_Operand* opnd, PointsToAnalysis& pointsToAnalysis,
139         bool spill, unsigned int bbid);
140     void insertAddrTakenLSSpillAndFillCode(G4_Kernel* kernel, G4_BB* bb,
141         INST_LIST::iterator inst_it, G4_Operand* opnd,
142         PointsToAnalysis& pointsToAnalysis, bool spill, unsigned int bbid);
143     void prunePointsTo(G4_Kernel* kernel, PointsToAnalysis& pointsToAnalysis);
144 
145     void prunePointsToLS(G4_Kernel* kernel, PointsToAnalysis& pointsToAnalysis);
146 
147     bool isComprInst (G4_INST * inst) const;
148 
149     bool isMultiRegComprSource (
150         G4_SrcRegRegion* src,
151         G4_INST *        inst) const;
152 
153     unsigned getSendRspLengthBitOffset() const;
154 
155     unsigned getSendMaxResponseLength() const;
156 
157     static unsigned getSendMsgLengthBitOffset();
158 
159     unsigned getSendMaxMessageLength() const;
160 
161     static unsigned getSendDescDataSizeBitOffset();
162 
163     unsigned getSendReadTypeBitOffset() const;
164 
165     static unsigned getSendWriteTypeBitOffset();
166 
167     unsigned getSendScReadType() const;
168 
169     unsigned getSendScWriteType() const;
170 
171     unsigned getSendOwordReadType() const;
172     static unsigned getSendOwordWriteType();
173     unsigned getSendExDesc(bool isWrite, bool isScatter) const;
174 
175     unsigned getSpillIndex(G4_RegVar *  spilledRegVar);
176 
177     unsigned getFillIndex(G4_RegVar *  spilledRegVar);
178 
179     unsigned getTmpIndex(G4_RegVar *  spilledRegVar);
180 
181     unsigned getMsgSpillIndex(G4_RegVar *  spilledRegVar);
182 
183     unsigned getMsgFillIndex(G4_RegVar *  spilledRegVar);
184 
185     unsigned getAddrSpillFillIndex(G4_RegVar *  spilledRegVar);
186 
187     const char *
188     createImplicitRangeName (
189         const char * baseName,
190         G4_RegVar *  spilledRegVar,
191         unsigned     index
192     );
193 
194     G4_RegVar *
195     getReprRegVar (
196         G4_RegVar * regVar
197     ) const;
198 
199     template <class REGION_TYPE>
200     G4_RegVar *
201     getRegVar (
202         REGION_TYPE * region
203     ) const;
204 
205     G4_RegFileKind
206     getRFType (
207         G4_RegVar * regvar
208     ) const;
209 
210     template <class REGION_TYPE>
211     G4_RegFileKind getRFType(REGION_TYPE * region) const;
212 
213     template <class REGION_TYPE>
214     unsigned getRegionOriginOffset(REGION_TYPE * region) const;
215 
216     unsigned grfMask() const;
217 
218     unsigned hwordMask() const;
219 
220     unsigned owordMask() const;
221 
222     unsigned dwordMask() const;
223 
224     bool owordAligned(unsigned offset) const;
225 
226     bool dwordAligned(unsigned offset) const;
227 
228     static unsigned cdiv(unsigned dvd, unsigned dvr);
229 
230     G4_RegVar *getRegVar(unsigned id) const;
231 
232     bool shouldSpillRegister(G4_RegVar * regVar) const;
233 
234     unsigned getByteSize(G4_RegVar * regVar) const;
235 
236     template <class REGION_TYPE>
237     unsigned getSegmentDisp(REGION_TYPE * region, G4_ExecSize   execSize);
238 
239     unsigned getDisp(G4_RegVar *   lRange);
240 
241     template <class REGION_TYPE>
242     unsigned getRegionDisp(REGION_TYPE * region);
243 
244     bool spillMemLifetimeInterfere(unsigned i, unsigned j) const;
245 
246     unsigned calculateSpillDisp(G4_RegVar * lRange) const;
247 
248     unsigned calculateSpillDispForLS(G4_RegVar* regVar) const;
249 
250     template <class REGION_TYPE>
251     unsigned getMsgType(REGION_TYPE * region, G4_ExecSize   execSize);
252 
253     template <class REGION_TYPE>
254     bool isUnalignedRegion(REGION_TYPE * region, G4_ExecSize   execSize);
255 
256     template <class REGION_TYPE>
257     void calculateEncAlignedSegment(
258         REGION_TYPE * region,
259         G4_ExecSize   execSize,
260         unsigned &    start,
261         unsigned &    end,
262         unsigned &    type);
263 
264     template <class REGION_TYPE>
265     unsigned getEncAlignedSegmentByteSize(REGION_TYPE * region, G4_ExecSize execSize);
266 
267     template <class REGION_TYPE>
268     unsigned getEncAlignedSegmentDisp(REGION_TYPE * region, G4_ExecSize execSize);
269 
270     template <class REGION_TYPE>
271     unsigned getEncAlignedSegmentMsgType(REGION_TYPE * region, G4_ExecSize execSize);
272 
273     template <class REGION_TYPE>
274     unsigned getSegmentByteSize(REGION_TYPE * region, G4_ExecSize   execSize);
275 
276     unsigned getRegionByteSize (G4_DstRegRegion * region, G4_ExecSize execSize) const;
277 
278     unsigned getRegionByteSize(G4_SrcRegRegion * region, G4_ExecSize execSize) const;
279 
280     bool isScalarReplication(G4_SrcRegRegion * region) const;
281 
282     bool repeatSIMD16or32Source(G4_SrcRegRegion * region) const;
283 
284     G4_Declare *
285     createRangeDeclare(
286         const char*    name,
287         G4_RegFileKind regFile,
288         unsigned short nElems,
289         unsigned short nRows,
290         G4_Type        type,
291         DeclareType    kind,
292         G4_RegVar *    base,
293         G4_Operand *   repRegion,
294         G4_ExecSize    execSize);
295 
296     template <class REGION_TYPE>
297     G4_Declare *
298     createTransientGRFRangeDeclare(
299         REGION_TYPE * region,
300         const char  * name,
301         unsigned      index,
302         G4_ExecSize   execSize,
303         G4_INST     * inst
304     );
305 
306     G4_Declare *
307     createPostDstSpillRangeDeclare(G4_INST * sendOut);
308 
309     G4_Declare *
310     createSpillRangeDeclare(
311         G4_DstRegRegion * spillRegion,
312         G4_ExecSize       execSize,
313         G4_INST         * inst);
314 
315     G4_Declare *
316     createGRFFillRangeDeclare (
317         G4_SrcRegRegion * fillRegion,
318         G4_ExecSize       execSize,
319         G4_INST         * inst
320     );
321 
322     G4_Declare *
323     createSendFillRangeDeclare (
324         G4_SrcRegRegion * filledRegion,
325         G4_INST *         sendInst
326     );
327 
328     G4_Declare *
329     createTemporaryRangeDeclare(
330         G4_DstRegRegion * fillRegion,
331         G4_ExecSize       execSize,
332         bool              forceSegmentAlignment = false);
333 
334     G4_DstRegRegion *
335     createSpillRangeDstRegion(
336         G4_RegVar *       spillRangeRegVar,
337         G4_DstRegRegion * spilledRegion,
338         G4_ExecSize       execSize,
339         unsigned          regOff = 0);
340 
341     G4_SrcRegRegion *
342     createFillRangeSrcRegion(
343         G4_RegVar *       fillRangeRegVar,
344         G4_SrcRegRegion * filledRegion,
345         G4_ExecSize       execSize);
346 
347     G4_SrcRegRegion *
348     createTemporaryRangeSrcRegion(
349         G4_RegVar *       tmpRangeRegVar,
350         G4_DstRegRegion * spilledRegion,
351         G4_ExecSize       execSize,
352         unsigned          regOff = 0);
353 
354     G4_SrcRegRegion *
355     createBlockSpillRangeSrcRegion(
356         G4_RegVar *       spillRangeRegVar,
357         unsigned          regOff = 0,
358         unsigned          subregOff = 0);
359 
360     G4_Declare *
361     createMRangeDeclare(G4_RegVar * regVar);
362 
363     G4_Declare *
364     createMRangeDeclare(G4_DstRegRegion * region, G4_ExecSize execSize);
365 
366     G4_Declare *
367     createMRangeDeclare(G4_SrcRegRegion * region, G4_ExecSize execSize);
368 
369     G4_DstRegRegion *
370     createMPayloadBlockWriteDstRegion(
371         G4_RegVar *       grfRange,
372         unsigned          regOff = 0,
373         unsigned          subregOff = 0);
374 
375     G4_DstRegRegion * createMHeaderInputDstRegion(
376         G4_RegVar *       grfRange,
377         unsigned          subregOff = 0);
378 
379     G4_DstRegRegion *
380     createMHeaderBlockOffsetDstRegion(G4_RegVar * grfRange);
381 
382 
383     G4_SrcRegRegion * createInputPayloadSrcRegion();
384 
385     G4_Declare * initMHeader(G4_Declare * mRangeDcl);
386 
387     G4_Declare * createAndInitMHeader(G4_RegVar * regVar);
388 
389     template <class REGION_TYPE>
390     G4_Declare * initMHeader(
391         G4_Declare *      mRangeDcl,
392         REGION_TYPE *     region,
393         G4_ExecSize       execSize);
394 
395     template <class REGION_TYPE>
396     G4_Declare * createAndInitMHeader(
397         REGION_TYPE *      region,
398         G4_ExecSize        execSize);
399 
400     void sendInSpilledRegVarPortions(
401         G4_Declare *      fillRangeDcl,
402         G4_Declare *      mRangeDcl,
403         unsigned          regOff,
404         unsigned          height,
405         unsigned          srcRegOff = 0);
406 
407     void sendOutSpilledRegVarPortions(
408         G4_Declare *      spillRangeDcl,
409         G4_Declare *      mRangeDcl,
410         unsigned          regOff,
411         unsigned          height,
412         unsigned          srcRegOff = 0);
413 
414     void initMWritePayload(
415         G4_Declare *      spillRangeDcl,
416         G4_Declare *      mRangeDcl,
417         unsigned          regOff,
418         unsigned          height
419     );
420 
421     void
422     initMWritePayload (
423         G4_Declare *      spillRangeDcl,
424         G4_Declare *      mRangeDcl,
425         G4_DstRegRegion * spilledRangeRegion,
426         G4_ExecSize       execSize,
427         unsigned          regOff = 0);
428 
429     static unsigned blockSendBlockSizeCode(unsigned regOff);
430 
431     unsigned scatterSendBlockSizeCode(unsigned regOff) const;
432 
433     G4_Imm * createSpillSendMsgDesc(
434         unsigned        regOff,
435         unsigned        height,
436         G4_ExecSize &   execSize,
437         G4_RegVar*      base = NULL);
438 
439     std::tuple<G4_Imm*, G4_ExecSize> createSpillSendMsgDesc(
440         G4_DstRegRegion * spilledRangeRegion,
441         G4_ExecSize     execSize);
442 
443     G4_INST * createAddFPInst(
444         G4_ExecSize       execSize,
445         G4_DstRegRegion * dst,
446         G4_Operand *      src
447     );
448 
449     G4_INST * createMovInst(
450         G4_ExecSize       execSize,
451         G4_DstRegRegion * dst,
452         G4_Operand *      src,
453         G4_Predicate *    predicate = NULL,
454         G4_InstOpts       options = InstOpt_WriteEnable
455     );
456 
457     G4_INST * createSendInst(
458         G4_ExecSize       execSize,
459         G4_DstRegRegion * postDst,
460         G4_SrcRegRegion * payload,
461         G4_Imm *          desc,
462         SFID              funcID,
463         bool              isWrite,
464         G4_InstOpts       option);
465 
466     bool shouldPreloadSpillRange(
467         G4_INST* instContext,
468         G4_BB* parentBB);
469 
470     void preloadSpillRange(
471         G4_Declare *      spillRangeDcl,
472         G4_Declare *      mRangeDcl,
473         G4_DstRegRegion * spilledRangeRegion,
474         G4_ExecSize       execSize);
475 
476     G4_INST * createSpillSendInstr(
477         G4_Declare *      spillRangeDcl,
478         G4_Declare *      mRangeDcl,
479         unsigned          regOff,
480         unsigned          height,
481         unsigned          spillOff);
482 
483     G4_INST *createSpillSendInstr (
484         G4_Declare *      spillRangeDcl,
485         G4_Declare *      mRangeDcl,
486         G4_DstRegRegion * spilledRangeRegion,
487         G4_ExecSize       execSize,
488         unsigned          option);
489 
490     G4_Imm *createFillSendMsgDesc (
491         unsigned          regOff,
492         unsigned          height,
493         G4_ExecSize &     execSize,
494         G4_RegVar* base = NULL);
495 
496     template <class REGION_TYPE>
497     G4_Imm* createFillSendMsgDesc(
498         REGION_TYPE* filledRangeRegion,
499         G4_ExecSize     execSize
500     );
501 
502     G4_INST * createFillSendInstr (
503         G4_Declare *      fillRangeDcl,
504         G4_Declare *      mRangeDcl,
505         unsigned          regOff,
506         unsigned          height,
507         unsigned          spillOff);
508 
509     G4_INST * createFillSendInstr(
510         G4_Declare *       fillRangeDcl,
511         G4_Declare *       mRangeDcl,
512         G4_SrcRegRegion *  filledRangeRegion,
513         G4_ExecSize        execSize);
514 
515     G4_SrcRegRegion* getLSCSpillFillHeader(
516         G4_Declare* mRangeDcl,
517         const G4_Declare *fp,
518         int offset);
519 
520     G4_INST* createLSCSpill(
521         G4_Declare* spillRangeDcl,
522         G4_Declare* mRangeDcl,
523         unsigned          regOff,
524         unsigned          height,
525         unsigned          spillOff);
526 
527     G4_INST* createLSCSpill(
528         G4_Declare* spillRangeDcl,
529         G4_Declare* mRangeDcl,
530         G4_DstRegRegion* spilledRangeRegion,
531         G4_ExecSize       execSize,
532         unsigned          option);
533 
534     G4_INST* createLSCFill(
535         G4_Declare* fillRangeDcl,
536         G4_Declare* mRangeDcl,
537         unsigned          regOff,
538         unsigned          height,
539         unsigned          spillOff);
540 
541     G4_INST* createLSCFill(
542         G4_Declare* fillRangeDcl,
543         G4_Declare* mRangeDcl,
544         G4_SrcRegRegion* filledRangeRegion,
545         G4_ExecSize        execSize);
546 
547     void replaceSpilledRange(
548         G4_Declare *      spillRangeDcl,
549         G4_DstRegRegion * spilledRegion,
550         G4_INST *         spilledInst,
551         uint32_t subregOff);
552 
553     void replaceFilledRange(
554         G4_Declare *      fillRangeDcl,
555         G4_SrcRegRegion * filledRegion,
556         G4_INST *         filledInst);
557 
558     void insertSpillRangeCode(
559         INST_LIST::iterator spilledInstIter,
560         G4_BB* bb
561     );
562 
563     INST_LIST::iterator insertSendFillRangeCode(
564         G4_SrcRegRegion *   filledRegion,
565         INST_LIST::iterator filledInstIter,
566         G4_BB* bb);
567 
568     void insertFillGRFRangeCode(
569         G4_SrcRegRegion *   filledRegion,
570         INST_LIST::iterator filledInstIter,
571         G4_BB* bb);
572 
573     void *allocMem (unsigned size) const;
574 
575     SpillManagerGRF(const SpillManagerGRF & other);
576 
577     bool useSplitSend() const;
578 
getHWordEncoding(int numHWord)579     int getHWordEncoding(int numHWord)
580     {
581         switch (numHWord)
582         {
583         case 1:
584             return 0;
585         case 2:
586             return 1;
587         case 4:
588             return 2;
589         case 8:
590             return 3;
591         default:
592             MUST_BE_TRUE(false, "only 1/2/4/8 HWords are supported");
593             return 0;
594         }
595     }
596 
getChMaskForSpill(int numHWord)597     ChannelMask getChMaskForSpill(int numHWord) const
598     {
599         switch (numHWord)
600         {
601         case 1:
602         case 2:
603             return ChannelMask::createFromAPI(CHANNEL_MASK_R);
604         case 4:
605             return ChannelMask::createFromAPI(CHANNEL_MASK_RG);
606         case 8:
607             return ChannelMask::createFromAPI(CHANNEL_MASK_RGBA);
608         default:
609             assert(false && "illegal spill size");
610             return ChannelMask::createFromAPI(CHANNEL_MASK_R);
611         }
612     }
613 
614     // Data
615     GlobalRA&                gra;
616     IR_Builder *             builder_;
617     unsigned                 varIdCount_;
618     unsigned                 latestImplicitVarIdCount_;
619     const LivenessAnalysis * lvInfo_;
620     LiveRange **             lrInfo_;
621     const LR_LIST *          spilledLRs_;
622     LSLR_LIST*               spilledLSLRs_;
623     unsigned *               spillRangeCount_;
624     unsigned *               fillRangeCount_;
625     unsigned *               tmpRangeCount_;
626     unsigned *               msgSpillRangeCount_;
627     unsigned *               msgFillRangeCount_;
628     unsigned *              addrSpillFillRangeCount_;
629     unsigned                 nextSpillOffset_;
630     unsigned                 iterationNo_;
631     unsigned                 bbId_ = UINT_MAX;
632     unsigned                 spillAreaOffset_;
633     bool                     doSpillSpaceCompression;
634 
635     bool                     failSafeSpill_;
636     unsigned                 spillRegStart_;
637     unsigned                 indrSpillRegStart_;
638     unsigned                 spillRegOffset_;
639     LSLR_LIST                activeLR_;
640     std::unordered_set<G4_DstRegRegion*> noRMWNeeded;
641 
642     const Interference *     spillIntf_;
643     vISA::Mem_Manager              mem_;
644 
645     // The number of GRF spill.
646     unsigned numGRFSpill = 0;
647 
648     // The number of GRF fill.
649     unsigned numGRFFill = 0;
650 
651     // The number of mov.
652     unsigned numGRFMove = 0;
653 
654     // CISA instruction id of current instruction
655     G4_INST* curInst;
656 
657     int globalScratchOffset;
658 
659     bool useScratchMsg_;
660     bool avoidDstSrcOverlap_;
661     // spilled declares that represent a scalar immediate (created due to encoding restrictions)
662     // We rematerialize the immediate value instead of spill/fill them
663     std::unordered_map<G4_Declare*, G4_Imm*> scalarImmSpill;
664 
665     VarReferences refs;
666 
667     // analysis pass to assist in spill/fill code gen
668     // currently it identifies scalar imm variables that should be re-mat
669     // later on we can add detection to avoid unncessary read-modify-write for spills
670     void runSpillAnalysis();
671 
672     bool checkUniqueDefAligned(G4_DstRegRegion* dst, G4_BB* defBB);
673     bool checkDefUseDomRel(G4_DstRegRegion* dst, G4_BB* bb);
674     void updateRMWNeeded();
675 
676     bool useLSCMsg = false;
677     bool useLscNonstackCall = false;
678 
headerNeeded()679     bool headerNeeded() const
680     {
681         bool needed = true;
682 
683         if (useScratchMsg_ && builder_->getPlatform() >= GENX_SKL)
684             needed = false;
685 
686         if (builder_->kernel.fg.getHasStackCalls() ||
687             builder_->kernel.fg.getIsStackCallFunc())
688             needed = false;
689 
690         if (useLSCMsg)
691             needed = false;
692 
693         return needed;
694     }
695 
696     // return true if offset for spill/fill message needs to be GRF-aligned
needGRFAlignedOffset()697     bool needGRFAlignedOffset() const
698     {
699         return useScratchMsg_ || useSplitSend();
700     }
701 }; // class SpillManagerGRF
702 
703    // Check if the destination region is discontiguous or not.
704    // A destination region is discontiguous if there are portions of the
705    // region that are not written and unaffected.
isDisContRegion(G4_DstRegRegion * region,unsigned execSize)706 static inline bool isDisContRegion(G4_DstRegRegion * region, unsigned execSize)
707 {
708     // If the horizontal stride is greater than 1, then it has gaps.
709     // NOTE: Horizontal stride of 0 is not allowed for destination regions.
710     return region->getHorzStride() != 1;
711 }
712 
713 // Check if the source region is discontiguous or not.
714 // A source region is discontiguous in there are portions of the region
715 // that are not read.
isDisContRegion(G4_SrcRegRegion * region,unsigned execSize)716 static inline bool isDisContRegion(G4_SrcRegRegion * region, unsigned execSize)
717 {
718     return region->getRegion()->isContiguous(execSize);
719 }
720 
721 
722 // Check if the region is partial or not, i.e does it read/write the
723 // whole segment.
724 template <class REGION_TYPE>
isPartialRegion(REGION_TYPE * region,unsigned execSize)725 static inline bool isPartialRegion(REGION_TYPE * region, unsigned execSize)
726 {
727     // If the region is discontiguous then it is partial.
728     if (isDisContRegion(region, execSize)) {
729         return true;
730     }
731     else
732     {
733         return false;
734     }
735 }
736 
737 G4_SrcRegRegion* getSpillFillHeader(IR_Builder& builder, G4_Declare* decl);
738 
739 // Class used to analyze spill/fill decisions
740 class SpillAnalysis
741 {
742 public:
743     SpillAnalysis() = default;
744     ~SpillAnalysis();
745 
746     void Dump(std::ostream& OS = std::cerr);
747     void DumpHistogram(std::ostream& OS = std::cerr);
748 
749     unsigned int GetDistance(G4_Declare* Dcl);
750     void LoadAugIntervals(DECLARE_LIST&, GlobalRA&);
751     void LoadDegree(G4_Declare* Dcl, unsigned int degree);
752 
SetLivenessAnalysis(LivenessAnalysis * L)753     void SetLivenessAnalysis(LivenessAnalysis* L) { LA = L; }
SetGraphColor(GraphColor * C)754     void SetGraphColor(GraphColor* C) { GC = C; }
SetSpillManager(SpillManagerGRF * S)755     void SetSpillManager(SpillManagerGRF* S) { SM = S; }
756 
757     void Clear();
758 
759     void Do(LivenessAnalysis* L, GraphColor* C, SpillManagerGRF* S);
760 
761 private:
762     VarReferences* Refs = nullptr;
763 
764     LivenessAnalysis* LA = nullptr;
765     GraphColor* GC = nullptr;
766     SpillManagerGRF* SM = nullptr;
767 
768     std::unordered_map<G4_Declare*, std::pair<G4_INST*, G4_INST*>> AugIntervals;
769     std::unordered_map<G4_Declare*, unsigned int> DclDegree;
770 
771     std::vector<G4_BB*> GetLiveBBs(G4_Declare*, std::unordered_map<G4_INST*, G4_BB*>&);
772     std::vector<G4_BB*> GetIntervalBBs(G4_INST* Start, G4_INST* End, std::unordered_map<G4_INST*, G4_BB*>& InstBBMap);
773 };
774 
775 } // vISA::
776 
777 #endif // __SPILLMANAGERGMRF_H__
778