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