[InstCombine] Signed saturation patterns
[llvm-complete.git] / include / llvm / Target / GenericOpcodes.td
blob4b49dfd4dd18e8d40f19a5db2ca45be119ba2ba1
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.
12 //===----------------------------------------------------------------------===//
14 //------------------------------------------------------------------------------
15 // Unary ops.
16 //------------------------------------------------------------------------------
18 class GenericInstruction : StandardPseudoInstruction {
19   let isPreISelOpcode = 1;
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;
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;
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;
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;
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;
69 def G_IMPLICIT_DEF : GenericInstruction {
70   let OutOperandList = (outs type0:$dst);
71   let InOperandList = (ins);
72   let hasSideEffects = 0;
75 def G_PHI : GenericInstruction {
76   let OutOperandList = (outs type0:$dst);
77   let InOperandList = (ins variable_ops);
78   let hasSideEffects = 0;
81 def G_FRAME_INDEX : GenericInstruction {
82   let OutOperandList = (outs type0:$dst);
83   let InOperandList = (ins unknown:$src2);
84   let hasSideEffects = 0;
87 def G_GLOBAL_VALUE : GenericInstruction {
88   let OutOperandList = (outs type0:$dst);
89   let InOperandList = (ins unknown:$src);
90   let hasSideEffects = 0;
93 def G_INTTOPTR : GenericInstruction {
94   let OutOperandList = (outs type0:$dst);
95   let InOperandList = (ins type1:$src);
96   let hasSideEffects = 0;
99 def G_PTRTOINT : GenericInstruction {
100   let OutOperandList = (outs type0:$dst);
101   let InOperandList = (ins type1:$src);
102   let hasSideEffects = 0;
105 def G_BITCAST : GenericInstruction {
106   let OutOperandList = (outs type0:$dst);
107   let InOperandList = (ins type1:$src);
108   let hasSideEffects = 0;
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;
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;
125 def G_VASTART : GenericInstruction {
126   let OutOperandList = (outs);
127   let InOperandList = (ins type0:$list);
128   let hasSideEffects = 0;
129   let mayStore = 1;
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;
140 def G_CTLZ : GenericInstruction {
141   let OutOperandList = (outs type0:$dst);
142   let InOperandList = (ins type1:$src);
143   let hasSideEffects = 0;
146 def G_CTLZ_ZERO_UNDEF : GenericInstruction {
147   let OutOperandList = (outs type0:$dst);
148   let InOperandList = (ins type1:$src);
149   let hasSideEffects = 0;
152 def G_CTTZ : GenericInstruction {
153   let OutOperandList = (outs type0:$dst);
154   let InOperandList = (ins type1:$src);
155   let hasSideEffects = 0;
158 def G_CTTZ_ZERO_UNDEF : GenericInstruction {
159   let OutOperandList = (outs type0:$dst);
160   let InOperandList = (ins type1:$src);
161   let hasSideEffects = 0;
164 def G_CTPOP : GenericInstruction {
165   let OutOperandList = (outs type0:$dst);
166   let InOperandList = (ins type1:$src);
167   let hasSideEffects = 0;
170 def G_BSWAP : GenericInstruction {
171   let OutOperandList = (outs type0:$dst);
172   let InOperandList = (ins type0:$src);
173   let hasSideEffects = 0;
176 def G_BITREVERSE : GenericInstruction {
177   let OutOperandList = (outs type0:$dst);
178   let InOperandList = (ins type0:$src);
179   let hasSideEffects = 0;
182 def G_ADDRSPACE_CAST : GenericInstruction {
183   let OutOperandList = (outs type0:$dst);
184   let InOperandList = (ins type1:$src);
185   let hasSideEffects = 0;
188 def G_BLOCK_ADDR : GenericInstruction {
189   let OutOperandList = (outs type0:$dst);
190   let InOperandList = (ins unknown:$ba);
191   let hasSideEffects = 0;
194 def G_JUMP_TABLE : GenericInstruction {
195   let OutOperandList = (outs type0:$dst);
196   let InOperandList = (ins unknown:$jti);
197   let hasSideEffects = 0;
200 def G_DYN_STACKALLOC : GenericInstruction {
201   let OutOperandList = (outs ptype0:$dst);
202   let InOperandList = (ins type1:$size, i32imm:$align);
203   let hasSideEffects = 1;
206 //------------------------------------------------------------------------------
207 // Binary ops.
208 //------------------------------------------------------------------------------
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
332 // Generic pointer offset.
333 def G_GEP : GenericInstruction {
334   let OutOperandList = (outs type0:$dst);
335   let InOperandList = (ins type0:$src1, type1:$src2);
336   let hasSideEffects = 0;
339 def G_PTR_MASK : GenericInstruction {
340   let OutOperandList = (outs type0:$dst);
341   let InOperandList = (ins type0:$src, unknown:$bits);
342   let hasSideEffects = 0;
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;
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;
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;
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;
377 //------------------------------------------------------------------------------
378 // Overflow ops
379 //------------------------------------------------------------------------------
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
472 //------------------------------------------------------------------------------
473 // Floating Point Unary Ops.
474 //------------------------------------------------------------------------------
476 def G_FNEG : GenericInstruction {
477   let OutOperandList = (outs type0:$dst);
478   let InOperandList = (ins type0:$src);
479   let hasSideEffects = 0;
482 def G_FPEXT : GenericInstruction {
483   let OutOperandList = (outs type0:$dst);
484   let InOperandList = (ins type1:$src);
485   let hasSideEffects = 0;
488 def G_FPTRUNC : GenericInstruction {
489   let OutOperandList = (outs type0:$dst);
490   let InOperandList = (ins type1:$src);
491   let hasSideEffects = 0;
494 def G_FPTOSI : GenericInstruction {
495   let OutOperandList = (outs type0:$dst);
496   let InOperandList = (ins type1:$src);
497   let hasSideEffects = 0;
500 def G_FPTOUI : GenericInstruction {
501   let OutOperandList = (outs type0:$dst);
502   let InOperandList = (ins type1:$src);
503   let hasSideEffects = 0;
506 def G_SITOFP : GenericInstruction {
507   let OutOperandList = (outs type0:$dst);
508   let InOperandList = (ins type1:$src);
509   let hasSideEffects = 0;
512 def G_UITOFP : GenericInstruction {
513   let OutOperandList = (outs type0:$dst);
514   let InOperandList = (ins type1:$src);
515   let hasSideEffects = 0;
518 def G_FABS : GenericInstruction {
519   let OutOperandList = (outs type0:$dst);
520   let InOperandList = (ins type0:$src);
521   let hasSideEffects = 0;
524 def G_FCOPYSIGN : GenericInstruction {
525   let OutOperandList = (outs type0:$dst);
526   let InOperandList = (ins type0:$src0, type1:$src1);
527   let hasSideEffects = 0;
530 def G_FCANONICALIZE : GenericInstruction {
531   let OutOperandList = (outs type0:$dst);
532   let InOperandList = (ins type0:$src);
533   let hasSideEffects = 0;
536 // FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
537 // values.
539 // In the case where a single input is a NaN (either signaling or quiet),
540 // the non-NaN input is returned.
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;
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;
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;
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;
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;
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;
592 //------------------------------------------------------------------------------
593 // Floating Point Binary ops.
594 //------------------------------------------------------------------------------
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
673 // Floating point base-2 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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
755 def G_INTRINSIC_ROUND : GenericInstruction {
756   let OutOperandList = (outs type0:$dst);
757   let InOperandList = (ins type0:$src1);
758   let hasSideEffects = 0;
761 //------------------------------------------------------------------------------
762 // Memory ops
763 //------------------------------------------------------------------------------
765 // Generic load. Expects a MachineMemOperand in addition to explicit
766 // operands. If the result size is larger than the memory size, the
767 // high bits are undefined. If the result is a vector type and larger
768 // than the memory size, the high elements are undefined (i.e. this is
769 // not a per-element, vector anyextload)
770 def G_LOAD : GenericInstruction {
771   let OutOperandList = (outs type0:$dst);
772   let InOperandList = (ins ptype1:$addr);
773   let hasSideEffects = 0;
774   let mayLoad = 1;
777 // Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
778 def G_SEXTLOAD : GenericInstruction {
779   let OutOperandList = (outs type0:$dst);
780   let InOperandList = (ins ptype1:$addr);
781   let hasSideEffects = 0;
782   let mayLoad = 1;
785 // Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
786 def G_ZEXTLOAD : GenericInstruction {
787   let OutOperandList = (outs type0:$dst);
788   let InOperandList = (ins ptype1:$addr);
789   let hasSideEffects = 0;
790   let mayLoad = 1;
793 // Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
794 // If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
795 //  then the value is loaded from $newaddr.
796 def G_INDEXED_LOAD : GenericInstruction {
797   let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
798   let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
799   let hasSideEffects = 0;
800   let mayLoad = 1;
803 // Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
804 def G_INDEXED_SEXTLOAD : GenericInstruction {
805   let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
806   let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
807   let hasSideEffects = 0;
808   let mayLoad = 1;
811 // Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
812 def G_INDEXED_ZEXTLOAD : GenericInstruction {
813   let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
814   let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
815   let hasSideEffects = 0;
816   let mayLoad = 1;
819 // Generic store. Expects a MachineMemOperand in addition to explicit operands.
820 def G_STORE : GenericInstruction {
821   let OutOperandList = (outs);
822   let InOperandList = (ins type0:$src, ptype1:$addr);
823   let hasSideEffects = 0;
824   let mayStore = 1;
827 // Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
828 def G_INDEXED_STORE : GenericInstruction {
829   let OutOperandList = (outs ptype0:$newaddr);
830   let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
831                            unknown:$am);
832   let hasSideEffects = 0;
833   let mayStore = 1;
836 // Generic atomic cmpxchg with internal success check. Expects a
837 // MachineMemOperand in addition to explicit operands.
838 def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
839   let OutOperandList = (outs type0:$oldval, type1:$success);
840   let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
841   let hasSideEffects = 0;
842   let mayLoad = 1;
843   let mayStore = 1;
846 // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
847 // operands.
848 def G_ATOMIC_CMPXCHG : GenericInstruction {
849   let OutOperandList = (outs type0:$oldval);
850   let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
851   let hasSideEffects = 0;
852   let mayLoad = 1;
853   let mayStore = 1;
856 // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
857 // operands.
858 class G_ATOMICRMW_OP : GenericInstruction {
859   let OutOperandList = (outs type0:$oldval);
860   let InOperandList = (ins ptype1:$addr, type0:$val);
861   let hasSideEffects = 0;
862   let mayLoad = 1;
863   let mayStore = 1;
866 def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
867 def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
868 def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
869 def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
870 def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
871 def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
872 def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
873 def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
874 def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
875 def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
876 def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
877 def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
878 def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
880 def G_FENCE : GenericInstruction {
881   let OutOperandList = (outs);
882   let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
883   let hasSideEffects = 1;
886 //------------------------------------------------------------------------------
887 // Variadic ops
888 //------------------------------------------------------------------------------
890 // Extract a register of the specified size, starting from the block given by
891 // index. This will almost certainly be mapped to sub-register COPYs after
892 // register banks have been selected.
893 def G_EXTRACT : GenericInstruction {
894   let OutOperandList = (outs type0:$res);
895   let InOperandList = (ins type1:$src, unknown:$offset);
896   let hasSideEffects = 0;
899 // Extract multiple registers specified size, starting from blocks given by
900 // indexes. This will almost certainly be mapped to sub-register COPYs after
901 // register banks have been selected.
902 // The output operands are always ordered from lowest bits to highest:
903 //   %bits_0_7:(s8), %bits_8_15:(s8),
904 //       %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
905 def G_UNMERGE_VALUES : GenericInstruction {
906   let OutOperandList = (outs type0:$dst0, variable_ops);
907   let InOperandList = (ins type1:$src);
908   let hasSideEffects = 0;
911 // Insert a smaller register into a larger one at the specified bit-index.
912 def G_INSERT : GenericInstruction {
913   let OutOperandList = (outs type0:$dst);
914   let InOperandList = (ins type0:$src, type1:$op, unknown:$offset);
915   let hasSideEffects = 0;
918 // Concatenate multiple registers of the same size into a wider register.
919 // The input operands are always ordered from lowest bits to highest:
920 //   %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
921 //                             %bits_16_23:(s8), %bits_24_31:(s8)
922 def G_MERGE_VALUES : GenericInstruction {
923   let OutOperandList = (outs type0:$dst);
924   let InOperandList = (ins type1:$src0, variable_ops);
925   let hasSideEffects = 0;
928 /// Create a vector from multiple scalar registers. No implicit
929 /// conversion is performed (i.e. the result element type must be the
930 /// same as all source operands)
931 def G_BUILD_VECTOR : GenericInstruction {
932   let OutOperandList = (outs type0:$dst);
933   let InOperandList = (ins type1:$src0, variable_ops);
934   let hasSideEffects = 0;
937 /// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
938 /// destination vector elt type.
939 def G_BUILD_VECTOR_TRUNC : GenericInstruction {
940   let OutOperandList = (outs type0:$dst);
941   let InOperandList = (ins type1:$src0, variable_ops);
942   let hasSideEffects = 0;
945 /// Create a vector by concatenating vectors together.
946 def G_CONCAT_VECTORS : GenericInstruction {
947   let OutOperandList = (outs type0:$dst);
948   let InOperandList = (ins type1:$src0, variable_ops);
949   let hasSideEffects = 0;
952 // Intrinsic without side effects.
953 def G_INTRINSIC : GenericInstruction {
954   let OutOperandList = (outs);
955   let InOperandList = (ins unknown:$intrin, variable_ops);
956   let hasSideEffects = 0;
959 // Intrinsic with side effects.
960 def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
961   let OutOperandList = (outs);
962   let InOperandList = (ins unknown:$intrin, variable_ops);
963   let hasSideEffects = 1;
964   let mayLoad = 1;
965   let mayStore = 1;
968 //------------------------------------------------------------------------------
969 // Branches.
970 //------------------------------------------------------------------------------
972 // Generic unconditional branch.
973 def G_BR : GenericInstruction {
974   let OutOperandList = (outs);
975   let InOperandList = (ins unknown:$src1);
976   let hasSideEffects = 0;
977   let isBranch = 1;
978   let isTerminator = 1;
979   let isBarrier = 1;
982 // Generic conditional branch.
983 def G_BRCOND : GenericInstruction {
984   let OutOperandList = (outs);
985   let InOperandList = (ins type0:$tst, unknown:$truebb);
986   let hasSideEffects = 0;
987   let isBranch = 1;
988   let isTerminator = 1;
991 // Generic indirect branch.
992 def G_BRINDIRECT : GenericInstruction {
993   let OutOperandList = (outs);
994   let InOperandList = (ins type0:$src1);
995   let hasSideEffects = 0;
996   let isBranch = 1;
997   let isTerminator = 1;
1000 // Generic branch to jump table entry
1001 def G_BRJT : GenericInstruction {
1002   let OutOperandList = (outs);
1003   let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1004   let hasSideEffects = 0;
1005   let isBranch = 1;
1006   let isTerminator = 1;
1009 //------------------------------------------------------------------------------
1010 // Vector ops
1011 //------------------------------------------------------------------------------
1013 // Generic insertelement.
1014 def G_INSERT_VECTOR_ELT : GenericInstruction {
1015   let OutOperandList = (outs type0:$dst);
1016   let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1017   let hasSideEffects = 0;
1020 // Generic extractelement.
1021 def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1022   let OutOperandList = (outs type0:$dst);
1023   let InOperandList = (ins type1:$src, type2:$idx);
1024   let hasSideEffects = 0;
1027 // Generic shufflevector.
1029 // The mask operand should be an IR Constant which exactly matches the
1030 // corresponding mask for the IR shufflevector instruction.
1031 def G_SHUFFLE_VECTOR: GenericInstruction {
1032   let OutOperandList = (outs type0:$dst);
1033   let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1034   let hasSideEffects = 0;
1037 // TODO: Add the other generic opcodes.