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 environment.
1024def G_GET_FPENV : GenericInstruction {
1025  let OutOperandList = (outs type0:$dst);
1026  let InOperandList = (ins);
1027  let hasSideEffects = true;
1028}
1029
1030// Setting floating-point environment.
1031def G_SET_FPENV : GenericInstruction {
1032  let OutOperandList = (outs);
1033  let InOperandList = (ins type0:$src);
1034  let hasSideEffects = true;
1035}
1036
1037// Setting default floating-point environment.
1038def G_RESET_FPENV : GenericInstruction {
1039  let OutOperandList = (outs);
1040  let InOperandList = (ins);
1041  let hasSideEffects = true;
1042}
1043
1044// Reading floating-point control modes.
1045def G_GET_FPMODE : GenericInstruction {
1046  let OutOperandList = (outs type0:$dst);
1047  let InOperandList = (ins);
1048  let hasSideEffects = true;
1049}
1050
1051// Setting floating-point control modes.
1052def G_SET_FPMODE : GenericInstruction {
1053  let OutOperandList = (outs);
1054  let InOperandList = (ins type0:$src);
1055  let hasSideEffects = true;
1056}
1057
1058// Setting floating-point control modes to default state.
1059def G_RESET_FPMODE : GenericInstruction {
1060  let OutOperandList = (outs);
1061  let InOperandList = (ins);
1062  let hasSideEffects = true;
1063}
1064
1065//------------------------------------------------------------------------------
1066// Opcodes for LLVM Intrinsics
1067//------------------------------------------------------------------------------
1068def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction {
1069  let OutOperandList = (outs type0:$dst);
1070  let InOperandList = (ins type1:$src1, i32imm:$round_mode);
1071  let hasSideEffects = false;
1072}
1073
1074def G_INTRINSIC_TRUNC : GenericInstruction {
1075  let OutOperandList = (outs type0:$dst);
1076  let InOperandList = (ins type0:$src1);
1077  let hasSideEffects = false;
1078}
1079
1080def G_INTRINSIC_ROUND : GenericInstruction {
1081  let OutOperandList = (outs type0:$dst);
1082  let InOperandList = (ins type0:$src1);
1083  let hasSideEffects = false;
1084}
1085
1086def G_INTRINSIC_LRINT : GenericInstruction {
1087  let OutOperandList = (outs type0:$dst);
1088  let InOperandList = (ins type1:$src);
1089  let hasSideEffects = false;
1090}
1091
1092def G_INTRINSIC_ROUNDEVEN : GenericInstruction {
1093  let OutOperandList = (outs type0:$dst);
1094  let InOperandList = (ins type0:$src1);
1095  let hasSideEffects = false;
1096}
1097
1098def G_READCYCLECOUNTER : GenericInstruction {
1099  let OutOperandList = (outs type0:$dst);
1100  let InOperandList = (ins);
1101  let hasSideEffects = true;
1102}
1103
1104//------------------------------------------------------------------------------
1105// Memory ops
1106//------------------------------------------------------------------------------
1107
1108// Generic load. Expects a MachineMemOperand in addition to explicit
1109// operands. If the result size is larger than the memory size, the
1110// high bits are undefined. If the result is a vector type and larger
1111// than the memory size, the high elements are undefined (i.e. this is
1112// not a per-element, vector anyextload)
1113def G_LOAD : GenericInstruction {
1114  let OutOperandList = (outs type0:$dst);
1115  let InOperandList = (ins ptype1:$addr);
1116  let hasSideEffects = false;
1117  let mayLoad = true;
1118}
1119
1120// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
1121def G_SEXTLOAD : GenericInstruction {
1122  let OutOperandList = (outs type0:$dst);
1123  let InOperandList = (ins ptype1:$addr);
1124  let hasSideEffects = false;
1125  let mayLoad = true;
1126}
1127
1128// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
1129def G_ZEXTLOAD : GenericInstruction {
1130  let OutOperandList = (outs type0:$dst);
1131  let InOperandList = (ins ptype1:$addr);
1132  let hasSideEffects = false;
1133  let mayLoad = true;
1134}
1135
1136// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
1137// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
1138//  then the value is loaded from $newaddr.
1139def G_INDEXED_LOAD : GenericInstruction {
1140  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1141  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1142  let hasSideEffects = false;
1143  let mayLoad = true;
1144}
1145
1146// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
1147def G_INDEXED_SEXTLOAD : GenericInstruction {
1148  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1149  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1150  let hasSideEffects = false;
1151  let mayLoad = true;
1152}
1153
1154// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
1155def G_INDEXED_ZEXTLOAD : GenericInstruction {
1156  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1157  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1158  let hasSideEffects = false;
1159  let mayLoad = true;
1160}
1161
1162// Generic store. Expects a MachineMemOperand in addition to explicit operands.
1163def G_STORE : GenericInstruction {
1164  let OutOperandList = (outs);
1165  let InOperandList = (ins type0:$src, ptype1:$addr);
1166  let hasSideEffects = false;
1167  let mayStore = true;
1168}
1169
1170// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
1171def G_INDEXED_STORE : GenericInstruction {
1172  let OutOperandList = (outs ptype0:$newaddr);
1173  let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
1174                           unknown:$am);
1175  let hasSideEffects = false;
1176  let mayStore = true;
1177}
1178
1179// Generic atomic cmpxchg with internal success check. Expects a
1180// MachineMemOperand in addition to explicit operands.
1181def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
1182  let OutOperandList = (outs type0:$oldval, type1:$success);
1183  let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
1184  let hasSideEffects = false;
1185  let mayLoad = true;
1186  let mayStore = true;
1187}
1188
1189// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
1190// operands.
1191def G_ATOMIC_CMPXCHG : GenericInstruction {
1192  let OutOperandList = (outs type0:$oldval);
1193  let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
1194  let hasSideEffects = false;
1195  let mayLoad = true;
1196  let mayStore = true;
1197}
1198
1199// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
1200// operands.
1201class G_ATOMICRMW_OP : GenericInstruction {
1202  let OutOperandList = (outs type0:$oldval);
1203  let InOperandList = (ins ptype1:$addr, type0:$val);
1204  let hasSideEffects = false;
1205  let mayLoad = true;
1206  let mayStore = true;
1207}
1208
1209def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
1210def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
1211def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
1212def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
1213def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
1214def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
1215def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
1216def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
1217def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
1218def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
1219def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
1220def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
1221def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
1222def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP;
1223def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP;
1224def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP;
1225def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP;
1226
1227def G_FENCE : GenericInstruction {
1228  let OutOperandList = (outs);
1229  let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
1230  let hasSideEffects = true;
1231}
1232
1233// Generic opcode equivalent to the llvm.prefetch intrinsic.
1234def G_PREFETCH : GenericInstruction {
1235  let OutOperandList = (outs);
1236  let InOperandList = (ins ptype0:$address, i32imm:$rw, i32imm:$locality, i32imm:$cachetype);
1237  let hasSideEffects = true;
1238  let mayLoad = true;
1239  let mayStore = true;
1240}
1241
1242//------------------------------------------------------------------------------
1243// Variadic ops
1244//------------------------------------------------------------------------------
1245
1246// Extract a register of the specified size, starting from the block given by
1247// index. This will almost certainly be mapped to sub-register COPYs after
1248// register banks have been selected.
1249def G_EXTRACT : GenericInstruction {
1250  let OutOperandList = (outs type0:$res);
1251  let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
1252  let hasSideEffects = false;
1253}
1254
1255// Extract multiple registers specified size, starting from blocks given by
1256// indexes. This will almost certainly be mapped to sub-register COPYs after
1257// register banks have been selected.
1258// The output operands are always ordered from lowest bits to highest:
1259//   %bits_0_7:(s8), %bits_8_15:(s8),
1260//       %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
1261def G_UNMERGE_VALUES : GenericInstruction {
1262  let OutOperandList = (outs type0:$dst0, variable_ops);
1263  let InOperandList = (ins type1:$src);
1264  let hasSideEffects = false;
1265  let variadicOpsType = type0;
1266}
1267
1268// Insert a smaller register into a larger one at the specified bit-index.
1269def G_INSERT : GenericInstruction {
1270  let OutOperandList = (outs type0:$dst);
1271  let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
1272  let hasSideEffects = false;
1273}
1274
1275// Concatenate multiple registers of the same size into a wider register.
1276// The input operands are always ordered from lowest bits to highest:
1277//   %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
1278//                             %bits_16_23:(s8), %bits_24_31:(s8)
1279def G_MERGE_VALUES : GenericInstruction {
1280  let OutOperandList = (outs type0:$dst);
1281  let InOperandList = (ins type1:$src0, variable_ops);
1282  let hasSideEffects = false;
1283  let variadicOpsType = type1;
1284}
1285
1286/// Create a vector from multiple scalar registers. No implicit
1287/// conversion is performed (i.e. the result element type must be the
1288/// same as all source operands)
1289def G_BUILD_VECTOR : GenericInstruction {
1290  let OutOperandList = (outs type0:$dst);
1291  let InOperandList = (ins type1:$src0, variable_ops);
1292  let hasSideEffects = false;
1293  let variadicOpsType = type1;
1294}
1295
1296/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
1297/// destination vector elt type.
1298def G_BUILD_VECTOR_TRUNC : GenericInstruction {
1299  let OutOperandList = (outs type0:$dst);
1300  let InOperandList = (ins type1:$src0, variable_ops);
1301  let hasSideEffects = false;
1302}
1303
1304/// Create a vector by concatenating vectors together.
1305def G_CONCAT_VECTORS : GenericInstruction {
1306  let OutOperandList = (outs type0:$dst);
1307  let InOperandList = (ins type1:$src0, variable_ops);
1308  let hasSideEffects = false;
1309}
1310
1311// Intrinsic without side effects.
1312def G_INTRINSIC : GenericInstruction {
1313  let OutOperandList = (outs);
1314  let InOperandList = (ins unknown:$intrin, variable_ops);
1315  let hasSideEffects = false;
1316}
1317
1318// Intrinsic with side effects.
1319def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
1320  let OutOperandList = (outs);
1321  let InOperandList = (ins unknown:$intrin, variable_ops);
1322  let hasSideEffects = true;
1323  let mayLoad = true;
1324  let mayStore = true;
1325}
1326
1327// Convergent intrinsic without side effects.
1328def G_INTRINSIC_CONVERGENT : GenericInstruction {
1329  let OutOperandList = (outs);
1330  let InOperandList = (ins unknown:$intrin, variable_ops);
1331  let hasSideEffects = false;
1332  let isConvergent = true;
1333}
1334
1335// Convergent intrinsic with side effects.
1336def G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS : GenericInstruction {
1337  let OutOperandList = (outs);
1338  let InOperandList = (ins unknown:$intrin, variable_ops);
1339  let hasSideEffects = true;
1340  let mayLoad = true;
1341  let mayStore = true;
1342  let isConvergent = true;
1343}
1344
1345//------------------------------------------------------------------------------
1346// Branches.
1347//------------------------------------------------------------------------------
1348
1349// Generic unconditional branch.
1350def G_BR : GenericInstruction {
1351  let OutOperandList = (outs);
1352  let InOperandList = (ins unknown:$src1);
1353  let hasSideEffects = false;
1354  let isBranch = true;
1355  let isTerminator = true;
1356  let isBarrier = true;
1357}
1358
1359// Generic conditional branch.
1360def G_BRCOND : GenericInstruction {
1361  let OutOperandList = (outs);
1362  let InOperandList = (ins type0:$tst, unknown:$truebb);
1363  let hasSideEffects = false;
1364  let isBranch = true;
1365  let isTerminator = true;
1366}
1367
1368// Generic indirect branch.
1369def G_BRINDIRECT : GenericInstruction {
1370  let OutOperandList = (outs);
1371  let InOperandList = (ins type0:$src1);
1372  let hasSideEffects = false;
1373  let isBranch = true;
1374  let isTerminator = true;
1375  let isBarrier = true;
1376  let isIndirectBranch = true;
1377}
1378
1379// Generic branch to jump table entry
1380def G_BRJT : GenericInstruction {
1381  let OutOperandList = (outs);
1382  let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1383  let hasSideEffects = false;
1384  let isBranch = true;
1385  let isTerminator = true;
1386  let isBarrier = true;
1387  let isIndirectBranch = true;
1388}
1389
1390// A marker to signal the following code is an invoke region, that may throw
1391// an exception and therefore not return.
1392def G_INVOKE_REGION_START : GenericInstruction {
1393  let OutOperandList = (outs);
1394  let InOperandList = (ins);
1395  let isTerminator = true; // This must be a terminator.
1396  let hasSideEffects = false;
1397}
1398
1399def G_READ_REGISTER : GenericInstruction {
1400  let OutOperandList = (outs type0:$dst);
1401  let InOperandList = (ins unknown:$register);
1402  let hasSideEffects = true;
1403
1404  // Assume convergent. It's probably not worth the effort of somehow
1405  // modeling convergent and nonconvergent register accesses.
1406  let isConvergent = true;
1407}
1408
1409def G_WRITE_REGISTER : GenericInstruction {
1410  let OutOperandList = (outs);
1411  let InOperandList = (ins unknown:$register, type0:$value);
1412  let hasSideEffects = true;
1413
1414  // Assume convergent. It's probably not worth the effort of somehow
1415  // modeling convergent and nonconvergent register accesses.
1416  let isConvergent = true;
1417}
1418
1419//------------------------------------------------------------------------------
1420// Vector ops
1421//------------------------------------------------------------------------------
1422
1423// Generic insertelement.
1424def G_INSERT_VECTOR_ELT : GenericInstruction {
1425  let OutOperandList = (outs type0:$dst);
1426  let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1427  let hasSideEffects = false;
1428}
1429
1430// Generic extractelement.
1431def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1432  let OutOperandList = (outs type0:$dst);
1433  let InOperandList = (ins type1:$src, type2:$idx);
1434  let hasSideEffects = false;
1435}
1436
1437// Generic shufflevector.
1438//
1439// The mask operand should be an IR Constant which exactly matches the
1440// corresponding mask for the IR shufflevector instruction.
1441def G_SHUFFLE_VECTOR: GenericInstruction {
1442  let OutOperandList = (outs type0:$dst);
1443  let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1444  let hasSideEffects = false;
1445}
1446
1447//------------------------------------------------------------------------------
1448// Vector reductions
1449//------------------------------------------------------------------------------
1450
1451class VectorReduction : GenericInstruction {
1452  let OutOperandList = (outs type0:$dst);
1453  let InOperandList = (ins type1:$v);
1454  let hasSideEffects = false;
1455}
1456
1457def G_VECREDUCE_SEQ_FADD : GenericInstruction {
1458  let OutOperandList = (outs type0:$dst);
1459  let InOperandList = (ins type1:$acc, type2:$v);
1460  let hasSideEffects = false;
1461}
1462
1463def G_VECREDUCE_SEQ_FMUL : GenericInstruction {
1464  let OutOperandList = (outs type0:$dst);
1465  let InOperandList = (ins type1:$acc, type2:$v);
1466  let hasSideEffects = false;
1467}
1468
1469def G_VECREDUCE_FADD : VectorReduction;
1470def G_VECREDUCE_FMUL : VectorReduction;
1471
1472def G_VECREDUCE_FMAX : VectorReduction;
1473def G_VECREDUCE_FMIN : VectorReduction;
1474def G_VECREDUCE_FMAXIMUM : VectorReduction;
1475def G_VECREDUCE_FMINIMUM : VectorReduction;
1476
1477def G_VECREDUCE_ADD : VectorReduction;
1478def G_VECREDUCE_MUL : VectorReduction;
1479def G_VECREDUCE_AND : VectorReduction;
1480def G_VECREDUCE_OR : VectorReduction;
1481def G_VECREDUCE_XOR : VectorReduction;
1482def G_VECREDUCE_SMAX : VectorReduction;
1483def G_VECREDUCE_SMIN : VectorReduction;
1484def G_VECREDUCE_UMAX : VectorReduction;
1485def G_VECREDUCE_UMIN : VectorReduction;
1486
1487//------------------------------------------------------------------------------
1488// Constrained floating point ops
1489//------------------------------------------------------------------------------
1490
1491def G_STRICT_FADD : ConstrainedInstruction<G_FADD>;
1492def G_STRICT_FSUB : ConstrainedInstruction<G_FSUB>;
1493def G_STRICT_FMUL : ConstrainedInstruction<G_FMUL>;
1494def G_STRICT_FDIV : ConstrainedInstruction<G_FDIV>;
1495def G_STRICT_FREM : ConstrainedInstruction<G_FREM>;
1496def G_STRICT_FMA : ConstrainedInstruction<G_FMA>;
1497def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>;
1498def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>;
1499
1500//------------------------------------------------------------------------------
1501// Memory intrinsics
1502//------------------------------------------------------------------------------
1503
1504def G_MEMCPY : GenericInstruction {
1505  let OutOperandList = (outs);
1506  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1507  let hasSideEffects = false;
1508  let mayLoad = true;
1509  let mayStore = true;
1510}
1511
1512def G_MEMCPY_INLINE : GenericInstruction {
1513  let OutOperandList = (outs);
1514  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size);
1515  let hasSideEffects = false;
1516  let mayLoad = true;
1517  let mayStore = true;
1518}
1519
1520def G_MEMMOVE : GenericInstruction {
1521  let OutOperandList = (outs);
1522  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1523  let hasSideEffects = false;
1524  let mayLoad = true;
1525  let mayStore = true;
1526}
1527
1528def G_MEMSET : GenericInstruction {
1529  let OutOperandList = (outs);
1530  let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
1531  let hasSideEffects = false;
1532  let mayStore = true;
1533}
1534
1535def G_BZERO : GenericInstruction {
1536  let OutOperandList = (outs);
1537  let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall);
1538  let hasSideEffects = false;
1539  let mayStore = true;
1540}
1541
1542//------------------------------------------------------------------------------
1543// Bitfield extraction.
1544//------------------------------------------------------------------------------
1545
1546// Generic signed bitfield extraction. The operands are in the range
1547// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1548def G_SBFX : GenericInstruction {
1549  let OutOperandList = (outs type0:$dst);
1550  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1551  let hasSideEffects = false;
1552}
1553
1554// Generic unsigned bitfield extraction. The operands are in the range
1555// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1556def G_UBFX : GenericInstruction {
1557  let OutOperandList = (outs type0:$dst);
1558  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1559  let hasSideEffects = false;
1560}
1561
1562//------------------------------------------------------------------------------
1563// Optimization hints
1564//------------------------------------------------------------------------------
1565
1566// Asserts that an operation has already been zero-extended from a specific
1567// type.
1568def G_ASSERT_ZEXT : GenericInstruction {
1569  let OutOperandList = (outs type0:$dst);
1570  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1571  let hasSideEffects = false;
1572}
1573
1574// Asserts that an operation has already been sign-extended from a specific
1575// type.
1576def G_ASSERT_SEXT : GenericInstruction {
1577  let OutOperandList = (outs type0:$dst);
1578  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1579  let hasSideEffects = false;
1580}
1581
1582// Asserts that a value has at least the given alignment.
1583def G_ASSERT_ALIGN : GenericInstruction {
1584  let OutOperandList = (outs type0:$dst);
1585  let InOperandList = (ins type0:$src, untyped_imm_0:$align);
1586  let hasSideEffects = false;
1587}
1588
1589// Prevent constant folding of the source value with any users.
1590def G_CONSTANT_FOLD_BARRIER : GenericInstruction {
1591  let OutOperandList = (outs type0:$dst);
1592  let InOperandList = (ins type0:$src);
1593  let hasSideEffects = false;
1594}
1595