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 /*========================== begin_copyright_notice ============================
10 
11 This file is distributed under the University of Illinois Open Source License.
12 See LICENSE.TXT for details.
13 
14 ============================= end_copyright_notice ===========================*/
15 
16 //===----------------------------------------------------------------------===//
17 //
18 // This file defines classes that make it really easy to deal with intrinsic
19 // functions with the isa/dyncast family of functions.  In particular, this
20 // allows you to do things like:
21 //
22 //     if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst))
23 //        ... MCI->getDest() ... MCI->getSource() ...
24 //
25 // All intrinsic function calls are instances of the call instruction, so these
26 // are all subclasses of the CallInst class.  Note that none of these classes
27 // has state or virtual methods, which is an important part of this gross/neat
28 // hack working.
29 //
30 //===----------------------------------------------------------------------===//
31 
32 #pragma once
33 
34 #include "common/LLVMWarningsPush.hpp"
35 #include "llvm/IR/Constants.h"
36 #include "llvm/IR/Function.h"
37 #include "llvm/IR/Instructions.h"
38 #include "llvm/IR/IRBuilder.h"
39 #include "llvm/IR/Module.h"
40 #include "common/LLVMWarningsPop.hpp"
41 #include "Compiler/CodeGenPublicEnums.h"
42 #include "common/EmUtils.h"
43 #include "common/Types.hpp"
44 #include "GenIntrinsics.h"
45 #include "Probe/Assertion.h"
46 
47 namespace llvm {
48 /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic
49 /// functions.  This allows the standard isa/dyncast/cast functionality to
50 /// work with calls to intrinsic functions.
51 class GenIntrinsicInst : public CallInst {
52     GenIntrinsicInst() = delete;
53     GenIntrinsicInst(const GenIntrinsicInst&) = delete;
54     void operator=(const GenIntrinsicInst&) = delete;
55 
56 protected:
valueToImm64(Value * cv)57     inline uint64_t valueToImm64(Value* cv) const
58     {
59         return cast<ConstantInt>(cv)->getZExtValue();
60     }
61 
62 public:
63     /// getIntrinsicID - Return the intrinsic ID of this intrinsic.
64     ///
getIntrinsicID()65     GenISAIntrinsic::ID getIntrinsicID() const {
66         return GenISAIntrinsic::getIntrinsicID(getCalledFunction());
67     }
68 
isGenIntrinsic(GenISAIntrinsic::ID intrinID)69     bool isGenIntrinsic(GenISAIntrinsic::ID intrinID) const {
70         return getIntrinsicID() == intrinID;
71     }
72 
73     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const CallInst * I)74     static inline bool classof(const CallInst *I) {
75         if (const Function *CF = I->getCalledFunction()) {
76             return (CF->getName().startswith(GenISAIntrinsic::getGenIntrinsicPrefix()));
77         }
78         return false;
79     }
classof(const Value * V)80     static inline bool classof(const Value *V) {
81         return isa<CallInst>(V) && classof(cast<CallInst>(V));
82     }
83 
getImm64Operand(unsigned idx)84     uint64_t getImm64Operand(unsigned idx) const {
85         IGC_ASSERT(isa<ConstantInt>(getOperand(idx)));
86         return valueToImm64(getOperand(idx));
87     }
88 };
89 
90 class RTWritIntrinsic : public GenIntrinsicInst {
91 protected:
getOperand(unsigned i)92     Value* getOperand(unsigned i) const { return GenIntrinsicInst::getOperand(i); }
setOperand(unsigned i,Value * v)93     void setOperand(unsigned i, Value* v) { return GenIntrinsicInst::setOperand(i, v); }
94 
95 public:
getSource0Alpha()96     inline Value* getSource0Alpha()     const { return getOperand(0); }
getOMask()97     inline Value* getOMask()            const { return getOperand(1); }
getPMask()98     inline Value* getPMask()            const { return getOperand(2); }
setPMask(Value * pmask)99     inline void setPMask(Value* pmask)        { setOperand(2, pmask); }
getRed()100     inline Value* getRed()              const { return getOperand(3); }
getGreen()101     inline Value* getGreen()            const { return getOperand(4); }
getBlue()102     inline Value* getBlue()             const { return getOperand(5); }
getAlpha()103     inline Value* getAlpha()            const { return getOperand(6); }
getDepth()104     inline Value* getDepth()            const { return getOperand(7); }
getStencil()105     inline Value* getStencil()          const { return getOperand(8); }
getRTIndex()106     inline Value* getRTIndex()          const { return getOperand(9); }
getBlendStateIndex()107     inline Value* getBlendStateIndex()  const { return getOperand(10); }
getSampleIndex()108     inline Value* getSampleIndex()      const { return getOperand(15); }
109 
isImmRTIndex()110     inline bool isImmRTIndex() const
111     { return llvm::isa<llvm::ConstantInt>(getRTIndex()); }
112 
getRTIndexImm()113     inline int getRTIndexImm()  const
114     { return (int)llvm::cast<llvm::ConstantInt>(getRTIndex())->getZExtValue(); }
115 
hasMask()116     inline bool hasMask()    const
117     {
118         return valueToImm64(getOperand(11)) != 0;
119     }
hasDepth()120     inline bool hasDepth()   const
121     {
122         return valueToImm64(getOperand(12)) != 0;
123     }
hasStencil()124     inline bool hasStencil() const
125     {
126         return valueToImm64(getOperand(13)) != 0;
127     }
perSample()128     inline bool perSample()  const
129     {
130         return valueToImm64(getOperand(14)) != 0;
131     }
132 
setPerSample()133     void setPerSample()
134     {
135         Value* btrue = ConstantInt::get(
136             Type::getInt1Ty(this->getParent()->getContext()), 1);
137         setOperand(14, btrue);
138     }
setSampleIndex(Value * v)139     void setSampleIndex(Value* v)       { setOperand(15, v); }
140 
141     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)142     static inline bool classof(const GenIntrinsicInst *I) {
143         switch (I->getIntrinsicID()) {
144         case GenISAIntrinsic::GenISA_RTWrite:
145             return true;
146         default: return false;
147         }
148     }
classof(const Value * V)149     static inline bool classof(const Value *V) {
150         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
151     }
152 };
153 
154 class RTDualBlendSourceIntrinsic : public GenIntrinsicInst {
155 protected:
getOperand(unsigned i)156     Value* getOperand(unsigned i) const { return GenIntrinsicInst::getOperand(i); }
setOperand(unsigned i,Value * v)157     void setOperand(unsigned i, Value* v) { return GenIntrinsicInst::setOperand(i, v); }
158 
159 public:
getSource0Alpha()160     inline Value* getSource0Alpha()     const { return nullptr; }
getOMask()161     inline Value* getOMask()            const { return getOperand(0); }
getPMask()162     inline Value* getPMask()            const { return getOperand(1); }
setPMask(Value * mask)163     inline void setPMask(Value* mask)         { setOperand(1, mask);  }
getRed0()164     inline Value* getRed0()             const { return getOperand(2); }
getGreen0()165     inline Value* getGreen0()           const { return getOperand(3); }
getBlue0()166     inline Value* getBlue0()            const { return getOperand(4); }
getAlpha0()167     inline Value* getAlpha0()           const { return getOperand(5); }
getRed1()168     inline Value* getRed1()             const { return getOperand(6); }
getGreen1()169     inline Value* getGreen1()           const { return getOperand(7); }
getBlue1()170     inline Value* getBlue1()            const { return getOperand(8); }
getAlpha1()171     inline Value* getAlpha1()           const { return getOperand(9); }
getDepth()172     inline Value* getDepth()            const { return getOperand(10); }
getStencil()173     inline Value* getStencil()          const { return getOperand(11); }
getRTIndex()174     inline Value* getRTIndex()          const { return getOperand(12); }
getSampleIndex()175     inline Value* getSampleIndex()      const { return getOperand(17); }
176 
getRTIndexImm()177     inline int getRTIndexImm()  const
178     { return (int)llvm::cast<llvm::ConstantInt>(getRTIndex())->getZExtValue(); }
179 
hasMask()180     inline bool hasMask()    const
181     {
182         return valueToImm64(getOperand(13)) != 0;
183     }
hasDepth()184     inline bool hasDepth()   const
185     {
186         return valueToImm64(getOperand(14)) != 0;
187     }
hasStencil()188     inline bool hasStencil() const
189     {
190         return valueToImm64(getOperand(15)) != 0;
191     }
perSample()192     inline bool perSample()  const
193     {
194         return valueToImm64(getOperand(16)) != 0;
195     }
196 
setPerSample()197     void setPerSample()
198     {
199         Value* btrue = ConstantInt::get(
200             Type::getInt1Ty(this->getParent()->getContext()), 1);
201         setOperand(16, btrue);
202     }
setSampleIndex(Value * v)203     void setSampleIndex(Value* v)       { setOperand(17, v); }
204 
classof(const GenIntrinsicInst * I)205     static inline bool classof(const GenIntrinsicInst *I) {
206         switch (I->getIntrinsicID()) {
207         case GenISAIntrinsic::GenISA_RTDualBlendSource:
208             return true;
209         default: return false;
210         }
211     }
classof(const Value * V)212     static inline bool classof(const Value *V) {
213         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
214     }
215 };
216 
217 
218 class SamplerGatherIntrinsic : public GenIntrinsicInst {
219 public:
hasRef()220     bool hasRef() const
221     {
222         switch (getIntrinsicID())
223         {
224         case GenISAIntrinsic::GenISA_gather4Cptr:
225         case GenISAIntrinsic::GenISA_gather4POCptr:
226             return true;
227         default:
228             break;
229         }
230         return false;
231     }
232 
233 
getTextureIndex()234     inline unsigned int getTextureIndex() const { return getNumOperands() - 7; }
getSamplerIndex()235     inline unsigned int getSamplerIndex() const { return getNumOperands() - 6; }
getTextureValue()236     inline Value* getTextureValue() const { return getOperand(getTextureIndex()); }
getSamplerValue()237     inline Value* getSamplerValue() const { return getOperand(getSamplerIndex()); }
238 
classof(const GenIntrinsicInst * I)239     static inline bool classof(const GenIntrinsicInst *I) {
240         switch(I->getIntrinsicID()) {
241         case GenISAIntrinsic::GenISA_gather4ptr:
242         case GenISAIntrinsic::GenISA_gather4Cptr:
243         case GenISAIntrinsic::GenISA_gather4POptr:
244         case GenISAIntrinsic::GenISA_gather4POCptr:
245             return true;
246         default: return false;
247         }
248     }
249 
classof(const Value * V)250     static inline bool classof(const Value *V) {
251         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
252     }
253 };
254 
255 class InfoIntrinsic : public GenIntrinsicInst {
256 public:
classof(const GenIntrinsicInst * I)257     static inline bool classof(const GenIntrinsicInst *I) {
258         switch (I->getIntrinsicID()) {
259         case GenISAIntrinsic::GenISA_sampleinfoptr:
260         case GenISAIntrinsic::GenISA_resinfoptr:
261             return true;
262         default: return false;
263         }
264     }
265 
classof(const Value * V)266     static inline bool classof(const Value *V) {
267         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
268     }
269 };
270 
271 class SamplerLoadIntrinsic : public GenIntrinsicInst {
272 public:
getTextureIndex()273     inline unsigned int getTextureIndex() const { return getNumOperands() - 5; }
getTextureValue()274     inline Value* getTextureValue() const { return getOperand(getTextureIndex()); }
275 
classof(const GenIntrinsicInst * I)276     static inline bool classof(const GenIntrinsicInst *I) {
277         switch(I->getIntrinsicID()) {
278         case GenISAIntrinsic::GenISA_ldptr:
279         case GenISAIntrinsic::GenISA_ldmsptr:
280         case GenISAIntrinsic::GenISA_ldmcsptr:
281             return true;
282         default: return false;
283         }
284     }
285 
classof(const Value * V)286     static inline bool classof(const Value *V) {
287         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
288     }
289 };
290 
291 class LdMSIntrinsic : public SamplerLoadIntrinsic {
292 public:
getImmOffset(unsigned int i)293     inline Value* getImmOffset(unsigned int i)
294     {
295         return getOperand(getNumArgOperands() - 3 + i);
296     }
setImmOffset(unsigned int i,Value * val)297     inline void setImmOffset(unsigned int i, Value* val)
298     {
299         return setOperand(getNumArgOperands() - 3 + i, val);
300     }
getCoordinate(unsigned int i)301     inline Value* getCoordinate(unsigned int i)
302     {
303         return getOperand(getNumArgOperands() - 8 + i);
304     }
setCoordinate(unsigned int i,Value * val)305     inline void setCoordinate(unsigned int i, Value* val)
306     {
307         return setOperand(getNumArgOperands() - 8 + i, val);
308     }
classof(const GenIntrinsicInst * I)309     static inline bool classof(const GenIntrinsicInst *I) {
310         switch(I->getIntrinsicID()) {
311         case GenISAIntrinsic::GenISA_ldmsptr:
312             return true;
313         default: return false;
314         }
315     }
316 
classof(const Value * V)317     static inline bool classof(const Value *V) {
318         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
319     }
320 };
321 
322 
323 class LdmcsInstrinsic : public SamplerLoadIntrinsic
324 {
325 public:
classof(const GenIntrinsicInst * I)326     static inline bool classof(const GenIntrinsicInst *I) {
327         switch(I->getIntrinsicID()) {
328         case GenISAIntrinsic::GenISA_ldmcsptr:
329             return true;
330         default: return false;
331         }
332     }
333 
classof(const Value * V)334     static inline bool classof(const Value *V) {
335         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
336     }
337 };
338 
339 class LdmsInstrinsic : public SamplerLoadIntrinsic
340 {
341 public:
classof(const GenIntrinsicInst * I)342     static inline bool classof(const GenIntrinsicInst *I) {
343         switch(I->getIntrinsicID()) {
344         case GenISAIntrinsic::GenISA_ldmsptr:
345             return true;
346         default: return false;
347         }
348     }
getNumMcsOperands()349     unsigned int getNumMcsOperands()
350     {
351         return 2;
352     }
getMcsOperand(unsigned int i)353     Value* getMcsOperand(unsigned int i) { return getOperand(i + 1); }
getSampleIndexValue()354     Value* getSampleIndexValue() { return getOperand(0); }
classof(const Value * V)355     static inline bool classof(const Value *V) {
356         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
357     }
358 };
359 
360 class SampleIntrinsic : public GenIntrinsicInst {
361 public:
hasRef()362     bool hasRef() const
363     {
364         switch (getIntrinsicID())
365         {
366         case GenISAIntrinsic::GenISA_sampleCptr:
367         case GenISAIntrinsic::GenISA_sampleDCptr:
368         case GenISAIntrinsic::GenISA_sampleLCptr:
369         case GenISAIntrinsic::GenISA_sampleBCptr:
370             return true;
371         default:
372             break;
373         }
374         return false;
375     }
376 
hasBias()377     bool hasBias() const
378     {
379         switch (getIntrinsicID())
380         {
381         case GenISAIntrinsic::GenISA_sampleBptr:
382         case GenISAIntrinsic::GenISA_sampleBCptr:
383             return true;
384         default:
385             break;
386         }
387         return false;
388     }
hasLod()389     bool hasLod() const
390     {
391         switch (getIntrinsicID())
392         {
393         case GenISAIntrinsic::GenISA_sampleLptr:
394         case GenISAIntrinsic::GenISA_sampleLCptr:
395             return true;
396         default:
397             break;
398         }
399         return false;
400     }
401 
getSamplerValue()402     inline Value* getSamplerValue() const
403     {
404         unsigned int index = getSamplerIndex();
405         return getOperand(index);
406     }
407 
getTextureValue()408     inline Value* getTextureValue() const
409     {
410         unsigned int index = getTextureIndex();
411         return getOperand(index);
412     }
413 
getTextureIndex()414     inline unsigned int getTextureIndex() const
415     {
416         unsigned int index = getNumOperands() - 6;
417         if (IsLODInst())
418         {
419             index = getNumOperands() - 3;
420         }
421 
422         return index;
423     }
424 
getSamplerIndex()425     inline int getSamplerIndex() const
426     {
427         unsigned int index = getNumOperands() - 5;
428         if(IsLODInst())
429         {
430             index = getNumOperands() - 2;
431         }
432         return index;
433     }
434 
IsLODInst()435     inline bool IsLODInst() const
436     {
437         return getIntrinsicID() == GenISAIntrinsic::GenISA_lodptr;
438     }
439 
440 
ZeroLOD()441     bool ZeroLOD() const
442     {
443         if(getIntrinsicID() == GenISAIntrinsic::GenISA_sampleLptr)
444         {
445             if(ConstantFP* lod = dyn_cast<ConstantFP>(getOperand(0)))
446             {
447                 return lod->isZero();
448             }
449         }
450         else if(getIntrinsicID() == GenISAIntrinsic::GenISA_sampleLCptr)
451         {
452             if(ConstantFP* lod = dyn_cast<ConstantFP>(getOperand(1)))
453             {
454                 return lod->isZero();
455             }
456         }
457         return false;
458     }
459 
IsDerivative()460     bool IsDerivative() const
461     {
462         switch(getIntrinsicID())
463         {
464         case GenISAIntrinsic::GenISA_sampleptr:
465         case GenISAIntrinsic::GenISA_sampleKillPix:
466         case GenISAIntrinsic::GenISA_sampleBptr:
467         case GenISAIntrinsic::GenISA_sampleCptr:
468         case GenISAIntrinsic::GenISA_sampleBCptr:
469         case GenISAIntrinsic::GenISA_lodptr:
470             return true;
471         default:
472             break;
473         }
474         return false;
475     }
476 
477     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)478     static inline bool classof(const GenIntrinsicInst *I) {
479         switch(I->getIntrinsicID()) {
480         case GenISAIntrinsic::GenISA_sampleptr:
481         case GenISAIntrinsic::GenISA_sampleBptr:
482         case GenISAIntrinsic::GenISA_sampleCptr:
483         case GenISAIntrinsic::GenISA_sampleDptr:
484         case GenISAIntrinsic::GenISA_sampleDCptr:
485         case GenISAIntrinsic::GenISA_sampleLptr:
486         case GenISAIntrinsic::GenISA_sampleLCptr:
487         case GenISAIntrinsic::GenISA_sampleBCptr:
488         case GenISAIntrinsic::GenISA_lodptr:
489         case GenISAIntrinsic::GenISA_sampleKillPix:
490             return true;
491         default: return false;
492         }
493     }
494 
classof(const Value * V)495     static inline bool classof(const Value *V) {
496         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
497     }
498 
499 };
500 
501 class LdRawIntrinsic : public GenIntrinsicInst {
502 public:
503     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)504     static inline bool classof(const GenIntrinsicInst *I) {
505         GenISAIntrinsic::ID ID = I->getIntrinsicID();
506         if(ID == GenISAIntrinsic::GenISA_ldraw_indexed ||
507             ID == GenISAIntrinsic::GenISA_ldrawvector_indexed)
508         {
509             return true;
510         }
511         return false;
512     }
513 
classof(const Value * V)514     static inline bool classof(const Value *V) {
515         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
516     }
getOffsetValue()517     inline Value* getOffsetValue() const
518     {
519         return getOperand(1);
520     }
getResourceValue()521     inline Value* getResourceValue() const{
522         return getOperand(0);
523     }
getAlignmentValue()524     inline Value* getAlignmentValue() const {
525         return getOperand(2);
526     }
getAlignment()527     inline unsigned int getAlignment() const {
528         return static_cast<unsigned int>(cast<ConstantInt>(getAlignmentValue())->getZExtValue());
529     }
isVolatile()530     inline bool isVolatile() const {
531         IGC_ASSERT(isa<ConstantInt>(getOperand(3)));
532         ConstantInt* val = dyn_cast<ConstantInt>(getOperand(3));
533         const bool isVolatile = val ? val->getZExtValue() : false;
534         return isVolatile;
535     }
536 
537 
setAlignment(unsigned int alignment)538     inline void setAlignment(unsigned int alignment)
539     {
540         Value* newAlignment = ConstantInt::get(getOperand(2)->getType(), alignment);
541         setOperand(2, newAlignment);
542     }
543 
setOffsetValue(Value * V)544     inline void setOffsetValue(Value* V){
545         setOperand(1, V);
546     }
547 };
548 
549 class StoreRawIntrinsic : public GenIntrinsicInst {
550 public:
551     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)552     static inline bool classof(const GenIntrinsicInst *I) {
553         GenISAIntrinsic::ID ID = I->getIntrinsicID();
554         if (ID == GenISAIntrinsic::GenISA_storeraw_indexed ||
555             ID == GenISAIntrinsic::GenISA_storerawvector_indexed)
556         {
557             return true;
558         }
559         return false;
560     }
561 
classof(const Value * V)562     static inline bool classof(const Value *V) {
563         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
564     }
getAlignmentValue()565     inline Value* getAlignmentValue() const {
566         return getOperand(3);
567     }
getOffsetValue()568     inline Value* getOffsetValue() const
569     {
570         return getOperand(1);
571     }
getResourceValue()572     inline Value* getResourceValue() const {
573         return getOperand(0);
574     }
getStoreValue()575     inline Value* getStoreValue() const {
576         return getOperand(2);
577     }
getAlignment()578     inline unsigned int getAlignment() const {
579         IGC_ASSERT(isa<ConstantInt>(getAlignmentValue()));
580         ConstantInt* val = dyn_cast<ConstantInt>(getAlignmentValue());
581         const unsigned int alignment = val ? int_cast<unsigned int>(val->getZExtValue()) : 1;
582         return alignment;
583     }
isVolatile()584     inline bool isVolatile() const {
585         IGC_ASSERT(isa<ConstantInt>(getOperand(4)));
586         ConstantInt* val = dyn_cast<ConstantInt>(getOperand(4));
587         const bool isVolatile = val ? val->getZExtValue() : false;
588         return isVolatile;
589     }
590 
setOffsetValue(Value * V)591     inline void setOffsetValue(Value* V) {
592         setOperand(1, V);
593     }
setAlignment(unsigned int alignment)594     inline void setAlignment(unsigned int alignment)
595     {
596         Value* newAlignment = ConstantInt::get(getOperand(3)->getType(), alignment);
597         setOperand(3, newAlignment);
598     }
599 };
600 
601 class AtomicRawIntrinsic : public GenIntrinsicInst {
602 public:
603     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)604     static inline bool classof(const GenIntrinsicInst *I) {
605         GenISAIntrinsic::ID ID = I->getIntrinsicID();
606         if (ID == GenISAIntrinsic::GenISA_intatomicraw ||
607             ID == GenISAIntrinsic::GenISA_intatomicrawA64 ||
608             ID == GenISAIntrinsic::GenISA_floatatomicraw ||
609             ID == GenISAIntrinsic::GenISA_floatatomicrawA64 ||
610             ID == GenISAIntrinsic::GenISA_icmpxchgatomicraw ||
611             ID == GenISAIntrinsic::GenISA_icmpxchgatomicrawA64 ||
612             ID == GenISAIntrinsic::GenISA_fcmpxchgatomicraw ||
613             ID == GenISAIntrinsic::GenISA_fcmpxchgatomicrawA64)
614         {
615             return true;
616         }
617         return false;
618     }
619 
classof(const Value * V)620     static inline bool classof(const Value *V) {
621         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
622     }
623 
getResourceValue()624     inline Value* getResourceValue() const {
625         return getOperand(0);
626     }
627 
getAtomicOp()628     inline IGC::AtomicOp getAtomicOp() const {
629         GenISAIntrinsic::ID ID = getIntrinsicID();
630         switch (ID)
631         {
632         case GenISAIntrinsic::GenISA_intatomicraw:
633         case GenISAIntrinsic::GenISA_intatomicrawA64:
634         case GenISAIntrinsic::GenISA_floatatomicraw:
635         case GenISAIntrinsic::GenISA_floatatomicrawA64:
636             return static_cast<IGC::AtomicOp>(getImm64Operand(3));
637         case GenISAIntrinsic::GenISA_icmpxchgatomicraw:
638             return IGC::EATOMIC_CMPXCHG;
639         case GenISAIntrinsic::GenISA_icmpxchgatomicrawA64:
640             return IGC::EATOMIC_CMPXCHG64;
641         case GenISAIntrinsic::GenISA_fcmpxchgatomicraw:
642         case GenISAIntrinsic::GenISA_fcmpxchgatomicrawA64:
643             return IGC::EATOMIC_FCMPWR;
644         default:
645             IGC_ASSERT_MESSAGE(false, "Unexpected atomic raw intrinisc!");
646         }
647         return IGC::EATOMIC_UNDEF;
648     }
649 };
650 
651 class AtomicStructuredIntrinsic : public GenIntrinsicInst {
652 public:
653     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)654     static inline bool classof(const GenIntrinsicInst *I) {
655         GenISAIntrinsic::ID ID = I->getIntrinsicID();
656         if (ID == GenISAIntrinsic::GenISA_dwordatomicstructured ||
657             ID == GenISAIntrinsic::GenISA_floatatomicstructured ||
658             ID == GenISAIntrinsic::GenISA_cmpxchgatomicstructured ||
659             ID == GenISAIntrinsic::GenISA_fcmpxchgatomicstructured)
660         {
661             return true;
662         }
663         return false;
664     }
665 
classof(const Value * V)666     static inline bool classof(const Value *V) {
667         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
668     }
669 
getResourceValue()670     inline Value* getResourceValue() const {
671         return getOperand(0);
672     }
673 
getArrayIdx()674     inline Value* getArrayIdx() const {
675         return getOperand(1);
676     }
677 
setOffsetValue(Value * V)678     inline void setOffsetValue(Value* V) {
679         setOperand(1, V);
680     }
681 };
682 
683 class AtomicTypedIntrinsic : public GenIntrinsicInst {
684 public:
685     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)686     static inline bool classof(const GenIntrinsicInst *I) {
687         GenISAIntrinsic::ID ID = I->getIntrinsicID();
688         if (ID == GenISAIntrinsic::GenISA_intatomictyped ||
689             ID == GenISAIntrinsic::GenISA_icmpxchgatomictyped )
690         {
691             return true;
692         }
693         return false;
694     }
695 
classof(const Value * V)696     static inline bool classof(const Value *V) {
697         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
698     }
699 
getResourceValue()700     inline Value* getResourceValue() const {
701         return getOperand(0);
702     }
703 };
704 
705 class AtomicCounterIntrinsic : public GenIntrinsicInst {
706 public:
707     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)708     static inline bool classof(const GenIntrinsicInst *I) {
709         GenISAIntrinsic::ID ID = I->getIntrinsicID();
710         if (ID == GenISAIntrinsic::GenISA_atomiccounterinc ||
711             ID == GenISAIntrinsic::GenISA_atomiccounterpredec)
712         {
713             return true;
714         }
715         return false;
716     }
717 
classof(const Value * V)718     static inline bool classof(const Value *V) {
719         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
720     }
721 
getResourceValue()722     inline Value* getResourceValue() const {
723         return getOperand(0);
724     }
725 };
726 
727 class SGVIntrinsic : public GenIntrinsicInst {
728 public:
729     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)730     static inline bool classof(const GenIntrinsicInst *I) {
731         GenISAIntrinsic::ID ID = I->getIntrinsicID();
732         if(ID == GenISAIntrinsic::GenISA_DCL_GSsystemValue ||
733             ID == GenISAIntrinsic::GenISA_DCL_SystemValue)
734         {
735             return true;
736         }
737         return false;
738     }
739 
classof(const Value * V)740     static inline bool classof(const Value *V) {
741         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
742     }
getUsage()743     inline IGC::SGVUsage getUsage() const
744     {
745         IGC::SGVUsage usage;
746         if(getIntrinsicID() == GenISAIntrinsic::GenISA_DCL_GSsystemValue)
747         {
748             // TODO: deprecate usage of GSSystemValue intrinsic
749             usage = static_cast<IGC::SGVUsage>(
750                 llvm::cast<llvm::ConstantInt>(getOperand(1))->getZExtValue());
751         }
752         else
753         {
754             usage = static_cast<IGC::SGVUsage>(
755                 llvm::cast<llvm::ConstantInt>(getOperand(0))->getZExtValue());
756         }
757         return usage;
758     }
759 };
760 
761 class WavePrefixIntrinsic : public GenIntrinsicInst
762 {
763 public:
getSrc()764     Value  *getSrc() const { return getOperand(0); }
getOpKind()765     IGC::WaveOps getOpKind() const
766     {
767         return static_cast<IGC::WaveOps>(getImm64Operand(1));
768     }
isInclusiveScan()769     bool isInclusiveScan() const
770     {
771         return getImm64Operand(2) != 0;
772     }
getMask()773     Value *getMask() const { return getOperand(3); }
774 
775     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)776     static inline bool classof(const GenIntrinsicInst *I) {
777         return I->getIntrinsicID() == GenISAIntrinsic::GenISA_WavePrefix;
778     }
classof(const Value * V)779     static inline bool classof(const Value *V) {
780         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
781     }
782 };
783 
784 class QuadPrefixIntrinsic : public GenIntrinsicInst
785 {
786 public:
getSrc()787     Value  *getSrc() const { return getOperand(0); }
getOpKind()788     IGC::WaveOps getOpKind() const
789     {
790         return static_cast<IGC::WaveOps>(getImm64Operand(1));
791     }
isInclusiveScan()792     bool isInclusiveScan() const
793     {
794         return getImm64Operand(2) != 0;
795     }
796 
797     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)798     static inline bool classof(const GenIntrinsicInst *I) {
799         return I->getIntrinsicID() == GenISAIntrinsic::GenISA_QuadPrefix;
800     }
classof(const Value * V)801     static inline bool classof(const Value *V) {
802         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
803     }
804 };
805 
806 
807 class StaticConstantPatchIntrinsic : public GenIntrinsicInst {
808 public:
809     // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const GenIntrinsicInst * I)810     static inline bool classof(const GenIntrinsicInst* I) {
811         GenISAIntrinsic::ID ID = I->getIntrinsicID();
812         return ID == GenISAIntrinsic::GenISA_staticConstantPatchValue;
813     }
814 
classof(const Value * V)815     static inline bool classof(const Value* V) {
816         return isa<GenIntrinsicInst>(V) && classof(cast<GenIntrinsicInst>(V));
817     }
818 
getPatchName()819     llvm::StringRef getPatchName() const
820     {
821         llvm::ConstantDataArray* constantVal = llvm::dyn_cast<llvm::ConstantDataArray>(getOperand(0));
822         return constantVal->getAsString();
823     }
824 };
825 
826 template <class X, class Y>
isa(const Y & Val,GenISAIntrinsic::ID id)827 inline bool isa(const Y &Val, GenISAIntrinsic::ID id)
828 {
829     if (isa<X>(Val))
830     {
831         X* r = cast<X>(Val);
832         if (r->getIntrinsicID() == id)
833         {
834             return true;
835         }
836     }
837     return false;
838 }
839 
840 template <class X, class Y>
841 inline typename cast_retty<X, Y *>::ret_type
dyn_cast(Y * Val,GenISAIntrinsic::ID id)842 dyn_cast(Y *Val, GenISAIntrinsic::ID id)
843 {
844     if (isa<X>(Val))
845     {
846         X* r = cast<X>(Val);
847         if (r->getIntrinsicID() == id)
848         {
849             return r;
850         }
851     }
852     return nullptr;
853 }
854 
855 template <class X, class Y>
856 inline typename cast_retty<X, Y>::ret_type
dyn_cast(Y & Val,GenISAIntrinsic::ID id)857 dyn_cast(Y &Val, GenISAIntrinsic::ID id)
858 {
859     if (isa<X>(Val))
860     {
861         typename cast_retty<X, Y>::ret_type r = cast<X>(Val);
862         if (r->getIntrinsicID() == id)
863         {
864             return r;
865         }
866     }
867     return nullptr;
868 }
869 
870 // TODO: add more classes to make our intrinsics easier to use
871 
872 }
873