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 uint64_t getMemSize() const { return getMMO().getSize(); }
58 /// Returns the size in bits of the memory access.
59 uint64_t 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_PTR_ADD.
290class GPtrAdd : public GenericMachineInstr {
291public:
292 Register getBaseReg() const { return getReg(Idx: 1); }
293 Register getOffsetReg() const { return getReg(Idx: 2); }
294
295 static bool classof(const MachineInstr *MI) {
296 return MI->getOpcode() == TargetOpcode::G_PTR_ADD;
297 }
298};
299
300/// Represents a G_IMPLICIT_DEF.
301class GImplicitDef : public GenericMachineInstr {
302public:
303 static bool classof(const MachineInstr *MI) {
304 return MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
305 }
306};
307
308/// Represents a G_SELECT.
309class GSelect : public GenericMachineInstr {
310public:
311 Register getCondReg() const { return getReg(Idx: 1); }
312 Register getTrueReg() const { return getReg(Idx: 2); }
313 Register getFalseReg() const { return getReg(Idx: 3); }
314
315 static bool classof(const MachineInstr *MI) {
316 return MI->getOpcode() == TargetOpcode::G_SELECT;
317 }
318};
319
320/// Represent a G_ICMP or G_FCMP.
321class GAnyCmp : public GenericMachineInstr {
322public:
323 CmpInst::Predicate getCond() const {
324 return static_cast<CmpInst::Predicate>(getOperand(i: 1).getPredicate());
325 }
326 Register getLHSReg() const { return getReg(Idx: 2); }
327 Register getRHSReg() const { return getReg(Idx: 3); }
328
329 static bool classof(const MachineInstr *MI) {
330 return MI->getOpcode() == TargetOpcode::G_ICMP ||
331 MI->getOpcode() == TargetOpcode::G_FCMP;
332 }
333};
334
335/// Represent a G_ICMP.
336class GICmp : public GAnyCmp {
337public:
338 static bool classof(const MachineInstr *MI) {
339 return MI->getOpcode() == TargetOpcode::G_ICMP;
340 }
341};
342
343/// Represent a G_FCMP.
344class GFCmp : public GAnyCmp {
345public:
346 static bool classof(const MachineInstr *MI) {
347 return MI->getOpcode() == TargetOpcode::G_FCMP;
348 }
349};
350
351/// Represents overflowing binary operations.
352/// Only carry-out:
353/// G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO
354/// Carry-in and carry-out:
355/// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
356class GBinOpCarryOut : public GenericMachineInstr {
357public:
358 Register getDstReg() const { return getReg(Idx: 0); }
359 Register getCarryOutReg() const { return getReg(Idx: 1); }
360 MachineOperand &getLHS() { return getOperand(i: 2); }
361 MachineOperand &getRHS() { return getOperand(i: 3); }
362
363 static bool classof(const MachineInstr *MI) {
364 switch (MI->getOpcode()) {
365 case TargetOpcode::G_UADDO:
366 case TargetOpcode::G_SADDO:
367 case TargetOpcode::G_USUBO:
368 case TargetOpcode::G_SSUBO:
369 case TargetOpcode::G_UADDE:
370 case TargetOpcode::G_SADDE:
371 case TargetOpcode::G_USUBE:
372 case TargetOpcode::G_SSUBE:
373 case TargetOpcode::G_UMULO:
374 case TargetOpcode::G_SMULO:
375 return true;
376 default:
377 return false;
378 }
379 }
380};
381
382/// Represents overflowing add/sub operations.
383/// Only carry-out:
384/// G_UADDO, G_SADDO, G_USUBO, G_SSUBO
385/// Carry-in and carry-out:
386/// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
387class GAddSubCarryOut : public GBinOpCarryOut {
388public:
389 bool isAdd() const {
390 switch (getOpcode()) {
391 case TargetOpcode::G_UADDO:
392 case TargetOpcode::G_SADDO:
393 case TargetOpcode::G_UADDE:
394 case TargetOpcode::G_SADDE:
395 return true;
396 default:
397 return false;
398 }
399 }
400 bool isSub() const { return !isAdd(); }
401
402 bool isSigned() const {
403 switch (getOpcode()) {
404 case TargetOpcode::G_SADDO:
405 case TargetOpcode::G_SSUBO:
406 case TargetOpcode::G_SADDE:
407 case TargetOpcode::G_SSUBE:
408 return true;
409 default:
410 return false;
411 }
412 }
413 bool isUnsigned() const { return !isSigned(); }
414
415 static bool classof(const MachineInstr *MI) {
416 switch (MI->getOpcode()) {
417 case TargetOpcode::G_UADDO:
418 case TargetOpcode::G_SADDO:
419 case TargetOpcode::G_USUBO:
420 case TargetOpcode::G_SSUBO:
421 case TargetOpcode::G_UADDE:
422 case TargetOpcode::G_SADDE:
423 case TargetOpcode::G_USUBE:
424 case TargetOpcode::G_SSUBE:
425 return true;
426 default:
427 return false;
428 }
429 }
430};
431
432/// Represents overflowing add/sub operations that also consume a carry-in.
433/// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
434class GAddSubCarryInOut : public GAddSubCarryOut {
435public:
436 Register getCarryInReg() const { return getReg(Idx: 4); }
437
438 static bool classof(const MachineInstr *MI) {
439 switch (MI->getOpcode()) {
440 case TargetOpcode::G_UADDE:
441 case TargetOpcode::G_SADDE:
442 case TargetOpcode::G_USUBE:
443 case TargetOpcode::G_SSUBE:
444 return true;
445 default:
446 return false;
447 }
448 }
449};
450
451/// Represents a call to an intrinsic.
452class GIntrinsic final : public GenericMachineInstr {
453public:
454 Intrinsic::ID getIntrinsicID() const {
455 return getOperand(i: getNumExplicitDefs()).getIntrinsicID();
456 }
457
458 bool is(Intrinsic::ID ID) const { return getIntrinsicID() == ID; }
459
460 bool hasSideEffects() const {
461 switch (getOpcode()) {
462 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
463 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
464 return true;
465 default:
466 return false;
467 }
468 }
469
470 bool isConvergent() const {
471 switch (getOpcode()) {
472 case TargetOpcode::G_INTRINSIC_CONVERGENT:
473 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
474 return true;
475 default:
476 return false;
477 }
478 }
479
480 static bool classof(const MachineInstr *MI) {
481 switch (MI->getOpcode()) {
482 case TargetOpcode::G_INTRINSIC:
483 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
484 case TargetOpcode::G_INTRINSIC_CONVERGENT:
485 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
486 return true;
487 default:
488 return false;
489 }
490 }
491};
492
493// Represents a (non-sequential) vector reduction operation.
494class GVecReduce : public GenericMachineInstr {
495public:
496 static bool classof(const MachineInstr *MI) {
497 switch (MI->getOpcode()) {
498 case TargetOpcode::G_VECREDUCE_FADD:
499 case TargetOpcode::G_VECREDUCE_FMUL:
500 case TargetOpcode::G_VECREDUCE_FMAX:
501 case TargetOpcode::G_VECREDUCE_FMIN:
502 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
503 case TargetOpcode::G_VECREDUCE_FMINIMUM:
504 case TargetOpcode::G_VECREDUCE_ADD:
505 case TargetOpcode::G_VECREDUCE_MUL:
506 case TargetOpcode::G_VECREDUCE_AND:
507 case TargetOpcode::G_VECREDUCE_OR:
508 case TargetOpcode::G_VECREDUCE_XOR:
509 case TargetOpcode::G_VECREDUCE_SMAX:
510 case TargetOpcode::G_VECREDUCE_SMIN:
511 case TargetOpcode::G_VECREDUCE_UMAX:
512 case TargetOpcode::G_VECREDUCE_UMIN:
513 return true;
514 default:
515 return false;
516 }
517 }
518
519 /// Get the opcode for the equivalent scalar operation for this reduction.
520 /// E.g. for G_VECREDUCE_FADD, this returns G_FADD.
521 unsigned getScalarOpcForReduction() {
522 unsigned ScalarOpc;
523 switch (getOpcode()) {
524 case TargetOpcode::G_VECREDUCE_FADD:
525 ScalarOpc = TargetOpcode::G_FADD;
526 break;
527 case TargetOpcode::G_VECREDUCE_FMUL:
528 ScalarOpc = TargetOpcode::G_FMUL;
529 break;
530 case TargetOpcode::G_VECREDUCE_FMAX:
531 ScalarOpc = TargetOpcode::G_FMAXNUM;
532 break;
533 case TargetOpcode::G_VECREDUCE_FMIN:
534 ScalarOpc = TargetOpcode::G_FMINNUM;
535 break;
536 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
537 ScalarOpc = TargetOpcode::G_FMAXIMUM;
538 break;
539 case TargetOpcode::G_VECREDUCE_FMINIMUM:
540 ScalarOpc = TargetOpcode::G_FMINIMUM;
541 break;
542 case TargetOpcode::G_VECREDUCE_ADD:
543 ScalarOpc = TargetOpcode::G_ADD;
544 break;
545 case TargetOpcode::G_VECREDUCE_MUL:
546 ScalarOpc = TargetOpcode::G_MUL;
547 break;
548 case TargetOpcode::G_VECREDUCE_AND:
549 ScalarOpc = TargetOpcode::G_AND;
550 break;
551 case TargetOpcode::G_VECREDUCE_OR:
552 ScalarOpc = TargetOpcode::G_OR;
553 break;
554 case TargetOpcode::G_VECREDUCE_XOR:
555 ScalarOpc = TargetOpcode::G_XOR;
556 break;
557 case TargetOpcode::G_VECREDUCE_SMAX:
558 ScalarOpc = TargetOpcode::G_SMAX;
559 break;
560 case TargetOpcode::G_VECREDUCE_SMIN:
561 ScalarOpc = TargetOpcode::G_SMIN;
562 break;
563 case TargetOpcode::G_VECREDUCE_UMAX:
564 ScalarOpc = TargetOpcode::G_UMAX;
565 break;
566 case TargetOpcode::G_VECREDUCE_UMIN:
567 ScalarOpc = TargetOpcode::G_UMIN;
568 break;
569 default:
570 llvm_unreachable("Unhandled reduction");
571 }
572 return ScalarOpc;
573 }
574};
575
576/// Represents a G_PHI.
577class GPhi : public GenericMachineInstr {
578public:
579 /// Returns the number of incoming values.
580 unsigned getNumIncomingValues() const { return (getNumOperands() - 1) / 2; }
581 /// Returns the I'th incoming vreg.
582 Register getIncomingValue(unsigned I) const {
583 return getOperand(i: I * 2 + 1).getReg();
584 }
585 /// Returns the I'th incoming basic block.
586 MachineBasicBlock *getIncomingBlock(unsigned I) const {
587 return getOperand(i: I * 2 + 2).getMBB();
588 }
589
590 static bool classof(const MachineInstr *MI) {
591 return MI->getOpcode() == TargetOpcode::G_PHI;
592 }
593};
594
595/// Represents a binary operation, i.e, x = y op z.
596class GBinOp : public GenericMachineInstr {
597public:
598 Register getLHSReg() const { return getReg(Idx: 1); }
599 Register getRHSReg() const { return getReg(Idx: 2); }
600
601 static bool classof(const MachineInstr *MI) {
602 switch (MI->getOpcode()) {
603 // Integer.
604 case TargetOpcode::G_ADD:
605 case TargetOpcode::G_SUB:
606 case TargetOpcode::G_MUL:
607 case TargetOpcode::G_SDIV:
608 case TargetOpcode::G_UDIV:
609 case TargetOpcode::G_SREM:
610 case TargetOpcode::G_UREM:
611 case TargetOpcode::G_SMIN:
612 case TargetOpcode::G_SMAX:
613 case TargetOpcode::G_UMIN:
614 case TargetOpcode::G_UMAX:
615 // Floating point.
616 case TargetOpcode::G_FMINNUM:
617 case TargetOpcode::G_FMAXNUM:
618 case TargetOpcode::G_FMINNUM_IEEE:
619 case TargetOpcode::G_FMAXNUM_IEEE:
620 case TargetOpcode::G_FMINIMUM:
621 case TargetOpcode::G_FMAXIMUM:
622 case TargetOpcode::G_FADD:
623 case TargetOpcode::G_FSUB:
624 case TargetOpcode::G_FMUL:
625 case TargetOpcode::G_FDIV:
626 case TargetOpcode::G_FPOW:
627 // Logical.
628 case TargetOpcode::G_AND:
629 case TargetOpcode::G_OR:
630 case TargetOpcode::G_XOR:
631 return true;
632 default:
633 return false;
634 }
635 };
636};
637
638/// Represents an integer binary operation.
639class GIntBinOp : public GBinOp {
640public:
641 static bool classof(const MachineInstr *MI) {
642 switch (MI->getOpcode()) {
643 case TargetOpcode::G_ADD:
644 case TargetOpcode::G_SUB:
645 case TargetOpcode::G_MUL:
646 case TargetOpcode::G_SDIV:
647 case TargetOpcode::G_UDIV:
648 case TargetOpcode::G_SREM:
649 case TargetOpcode::G_UREM:
650 case TargetOpcode::G_SMIN:
651 case TargetOpcode::G_SMAX:
652 case TargetOpcode::G_UMIN:
653 case TargetOpcode::G_UMAX:
654 return true;
655 default:
656 return false;
657 }
658 };
659};
660
661/// Represents a floating point binary operation.
662class GFBinOp : public GBinOp {
663public:
664 static bool classof(const MachineInstr *MI) {
665 switch (MI->getOpcode()) {
666 case TargetOpcode::G_FMINNUM:
667 case TargetOpcode::G_FMAXNUM:
668 case TargetOpcode::G_FMINNUM_IEEE:
669 case TargetOpcode::G_FMAXNUM_IEEE:
670 case TargetOpcode::G_FMINIMUM:
671 case TargetOpcode::G_FMAXIMUM:
672 case TargetOpcode::G_FADD:
673 case TargetOpcode::G_FSUB:
674 case TargetOpcode::G_FMUL:
675 case TargetOpcode::G_FDIV:
676 case TargetOpcode::G_FPOW:
677 return true;
678 default:
679 return false;
680 }
681 };
682};
683
684/// Represents a logical binary operation.
685class GLogicalBinOp : public GBinOp {
686public:
687 static bool classof(const MachineInstr *MI) {
688 switch (MI->getOpcode()) {
689 case TargetOpcode::G_AND:
690 case TargetOpcode::G_OR:
691 case TargetOpcode::G_XOR:
692 return true;
693 default:
694 return false;
695 }
696 };
697};
698
699/// Represents an integer addition.
700class GAdd : public GIntBinOp {
701public:
702 static bool classof(const MachineInstr *MI) {
703 return MI->getOpcode() == TargetOpcode::G_ADD;
704 };
705};
706
707/// Represents a logical and.
708class GAnd : public GLogicalBinOp {
709public:
710 static bool classof(const MachineInstr *MI) {
711 return MI->getOpcode() == TargetOpcode::G_AND;
712 };
713};
714
715/// Represents a logical or.
716class GOr : public GLogicalBinOp {
717public:
718 static bool classof(const MachineInstr *MI) {
719 return MI->getOpcode() == TargetOpcode::G_OR;
720 };
721};
722
723} // namespace llvm
724
725#endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
726

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