1//===- llvm/CodeGen/GlobalISel/GenericMachineInstrs.h -----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// Declares convenience wrapper classes for interpreting MachineInstr instances
10/// as specific generic operations.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
15#define LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
16
17#include "llvm/IR/Instructions.h"
18#include "llvm/CodeGen/MachineInstr.h"
19#include "llvm/CodeGen/MachineMemOperand.h"
20#include "llvm/CodeGen/TargetOpcodes.h"
21#include "llvm/Support/Casting.h"
22
23namespace llvm {
24
25/// A base class for all GenericMachineInstrs.
26class GenericMachineInstr : public MachineInstr {
27public:
28 GenericMachineInstr() = delete;
29
30 /// Access the Idx'th operand as a register and return it.
31 /// This assumes that the Idx'th operand is a Register type.
32 Register getReg(unsigned Idx) const { return getOperand(i: Idx).getReg(); }
33
34 static bool classof(const MachineInstr *MI) {
35 return isPreISelGenericOpcode(Opcode: MI->getOpcode());
36 }
37};
38
39/// Provides common memory operand functionality.
40class GMemOperation : public GenericMachineInstr {
41public:
42 /// Get the MachineMemOperand on this instruction.
43 MachineMemOperand &getMMO() const { return **memoperands_begin(); }
44
45 /// Returns true if the attached MachineMemOperand has the atomic flag set.
46 bool isAtomic() const { return getMMO().isAtomic(); }
47 /// Returns true if the attached MachineMemOpeand as the volatile flag set.
48 bool isVolatile() const { return getMMO().isVolatile(); }
49 /// Returns true if the memory operation is neither atomic or volatile.
50 bool isSimple() const { return !isAtomic() && !isVolatile(); }
51 /// Returns true if this memory operation doesn't have any ordering
52 /// constraints other than normal aliasing. Volatile and (ordered) atomic
53 /// memory operations can't be reordered.
54 bool isUnordered() const { return getMMO().isUnordered(); }
55
56 /// Returns the size in bytes of the memory access.
57 LocationSize getMemSize() const { return getMMO().getSize(); }
58 /// Returns the size in bits of the memory access.
59 LocationSize getMemSizeInBits() const { return getMMO().getSizeInBits(); }
60
61 static bool classof(const MachineInstr *MI) {
62 return GenericMachineInstr::classof(MI) && MI->hasOneMemOperand();
63 }
64};
65
66/// Represents any type of generic load or store.
67/// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD.
68class GLoadStore : public GMemOperation {
69public:
70 /// Get the source register of the pointer value.
71 Register getPointerReg() const { return getOperand(i: 1).getReg(); }
72
73 static bool classof(const MachineInstr *MI) {
74 switch (MI->getOpcode()) {
75 case TargetOpcode::G_LOAD:
76 case TargetOpcode::G_STORE:
77 case TargetOpcode::G_ZEXTLOAD:
78 case TargetOpcode::G_SEXTLOAD:
79 return true;
80 default:
81 return false;
82 }
83 }
84};
85
86/// Represents indexed loads. These are different enough from regular loads
87/// that they get their own class. Including them in GAnyLoad would probably
88/// make a footgun for someone.
89class GIndexedLoad : public GMemOperation {
90public:
91 /// Get the definition register of the loaded value.
92 Register getDstReg() const { return getOperand(i: 0).getReg(); }
93 /// Get the def register of the writeback value.
94 Register getWritebackReg() const { return getOperand(i: 1).getReg(); }
95 /// Get the base register of the pointer value.
96 Register getBaseReg() const { return getOperand(i: 2).getReg(); }
97 /// Get the offset register of the pointer value.
98 Register getOffsetReg() const { return getOperand(i: 3).getReg(); }
99
100 bool isPre() const { return getOperand(i: 4).getImm() == 1; }
101 bool isPost() const { return !isPre(); }
102
103 static bool classof(const MachineInstr *MI) {
104 return MI->getOpcode() == TargetOpcode::G_INDEXED_LOAD;
105 }
106};
107
108/// Represents a G_INDEX_ZEXTLOAD/G_INDEXED_SEXTLOAD.
109class GIndexedExtLoad : public GIndexedLoad {
110public:
111 static bool classof(const MachineInstr *MI) {
112 return MI->getOpcode() == TargetOpcode::G_INDEXED_SEXTLOAD ||
113 MI->getOpcode() == TargetOpcode::G_INDEXED_ZEXTLOAD;
114 }
115};
116
117/// Represents either G_INDEXED_LOAD, G_INDEXED_ZEXTLOAD or G_INDEXED_SEXTLOAD.
118class GIndexedAnyExtLoad : public GIndexedLoad {
119public:
120 static bool classof(const MachineInstr *MI) {
121 switch (MI->getOpcode()) {
122 case TargetOpcode::G_INDEXED_LOAD:
123 case TargetOpcode::G_INDEXED_ZEXTLOAD:
124 case TargetOpcode::G_INDEXED_SEXTLOAD:
125 return true;
126 default:
127 return false;
128 }
129 }
130};
131
132/// Represents a G_ZEXTLOAD.
133class GIndexedZExtLoad : GIndexedExtLoad {
134public:
135 static bool classof(const MachineInstr *MI) {
136 return MI->getOpcode() == TargetOpcode::G_INDEXED_ZEXTLOAD;
137 }
138};
139
140/// Represents a G_SEXTLOAD.
141class GIndexedSExtLoad : GIndexedExtLoad {
142public:
143 static bool classof(const MachineInstr *MI) {
144 return MI->getOpcode() == TargetOpcode::G_INDEXED_SEXTLOAD;
145 }
146};
147
148/// Represents indexed stores.
149class GIndexedStore : public GMemOperation {
150public:
151 /// Get the def register of the writeback value.
152 Register getWritebackReg() const { return getOperand(i: 0).getReg(); }
153 /// Get the stored value register.
154 Register getValueReg() const { return getOperand(i: 1).getReg(); }
155 /// Get the base register of the pointer value.
156 Register getBaseReg() const { return getOperand(i: 2).getReg(); }
157 /// Get the offset register of the pointer value.
158 Register getOffsetReg() const { return getOperand(i: 3).getReg(); }
159
160 bool isPre() const { return getOperand(i: 4).getImm() == 1; }
161 bool isPost() const { return !isPre(); }
162
163 static bool classof(const MachineInstr *MI) {
164 return MI->getOpcode() == TargetOpcode::G_INDEXED_STORE;
165 }
166};
167
168/// Represents any generic load, including sign/zero extending variants.
169class GAnyLoad : public GLoadStore {
170public:
171 /// Get the definition register of the loaded value.
172 Register getDstReg() const { return getOperand(i: 0).getReg(); }
173
174 static bool classof(const MachineInstr *MI) {
175 switch (MI->getOpcode()) {
176 case TargetOpcode::G_LOAD:
177 case TargetOpcode::G_ZEXTLOAD:
178 case TargetOpcode::G_SEXTLOAD:
179 return true;
180 default:
181 return false;
182 }
183 }
184};
185
186/// Represents a G_LOAD.
187class GLoad : public GAnyLoad {
188public:
189 static bool classof(const MachineInstr *MI) {
190 return MI->getOpcode() == TargetOpcode::G_LOAD;
191 }
192};
193
194/// Represents either a G_SEXTLOAD or G_ZEXTLOAD.
195class GExtLoad : public GAnyLoad {
196public:
197 static bool classof(const MachineInstr *MI) {
198 return MI->getOpcode() == TargetOpcode::G_SEXTLOAD ||
199 MI->getOpcode() == TargetOpcode::G_ZEXTLOAD;
200 }
201};
202
203/// Represents a G_SEXTLOAD.
204class GSExtLoad : public GExtLoad {
205public:
206 static bool classof(const MachineInstr *MI) {
207 return MI->getOpcode() == TargetOpcode::G_SEXTLOAD;
208 }
209};
210
211/// Represents a G_ZEXTLOAD.
212class GZExtLoad : public GExtLoad {
213public:
214 static bool classof(const MachineInstr *MI) {
215 return MI->getOpcode() == TargetOpcode::G_ZEXTLOAD;
216 }
217};
218
219/// Represents a G_STORE.
220class GStore : public GLoadStore {
221public:
222 /// Get the stored value register.
223 Register getValueReg() const { return getOperand(i: 0).getReg(); }
224
225 static bool classof(const MachineInstr *MI) {
226 return MI->getOpcode() == TargetOpcode::G_STORE;
227 }
228};
229
230/// Represents a G_UNMERGE_VALUES.
231class GUnmerge : public GenericMachineInstr {
232public:
233 /// Returns the number of def registers.
234 unsigned getNumDefs() const { return getNumOperands() - 1; }
235 /// Get the unmerge source register.
236 Register getSourceReg() const { return getOperand(i: getNumDefs()).getReg(); }
237
238 static bool classof(const MachineInstr *MI) {
239 return MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES;
240 }
241};
242
243/// Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES.
244/// All these have the common property of generating a single value from
245/// multiple sources.
246class GMergeLikeInstr : public GenericMachineInstr {
247public:
248 /// Returns the number of source registers.
249 unsigned getNumSources() const { return getNumOperands() - 1; }
250 /// Returns the I'th source register.
251 Register getSourceReg(unsigned I) const { return getReg(Idx: I + 1); }
252
253 static bool classof(const MachineInstr *MI) {
254 switch (MI->getOpcode()) {
255 case TargetOpcode::G_MERGE_VALUES:
256 case TargetOpcode::G_CONCAT_VECTORS:
257 case TargetOpcode::G_BUILD_VECTOR:
258 return true;
259 default:
260 return false;
261 }
262 }
263};
264
265/// Represents a G_MERGE_VALUES.
266class GMerge : public GMergeLikeInstr {
267public:
268 static bool classof(const MachineInstr *MI) {
269 return MI->getOpcode() == TargetOpcode::G_MERGE_VALUES;
270 }
271};
272
273/// Represents a G_CONCAT_VECTORS.
274class GConcatVectors : public GMergeLikeInstr {
275public:
276 static bool classof(const MachineInstr *MI) {
277 return MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS;
278 }
279};
280
281/// Represents a G_BUILD_VECTOR.
282class GBuildVector : public GMergeLikeInstr {
283public:
284 static bool classof(const MachineInstr *MI) {
285 return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR;
286 }
287};
288
289/// Represents a G_BUILD_VECTOR_TRUNC.
290class GBuildVectorTrunc : public GMergeLikeInstr {
291public:
292 static bool classof(const MachineInstr *MI) {
293 return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC;
294 }
295};
296
297/// Represents a G_PTR_ADD.
298class GPtrAdd : public GenericMachineInstr {
299public:
300 Register getBaseReg() const { return getReg(Idx: 1); }
301 Register getOffsetReg() const { return getReg(Idx: 2); }
302
303 static bool classof(const MachineInstr *MI) {
304 return MI->getOpcode() == TargetOpcode::G_PTR_ADD;
305 }
306};
307
308/// Represents a G_IMPLICIT_DEF.
309class GImplicitDef : public GenericMachineInstr {
310public:
311 static bool classof(const MachineInstr *MI) {
312 return MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
313 }
314};
315
316/// Represents a G_SELECT.
317class GSelect : public GenericMachineInstr {
318public:
319 Register getCondReg() const { return getReg(Idx: 1); }
320 Register getTrueReg() const { return getReg(Idx: 2); }
321 Register getFalseReg() const { return getReg(Idx: 3); }
322
323 static bool classof(const MachineInstr *MI) {
324 return MI->getOpcode() == TargetOpcode::G_SELECT;
325 }
326};
327
328/// Represent a G_ICMP or G_FCMP.
329class GAnyCmp : public GenericMachineInstr {
330public:
331 CmpInst::Predicate getCond() const {
332 return static_cast<CmpInst::Predicate>(getOperand(i: 1).getPredicate());
333 }
334 Register getLHSReg() const { return getReg(Idx: 2); }
335 Register getRHSReg() const { return getReg(Idx: 3); }
336
337 static bool classof(const MachineInstr *MI) {
338 return MI->getOpcode() == TargetOpcode::G_ICMP ||
339 MI->getOpcode() == TargetOpcode::G_FCMP;
340 }
341};
342
343/// Represent a G_ICMP.
344class GICmp : public GAnyCmp {
345public:
346 static bool classof(const MachineInstr *MI) {
347 return MI->getOpcode() == TargetOpcode::G_ICMP;
348 }
349};
350
351/// Represent a G_FCMP.
352class GFCmp : public GAnyCmp {
353public:
354 static bool classof(const MachineInstr *MI) {
355 return MI->getOpcode() == TargetOpcode::G_FCMP;
356 }
357};
358
359/// Represents overflowing binary operations.
360/// Only carry-out:
361/// G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO
362/// Carry-in and carry-out:
363/// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
364class GBinOpCarryOut : public GenericMachineInstr {
365public:
366 Register getDstReg() const { return getReg(Idx: 0); }
367 Register getCarryOutReg() const { return getReg(Idx: 1); }
368 MachineOperand &getLHS() { return getOperand(i: 2); }
369 MachineOperand &getRHS() { return getOperand(i: 3); }
370 Register getLHSReg() const { return getOperand(i: 2).getReg(); }
371 Register getRHSReg() const { return getOperand(i: 3).getReg(); }
372
373 static bool classof(const MachineInstr *MI) {
374 switch (MI->getOpcode()) {
375 case TargetOpcode::G_UADDO:
376 case TargetOpcode::G_SADDO:
377 case TargetOpcode::G_USUBO:
378 case TargetOpcode::G_SSUBO:
379 case TargetOpcode::G_UADDE:
380 case TargetOpcode::G_SADDE:
381 case TargetOpcode::G_USUBE:
382 case TargetOpcode::G_SSUBE:
383 case TargetOpcode::G_UMULO:
384 case TargetOpcode::G_SMULO:
385 return true;
386 default:
387 return false;
388 }
389 }
390};
391
392/// Represents overflowing add/sub operations.
393/// Only carry-out:
394/// G_UADDO, G_SADDO, G_USUBO, G_SSUBO
395/// Carry-in and carry-out:
396/// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
397class GAddSubCarryOut : public GBinOpCarryOut {
398public:
399 bool isAdd() const {
400 switch (getOpcode()) {
401 case TargetOpcode::G_UADDO:
402 case TargetOpcode::G_SADDO:
403 case TargetOpcode::G_UADDE:
404 case TargetOpcode::G_SADDE:
405 return true;
406 default:
407 return false;
408 }
409 }
410 bool isSub() const { return !isAdd(); }
411
412 bool isSigned() const {
413 switch (getOpcode()) {
414 case TargetOpcode::G_SADDO:
415 case TargetOpcode::G_SSUBO:
416 case TargetOpcode::G_SADDE:
417 case TargetOpcode::G_SSUBE:
418 return true;
419 default:
420 return false;
421 }
422 }
423 bool isUnsigned() const { return !isSigned(); }
424
425 static bool classof(const MachineInstr *MI) {
426 switch (MI->getOpcode()) {
427 case TargetOpcode::G_UADDO:
428 case TargetOpcode::G_SADDO:
429 case TargetOpcode::G_USUBO:
430 case TargetOpcode::G_SSUBO:
431 case TargetOpcode::G_UADDE:
432 case TargetOpcode::G_SADDE:
433 case TargetOpcode::G_USUBE:
434 case TargetOpcode::G_SSUBE:
435 return true;
436 default:
437 return false;
438 }
439 }
440};
441
442/// Represents overflowing add operations.
443/// G_UADDO, G_SADDO
444class GAddCarryOut : public GBinOpCarryOut {
445public:
446 bool isSigned() const { return getOpcode() == TargetOpcode::G_SADDO; }
447
448 static bool classof(const MachineInstr *MI) {
449 switch (MI->getOpcode()) {
450 case TargetOpcode::G_UADDO:
451 case TargetOpcode::G_SADDO:
452 return true;
453 default:
454 return false;
455 }
456 }
457};
458
459/// Represents overflowing add/sub operations that also consume a carry-in.
460/// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
461class GAddSubCarryInOut : public GAddSubCarryOut {
462public:
463 Register getCarryInReg() const { return getReg(Idx: 4); }
464
465 static bool classof(const MachineInstr *MI) {
466 switch (MI->getOpcode()) {
467 case TargetOpcode::G_UADDE:
468 case TargetOpcode::G_SADDE:
469 case TargetOpcode::G_USUBE:
470 case TargetOpcode::G_SSUBE:
471 return true;
472 default:
473 return false;
474 }
475 }
476};
477
478/// Represents a call to an intrinsic.
479class GIntrinsic final : public GenericMachineInstr {
480public:
481 Intrinsic::ID getIntrinsicID() const {
482 return getOperand(i: getNumExplicitDefs()).getIntrinsicID();
483 }
484
485 bool is(Intrinsic::ID ID) const { return getIntrinsicID() == ID; }
486
487 bool hasSideEffects() const {
488 switch (getOpcode()) {
489 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
490 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
491 return true;
492 default:
493 return false;
494 }
495 }
496
497 bool isConvergent() const {
498 switch (getOpcode()) {
499 case TargetOpcode::G_INTRINSIC_CONVERGENT:
500 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
501 return true;
502 default:
503 return false;
504 }
505 }
506
507 static bool classof(const MachineInstr *MI) {
508 switch (MI->getOpcode()) {
509 case TargetOpcode::G_INTRINSIC:
510 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
511 case TargetOpcode::G_INTRINSIC_CONVERGENT:
512 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
513 return true;
514 default:
515 return false;
516 }
517 }
518};
519
520// Represents a (non-sequential) vector reduction operation.
521class GVecReduce : public GenericMachineInstr {
522public:
523 static bool classof(const MachineInstr *MI) {
524 switch (MI->getOpcode()) {
525 case TargetOpcode::G_VECREDUCE_FADD:
526 case TargetOpcode::G_VECREDUCE_FMUL:
527 case TargetOpcode::G_VECREDUCE_FMAX:
528 case TargetOpcode::G_VECREDUCE_FMIN:
529 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
530 case TargetOpcode::G_VECREDUCE_FMINIMUM:
531 case TargetOpcode::G_VECREDUCE_ADD:
532 case TargetOpcode::G_VECREDUCE_MUL:
533 case TargetOpcode::G_VECREDUCE_AND:
534 case TargetOpcode::G_VECREDUCE_OR:
535 case TargetOpcode::G_VECREDUCE_XOR:
536 case TargetOpcode::G_VECREDUCE_SMAX:
537 case TargetOpcode::G_VECREDUCE_SMIN:
538 case TargetOpcode::G_VECREDUCE_UMAX:
539 case TargetOpcode::G_VECREDUCE_UMIN:
540 return true;
541 default:
542 return false;
543 }
544 }
545
546 /// Get the opcode for the equivalent scalar operation for this reduction.
547 /// E.g. for G_VECREDUCE_FADD, this returns G_FADD.
548 unsigned getScalarOpcForReduction() {
549 unsigned ScalarOpc;
550 switch (getOpcode()) {
551 case TargetOpcode::G_VECREDUCE_FADD:
552 ScalarOpc = TargetOpcode::G_FADD;
553 break;
554 case TargetOpcode::G_VECREDUCE_FMUL:
555 ScalarOpc = TargetOpcode::G_FMUL;
556 break;
557 case TargetOpcode::G_VECREDUCE_FMAX:
558 ScalarOpc = TargetOpcode::G_FMAXNUM;
559 break;
560 case TargetOpcode::G_VECREDUCE_FMIN:
561 ScalarOpc = TargetOpcode::G_FMINNUM;
562 break;
563 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
564 ScalarOpc = TargetOpcode::G_FMAXIMUM;
565 break;
566 case TargetOpcode::G_VECREDUCE_FMINIMUM:
567 ScalarOpc = TargetOpcode::G_FMINIMUM;
568 break;
569 case TargetOpcode::G_VECREDUCE_ADD:
570 ScalarOpc = TargetOpcode::G_ADD;
571 break;
572 case TargetOpcode::G_VECREDUCE_MUL:
573 ScalarOpc = TargetOpcode::G_MUL;
574 break;
575 case TargetOpcode::G_VECREDUCE_AND:
576 ScalarOpc = TargetOpcode::G_AND;
577 break;
578 case TargetOpcode::G_VECREDUCE_OR:
579 ScalarOpc = TargetOpcode::G_OR;
580 break;
581 case TargetOpcode::G_VECREDUCE_XOR:
582 ScalarOpc = TargetOpcode::G_XOR;
583 break;
584 case TargetOpcode::G_VECREDUCE_SMAX:
585 ScalarOpc = TargetOpcode::G_SMAX;
586 break;
587 case TargetOpcode::G_VECREDUCE_SMIN:
588 ScalarOpc = TargetOpcode::G_SMIN;
589 break;
590 case TargetOpcode::G_VECREDUCE_UMAX:
591 ScalarOpc = TargetOpcode::G_UMAX;
592 break;
593 case TargetOpcode::G_VECREDUCE_UMIN:
594 ScalarOpc = TargetOpcode::G_UMIN;
595 break;
596 default:
597 llvm_unreachable("Unhandled reduction");
598 }
599 return ScalarOpc;
600 }
601};
602
603/// Represents a G_PHI.
604class GPhi : public GenericMachineInstr {
605public:
606 /// Returns the number of incoming values.
607 unsigned getNumIncomingValues() const { return (getNumOperands() - 1) / 2; }
608 /// Returns the I'th incoming vreg.
609 Register getIncomingValue(unsigned I) const {
610 return getOperand(i: I * 2 + 1).getReg();
611 }
612 /// Returns the I'th incoming basic block.
613 MachineBasicBlock *getIncomingBlock(unsigned I) const {
614 return getOperand(i: I * 2 + 2).getMBB();
615 }
616
617 static bool classof(const MachineInstr *MI) {
618 return MI->getOpcode() == TargetOpcode::G_PHI;
619 }
620};
621
622/// Represents a binary operation, i.e, x = y op z.
623class GBinOp : public GenericMachineInstr {
624public:
625 Register getLHSReg() const { return getReg(Idx: 1); }
626 Register getRHSReg() const { return getReg(Idx: 2); }
627
628 static bool classof(const MachineInstr *MI) {
629 switch (MI->getOpcode()) {
630 // Integer.
631 case TargetOpcode::G_ADD:
632 case TargetOpcode::G_SUB:
633 case TargetOpcode::G_MUL:
634 case TargetOpcode::G_SDIV:
635 case TargetOpcode::G_UDIV:
636 case TargetOpcode::G_SREM:
637 case TargetOpcode::G_UREM:
638 case TargetOpcode::G_SMIN:
639 case TargetOpcode::G_SMAX:
640 case TargetOpcode::G_UMIN:
641 case TargetOpcode::G_UMAX:
642 // Floating point.
643 case TargetOpcode::G_FMINNUM:
644 case TargetOpcode::G_FMAXNUM:
645 case TargetOpcode::G_FMINNUM_IEEE:
646 case TargetOpcode::G_FMAXNUM_IEEE:
647 case TargetOpcode::G_FMINIMUM:
648 case TargetOpcode::G_FMAXIMUM:
649 case TargetOpcode::G_FADD:
650 case TargetOpcode::G_FSUB:
651 case TargetOpcode::G_FMUL:
652 case TargetOpcode::G_FDIV:
653 case TargetOpcode::G_FPOW:
654 // Logical.
655 case TargetOpcode::G_AND:
656 case TargetOpcode::G_OR:
657 case TargetOpcode::G_XOR:
658 return true;
659 default:
660 return false;
661 }
662 };
663};
664
665/// Represents an integer binary operation.
666class GIntBinOp : public GBinOp {
667public:
668 static bool classof(const MachineInstr *MI) {
669 switch (MI->getOpcode()) {
670 case TargetOpcode::G_ADD:
671 case TargetOpcode::G_SUB:
672 case TargetOpcode::G_MUL:
673 case TargetOpcode::G_SDIV:
674 case TargetOpcode::G_UDIV:
675 case TargetOpcode::G_SREM:
676 case TargetOpcode::G_UREM:
677 case TargetOpcode::G_SMIN:
678 case TargetOpcode::G_SMAX:
679 case TargetOpcode::G_UMIN:
680 case TargetOpcode::G_UMAX:
681 return true;
682 default:
683 return false;
684 }
685 };
686};
687
688/// Represents a floating point binary operation.
689class GFBinOp : public GBinOp {
690public:
691 static bool classof(const MachineInstr *MI) {
692 switch (MI->getOpcode()) {
693 case TargetOpcode::G_FMINNUM:
694 case TargetOpcode::G_FMAXNUM:
695 case TargetOpcode::G_FMINNUM_IEEE:
696 case TargetOpcode::G_FMAXNUM_IEEE:
697 case TargetOpcode::G_FMINIMUM:
698 case TargetOpcode::G_FMAXIMUM:
699 case TargetOpcode::G_FADD:
700 case TargetOpcode::G_FSUB:
701 case TargetOpcode::G_FMUL:
702 case TargetOpcode::G_FDIV:
703 case TargetOpcode::G_FPOW:
704 return true;
705 default:
706 return false;
707 }
708 };
709};
710
711/// Represents a logical binary operation.
712class GLogicalBinOp : public GBinOp {
713public:
714 static bool classof(const MachineInstr *MI) {
715 switch (MI->getOpcode()) {
716 case TargetOpcode::G_AND:
717 case TargetOpcode::G_OR:
718 case TargetOpcode::G_XOR:
719 return true;
720 default:
721 return false;
722 }
723 };
724};
725
726/// Represents an integer addition.
727class GAdd : public GIntBinOp {
728public:
729 static bool classof(const MachineInstr *MI) {
730 return MI->getOpcode() == TargetOpcode::G_ADD;
731 };
732};
733
734/// Represents a logical and.
735class GAnd : public GLogicalBinOp {
736public:
737 static bool classof(const MachineInstr *MI) {
738 return MI->getOpcode() == TargetOpcode::G_AND;
739 };
740};
741
742/// Represents a logical or.
743class GOr : public GLogicalBinOp {
744public:
745 static bool classof(const MachineInstr *MI) {
746 return MI->getOpcode() == TargetOpcode::G_OR;
747 };
748};
749
750/// Represents an extract vector element.
751class GExtractVectorElement : public GenericMachineInstr {
752public:
753 Register getVectorReg() const { return getOperand(i: 1).getReg(); }
754 Register getIndexReg() const { return getOperand(i: 2).getReg(); }
755
756 static bool classof(const MachineInstr *MI) {
757 return MI->getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT;
758 }
759};
760
761/// Represents an insert vector element.
762class GInsertVectorElement : public GenericMachineInstr {
763public:
764 Register getVectorReg() const { return getOperand(i: 1).getReg(); }
765 Register getElementReg() const { return getOperand(i: 2).getReg(); }
766 Register getIndexReg() const { return getOperand(i: 3).getReg(); }
767
768 static bool classof(const MachineInstr *MI) {
769 return MI->getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
770 }
771};
772
773/// Represents a freeze.
774class GFreeze : public GenericMachineInstr {
775public:
776 Register getSourceReg() const { return getOperand(i: 1).getReg(); }
777
778 static bool classof(const MachineInstr *MI) {
779 return MI->getOpcode() == TargetOpcode::G_FREEZE;
780 }
781};
782
783} // namespace llvm
784
785#endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
786

source code of llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h