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