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