1//===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===//
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//
9// This file defines the generic opcodes used with GlobalISel.
10// After instruction selection, these opcodes should not appear.
11//
12//===----------------------------------------------------------------------===//
13
14//------------------------------------------------------------------------------
15// Unary ops.
16//------------------------------------------------------------------------------
17
18class GenericInstruction : StandardPseudoInstruction {
19  let isPreISelOpcode = true;
20
21  // When all variadic ops share a type with another operand,
22  // this is the type they share. Used by MIR patterns type inference.
23  TypedOperand variadicOpsType = ?;
24}
25
26// Provide a variant of an instruction with the same operands, but
27// different instruction flags. This is intended to provide a
28// convenient way to define strict floating point variants of ordinary
29// floating point instructions.
30class ConstrainedInstruction<GenericInstruction baseInst> :
31  GenericInstruction {
32  let OutOperandList = baseInst.OutOperandList;
33  let InOperandList =  baseInst.InOperandList;
34  let isCommutable = baseInst.isCommutable;
35
36  // TODO: Do we need a better way to mark reads from FP mode than
37  // hasSideEffects?
38  let hasSideEffects = true;
39  let mayRaiseFPException = true;
40}
41
42// Extend the underlying scalar type of an operation, leaving the high bits
43// unspecified.
44def G_ANYEXT : GenericInstruction {
45  let OutOperandList = (outs type0:$dst);
46  let InOperandList = (ins type1:$src);
47  let hasSideEffects = false;
48}
49
50// Sign extend the underlying scalar type of an operation, copying the sign bit
51// into the newly-created space.
52def G_SEXT : GenericInstruction {
53  let OutOperandList = (outs type0:$dst);
54  let InOperandList = (ins type1:$src);
55  let hasSideEffects = false;
56}
57
58// Sign extend the a value from an arbitrary bit position, copying the sign bit
59// into all bits above it. This is equivalent to a shl + ashr pair with an
60// appropriate shift amount. $sz is an immediate (MachineOperand::isImm()
61// returns true) to allow targets to have some bitwidths legal and others
62// lowered. This opcode is particularly useful if the target has sign-extension
63// instructions that are cheaper than the constituent shifts as the optimizer is
64// able to make decisions on whether it's better to hang on to the G_SEXT_INREG
65// or to lower it and optimize the individual shifts.
66def G_SEXT_INREG : GenericInstruction {
67  let OutOperandList = (outs type0:$dst);
68  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
69  let hasSideEffects = false;
70}
71
72// Zero extend the underlying scalar type of an operation, putting zero bits
73// into the newly-created space.
74def G_ZEXT : GenericInstruction {
75  let OutOperandList = (outs type0:$dst);
76  let InOperandList = (ins type1:$src);
77  let hasSideEffects = false;
78}
79
80
81// Truncate the underlying scalar type of an operation. This is equivalent to
82// G_EXTRACT for scalar types, but acts elementwise on vectors.
83def G_TRUNC : GenericInstruction {
84  let OutOperandList = (outs type0:$dst);
85  let InOperandList = (ins type1:$src);
86  let hasSideEffects = false;
87}
88
89def G_IMPLICIT_DEF : GenericInstruction {
90  let OutOperandList = (outs type0:$dst);
91  let InOperandList = (ins);
92  let hasSideEffects = false;
93}
94
95def G_PHI : GenericInstruction {
96  let OutOperandList = (outs type0:$dst);
97  let InOperandList = (ins variable_ops);
98  let hasSideEffects = false;
99}
100
101def G_FRAME_INDEX : GenericInstruction {
102  let OutOperandList = (outs type0:$dst);
103  let InOperandList = (ins unknown:$src2);
104  let hasSideEffects = false;
105}
106
107def G_GLOBAL_VALUE : GenericInstruction {
108  let OutOperandList = (outs type0:$dst);
109  let InOperandList = (ins unknown:$src);
110  let hasSideEffects = false;
111}
112
113def G_CONSTANT_POOL : GenericInstruction {
114  let OutOperandList = (outs type0:$dst);
115  let InOperandList = (ins unknown:$src);
116  let hasSideEffects = false;
117}
118
119def G_INTTOPTR : GenericInstruction {
120  let OutOperandList = (outs type0:$dst);
121  let InOperandList = (ins type1:$src);
122  let hasSideEffects = false;
123}
124
125def G_PTRTOINT : GenericInstruction {
126  let OutOperandList = (outs type0:$dst);
127  let InOperandList = (ins type1:$src);
128  let hasSideEffects = false;
129}
130
131def G_BITCAST : GenericInstruction {
132  let OutOperandList = (outs type0:$dst);
133  let InOperandList = (ins type1:$src);
134  let hasSideEffects = false;
135}
136
137// Only supports scalar result types
138def G_CONSTANT : GenericInstruction {
139  let OutOperandList = (outs type0:$dst);
140  let InOperandList = (ins unknown:$imm);
141  let hasSideEffects = false;
142}
143
144// Only supports scalar result types
145def G_FCONSTANT : GenericInstruction {
146  let OutOperandList = (outs type0:$dst);
147  let InOperandList = (ins unknown:$imm);
148  let hasSideEffects = false;
149}
150
151def G_VASTART : GenericInstruction {
152  let OutOperandList = (outs);
153  let InOperandList = (ins type0:$list);
154  let hasSideEffects = false;
155  let mayStore = true;
156}
157
158def G_VAARG : GenericInstruction {
159  let OutOperandList = (outs type0:$val);
160  let InOperandList = (ins type1:$list, unknown:$align);
161  let hasSideEffects = false;
162  let mayLoad = true;
163  let mayStore = true;
164}
165
166def G_CTLZ : GenericInstruction {
167  let OutOperandList = (outs type0:$dst);
168  let InOperandList = (ins type1:$src);
169  let hasSideEffects = false;
170}
171
172def G_CTLZ_ZERO_UNDEF : GenericInstruction {
173  let OutOperandList = (outs type0:$dst);
174  let InOperandList = (ins type1:$src);
175  let hasSideEffects = false;
176}
177
178def G_CTTZ : GenericInstruction {
179  let OutOperandList = (outs type0:$dst);
180  let InOperandList = (ins type1:$src);
181  let hasSideEffects = false;
182}
183
184def G_CTTZ_ZERO_UNDEF : GenericInstruction {
185  let OutOperandList = (outs type0:$dst);
186  let InOperandList = (ins type1:$src);
187  let hasSideEffects = false;
188}
189
190def G_CTPOP : GenericInstruction {
191  let OutOperandList = (outs type0:$dst);
192  let InOperandList = (ins type1:$src);
193  let hasSideEffects = false;
194}
195
196def G_BSWAP : GenericInstruction {
197  let OutOperandList = (outs type0:$dst);
198  let InOperandList = (ins type0:$src);
199  let hasSideEffects = false;
200}
201
202def G_BITREVERSE : GenericInstruction {
203  let OutOperandList = (outs type0:$dst);
204  let InOperandList = (ins type0:$src);
205  let hasSideEffects = false;
206}
207
208def G_ADDRSPACE_CAST : GenericInstruction {
209  let OutOperandList = (outs type0:$dst);
210  let InOperandList = (ins type1:$src);
211  let hasSideEffects = false;
212}
213
214def G_BLOCK_ADDR : GenericInstruction {
215  let OutOperandList = (outs type0:$dst);
216  let InOperandList = (ins unknown:$ba);
217  let hasSideEffects = false;
218}
219
220def G_JUMP_TABLE : GenericInstruction {
221  let OutOperandList = (outs type0:$dst);
222  let InOperandList = (ins unknown:$jti);
223  let hasSideEffects = false;
224}
225
226def G_DYN_STACKALLOC : GenericInstruction {
227  let OutOperandList = (outs ptype0:$dst);
228  let InOperandList = (ins type1:$size, i32imm:$align);
229  let hasSideEffects = true;
230}
231
232def G_STACKSAVE : GenericInstruction {
233  let OutOperandList = (outs ptype0:$dst);
234  let InOperandList = (ins);
235  let hasSideEffects = true;
236}
237
238def G_STACKRESTORE : GenericInstruction {
239  let OutOperandList = (outs);
240  let InOperandList = (ins ptype0:$src);
241  let hasSideEffects = true;
242}
243
244def G_FREEZE : GenericInstruction {
245  let OutOperandList = (outs type0:$dst);
246  let InOperandList = (ins type0:$src);
247  let hasSideEffects = false;
248}
249
250def G_LROUND: GenericInstruction {
251  let OutOperandList = (outs type0:$dst);
252  let InOperandList = (ins type1:$src);
253  let hasSideEffects = false;
254}
255
256def G_LLROUND: GenericInstruction {
257  let OutOperandList = (outs type0:$dst);
258  let InOperandList = (ins type1:$src);
259  let hasSideEffects = false;
260}
261
262//------------------------------------------------------------------------------
263// Binary ops.
264//------------------------------------------------------------------------------
265
266// Generic addition.
267def G_ADD : GenericInstruction {
268  let OutOperandList = (outs type0:$dst);
269  let InOperandList = (ins type0:$src1, type0:$src2);
270  let hasSideEffects = false;
271  let isCommutable = true;
272}
273
274// Generic subtraction.
275def G_SUB : GenericInstruction {
276  let OutOperandList = (outs type0:$dst);
277  let InOperandList = (ins type0:$src1, type0:$src2);
278  let hasSideEffects = false;
279  let isCommutable = false;
280}
281
282// Generic multiplication.
283def G_MUL : GenericInstruction {
284  let OutOperandList = (outs type0:$dst);
285  let InOperandList = (ins type0:$src1, type0:$src2);
286  let hasSideEffects = false;
287  let isCommutable = true;
288}
289
290// Generic signed division.
291def G_SDIV : GenericInstruction {
292  let OutOperandList = (outs type0:$dst);
293  let InOperandList = (ins type0:$src1, type0:$src2);
294  let hasSideEffects = false;
295  let isCommutable = false;
296}
297
298// Generic unsigned division.
299def G_UDIV : GenericInstruction {
300  let OutOperandList = (outs type0:$dst);
301  let InOperandList = (ins type0:$src1, type0:$src2);
302  let hasSideEffects = false;
303  let isCommutable = false;
304}
305
306// Generic signed remainder.
307def G_SREM : GenericInstruction {
308  let OutOperandList = (outs type0:$dst);
309  let InOperandList = (ins type0:$src1, type0:$src2);
310  let hasSideEffects = false;
311  let isCommutable = false;
312}
313
314// Generic unsigned remainder.
315def G_UREM : GenericInstruction {
316  let OutOperandList = (outs type0:$dst);
317  let InOperandList = (ins type0:$src1, type0:$src2);
318  let hasSideEffects = false;
319  let isCommutable = false;
320}
321
322// Generic signed division and remainder.
323def G_SDIVREM : GenericInstruction {
324  let OutOperandList = (outs type0:$div, type0:$rem);
325  let InOperandList = (ins type0:$src1, type0:$src2);
326  let hasSideEffects = false;
327  let isCommutable = false;
328}
329
330// Generic unsigned division and remainder.
331def G_UDIVREM : GenericInstruction {
332  let OutOperandList = (outs type0:$div, type0:$rem);
333  let InOperandList = (ins type0:$src1, type0:$src2);
334  let hasSideEffects = false;
335  let isCommutable = false;
336}
337
338// Generic bitwise and.
339def G_AND : GenericInstruction {
340  let OutOperandList = (outs type0:$dst);
341  let InOperandList = (ins type0:$src1, type0:$src2);
342  let hasSideEffects = false;
343  let isCommutable = true;
344}
345
346// Generic bitwise or.
347def G_OR : GenericInstruction {
348  let OutOperandList = (outs type0:$dst);
349  let InOperandList = (ins type0:$src1, type0:$src2);
350  let hasSideEffects = false;
351  let isCommutable = true;
352}
353
354// Generic bitwise xor.
355def G_XOR : GenericInstruction {
356  let OutOperandList = (outs type0:$dst);
357  let InOperandList = (ins type0:$src1, type0:$src2);
358  let hasSideEffects = false;
359  let isCommutable = true;
360}
361
362// Generic left-shift.
363def G_SHL : GenericInstruction {
364  let OutOperandList = (outs type0:$dst);
365  let InOperandList = (ins type0:$src1, type1:$src2);
366  let hasSideEffects = false;
367}
368
369// Generic logical right-shift.
370def G_LSHR : GenericInstruction {
371  let OutOperandList = (outs type0:$dst);
372  let InOperandList = (ins type0:$src1, type1:$src2);
373  let hasSideEffects = false;
374}
375
376// Generic arithmetic right-shift.
377def G_ASHR : GenericInstruction {
378  let OutOperandList = (outs type0:$dst);
379  let InOperandList = (ins type0:$src1, type1:$src2);
380  let hasSideEffects = false;
381}
382
383/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
384/// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth)))
385def G_FSHL : GenericInstruction {
386  let OutOperandList = (outs type0:$dst);
387  let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
388  let hasSideEffects = false;
389}
390
391/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
392/// fshr(X,Y,Z): (X << (bitwidth - (Z % bitwidth))) | (Y >> (Z % bitwidth))
393def G_FSHR : GenericInstruction {
394  let OutOperandList = (outs type0:$dst);
395  let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
396  let hasSideEffects = false;
397}
398
399/// Rotate bits right.
400def G_ROTR : GenericInstruction {
401  let OutOperandList = (outs type0:$dst);
402  let InOperandList = (ins type0:$src1, type1:$src2);
403  let hasSideEffects = false;
404}
405
406/// Rotate bits left.
407def G_ROTL : GenericInstruction {
408  let OutOperandList = (outs type0:$dst);
409  let InOperandList = (ins type0:$src1, type1:$src2);
410  let hasSideEffects = false;
411}
412
413// Generic integer comparison.
414def G_ICMP : GenericInstruction {
415  let OutOperandList = (outs type0:$dst);
416  let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
417  let hasSideEffects = false;
418}
419
420// Generic floating-point comparison.
421def G_FCMP : GenericInstruction {
422  let OutOperandList = (outs type0:$dst);
423  let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
424  let hasSideEffects = false;
425}
426
427// Generic select
428def G_SELECT : GenericInstruction {
429  let OutOperandList = (outs type0:$dst);
430  let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
431  let hasSideEffects = false;
432}
433
434// Generic pointer offset.
435def G_PTR_ADD : GenericInstruction {
436  let OutOperandList = (outs ptype0:$dst);
437  let InOperandList = (ins ptype0:$src1, type1:$src2);
438  let hasSideEffects = false;
439}
440
441// Generic pointer mask. type1 should be an integer with the same
442// bitwidth as the pointer type.
443def G_PTRMASK : GenericInstruction {
444  let OutOperandList = (outs ptype0:$dst);
445  let InOperandList = (ins ptype0:$src, type1:$bits);
446  let hasSideEffects = false;
447}
448
449// Generic signed integer minimum.
450def G_SMIN : GenericInstruction {
451  let OutOperandList = (outs type0:$dst);
452  let InOperandList = (ins type0:$src1, type0:$src2);
453  let hasSideEffects = false;
454  let isCommutable = true;
455}
456
457// Generic signed integer maximum.
458def G_SMAX : GenericInstruction {
459  let OutOperandList = (outs type0:$dst);
460  let InOperandList = (ins type0:$src1, type0:$src2);
461  let hasSideEffects = false;
462  let isCommutable = true;
463}
464
465// Generic unsigned integer minimum.
466def G_UMIN : GenericInstruction {
467  let OutOperandList = (outs type0:$dst);
468  let InOperandList = (ins type0:$src1, type0:$src2);
469  let hasSideEffects = false;
470  let isCommutable = true;
471}
472
473// Generic unsigned integer maximum.
474def G_UMAX : GenericInstruction {
475  let OutOperandList = (outs type0:$dst);
476  let InOperandList = (ins type0:$src1, type0:$src2);
477  let hasSideEffects = false;
478  let isCommutable = true;
479}
480
481// Generic integer absolute value.
482def G_ABS : GenericInstruction {
483  let OutOperandList = (outs type0:$dst);
484  let InOperandList = (ins type0:$src);
485  let hasSideEffects = false;
486}
487
488//------------------------------------------------------------------------------
489// Overflow ops
490//------------------------------------------------------------------------------
491
492// Generic unsigned addition producing a carry flag.
493def G_UADDO : GenericInstruction {
494  let OutOperandList = (outs type0:$dst, type1:$carry_out);
495  let InOperandList = (ins type0:$src1, type0:$src2);
496  let hasSideEffects = false;
497  let isCommutable = true;
498}
499
500// Generic unsigned addition consuming and producing a carry flag.
501def G_UADDE : GenericInstruction {
502  let OutOperandList = (outs type0:$dst, type1:$carry_out);
503  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
504  let hasSideEffects = false;
505}
506
507// Generic signed addition producing a carry flag.
508def G_SADDO : GenericInstruction {
509  let OutOperandList = (outs type0:$dst, type1:$carry_out);
510  let InOperandList = (ins type0:$src1, type0:$src2);
511  let hasSideEffects = false;
512  let isCommutable = true;
513}
514
515// Generic signed addition consuming and producing a carry flag.
516def G_SADDE : GenericInstruction {
517  let OutOperandList = (outs type0:$dst, type1:$carry_out);
518  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
519  let hasSideEffects = false;
520}
521
522// Generic unsigned subtraction producing a carry flag.
523def G_USUBO : GenericInstruction {
524  let OutOperandList = (outs type0:$dst, type1:$carry_out);
525  let InOperandList = (ins type0:$src1, type0:$src2);
526  let hasSideEffects = false;
527}
528// Generic unsigned subtraction consuming and producing a carry flag.
529def G_USUBE : GenericInstruction {
530  let OutOperandList = (outs type0:$dst, type1:$carry_out);
531  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
532  let hasSideEffects = false;
533}
534
535// Generic signed subtraction producing a carry flag.
536def G_SSUBO : GenericInstruction {
537  let OutOperandList = (outs type0:$dst, type1:$carry_out);
538  let InOperandList = (ins type0:$src1, type0:$src2);
539  let hasSideEffects = false;
540}
541
542// Generic signed subtraction consuming and producing a carry flag.
543def G_SSUBE : GenericInstruction {
544  let OutOperandList = (outs type0:$dst, type1:$carry_out);
545  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
546  let hasSideEffects = false;
547}
548
549// Generic unsigned multiplication producing a carry flag.
550def G_UMULO : GenericInstruction {
551  let OutOperandList = (outs type0:$dst, type1:$carry_out);
552  let InOperandList = (ins type0:$src1, type0:$src2);
553  let hasSideEffects = false;
554  let isCommutable = true;
555}
556
557// Generic signed multiplication producing a carry flag.
558def G_SMULO : GenericInstruction {
559  let OutOperandList = (outs type0:$dst, type1:$carry_out);
560  let InOperandList = (ins type0:$src1, type0:$src2);
561  let hasSideEffects = false;
562  let isCommutable = true;
563}
564
565// Multiply two numbers at twice the incoming bit width (unsigned) and return
566// the high half of the result.
567def G_UMULH : GenericInstruction {
568  let OutOperandList = (outs type0:$dst);
569  let InOperandList = (ins type0:$src1, type0:$src2);
570  let hasSideEffects = false;
571  let isCommutable = true;
572}
573
574// Multiply two numbers at twice the incoming bit width (signed) and return
575// the high half of the result.
576def G_SMULH : GenericInstruction {
577  let OutOperandList = (outs type0:$dst);
578  let InOperandList = (ins type0:$src1, type0:$src2);
579  let hasSideEffects = false;
580  let isCommutable = true;
581}
582
583//------------------------------------------------------------------------------
584// Saturating ops
585//------------------------------------------------------------------------------
586
587// Generic saturating unsigned addition.
588def G_UADDSAT : GenericInstruction {
589  let OutOperandList = (outs type0:$dst);
590  let InOperandList = (ins type0:$src1, type0:$src2);
591  let hasSideEffects = false;
592  let isCommutable = true;
593}
594
595// Generic saturating signed addition.
596def G_SADDSAT : GenericInstruction {
597  let OutOperandList = (outs type0:$dst);
598  let InOperandList = (ins type0:$src1, type0:$src2);
599  let hasSideEffects = false;
600  let isCommutable = true;
601}
602
603// Generic saturating unsigned subtraction.
604def G_USUBSAT : GenericInstruction {
605  let OutOperandList = (outs type0:$dst);
606  let InOperandList = (ins type0:$src1, type0:$src2);
607  let hasSideEffects = false;
608  let isCommutable = false;
609}
610
611// Generic saturating signed subtraction.
612def G_SSUBSAT : GenericInstruction {
613  let OutOperandList = (outs type0:$dst);
614  let InOperandList = (ins type0:$src1, type0:$src2);
615  let hasSideEffects = false;
616  let isCommutable = false;
617}
618
619// Generic saturating unsigned left shift.
620def G_USHLSAT : GenericInstruction {
621  let OutOperandList = (outs type0:$dst);
622  let InOperandList = (ins type0:$src1, type1:$src2);
623  let hasSideEffects = false;
624  let isCommutable = false;
625}
626
627// Generic saturating signed left shift.
628def G_SSHLSAT : GenericInstruction {
629  let OutOperandList = (outs type0:$dst);
630  let InOperandList = (ins type0:$src1, type1:$src2);
631  let hasSideEffects = false;
632  let isCommutable = false;
633}
634
635/// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point
636/// multiplication on 2 integers with the same width and scale. SCALE
637/// represents the scale of both operands as fixed point numbers. This
638/// SCALE parameter must be a constant integer. A scale of zero is
639/// effectively performing multiplication on 2 integers.
640def G_SMULFIX : GenericInstruction {
641  let OutOperandList = (outs type0:$dst);
642  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
643  let hasSideEffects = false;
644  let isCommutable = true;
645}
646
647def G_UMULFIX : GenericInstruction {
648  let OutOperandList = (outs type0:$dst);
649  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
650  let hasSideEffects = false;
651  let isCommutable = true;
652}
653
654/// Same as the corresponding unsaturated fixed point instructions, but the
655/// result is clamped between the min and max values representable by the
656/// bits of the first 2 operands.
657def G_SMULFIXSAT : GenericInstruction {
658  let OutOperandList = (outs type0:$dst);
659  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
660  let hasSideEffects = false;
661  let isCommutable = true;
662}
663
664def G_UMULFIXSAT : GenericInstruction {
665  let OutOperandList = (outs type0:$dst);
666  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
667  let hasSideEffects = false;
668  let isCommutable = true;
669}
670
671/// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on
672/// 2 integers with the same width and scale. SCALE represents the scale
673/// of both operands as fixed point numbers. This SCALE parameter must be a
674/// constant integer.
675def G_SDIVFIX : GenericInstruction {
676  let OutOperandList = (outs type0:$dst);
677  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
678  let hasSideEffects = false;
679  let isCommutable = false;
680}
681
682def G_UDIVFIX : GenericInstruction {
683  let OutOperandList = (outs type0:$dst);
684  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
685  let hasSideEffects = false;
686  let isCommutable = false;
687}
688
689/// Same as the corresponding unsaturated fixed point instructions,
690/// but the result is clamped between the min and max values
691/// representable by the bits of the first 2 operands.
692def G_SDIVFIXSAT : GenericInstruction {
693  let OutOperandList = (outs type0:$dst);
694  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
695  let hasSideEffects = false;
696  let isCommutable = false;
697}
698
699def G_UDIVFIXSAT : GenericInstruction {
700  let OutOperandList = (outs type0:$dst);
701  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
702  let hasSideEffects = false;
703  let isCommutable = false;
704}
705
706//------------------------------------------------------------------------------
707// Floating Point Unary Ops.
708//------------------------------------------------------------------------------
709
710def G_FNEG : GenericInstruction {
711  let OutOperandList = (outs type0:$dst);
712  let InOperandList = (ins type0:$src);
713  let hasSideEffects = false;
714}
715
716def G_FPEXT : GenericInstruction {
717  let OutOperandList = (outs type0:$dst);
718  let InOperandList = (ins type1:$src);
719  let hasSideEffects = false;
720}
721
722def G_FPTRUNC : GenericInstruction {
723  let OutOperandList = (outs type0:$dst);
724  let InOperandList = (ins type1:$src);
725  let hasSideEffects = false;
726}
727
728def G_FPTOSI : GenericInstruction {
729  let OutOperandList = (outs type0:$dst);
730  let InOperandList = (ins type1:$src);
731  let hasSideEffects = false;
732}
733
734def G_FPTOUI : GenericInstruction {
735  let OutOperandList = (outs type0:$dst);
736  let InOperandList = (ins type1:$src);
737  let hasSideEffects = false;
738}
739
740def G_SITOFP : GenericInstruction {
741  let OutOperandList = (outs type0:$dst);
742  let InOperandList = (ins type1:$src);
743  let hasSideEffects = false;
744}
745
746def G_UITOFP : GenericInstruction {
747  let OutOperandList = (outs type0:$dst);
748  let InOperandList = (ins type1:$src);
749  let hasSideEffects = false;
750}
751
752def G_FABS : GenericInstruction {
753  let OutOperandList = (outs type0:$dst);
754  let InOperandList = (ins type0:$src);
755  let hasSideEffects = false;
756}
757
758def G_FCOPYSIGN : GenericInstruction {
759  let OutOperandList = (outs type0:$dst);
760  let InOperandList = (ins type0:$src0, type1:$src1);
761  let hasSideEffects = false;
762}
763
764def G_FCANONICALIZE : GenericInstruction {
765  let OutOperandList = (outs type0:$dst);
766  let InOperandList = (ins type0:$src);
767  let hasSideEffects = false;
768}
769
770// Generic opcode equivalent to the llvm.is_fpclass intrinsic.
771def G_IS_FPCLASS: GenericInstruction {
772  let OutOperandList = (outs type0:$dst);
773  let InOperandList = (ins type1:$src, unknown:$test);
774  let hasSideEffects = false;
775}
776
777// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
778// values.
779//
780// In the case where a single input is a NaN (either signaling or quiet),
781// the non-NaN input is returned.
782//
783// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
784def G_FMINNUM : GenericInstruction {
785  let OutOperandList = (outs type0:$dst);
786  let InOperandList = (ins type0:$src1, type0:$src2);
787  let hasSideEffects = false;
788  let isCommutable = true;
789}
790
791def G_FMAXNUM : GenericInstruction {
792  let OutOperandList = (outs type0:$dst);
793  let InOperandList = (ins type0:$src1, type0:$src2);
794  let hasSideEffects = false;
795  let isCommutable = true;
796}
797
798// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
799// two values, following the IEEE-754 2008 definition. This differs from
800// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
801// signaling NaN, returns a quiet NaN.
802def G_FMINNUM_IEEE : GenericInstruction {
803  let OutOperandList = (outs type0:$dst);
804  let InOperandList = (ins type0:$src1, type0:$src2);
805  let hasSideEffects = false;
806  let isCommutable = true;
807}
808
809def G_FMAXNUM_IEEE : GenericInstruction {
810  let OutOperandList = (outs type0:$dst);
811  let InOperandList = (ins type0:$src1, type0:$src2);
812  let hasSideEffects = false;
813  let isCommutable = true;
814}
815
816// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
817// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
818// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.
819def G_FMINIMUM : GenericInstruction {
820  let OutOperandList = (outs type0:$dst);
821  let InOperandList = (ins type0:$src1, type0:$src2);
822  let hasSideEffects = false;
823  let isCommutable = true;
824}
825
826def G_FMAXIMUM : GenericInstruction {
827  let OutOperandList = (outs type0:$dst);
828  let InOperandList = (ins type0:$src1, type0:$src2);
829  let hasSideEffects = false;
830  let isCommutable = true;
831}
832
833//------------------------------------------------------------------------------
834// Floating Point Binary ops.
835//------------------------------------------------------------------------------
836
837// Generic FP addition.
838def G_FADD : GenericInstruction {
839  let OutOperandList = (outs type0:$dst);
840  let InOperandList = (ins type0:$src1, type0:$src2);
841  let hasSideEffects = false;
842  let isCommutable = true;
843}
844
845// Generic FP subtraction.
846def G_FSUB : GenericInstruction {
847  let OutOperandList = (outs type0:$dst);
848  let InOperandList = (ins type0:$src1, type0:$src2);
849  let hasSideEffects = false;
850  let isCommutable = false;
851}
852
853// Generic FP multiplication.
854def G_FMUL : GenericInstruction {
855  let OutOperandList = (outs type0:$dst);
856  let InOperandList = (ins type0:$src1, type0:$src2);
857  let hasSideEffects = false;
858  let isCommutable = true;
859}
860
861// Generic fused multiply-add instruction.
862// Behaves like llvm fma intrinsic ie src1 * src2 + src3
863def G_FMA : GenericInstruction {
864  let OutOperandList = (outs type0:$dst);
865  let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
866  let hasSideEffects = false;
867  let isCommutable = false;
868}
869
870/// Generic FP multiply and add. Perform a * b + c, while getting the
871/// same result as the separately rounded operations, unlike G_FMA.
872def G_FMAD : GenericInstruction {
873  let OutOperandList = (outs type0:$dst);
874  let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
875  let hasSideEffects = false;
876  let isCommutable = false;
877}
878
879// Generic FP division.
880def G_FDIV : GenericInstruction {
881  let OutOperandList = (outs type0:$dst);
882  let InOperandList = (ins type0:$src1, type0:$src2);
883  let hasSideEffects = false;
884}
885
886// Generic FP remainder.
887def G_FREM : GenericInstruction {
888  let OutOperandList = (outs type0:$dst);
889  let InOperandList = (ins type0:$src1, type0:$src2);
890  let hasSideEffects = false;
891}
892
893// Floating point exponentiation.
894def G_FPOW : GenericInstruction {
895  let OutOperandList = (outs type0:$dst);
896  let InOperandList = (ins type0:$src1, type0:$src2);
897  let hasSideEffects = false;
898}
899
900// Floating point exponentiation, with an integer power.
901def G_FPOWI : GenericInstruction {
902  let OutOperandList = (outs type0:$dst);
903  let InOperandList = (ins type0:$src0, type1:$src1);
904  let hasSideEffects = false;
905}
906
907// Floating point base-e exponential of a value.
908def G_FEXP : GenericInstruction {
909  let OutOperandList = (outs type0:$dst);
910  let InOperandList = (ins type0:$src1);
911  let hasSideEffects = false;
912}
913
914// Floating point base-2 exponential of a value.
915def G_FEXP2 : GenericInstruction {
916  let OutOperandList = (outs type0:$dst);
917  let InOperandList = (ins type0:$src1);
918  let hasSideEffects = false;
919}
920
921// Floating point base-10 exponential of a value.
922def G_FEXP10 : GenericInstruction {
923  let OutOperandList = (outs type0:$dst);
924  let InOperandList = (ins type0:$src1);
925  let hasSideEffects = false;
926}
927
928// Floating point base-e logarithm of a value.
929def G_FLOG : GenericInstruction {
930  let OutOperandList = (outs type0:$dst);
931  let InOperandList = (ins type0:$src1);
932  let hasSideEffects = false;
933}
934
935// Floating point base-2 logarithm of a value.
936def G_FLOG2 : GenericInstruction {
937  let OutOperandList = (outs type0:$dst);
938  let InOperandList = (ins type0:$src1);
939  let hasSideEffects = false;
940}
941
942// Floating point base-10 logarithm of a value.
943def G_FLOG10 : GenericInstruction {
944  let OutOperandList = (outs type0:$dst);
945  let InOperandList = (ins type0:$src1);
946  let hasSideEffects = false;
947}
948
949// Floating point x * 2^n
950def G_FLDEXP : GenericInstruction {
951  let OutOperandList = (outs type0:$dst);
952  let InOperandList = (ins type0:$src0, type1:$src1);
953  let hasSideEffects = false;
954}
955
956// Floating point frexp
957def G_FFREXP : GenericInstruction {
958  let OutOperandList = (outs type0:$dst0, type1:$dst1);
959  let InOperandList = (ins type0:$src0);
960  let hasSideEffects = false;
961}
962
963// Floating point ceiling of a value.
964def G_FCEIL : GenericInstruction {
965  let OutOperandList = (outs type0:$dst);
966  let InOperandList = (ins type0:$src1);
967  let hasSideEffects = false;
968}
969
970// Floating point cosine of a value.
971def G_FCOS : GenericInstruction {
972  let OutOperandList = (outs type0:$dst);
973  let InOperandList = (ins type0:$src1);
974  let hasSideEffects = false;
975}
976
977// Floating point sine of a value.
978def G_FSIN : GenericInstruction {
979  let OutOperandList = (outs type0:$dst);
980  let InOperandList = (ins type0:$src1);
981  let hasSideEffects = false;
982}
983
984// Floating point square root of a value.
985// This returns NaN for negative nonzero values.
986// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
987// libm-conformant.
988def G_FSQRT : GenericInstruction {
989  let OutOperandList = (outs type0:$dst);
990  let InOperandList = (ins type0:$src1);
991  let hasSideEffects = false;
992}
993
994// Floating point floor of a value.
995def G_FFLOOR : GenericInstruction {
996  let OutOperandList = (outs type0:$dst);
997  let InOperandList = (ins type0:$src1);
998  let hasSideEffects = false;
999}
1000
1001// Floating point round to next integer.
1002def G_FRINT : GenericInstruction {
1003  let OutOperandList = (outs type0:$dst);
1004  let InOperandList = (ins type0:$src1);
1005  let hasSideEffects = false;
1006}
1007
1008// Floating point round to the nearest integer.
1009def G_FNEARBYINT : GenericInstruction {
1010  let OutOperandList = (outs type0:$dst);
1011  let InOperandList = (ins type0:$src1);
1012  let hasSideEffects = false;
1013}
1014
1015//------------------------------------------------------------------------------
1016// Access to floating-point environment.
1017//------------------------------------------------------------------------------
1018
1019// These operations read/write floating-point environment. The interaction with
1020// it is modeled as a side effect, because constrained intrinsics use the same
1021// method.
1022
1023// Reading floating-point control modes.
1024def G_GET_FPMODE : GenericInstruction {
1025  let OutOperandList = (outs type0:$dst);
1026  let InOperandList = (ins);
1027  let hasSideEffects = true;
1028}
1029
1030// Setting floating-point control modes.
1031def G_SET_FPMODE : GenericInstruction {
1032  let OutOperandList = (outs);
1033  let InOperandList = (ins type0:$src);
1034  let hasSideEffects = true;
1035}
1036
1037// Setting floating-point control modes to default state.
1038def G_RESET_FPMODE : GenericInstruction {
1039  let OutOperandList = (outs);
1040  let InOperandList = (ins);
1041  let hasSideEffects = true;
1042}
1043
1044//------------------------------------------------------------------------------
1045// Opcodes for LLVM Intrinsics
1046//------------------------------------------------------------------------------
1047def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction {
1048  let OutOperandList = (outs type0:$dst);
1049  let InOperandList = (ins type1:$src1, i32imm:$round_mode);
1050  let hasSideEffects = false;
1051}
1052
1053def G_INTRINSIC_TRUNC : GenericInstruction {
1054  let OutOperandList = (outs type0:$dst);
1055  let InOperandList = (ins type0:$src1);
1056  let hasSideEffects = false;
1057}
1058
1059def G_INTRINSIC_ROUND : GenericInstruction {
1060  let OutOperandList = (outs type0:$dst);
1061  let InOperandList = (ins type0:$src1);
1062  let hasSideEffects = false;
1063}
1064
1065def G_INTRINSIC_LRINT : GenericInstruction {
1066  let OutOperandList = (outs type0:$dst);
1067  let InOperandList = (ins type1:$src);
1068  let hasSideEffects = false;
1069}
1070
1071def G_INTRINSIC_ROUNDEVEN : GenericInstruction {
1072  let OutOperandList = (outs type0:$dst);
1073  let InOperandList = (ins type0:$src1);
1074  let hasSideEffects = false;
1075}
1076
1077def G_READCYCLECOUNTER : GenericInstruction {
1078  let OutOperandList = (outs type0:$dst);
1079  let InOperandList = (ins);
1080  let hasSideEffects = true;
1081}
1082
1083//------------------------------------------------------------------------------
1084// Memory ops
1085//------------------------------------------------------------------------------
1086
1087// Generic load. Expects a MachineMemOperand in addition to explicit
1088// operands. If the result size is larger than the memory size, the
1089// high bits are undefined. If the result is a vector type and larger
1090// than the memory size, the high elements are undefined (i.e. this is
1091// not a per-element, vector anyextload)
1092def G_LOAD : GenericInstruction {
1093  let OutOperandList = (outs type0:$dst);
1094  let InOperandList = (ins ptype1:$addr);
1095  let hasSideEffects = false;
1096  let mayLoad = true;
1097}
1098
1099// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
1100def G_SEXTLOAD : GenericInstruction {
1101  let OutOperandList = (outs type0:$dst);
1102  let InOperandList = (ins ptype1:$addr);
1103  let hasSideEffects = false;
1104  let mayLoad = true;
1105}
1106
1107// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
1108def G_ZEXTLOAD : GenericInstruction {
1109  let OutOperandList = (outs type0:$dst);
1110  let InOperandList = (ins ptype1:$addr);
1111  let hasSideEffects = false;
1112  let mayLoad = true;
1113}
1114
1115// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
1116// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
1117//  then the value is loaded from $newaddr.
1118def G_INDEXED_LOAD : GenericInstruction {
1119  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1120  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1121  let hasSideEffects = false;
1122  let mayLoad = true;
1123}
1124
1125// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
1126def G_INDEXED_SEXTLOAD : GenericInstruction {
1127  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1128  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1129  let hasSideEffects = false;
1130  let mayLoad = true;
1131}
1132
1133// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
1134def G_INDEXED_ZEXTLOAD : GenericInstruction {
1135  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1136  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1137  let hasSideEffects = false;
1138  let mayLoad = true;
1139}
1140
1141// Generic store. Expects a MachineMemOperand in addition to explicit operands.
1142def G_STORE : GenericInstruction {
1143  let OutOperandList = (outs);
1144  let InOperandList = (ins type0:$src, ptype1:$addr);
1145  let hasSideEffects = false;
1146  let mayStore = true;
1147}
1148
1149// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
1150def G_INDEXED_STORE : GenericInstruction {
1151  let OutOperandList = (outs ptype0:$newaddr);
1152  let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
1153                           unknown:$am);
1154  let hasSideEffects = false;
1155  let mayStore = true;
1156}
1157
1158// Generic atomic cmpxchg with internal success check. Expects a
1159// MachineMemOperand in addition to explicit operands.
1160def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
1161  let OutOperandList = (outs type0:$oldval, type1:$success);
1162  let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
1163  let hasSideEffects = false;
1164  let mayLoad = true;
1165  let mayStore = true;
1166}
1167
1168// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
1169// operands.
1170def G_ATOMIC_CMPXCHG : GenericInstruction {
1171  let OutOperandList = (outs type0:$oldval);
1172  let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
1173  let hasSideEffects = false;
1174  let mayLoad = true;
1175  let mayStore = true;
1176}
1177
1178// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
1179// operands.
1180class G_ATOMICRMW_OP : GenericInstruction {
1181  let OutOperandList = (outs type0:$oldval);
1182  let InOperandList = (ins ptype1:$addr, type0:$val);
1183  let hasSideEffects = false;
1184  let mayLoad = true;
1185  let mayStore = true;
1186}
1187
1188def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
1189def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
1190def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
1191def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
1192def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
1193def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
1194def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
1195def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
1196def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
1197def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
1198def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
1199def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
1200def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
1201def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP;
1202def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP;
1203def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP;
1204def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP;
1205
1206def G_FENCE : GenericInstruction {
1207  let OutOperandList = (outs);
1208  let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
1209  let hasSideEffects = true;
1210}
1211
1212// Generic opcode equivalent to the llvm.prefetch intrinsic.
1213def G_PREFETCH : GenericInstruction {
1214  let OutOperandList = (outs);
1215  let InOperandList = (ins ptype0:$address, i32imm:$rw, i32imm:$locality, i32imm:$cachetype);
1216  let hasSideEffects = true;
1217  let mayLoad = true;
1218  let mayStore = true;
1219}
1220
1221//------------------------------------------------------------------------------
1222// Variadic ops
1223//------------------------------------------------------------------------------
1224
1225// Extract a register of the specified size, starting from the block given by
1226// index. This will almost certainly be mapped to sub-register COPYs after
1227// register banks have been selected.
1228def G_EXTRACT : GenericInstruction {
1229  let OutOperandList = (outs type0:$res);
1230  let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
1231  let hasSideEffects = false;
1232}
1233
1234// Extract multiple registers specified size, starting from blocks given by
1235// indexes. This will almost certainly be mapped to sub-register COPYs after
1236// register banks have been selected.
1237// The output operands are always ordered from lowest bits to highest:
1238//   %bits_0_7:(s8), %bits_8_15:(s8),
1239//       %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
1240def G_UNMERGE_VALUES : GenericInstruction {
1241  let OutOperandList = (outs type0:$dst0, variable_ops);
1242  let InOperandList = (ins type1:$src);
1243  let hasSideEffects = false;
1244  let variadicOpsType = type0;
1245}
1246
1247// Insert a smaller register into a larger one at the specified bit-index.
1248def G_INSERT : GenericInstruction {
1249  let OutOperandList = (outs type0:$dst);
1250  let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
1251  let hasSideEffects = false;
1252}
1253
1254// Concatenate multiple registers of the same size into a wider register.
1255// The input operands are always ordered from lowest bits to highest:
1256//   %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
1257//                             %bits_16_23:(s8), %bits_24_31:(s8)
1258def G_MERGE_VALUES : GenericInstruction {
1259  let OutOperandList = (outs type0:$dst);
1260  let InOperandList = (ins type1:$src0, variable_ops);
1261  let hasSideEffects = false;
1262  let variadicOpsType = type1;
1263}
1264
1265/// Create a vector from multiple scalar registers. No implicit
1266/// conversion is performed (i.e. the result element type must be the
1267/// same as all source operands)
1268def G_BUILD_VECTOR : GenericInstruction {
1269  let OutOperandList = (outs type0:$dst);
1270  let InOperandList = (ins type1:$src0, variable_ops);
1271  let hasSideEffects = false;
1272  let variadicOpsType = type1;
1273}
1274
1275/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
1276/// destination vector elt type.
1277def G_BUILD_VECTOR_TRUNC : GenericInstruction {
1278  let OutOperandList = (outs type0:$dst);
1279  let InOperandList = (ins type1:$src0, variable_ops);
1280  let hasSideEffects = false;
1281}
1282
1283/// Create a vector by concatenating vectors together.
1284def G_CONCAT_VECTORS : GenericInstruction {
1285  let OutOperandList = (outs type0:$dst);
1286  let InOperandList = (ins type1:$src0, variable_ops);
1287  let hasSideEffects = false;
1288}
1289
1290// Intrinsic without side effects.
1291def G_INTRINSIC : GenericInstruction {
1292  let OutOperandList = (outs);
1293  let InOperandList = (ins unknown:$intrin, variable_ops);
1294  let hasSideEffects = false;
1295}
1296
1297// Intrinsic with side effects.
1298def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
1299  let OutOperandList = (outs);
1300  let InOperandList = (ins unknown:$intrin, variable_ops);
1301  let hasSideEffects = true;
1302  let mayLoad = true;
1303  let mayStore = true;
1304}
1305
1306// Convergent intrinsic without side effects.
1307def G_INTRINSIC_CONVERGENT : GenericInstruction {
1308  let OutOperandList = (outs);
1309  let InOperandList = (ins unknown:$intrin, variable_ops);
1310  let hasSideEffects = false;
1311  let isConvergent = true;
1312}
1313
1314// Convergent intrinsic with side effects.
1315def G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS : GenericInstruction {
1316  let OutOperandList = (outs);
1317  let InOperandList = (ins unknown:$intrin, variable_ops);
1318  let hasSideEffects = true;
1319  let mayLoad = true;
1320  let mayStore = true;
1321  let isConvergent = true;
1322}
1323
1324//------------------------------------------------------------------------------
1325// Branches.
1326//------------------------------------------------------------------------------
1327
1328// Generic unconditional branch.
1329def G_BR : GenericInstruction {
1330  let OutOperandList = (outs);
1331  let InOperandList = (ins unknown:$src1);
1332  let hasSideEffects = false;
1333  let isBranch = true;
1334  let isTerminator = true;
1335  let isBarrier = true;
1336}
1337
1338// Generic conditional branch.
1339def G_BRCOND : GenericInstruction {
1340  let OutOperandList = (outs);
1341  let InOperandList = (ins type0:$tst, unknown:$truebb);
1342  let hasSideEffects = false;
1343  let isBranch = true;
1344  let isTerminator = true;
1345}
1346
1347// Generic indirect branch.
1348def G_BRINDIRECT : GenericInstruction {
1349  let OutOperandList = (outs);
1350  let InOperandList = (ins type0:$src1);
1351  let hasSideEffects = false;
1352  let isBranch = true;
1353  let isTerminator = true;
1354  let isBarrier = true;
1355  let isIndirectBranch = true;
1356}
1357
1358// Generic branch to jump table entry
1359def G_BRJT : GenericInstruction {
1360  let OutOperandList = (outs);
1361  let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1362  let hasSideEffects = false;
1363  let isBranch = true;
1364  let isTerminator = true;
1365  let isBarrier = true;
1366  let isIndirectBranch = true;
1367}
1368
1369// A marker to signal the following code is an invoke region, that may throw
1370// an exception and therefore not return.
1371def G_INVOKE_REGION_START : GenericInstruction {
1372  let OutOperandList = (outs);
1373  let InOperandList = (ins);
1374  let isTerminator = true; // This must be a terminator.
1375  let hasSideEffects = false;
1376}
1377
1378def G_READ_REGISTER : GenericInstruction {
1379  let OutOperandList = (outs type0:$dst);
1380  let InOperandList = (ins unknown:$register);
1381  let hasSideEffects = true;
1382
1383  // Assume convergent. It's probably not worth the effort of somehow
1384  // modeling convergent and nonconvergent register accesses.
1385  let isConvergent = true;
1386}
1387
1388def G_WRITE_REGISTER : GenericInstruction {
1389  let OutOperandList = (outs);
1390  let InOperandList = (ins unknown:$register, type0:$value);
1391  let hasSideEffects = true;
1392
1393  // Assume convergent. It's probably not worth the effort of somehow
1394  // modeling convergent and nonconvergent register accesses.
1395  let isConvergent = true;
1396}
1397
1398//------------------------------------------------------------------------------
1399// Vector ops
1400//------------------------------------------------------------------------------
1401
1402// Generic insertelement.
1403def G_INSERT_VECTOR_ELT : GenericInstruction {
1404  let OutOperandList = (outs type0:$dst);
1405  let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1406  let hasSideEffects = false;
1407}
1408
1409// Generic extractelement.
1410def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1411  let OutOperandList = (outs type0:$dst);
1412  let InOperandList = (ins type1:$src, type2:$idx);
1413  let hasSideEffects = false;
1414}
1415
1416// Generic shufflevector.
1417//
1418// The mask operand should be an IR Constant which exactly matches the
1419// corresponding mask for the IR shufflevector instruction.
1420def G_SHUFFLE_VECTOR: GenericInstruction {
1421  let OutOperandList = (outs type0:$dst);
1422  let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1423  let hasSideEffects = false;
1424}
1425
1426//------------------------------------------------------------------------------
1427// Vector reductions
1428//------------------------------------------------------------------------------
1429
1430class VectorReduction : GenericInstruction {
1431  let OutOperandList = (outs type0:$dst);
1432  let InOperandList = (ins type1:$v);
1433  let hasSideEffects = false;
1434}
1435
1436def G_VECREDUCE_SEQ_FADD : GenericInstruction {
1437  let OutOperandList = (outs type0:$dst);
1438  let InOperandList = (ins type1:$acc, type2:$v);
1439  let hasSideEffects = false;
1440}
1441
1442def G_VECREDUCE_SEQ_FMUL : GenericInstruction {
1443  let OutOperandList = (outs type0:$dst);
1444  let InOperandList = (ins type1:$acc, type2:$v);
1445  let hasSideEffects = false;
1446}
1447
1448def G_VECREDUCE_FADD : VectorReduction;
1449def G_VECREDUCE_FMUL : VectorReduction;
1450
1451def G_VECREDUCE_FMAX : VectorReduction;
1452def G_VECREDUCE_FMIN : VectorReduction;
1453def G_VECREDUCE_FMAXIMUM : VectorReduction;
1454def G_VECREDUCE_FMINIMUM : VectorReduction;
1455
1456def G_VECREDUCE_ADD : VectorReduction;
1457def G_VECREDUCE_MUL : VectorReduction;
1458def G_VECREDUCE_AND : VectorReduction;
1459def G_VECREDUCE_OR : VectorReduction;
1460def G_VECREDUCE_XOR : VectorReduction;
1461def G_VECREDUCE_SMAX : VectorReduction;
1462def G_VECREDUCE_SMIN : VectorReduction;
1463def G_VECREDUCE_UMAX : VectorReduction;
1464def G_VECREDUCE_UMIN : VectorReduction;
1465
1466//------------------------------------------------------------------------------
1467// Constrained floating point ops
1468//------------------------------------------------------------------------------
1469
1470def G_STRICT_FADD : ConstrainedInstruction<G_FADD>;
1471def G_STRICT_FSUB : ConstrainedInstruction<G_FSUB>;
1472def G_STRICT_FMUL : ConstrainedInstruction<G_FMUL>;
1473def G_STRICT_FDIV : ConstrainedInstruction<G_FDIV>;
1474def G_STRICT_FREM : ConstrainedInstruction<G_FREM>;
1475def G_STRICT_FMA : ConstrainedInstruction<G_FMA>;
1476def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>;
1477def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>;
1478
1479//------------------------------------------------------------------------------
1480// Memory intrinsics
1481//------------------------------------------------------------------------------
1482
1483def G_MEMCPY : GenericInstruction {
1484  let OutOperandList = (outs);
1485  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1486  let hasSideEffects = false;
1487  let mayLoad = true;
1488  let mayStore = true;
1489}
1490
1491def G_MEMCPY_INLINE : GenericInstruction {
1492  let OutOperandList = (outs);
1493  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size);
1494  let hasSideEffects = false;
1495  let mayLoad = true;
1496  let mayStore = true;
1497}
1498
1499def G_MEMMOVE : GenericInstruction {
1500  let OutOperandList = (outs);
1501  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1502  let hasSideEffects = false;
1503  let mayLoad = true;
1504  let mayStore = true;
1505}
1506
1507def G_MEMSET : GenericInstruction {
1508  let OutOperandList = (outs);
1509  let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
1510  let hasSideEffects = false;
1511  let mayStore = true;
1512}
1513
1514def G_BZERO : GenericInstruction {
1515  let OutOperandList = (outs);
1516  let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall);
1517  let hasSideEffects = false;
1518  let mayStore = true;
1519}
1520
1521//------------------------------------------------------------------------------
1522// Bitfield extraction.
1523//------------------------------------------------------------------------------
1524
1525// Generic signed bitfield extraction. The operands are in the range
1526// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1527def G_SBFX : GenericInstruction {
1528  let OutOperandList = (outs type0:$dst);
1529  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1530  let hasSideEffects = false;
1531}
1532
1533// Generic unsigned bitfield extraction. The operands are in the range
1534// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1535def G_UBFX : GenericInstruction {
1536  let OutOperandList = (outs type0:$dst);
1537  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1538  let hasSideEffects = false;
1539}
1540
1541//------------------------------------------------------------------------------
1542// Optimization hints
1543//------------------------------------------------------------------------------
1544
1545// Asserts that an operation has already been zero-extended from a specific
1546// type.
1547def G_ASSERT_ZEXT : GenericInstruction {
1548  let OutOperandList = (outs type0:$dst);
1549  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1550  let hasSideEffects = false;
1551}
1552
1553// Asserts that an operation has already been sign-extended from a specific
1554// type.
1555def G_ASSERT_SEXT : GenericInstruction {
1556  let OutOperandList = (outs type0:$dst);
1557  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1558  let hasSideEffects = false;
1559}
1560
1561// Asserts that a value has at least the given alignment.
1562def G_ASSERT_ALIGN : GenericInstruction {
1563  let OutOperandList = (outs type0:$dst);
1564  let InOperandList = (ins type0:$src, untyped_imm_0:$align);
1565  let hasSideEffects = false;
1566}
1567
1568// Prevent constant folding of the source value with any users.
1569def G_CONSTANT_FOLD_BARRIER : GenericInstruction {
1570  let OutOperandList = (outs type0:$dst);
1571  let InOperandList = (ins type0:$src);
1572  let hasSideEffects = false;
1573}
1574