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