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