1 //===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the generic opcodes used with GlobalISel.
10 // After instruction selection, these opcodes should not appear.
12 //===----------------------------------------------------------------------===//
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
18 class GenericInstruction : StandardPseudoInstruction {
19 let isPreISelOpcode = 1;
22 // Extend the underlying scalar type of an operation, leaving the high bits
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;
132 def G_VAARG : GenericInstruction {
133 let OutOperandList = (outs type0:$val);
134 let InOperandList = (ins type1:$list, unknown:$align);
135 let hasSideEffects = 0;
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 //------------------------------------------------------------------------------
208 //------------------------------------------------------------------------------
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;
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 //------------------------------------------------------------------------------
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
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
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 //------------------------------------------------------------------------------
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;
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;
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;
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;
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;
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;
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;
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,
832 let hasSideEffects = 0;
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;
846 // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
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;
856 // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
858 class G_ATOMICRMW_OP : GenericInstruction {
859 let OutOperandList = (outs type0:$oldval);
860 let InOperandList = (ins ptype1:$addr, type0:$val);
861 let hasSideEffects = 0;
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 //------------------------------------------------------------------------------
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;
968 //------------------------------------------------------------------------------
970 //------------------------------------------------------------------------------
972 // Generic unconditional branch.
973 def G_BR : GenericInstruction {
974 let OutOperandList = (outs);
975 let InOperandList = (ins unknown:$src1);
976 let hasSideEffects = 0;
978 let isTerminator = 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;
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;
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;
1006 let isTerminator = 1;
1009 //------------------------------------------------------------------------------
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.