]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/include/llvm/Target/GenericOpcodes.td
MFV: r363292
[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 = 1;
20 }
21
22 // Extend the underlying scalar type of an operation, leaving the high bits
23 // unspecified.
24 def G_ANYEXT : GenericInstruction {
25   let OutOperandList = (outs type0:$dst);
26   let InOperandList = (ins type1:$src);
27   let hasSideEffects = 0;
28 }
29
30 // Sign extend the underlying scalar type of an operation, copying the sign bit
31 // into the newly-created space.
32 def G_SEXT : GenericInstruction {
33   let OutOperandList = (outs type0:$dst);
34   let InOperandList = (ins type1:$src);
35   let hasSideEffects = 0;
36 }
37
38 // Sign extend the a value from an arbitrary bit position, copying the sign bit
39 // into all bits above it. This is equivalent to a shl + ashr pair with an
40 // appropriate shift amount. $sz is an immediate (MachineOperand::isImm()
41 // returns true) to allow targets to have some bitwidths legal and others
42 // lowered. This opcode is particularly useful if the target has sign-extension
43 // instructions that are cheaper than the constituent shifts as the optimizer is
44 // able to make decisions on whether it's better to hang on to the G_SEXT_INREG
45 // or to lower it and optimize the individual shifts.
46 def G_SEXT_INREG : GenericInstruction {
47   let OutOperandList = (outs type0:$dst);
48   let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
49   let hasSideEffects = 0;
50 }
51
52 // Zero extend the underlying scalar type of an operation, putting zero bits
53 // into the newly-created space.
54 def G_ZEXT : GenericInstruction {
55   let OutOperandList = (outs type0:$dst);
56   let InOperandList = (ins type1:$src);
57   let hasSideEffects = 0;
58 }
59
60
61 // Truncate the underlying scalar type of an operation. This is equivalent to
62 // G_EXTRACT for scalar types, but acts elementwise on vectors.
63 def G_TRUNC : GenericInstruction {
64   let OutOperandList = (outs type0:$dst);
65   let InOperandList = (ins type1:$src);
66   let hasSideEffects = 0;
67 }
68
69 def G_IMPLICIT_DEF : GenericInstruction {
70   let OutOperandList = (outs type0:$dst);
71   let InOperandList = (ins);
72   let hasSideEffects = 0;
73 }
74
75 def G_PHI : GenericInstruction {
76   let OutOperandList = (outs type0:$dst);
77   let InOperandList = (ins variable_ops);
78   let hasSideEffects = 0;
79 }
80
81 def G_FRAME_INDEX : GenericInstruction {
82   let OutOperandList = (outs type0:$dst);
83   let InOperandList = (ins unknown:$src2);
84   let hasSideEffects = 0;
85 }
86
87 def G_GLOBAL_VALUE : GenericInstruction {
88   let OutOperandList = (outs type0:$dst);
89   let InOperandList = (ins unknown:$src);
90   let hasSideEffects = 0;
91 }
92
93 def G_INTTOPTR : GenericInstruction {
94   let OutOperandList = (outs type0:$dst);
95   let InOperandList = (ins type1:$src);
96   let hasSideEffects = 0;
97 }
98
99 def G_PTRTOINT : GenericInstruction {
100   let OutOperandList = (outs type0:$dst);
101   let InOperandList = (ins type1:$src);
102   let hasSideEffects = 0;
103 }
104
105 def G_BITCAST : GenericInstruction {
106   let OutOperandList = (outs type0:$dst);
107   let InOperandList = (ins type1:$src);
108   let hasSideEffects = 0;
109 }
110
111 // Only supports scalar result types
112 def G_CONSTANT : GenericInstruction {
113   let OutOperandList = (outs type0:$dst);
114   let InOperandList = (ins unknown:$imm);
115   let hasSideEffects = 0;
116 }
117
118 // Only supports scalar result types
119 def G_FCONSTANT : GenericInstruction {
120   let OutOperandList = (outs type0:$dst);
121   let InOperandList = (ins unknown:$imm);
122   let hasSideEffects = 0;
123 }
124
125 def G_VASTART : GenericInstruction {
126   let OutOperandList = (outs);
127   let InOperandList = (ins type0:$list);
128   let hasSideEffects = 0;
129   let mayStore = 1;
130 }
131
132 def G_VAARG : GenericInstruction {
133   let OutOperandList = (outs type0:$val);
134   let InOperandList = (ins type1:$list, unknown:$align);
135   let hasSideEffects = 0;
136   let mayLoad = 1;
137   let mayStore = 1;
138 }
139
140 def G_CTLZ : GenericInstruction {
141   let OutOperandList = (outs type0:$dst);
142   let InOperandList = (ins type1:$src);
143   let hasSideEffects = 0;
144 }
145
146 def G_CTLZ_ZERO_UNDEF : GenericInstruction {
147   let OutOperandList = (outs type0:$dst);
148   let InOperandList = (ins type1:$src);
149   let hasSideEffects = 0;
150 }
151
152 def G_CTTZ : GenericInstruction {
153   let OutOperandList = (outs type0:$dst);
154   let InOperandList = (ins type1:$src);
155   let hasSideEffects = 0;
156 }
157
158 def G_CTTZ_ZERO_UNDEF : GenericInstruction {
159   let OutOperandList = (outs type0:$dst);
160   let InOperandList = (ins type1:$src);
161   let hasSideEffects = 0;
162 }
163
164 def G_CTPOP : GenericInstruction {
165   let OutOperandList = (outs type0:$dst);
166   let InOperandList = (ins type1:$src);
167   let hasSideEffects = 0;
168 }
169
170 def G_BSWAP : GenericInstruction {
171   let OutOperandList = (outs type0:$dst);
172   let InOperandList = (ins type0:$src);
173   let hasSideEffects = 0;
174 }
175
176 def G_BITREVERSE : GenericInstruction {
177   let OutOperandList = (outs type0:$dst);
178   let InOperandList = (ins type0:$src);
179   let hasSideEffects = 0;
180 }
181
182 def G_ADDRSPACE_CAST : GenericInstruction {
183   let OutOperandList = (outs type0:$dst);
184   let InOperandList = (ins type1:$src);
185   let hasSideEffects = 0;
186 }
187
188 def G_BLOCK_ADDR : GenericInstruction {
189   let OutOperandList = (outs type0:$dst);
190   let InOperandList = (ins unknown:$ba);
191   let hasSideEffects = 0;
192 }
193
194 def G_JUMP_TABLE : GenericInstruction {
195   let OutOperandList = (outs type0:$dst);
196   let InOperandList = (ins unknown:$jti);
197   let hasSideEffects = 0;
198 }
199
200 def G_DYN_STACKALLOC : GenericInstruction {
201   let OutOperandList = (outs ptype0:$dst);
202   let InOperandList = (ins type1:$size, i32imm:$align);
203   let hasSideEffects = 1;
204 }
205
206 //------------------------------------------------------------------------------
207 // Binary ops.
208 //------------------------------------------------------------------------------
209
210 // Generic addition.
211 def G_ADD : GenericInstruction {
212   let OutOperandList = (outs type0:$dst);
213   let InOperandList = (ins type0:$src1, type0:$src2);
214   let hasSideEffects = 0;
215   let isCommutable = 1;
216 }
217
218 // Generic subtraction.
219 def G_SUB : GenericInstruction {
220   let OutOperandList = (outs type0:$dst);
221   let InOperandList = (ins type0:$src1, type0:$src2);
222   let hasSideEffects = 0;
223   let isCommutable = 0;
224 }
225
226 // Generic multiplication.
227 def G_MUL : GenericInstruction {
228   let OutOperandList = (outs type0:$dst);
229   let InOperandList = (ins type0:$src1, type0:$src2);
230   let hasSideEffects = 0;
231   let isCommutable = 1;
232 }
233
234 // Generic signed division.
235 def G_SDIV : GenericInstruction {
236   let OutOperandList = (outs type0:$dst);
237   let InOperandList = (ins type0:$src1, type0:$src2);
238   let hasSideEffects = 0;
239   let isCommutable = 0;
240 }
241
242 // Generic unsigned division.
243 def G_UDIV : GenericInstruction {
244   let OutOperandList = (outs type0:$dst);
245   let InOperandList = (ins type0:$src1, type0:$src2);
246   let hasSideEffects = 0;
247   let isCommutable = 0;
248 }
249
250 // Generic signed remainder.
251 def G_SREM : GenericInstruction {
252   let OutOperandList = (outs type0:$dst);
253   let InOperandList = (ins type0:$src1, type0:$src2);
254   let hasSideEffects = 0;
255   let isCommutable = 0;
256 }
257
258 // Generic unsigned remainder.
259 def G_UREM : GenericInstruction {
260   let OutOperandList = (outs type0:$dst);
261   let InOperandList = (ins type0:$src1, type0:$src2);
262   let hasSideEffects = 0;
263   let isCommutable = 0;
264 }
265
266 // Generic bitwise and.
267 def G_AND : GenericInstruction {
268   let OutOperandList = (outs type0:$dst);
269   let InOperandList = (ins type0:$src1, type0:$src2);
270   let hasSideEffects = 0;
271   let isCommutable = 1;
272 }
273
274 // Generic bitwise or.
275 def G_OR : GenericInstruction {
276   let OutOperandList = (outs type0:$dst);
277   let InOperandList = (ins type0:$src1, type0:$src2);
278   let hasSideEffects = 0;
279   let isCommutable = 1;
280 }
281
282 // Generic bitwise xor.
283 def G_XOR : GenericInstruction {
284   let OutOperandList = (outs type0:$dst);
285   let InOperandList = (ins type0:$src1, type0:$src2);
286   let hasSideEffects = 0;
287   let isCommutable = 1;
288 }
289
290 // Generic left-shift.
291 def G_SHL : GenericInstruction {
292   let OutOperandList = (outs type0:$dst);
293   let InOperandList = (ins type0:$src1, type1:$src2);
294   let hasSideEffects = 0;
295 }
296
297 // Generic logical right-shift.
298 def G_LSHR : GenericInstruction {
299   let OutOperandList = (outs type0:$dst);
300   let InOperandList = (ins type0:$src1, type1:$src2);
301   let hasSideEffects = 0;
302 }
303
304 // Generic arithmetic right-shift.
305 def G_ASHR : GenericInstruction {
306   let OutOperandList = (outs type0:$dst);
307   let InOperandList = (ins type0:$src1, type1:$src2);
308   let hasSideEffects = 0;
309 }
310
311 // Generic integer comparison.
312 def G_ICMP : GenericInstruction {
313   let OutOperandList = (outs type0:$dst);
314   let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
315   let hasSideEffects = 0;
316 }
317
318 // Generic floating-point comparison.
319 def G_FCMP : GenericInstruction {
320   let OutOperandList = (outs type0:$dst);
321   let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
322   let hasSideEffects = 0;
323 }
324
325 // Generic select
326 def G_SELECT : GenericInstruction {
327   let OutOperandList = (outs type0:$dst);
328   let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
329   let hasSideEffects = 0;
330 }
331
332 // Generic pointer offset.
333 def G_PTR_ADD : GenericInstruction {
334   let OutOperandList = (outs type0:$dst);
335   let InOperandList = (ins type0:$src1, type1:$src2);
336   let hasSideEffects = 0;
337 }
338
339 def G_PTR_MASK : GenericInstruction {
340   let OutOperandList = (outs type0:$dst);
341   let InOperandList = (ins type0:$src, unknown:$bits);
342   let hasSideEffects = 0;
343 }
344
345 // Generic signed integer minimum.
346 def G_SMIN : GenericInstruction {
347   let OutOperandList = (outs type0:$dst);
348   let InOperandList = (ins type0:$src1, type0:$src2);
349   let hasSideEffects = 0;
350   let isCommutable = 1;
351 }
352
353 // Generic signed integer maximum.
354 def G_SMAX : GenericInstruction {
355   let OutOperandList = (outs type0:$dst);
356   let InOperandList = (ins type0:$src1, type0:$src2);
357   let hasSideEffects = 0;
358   let isCommutable = 1;
359 }
360
361 // Generic unsigned integer minimum.
362 def G_UMIN : GenericInstruction {
363   let OutOperandList = (outs type0:$dst);
364   let InOperandList = (ins type0:$src1, type0:$src2);
365   let hasSideEffects = 0;
366   let isCommutable = 1;
367 }
368
369 // Generic unsigned integer maximum.
370 def G_UMAX : GenericInstruction {
371   let OutOperandList = (outs type0:$dst);
372   let InOperandList = (ins type0:$src1, type0:$src2);
373   let hasSideEffects = 0;
374   let isCommutable = 1;
375 }
376
377 //------------------------------------------------------------------------------
378 // Overflow ops
379 //------------------------------------------------------------------------------
380
381 // Generic unsigned addition producing a carry flag.
382 def G_UADDO : GenericInstruction {
383   let OutOperandList = (outs type0:$dst, type1:$carry_out);
384   let InOperandList = (ins type0:$src1, type0:$src2);
385   let hasSideEffects = 0;
386   let isCommutable = 1;
387 }
388
389 // Generic unsigned addition consuming and producing a carry flag.
390 def G_UADDE : GenericInstruction {
391   let OutOperandList = (outs type0:$dst, type1:$carry_out);
392   let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
393   let hasSideEffects = 0;
394 }
395
396 // Generic signed addition producing a carry flag.
397 def G_SADDO : GenericInstruction {
398   let OutOperandList = (outs type0:$dst, type1:$carry_out);
399   let InOperandList = (ins type0:$src1, type0:$src2);
400   let hasSideEffects = 0;
401   let isCommutable = 1;
402 }
403
404 // Generic signed addition consuming and producing a carry flag.
405 def G_SADDE : GenericInstruction {
406   let OutOperandList = (outs type0:$dst, type1:$carry_out);
407   let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
408   let hasSideEffects = 0;
409 }
410
411 // Generic unsigned subtraction producing a carry flag.
412 def G_USUBO : GenericInstruction {
413   let OutOperandList = (outs type0:$dst, type1:$carry_out);
414   let InOperandList = (ins type0:$src1, type0:$src2);
415   let hasSideEffects = 0;
416 }
417 // Generic unsigned subtraction consuming and producing a carry flag.
418 def G_USUBE : GenericInstruction {
419   let OutOperandList = (outs type0:$dst, type1:$carry_out);
420   let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
421   let hasSideEffects = 0;
422 }
423
424 // Generic signed subtraction producing a carry flag.
425 def G_SSUBO : GenericInstruction {
426   let OutOperandList = (outs type0:$dst, type1:$carry_out);
427   let InOperandList = (ins type0:$src1, type0:$src2);
428   let hasSideEffects = 0;
429 }
430
431 // Generic signed subtraction consuming and producing a carry flag.
432 def G_SSUBE : GenericInstruction {
433   let OutOperandList = (outs type0:$dst, type1:$carry_out);
434   let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
435   let hasSideEffects = 0;
436 }
437
438 // Generic unsigned multiplication producing a carry flag.
439 def G_UMULO : GenericInstruction {
440   let OutOperandList = (outs type0:$dst, type1:$carry_out);
441   let InOperandList = (ins type0:$src1, type0:$src2);
442   let hasSideEffects = 0;
443   let isCommutable = 1;
444 }
445
446 // Generic signed multiplication producing a carry flag.
447 def G_SMULO : GenericInstruction {
448   let OutOperandList = (outs type0:$dst, type1:$carry_out);
449   let InOperandList = (ins type0:$src1, type0:$src2);
450   let hasSideEffects = 0;
451   let isCommutable = 1;
452 }
453
454 // Multiply two numbers at twice the incoming bit width (unsigned) and return
455 // the high half of the result.
456 def G_UMULH : GenericInstruction {
457   let OutOperandList = (outs type0:$dst);
458   let InOperandList = (ins type0:$src1, type0:$src2);
459   let hasSideEffects = 0;
460   let isCommutable = 1;
461 }
462
463 // Multiply two numbers at twice the incoming bit width (signed) and return
464 // the high half of the result.
465 def G_SMULH : GenericInstruction {
466   let OutOperandList = (outs type0:$dst);
467   let InOperandList = (ins type0:$src1, type0:$src2);
468   let hasSideEffects = 0;
469   let isCommutable = 1;
470 }
471
472 //------------------------------------------------------------------------------
473 // Floating Point Unary Ops.
474 //------------------------------------------------------------------------------
475
476 def G_FNEG : GenericInstruction {
477   let OutOperandList = (outs type0:$dst);
478   let InOperandList = (ins type0:$src);
479   let hasSideEffects = 0;
480 }
481
482 def G_FPEXT : GenericInstruction {
483   let OutOperandList = (outs type0:$dst);
484   let InOperandList = (ins type1:$src);
485   let hasSideEffects = 0;
486 }
487
488 def G_FPTRUNC : GenericInstruction {
489   let OutOperandList = (outs type0:$dst);
490   let InOperandList = (ins type1:$src);
491   let hasSideEffects = 0;
492 }
493
494 def G_FPTOSI : GenericInstruction {
495   let OutOperandList = (outs type0:$dst);
496   let InOperandList = (ins type1:$src);
497   let hasSideEffects = 0;
498 }
499
500 def G_FPTOUI : GenericInstruction {
501   let OutOperandList = (outs type0:$dst);
502   let InOperandList = (ins type1:$src);
503   let hasSideEffects = 0;
504 }
505
506 def G_SITOFP : GenericInstruction {
507   let OutOperandList = (outs type0:$dst);
508   let InOperandList = (ins type1:$src);
509   let hasSideEffects = 0;
510 }
511
512 def G_UITOFP : GenericInstruction {
513   let OutOperandList = (outs type0:$dst);
514   let InOperandList = (ins type1:$src);
515   let hasSideEffects = 0;
516 }
517
518 def G_FABS : GenericInstruction {
519   let OutOperandList = (outs type0:$dst);
520   let InOperandList = (ins type0:$src);
521   let hasSideEffects = 0;
522 }
523
524 def G_FCOPYSIGN : GenericInstruction {
525   let OutOperandList = (outs type0:$dst);
526   let InOperandList = (ins type0:$src0, type1:$src1);
527   let hasSideEffects = 0;
528 }
529
530 def G_FCANONICALIZE : GenericInstruction {
531   let OutOperandList = (outs type0:$dst);
532   let InOperandList = (ins type0:$src);
533   let hasSideEffects = 0;
534 }
535
536 // FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
537 // values.
538 //
539 // In the case where a single input is a NaN (either signaling or quiet),
540 // the non-NaN input is returned.
541 //
542 // The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
543 def G_FMINNUM : GenericInstruction {
544   let OutOperandList = (outs type0:$dst);
545   let InOperandList = (ins type0:$src1, type0:$src2);
546   let hasSideEffects = 0;
547   let isCommutable = 1;
548 }
549
550 def G_FMAXNUM : GenericInstruction {
551   let OutOperandList = (outs type0:$dst);
552   let InOperandList = (ins type0:$src1, type0:$src2);
553   let hasSideEffects = 0;
554   let isCommutable = 1;
555 }
556
557 // FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
558 // two values, following the IEEE-754 2008 definition. This differs from
559 // FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
560 // signaling NaN, returns a quiet NaN.
561 def G_FMINNUM_IEEE : GenericInstruction {
562   let OutOperandList = (outs type0:$dst);
563   let InOperandList = (ins type0:$src1, type0:$src2);
564   let hasSideEffects = 0;
565   let isCommutable = 1;
566 }
567
568 def G_FMAXNUM_IEEE : GenericInstruction {
569   let OutOperandList = (outs type0:$dst);
570   let InOperandList = (ins type0:$src1, type0:$src2);
571   let hasSideEffects = 0;
572   let isCommutable = 1;
573 }
574
575 // FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
576 // as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
577 // semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.
578 def G_FMINIMUM : GenericInstruction {
579   let OutOperandList = (outs type0:$dst);
580   let InOperandList = (ins type0:$src1, type0:$src2);
581   let hasSideEffects = 0;
582   let isCommutable = 1;
583 }
584
585 def G_FMAXIMUM : GenericInstruction {
586   let OutOperandList = (outs type0:$dst);
587   let InOperandList = (ins type0:$src1, type0:$src2);
588   let hasSideEffects = 0;
589   let isCommutable = 1;
590 }
591
592 //------------------------------------------------------------------------------
593 // Floating Point Binary ops.
594 //------------------------------------------------------------------------------
595
596 // Generic FP addition.
597 def G_FADD : GenericInstruction {
598   let OutOperandList = (outs type0:$dst);
599   let InOperandList = (ins type0:$src1, type0:$src2);
600   let hasSideEffects = 0;
601   let isCommutable = 1;
602 }
603
604 // Generic FP subtraction.
605 def G_FSUB : GenericInstruction {
606   let OutOperandList = (outs type0:$dst);
607   let InOperandList = (ins type0:$src1, type0:$src2);
608   let hasSideEffects = 0;
609   let isCommutable = 0;
610 }
611
612 // Generic FP multiplication.
613 def G_FMUL : GenericInstruction {
614   let OutOperandList = (outs type0:$dst);
615   let InOperandList = (ins type0:$src1, type0:$src2);
616   let hasSideEffects = 0;
617   let isCommutable = 1;
618 }
619
620 // Generic fused multiply-add instruction.
621 // Behaves like llvm fma intrinsic ie src1 * src2 + src3
622 def G_FMA : GenericInstruction {
623   let OutOperandList = (outs type0:$dst);
624   let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
625   let hasSideEffects = 0;
626   let isCommutable = 0;
627 }
628
629 /// Generic FP multiply and add. Perform a * b + c, while getting the
630 /// same result as the separately rounded operations, unlike G_FMA.
631 def G_FMAD : GenericInstruction {
632   let OutOperandList = (outs type0:$dst);
633   let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
634   let hasSideEffects = 0;
635   let isCommutable = 0;
636 }
637
638 // Generic FP division.
639 def G_FDIV : GenericInstruction {
640   let OutOperandList = (outs type0:$dst);
641   let InOperandList = (ins type0:$src1, type0:$src2);
642   let hasSideEffects = 0;
643 }
644
645 // Generic FP remainder.
646 def G_FREM : GenericInstruction {
647   let OutOperandList = (outs type0:$dst);
648   let InOperandList = (ins type0:$src1, type0:$src2);
649   let hasSideEffects = 0;
650 }
651
652 // Floating point exponentiation.
653 def G_FPOW : GenericInstruction {
654   let OutOperandList = (outs type0:$dst);
655   let InOperandList = (ins type0:$src1, type0:$src2);
656   let hasSideEffects = 0;
657 }
658
659 // Floating point base-e exponential of a value.
660 def G_FEXP : GenericInstruction {
661   let OutOperandList = (outs type0:$dst);
662   let InOperandList = (ins type0:$src1);
663   let hasSideEffects = 0;
664 }
665
666 // Floating point base-2 exponential of a value.
667 def G_FEXP2 : GenericInstruction {
668   let OutOperandList = (outs type0:$dst);
669   let InOperandList = (ins type0:$src1);
670   let hasSideEffects = 0;
671 }
672
673 // Floating point base-e logarithm of a value.
674 def G_FLOG : GenericInstruction {
675   let OutOperandList = (outs type0:$dst);
676   let InOperandList = (ins type0:$src1);
677   let hasSideEffects = 0;
678 }
679
680 // Floating point base-2 logarithm of a value.
681 def G_FLOG2 : GenericInstruction {
682   let OutOperandList = (outs type0:$dst);
683   let InOperandList = (ins type0:$src1);
684   let hasSideEffects = 0;
685 }
686
687 // Floating point base-10 logarithm of a value.
688 def G_FLOG10 : GenericInstruction {
689   let OutOperandList = (outs type0:$dst);
690   let InOperandList = (ins type0:$src1);
691   let hasSideEffects = 0;
692 }
693
694 // Floating point ceiling of a value.
695 def G_FCEIL : GenericInstruction {
696   let OutOperandList = (outs type0:$dst);
697   let InOperandList = (ins type0:$src1);
698   let hasSideEffects = 0;
699 }
700
701 // Floating point cosine of a value.
702 def G_FCOS : GenericInstruction {
703   let OutOperandList = (outs type0:$dst);
704   let InOperandList = (ins type0:$src1);
705   let hasSideEffects = 0;
706 }
707
708 // Floating point sine of a value.
709 def G_FSIN : GenericInstruction {
710   let OutOperandList = (outs type0:$dst);
711   let InOperandList = (ins type0:$src1);
712   let hasSideEffects = 0;
713 }
714
715 // Floating point square root of a value.
716 // This returns NaN for negative nonzero values.
717 // NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
718 // libm-conformant.
719 def G_FSQRT : GenericInstruction {
720   let OutOperandList = (outs type0:$dst);
721   let InOperandList = (ins type0:$src1);
722   let hasSideEffects = 0;
723 }
724
725 // Floating point floor of a value.
726 def G_FFLOOR : GenericInstruction {
727   let OutOperandList = (outs type0:$dst);
728   let InOperandList = (ins type0:$src1);
729   let hasSideEffects = 0;
730 }
731
732 // Floating point round to next integer.
733 def G_FRINT : GenericInstruction {
734   let OutOperandList = (outs type0:$dst);
735   let InOperandList = (ins type0:$src1);
736   let hasSideEffects = 0;
737 }
738
739 // Floating point round to the nearest integer.
740 def G_FNEARBYINT : GenericInstruction {
741   let OutOperandList = (outs type0:$dst);
742   let InOperandList = (ins type0:$src1);
743   let hasSideEffects = 0;
744 }
745
746 //------------------------------------------------------------------------------
747 // Opcodes for LLVM Intrinsics
748 //------------------------------------------------------------------------------
749 def G_INTRINSIC_TRUNC : GenericInstruction {
750   let OutOperandList = (outs type0:$dst);
751   let InOperandList = (ins type0:$src1);
752   let hasSideEffects = 0;
753 }
754
755 def G_INTRINSIC_ROUND : GenericInstruction {
756   let OutOperandList = (outs type0:$dst);
757   let InOperandList = (ins type0:$src1);
758   let hasSideEffects = 0;
759 }
760
761 def G_READCYCLECOUNTER : GenericInstruction {
762   let OutOperandList = (outs type0:$dst);
763   let InOperandList = (ins);
764   let hasSideEffects = 1;
765 }
766
767 //------------------------------------------------------------------------------
768 // Memory ops
769 //------------------------------------------------------------------------------
770
771 // Generic load. Expects a MachineMemOperand in addition to explicit
772 // operands. If the result size is larger than the memory size, the
773 // high bits are undefined. If the result is a vector type and larger
774 // than the memory size, the high elements are undefined (i.e. this is
775 // not a per-element, vector anyextload)
776 def G_LOAD : GenericInstruction {
777   let OutOperandList = (outs type0:$dst);
778   let InOperandList = (ins ptype1:$addr);
779   let hasSideEffects = 0;
780   let mayLoad = 1;
781 }
782
783 // Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
784 def G_SEXTLOAD : GenericInstruction {
785   let OutOperandList = (outs type0:$dst);
786   let InOperandList = (ins ptype1:$addr);
787   let hasSideEffects = 0;
788   let mayLoad = 1;
789 }
790
791 // Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
792 def G_ZEXTLOAD : GenericInstruction {
793   let OutOperandList = (outs type0:$dst);
794   let InOperandList = (ins ptype1:$addr);
795   let hasSideEffects = 0;
796   let mayLoad = 1;
797 }
798
799 // Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
800 // If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
801 //  then the value is loaded from $newaddr.
802 def G_INDEXED_LOAD : GenericInstruction {
803   let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
804   let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
805   let hasSideEffects = 0;
806   let mayLoad = 1;
807 }
808
809 // Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
810 def G_INDEXED_SEXTLOAD : GenericInstruction {
811   let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
812   let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
813   let hasSideEffects = 0;
814   let mayLoad = 1;
815 }
816
817 // Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
818 def G_INDEXED_ZEXTLOAD : GenericInstruction {
819   let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
820   let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
821   let hasSideEffects = 0;
822   let mayLoad = 1;
823 }
824
825 // Generic store. Expects a MachineMemOperand in addition to explicit operands.
826 def G_STORE : GenericInstruction {
827   let OutOperandList = (outs);
828   let InOperandList = (ins type0:$src, ptype1:$addr);
829   let hasSideEffects = 0;
830   let mayStore = 1;
831 }
832
833 // Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
834 def G_INDEXED_STORE : GenericInstruction {
835   let OutOperandList = (outs ptype0:$newaddr);
836   let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
837                            unknown:$am);
838   let hasSideEffects = 0;
839   let mayStore = 1;
840 }
841
842 // Generic atomic cmpxchg with internal success check. Expects a
843 // MachineMemOperand in addition to explicit operands.
844 def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
845   let OutOperandList = (outs type0:$oldval, type1:$success);
846   let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
847   let hasSideEffects = 0;
848   let mayLoad = 1;
849   let mayStore = 1;
850 }
851
852 // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
853 // operands.
854 def G_ATOMIC_CMPXCHG : GenericInstruction {
855   let OutOperandList = (outs type0:$oldval);
856   let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
857   let hasSideEffects = 0;
858   let mayLoad = 1;
859   let mayStore = 1;
860 }
861
862 // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
863 // operands.
864 class G_ATOMICRMW_OP : GenericInstruction {
865   let OutOperandList = (outs type0:$oldval);
866   let InOperandList = (ins ptype1:$addr, type0:$val);
867   let hasSideEffects = 0;
868   let mayLoad = 1;
869   let mayStore = 1;
870 }
871
872 def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
873 def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
874 def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
875 def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
876 def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
877 def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
878 def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
879 def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
880 def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
881 def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
882 def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
883 def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
884 def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
885
886 def G_FENCE : GenericInstruction {
887   let OutOperandList = (outs);
888   let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
889   let hasSideEffects = 1;
890 }
891
892 //------------------------------------------------------------------------------
893 // Variadic ops
894 //------------------------------------------------------------------------------
895
896 // Extract a register of the specified size, starting from the block given by
897 // index. This will almost certainly be mapped to sub-register COPYs after
898 // register banks have been selected.
899 def G_EXTRACT : GenericInstruction {
900   let OutOperandList = (outs type0:$res);
901   let InOperandList = (ins type1:$src, unknown:$offset);
902   let hasSideEffects = 0;
903 }
904
905 // Extract multiple registers specified size, starting from blocks given by
906 // indexes. This will almost certainly be mapped to sub-register COPYs after
907 // register banks have been selected.
908 // The output operands are always ordered from lowest bits to highest:
909 //   %bits_0_7:(s8), %bits_8_15:(s8),
910 //       %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
911 def G_UNMERGE_VALUES : GenericInstruction {
912   let OutOperandList = (outs type0:$dst0, variable_ops);
913   let InOperandList = (ins type1:$src);
914   let hasSideEffects = 0;
915 }
916
917 // Insert a smaller register into a larger one at the specified bit-index.
918 def G_INSERT : GenericInstruction {
919   let OutOperandList = (outs type0:$dst);
920   let InOperandList = (ins type0:$src, type1:$op, unknown:$offset);
921   let hasSideEffects = 0;
922 }
923
924 // Concatenate multiple registers of the same size into a wider register.
925 // The input operands are always ordered from lowest bits to highest:
926 //   %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
927 //                             %bits_16_23:(s8), %bits_24_31:(s8)
928 def G_MERGE_VALUES : GenericInstruction {
929   let OutOperandList = (outs type0:$dst);
930   let InOperandList = (ins type1:$src0, variable_ops);
931   let hasSideEffects = 0;
932 }
933
934 /// Create a vector from multiple scalar registers. No implicit
935 /// conversion is performed (i.e. the result element type must be the
936 /// same as all source operands)
937 def G_BUILD_VECTOR : GenericInstruction {
938   let OutOperandList = (outs type0:$dst);
939   let InOperandList = (ins type1:$src0, variable_ops);
940   let hasSideEffects = 0;
941 }
942
943 /// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
944 /// destination vector elt type.
945 def G_BUILD_VECTOR_TRUNC : GenericInstruction {
946   let OutOperandList = (outs type0:$dst);
947   let InOperandList = (ins type1:$src0, variable_ops);
948   let hasSideEffects = 0;
949 }
950
951 /// Create a vector by concatenating vectors together.
952 def G_CONCAT_VECTORS : GenericInstruction {
953   let OutOperandList = (outs type0:$dst);
954   let InOperandList = (ins type1:$src0, variable_ops);
955   let hasSideEffects = 0;
956 }
957
958 // Intrinsic without side effects.
959 def G_INTRINSIC : GenericInstruction {
960   let OutOperandList = (outs);
961   let InOperandList = (ins unknown:$intrin, variable_ops);
962   let hasSideEffects = 0;
963 }
964
965 // Intrinsic with side effects.
966 def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
967   let OutOperandList = (outs);
968   let InOperandList = (ins unknown:$intrin, variable_ops);
969   let hasSideEffects = 1;
970   let mayLoad = 1;
971   let mayStore = 1;
972 }
973
974 //------------------------------------------------------------------------------
975 // Branches.
976 //------------------------------------------------------------------------------
977
978 // Generic unconditional branch.
979 def G_BR : GenericInstruction {
980   let OutOperandList = (outs);
981   let InOperandList = (ins unknown:$src1);
982   let hasSideEffects = 0;
983   let isBranch = 1;
984   let isTerminator = 1;
985   let isBarrier = 1;
986 }
987
988 // Generic conditional branch.
989 def G_BRCOND : GenericInstruction {
990   let OutOperandList = (outs);
991   let InOperandList = (ins type0:$tst, unknown:$truebb);
992   let hasSideEffects = 0;
993   let isBranch = 1;
994   let isTerminator = 1;
995 }
996
997 // Generic indirect branch.
998 def G_BRINDIRECT : GenericInstruction {
999   let OutOperandList = (outs);
1000   let InOperandList = (ins type0:$src1);
1001   let hasSideEffects = 0;
1002   let isBranch = 1;
1003   let isTerminator = 1;
1004 }
1005
1006 // Generic branch to jump table entry
1007 def G_BRJT : GenericInstruction {
1008   let OutOperandList = (outs);
1009   let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1010   let hasSideEffects = 0;
1011   let isBranch = 1;
1012   let isTerminator = 1;
1013 }
1014
1015 def G_READ_REGISTER : GenericInstruction {
1016   let OutOperandList = (outs type0:$dst);
1017   let InOperandList = (ins unknown:$register);
1018   let hasSideEffects = 1;
1019
1020   // Assume convergent. It's probably not worth the effort of somehow
1021   // modeling convergent and nonconvergent register accesses.
1022   let isConvergent = 1;
1023 }
1024
1025 def G_WRITE_REGISTER : GenericInstruction {
1026   let OutOperandList = (outs);
1027   let InOperandList = (ins unknown:$register, type0:$value);
1028   let hasSideEffects = 1;
1029
1030   // Assume convergent. It's probably not worth the effort of somehow
1031   // modeling convergent and nonconvergent register accesses.
1032   let isConvergent = 1;
1033 }
1034
1035 //------------------------------------------------------------------------------
1036 // Vector ops
1037 //------------------------------------------------------------------------------
1038
1039 // Generic insertelement.
1040 def G_INSERT_VECTOR_ELT : GenericInstruction {
1041   let OutOperandList = (outs type0:$dst);
1042   let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1043   let hasSideEffects = 0;
1044 }
1045
1046 // Generic extractelement.
1047 def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1048   let OutOperandList = (outs type0:$dst);
1049   let InOperandList = (ins type1:$src, type2:$idx);
1050   let hasSideEffects = 0;
1051 }
1052
1053 // Generic shufflevector.
1054 //
1055 // The mask operand should be an IR Constant which exactly matches the
1056 // corresponding mask for the IR shufflevector instruction.
1057 def G_SHUFFLE_VECTOR: GenericInstruction {
1058   let OutOperandList = (outs type0:$dst);
1059   let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1060   let hasSideEffects = 0;
1061 }
1062
1063 // TODO: Add the other generic opcodes.