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;
20 // Extend the underlying scalar type of an operation, leaving the high bits
22 def G_ANYEXT : GenericInstruction {
23 let OutOperandList = (outs type0:$dst);
24 let InOperandList = (ins type1:$src);
25 let hasSideEffects = 0;
28 // Sign extend the underlying scalar type of an operation, copying the sign bit
29 // into the newly-created space.
30 def G_SEXT : GenericInstruction {
31 let OutOperandList = (outs type0:$dst);
32 let InOperandList = (ins type1:$src);
33 let hasSideEffects = 0;
36 // Sign extend the a value from an arbitrary bit position, copying the sign bit
37 // into all bits above it. This is equivalent to a shl + ashr pair with an
38 // appropriate shift amount. $sz is an immediate (MachineOperand::isImm()
39 // returns true) to allow targets to have some bitwidths legal and others
40 // lowered. This opcode is particularly useful if the target has sign-extension
41 // instructions that are cheaper than the constituent shifts as the optimizer is
42 // able to make decisions on whether it's better to hang on to the G_SEXT_INREG
43 // or to lower it and optimize the individual shifts.
44 def G_SEXT_INREG : GenericInstruction {
45 let OutOperandList = (outs type0:$dst);
46 let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
47 let hasSideEffects = 0;
50 // Zero extend the underlying scalar type of an operation, putting zero bits
51 // into the newly-created space.
52 def G_ZEXT : GenericInstruction {
53 let OutOperandList = (outs type0:$dst);
54 let InOperandList = (ins type1:$src);
55 let hasSideEffects = 0;
59 // Truncate the underlying scalar type of an operation. This is equivalent to
60 // G_EXTRACT for scalar types, but acts elementwise on vectors.
61 def G_TRUNC : GenericInstruction {
62 let OutOperandList = (outs type0:$dst);
63 let InOperandList = (ins type1:$src);
64 let hasSideEffects = 0;
67 def G_IMPLICIT_DEF : GenericInstruction {
68 let OutOperandList = (outs type0:$dst);
69 let InOperandList = (ins);
70 let hasSideEffects = 0;
73 def G_PHI : GenericInstruction {
74 let OutOperandList = (outs type0:$dst);
75 let InOperandList = (ins variable_ops);
76 let hasSideEffects = 0;
79 def G_FRAME_INDEX : GenericInstruction {
80 let OutOperandList = (outs type0:$dst);
81 let InOperandList = (ins unknown:$src2);
82 let hasSideEffects = 0;
85 def G_GLOBAL_VALUE : GenericInstruction {
86 let OutOperandList = (outs type0:$dst);
87 let InOperandList = (ins unknown:$src);
88 let hasSideEffects = 0;
91 def G_INTTOPTR : GenericInstruction {
92 let OutOperandList = (outs type0:$dst);
93 let InOperandList = (ins type1:$src);
94 let hasSideEffects = 0;
97 def G_PTRTOINT : GenericInstruction {
98 let OutOperandList = (outs type0:$dst);
99 let InOperandList = (ins type1:$src);
100 let hasSideEffects = 0;
103 def G_BITCAST : GenericInstruction {
104 let OutOperandList = (outs type0:$dst);
105 let InOperandList = (ins type1:$src);
106 let hasSideEffects = 0;
109 // Only supports scalar result types
110 def G_CONSTANT : GenericInstruction {
111 let OutOperandList = (outs type0:$dst);
112 let InOperandList = (ins unknown:$imm);
113 let hasSideEffects = 0;
116 // Only supports scalar result types
117 def G_FCONSTANT : GenericInstruction {
118 let OutOperandList = (outs type0:$dst);
119 let InOperandList = (ins unknown:$imm);
120 let hasSideEffects = 0;
123 def G_VASTART : GenericInstruction {
124 let OutOperandList = (outs);
125 let InOperandList = (ins type0:$list);
126 let hasSideEffects = 0;
130 def G_VAARG : GenericInstruction {
131 let OutOperandList = (outs type0:$val);
132 let InOperandList = (ins type1:$list, unknown:$align);
133 let hasSideEffects = 0;
138 def G_CTLZ : GenericInstruction {
139 let OutOperandList = (outs type0:$dst);
140 let InOperandList = (ins type1:$src);
141 let hasSideEffects = 0;
144 def G_CTLZ_ZERO_UNDEF : GenericInstruction {
145 let OutOperandList = (outs type0:$dst);
146 let InOperandList = (ins type1:$src);
147 let hasSideEffects = 0;
150 def G_CTTZ : GenericInstruction {
151 let OutOperandList = (outs type0:$dst);
152 let InOperandList = (ins type1:$src);
153 let hasSideEffects = 0;
156 def G_CTTZ_ZERO_UNDEF : GenericInstruction {
157 let OutOperandList = (outs type0:$dst);
158 let InOperandList = (ins type1:$src);
159 let hasSideEffects = 0;
162 def G_CTPOP : GenericInstruction {
163 let OutOperandList = (outs type0:$dst);
164 let InOperandList = (ins type1:$src);
165 let hasSideEffects = 0;
168 def G_BSWAP : GenericInstruction {
169 let OutOperandList = (outs type0:$dst);
170 let InOperandList = (ins type0:$src);
171 let hasSideEffects = 0;
174 def G_BITREVERSE : GenericInstruction {
175 let OutOperandList = (outs type0:$dst);
176 let InOperandList = (ins type0:$src);
177 let hasSideEffects = 0;
180 def G_ADDRSPACE_CAST : GenericInstruction {
181 let OutOperandList = (outs type0:$dst);
182 let InOperandList = (ins type1:$src);
183 let hasSideEffects = 0;
186 def G_BLOCK_ADDR : GenericInstruction {
187 let OutOperandList = (outs type0:$dst);
188 let InOperandList = (ins unknown:$ba);
189 let hasSideEffects = 0;
192 def G_JUMP_TABLE : GenericInstruction {
193 let OutOperandList = (outs type0:$dst);
194 let InOperandList = (ins unknown:$jti);
195 let hasSideEffects = 0;
198 def G_DYN_STACKALLOC : GenericInstruction {
199 let OutOperandList = (outs ptype0:$dst);
200 let InOperandList = (ins type1:$size, i32imm:$align);
201 let hasSideEffects = 1;
204 //------------------------------------------------------------------------------
206 //------------------------------------------------------------------------------
209 def G_ADD : GenericInstruction {
210 let OutOperandList = (outs type0:$dst);
211 let InOperandList = (ins type0:$src1, type0:$src2);
212 let hasSideEffects = 0;
213 let isCommutable = 1;
216 // Generic subtraction.
217 def G_SUB : GenericInstruction {
218 let OutOperandList = (outs type0:$dst);
219 let InOperandList = (ins type0:$src1, type0:$src2);
220 let hasSideEffects = 0;
221 let isCommutable = 0;
224 // Generic multiplication.
225 def G_MUL : GenericInstruction {
226 let OutOperandList = (outs type0:$dst);
227 let InOperandList = (ins type0:$src1, type0:$src2);
228 let hasSideEffects = 0;
229 let isCommutable = 1;
232 // Generic signed division.
233 def G_SDIV : GenericInstruction {
234 let OutOperandList = (outs type0:$dst);
235 let InOperandList = (ins type0:$src1, type0:$src2);
236 let hasSideEffects = 0;
237 let isCommutable = 0;
240 // Generic unsigned division.
241 def G_UDIV : GenericInstruction {
242 let OutOperandList = (outs type0:$dst);
243 let InOperandList = (ins type0:$src1, type0:$src2);
244 let hasSideEffects = 0;
245 let isCommutable = 0;
248 // Generic signed remainder.
249 def G_SREM : GenericInstruction {
250 let OutOperandList = (outs type0:$dst);
251 let InOperandList = (ins type0:$src1, type0:$src2);
252 let hasSideEffects = 0;
253 let isCommutable = 0;
256 // Generic unsigned remainder.
257 def G_UREM : GenericInstruction {
258 let OutOperandList = (outs type0:$dst);
259 let InOperandList = (ins type0:$src1, type0:$src2);
260 let hasSideEffects = 0;
261 let isCommutable = 0;
264 // Generic bitwise and.
265 def G_AND : GenericInstruction {
266 let OutOperandList = (outs type0:$dst);
267 let InOperandList = (ins type0:$src1, type0:$src2);
268 let hasSideEffects = 0;
269 let isCommutable = 1;
272 // Generic bitwise or.
273 def G_OR : GenericInstruction {
274 let OutOperandList = (outs type0:$dst);
275 let InOperandList = (ins type0:$src1, type0:$src2);
276 let hasSideEffects = 0;
277 let isCommutable = 1;
280 // Generic bitwise xor.
281 def G_XOR : GenericInstruction {
282 let OutOperandList = (outs type0:$dst);
283 let InOperandList = (ins type0:$src1, type0:$src2);
284 let hasSideEffects = 0;
285 let isCommutable = 1;
288 // Generic left-shift.
289 def G_SHL : GenericInstruction {
290 let OutOperandList = (outs type0:$dst);
291 let InOperandList = (ins type0:$src1, type1:$src2);
292 let hasSideEffects = 0;
295 // Generic logical right-shift.
296 def G_LSHR : GenericInstruction {
297 let OutOperandList = (outs type0:$dst);
298 let InOperandList = (ins type0:$src1, type1:$src2);
299 let hasSideEffects = 0;
302 // Generic arithmetic right-shift.
303 def G_ASHR : GenericInstruction {
304 let OutOperandList = (outs type0:$dst);
305 let InOperandList = (ins type0:$src1, type1:$src2);
306 let hasSideEffects = 0;
309 // Generic integer comparison.
310 def G_ICMP : GenericInstruction {
311 let OutOperandList = (outs type0:$dst);
312 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
313 let hasSideEffects = 0;
316 // Generic floating-point comparison.
317 def G_FCMP : GenericInstruction {
318 let OutOperandList = (outs type0:$dst);
319 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
320 let hasSideEffects = 0;
324 def G_SELECT : GenericInstruction {
325 let OutOperandList = (outs type0:$dst);
326 let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
327 let hasSideEffects = 0;
330 // Generic pointer offset.
331 def G_GEP : GenericInstruction {
332 let OutOperandList = (outs type0:$dst);
333 let InOperandList = (ins type0:$src1, type1:$src2);
334 let hasSideEffects = 0;
337 def G_PTR_MASK : GenericInstruction {
338 let OutOperandList = (outs type0:$dst);
339 let InOperandList = (ins type0:$src, unknown:$bits);
340 let hasSideEffects = 0;
343 // Generic signed integer minimum.
344 def G_SMIN : GenericInstruction {
345 let OutOperandList = (outs type0:$dst);
346 let InOperandList = (ins type0:$src1, type0:$src2);
347 let hasSideEffects = 0;
348 let isCommutable = 1;
351 // Generic signed integer maximum.
352 def G_SMAX : GenericInstruction {
353 let OutOperandList = (outs type0:$dst);
354 let InOperandList = (ins type0:$src1, type0:$src2);
355 let hasSideEffects = 0;
356 let isCommutable = 1;
359 // Generic unsigned integer minimum.
360 def G_UMIN : GenericInstruction {
361 let OutOperandList = (outs type0:$dst);
362 let InOperandList = (ins type0:$src1, type0:$src2);
363 let hasSideEffects = 0;
364 let isCommutable = 1;
367 // Generic unsigned integer maximum.
368 def G_UMAX : GenericInstruction {
369 let OutOperandList = (outs type0:$dst);
370 let InOperandList = (ins type0:$src1, type0:$src2);
371 let hasSideEffects = 0;
372 let isCommutable = 1;
375 //------------------------------------------------------------------------------
377 //------------------------------------------------------------------------------
379 // Generic unsigned addition producing a carry flag.
380 def G_UADDO : GenericInstruction {
381 let OutOperandList = (outs type0:$dst, type1:$carry_out);
382 let InOperandList = (ins type0:$src1, type0:$src2);
383 let hasSideEffects = 0;
384 let isCommutable = 1;
387 // Generic unsigned addition consuming and producing a carry flag.
388 def G_UADDE : GenericInstruction {
389 let OutOperandList = (outs type0:$dst, type1:$carry_out);
390 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
391 let hasSideEffects = 0;
394 // Generic signed addition producing a carry flag.
395 def G_SADDO : GenericInstruction {
396 let OutOperandList = (outs type0:$dst, type1:$carry_out);
397 let InOperandList = (ins type0:$src1, type0:$src2);
398 let hasSideEffects = 0;
399 let isCommutable = 1;
402 // Generic signed addition consuming and producing a carry flag.
403 def G_SADDE : GenericInstruction {
404 let OutOperandList = (outs type0:$dst, type1:$carry_out);
405 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
406 let hasSideEffects = 0;
409 // Generic unsigned subtraction producing a carry flag.
410 def G_USUBO : GenericInstruction {
411 let OutOperandList = (outs type0:$dst, type1:$carry_out);
412 let InOperandList = (ins type0:$src1, type0:$src2);
413 let hasSideEffects = 0;
415 // Generic unsigned subtraction consuming and producing a carry flag.
416 def G_USUBE : GenericInstruction {
417 let OutOperandList = (outs type0:$dst, type1:$carry_out);
418 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
419 let hasSideEffects = 0;
422 // Generic signed subtraction producing a carry flag.
423 def G_SSUBO : GenericInstruction {
424 let OutOperandList = (outs type0:$dst, type1:$carry_out);
425 let InOperandList = (ins type0:$src1, type0:$src2);
426 let hasSideEffects = 0;
429 // Generic signed subtraction consuming and producing a carry flag.
430 def G_SSUBE : GenericInstruction {
431 let OutOperandList = (outs type0:$dst, type1:$carry_out);
432 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
433 let hasSideEffects = 0;
436 // Generic unsigned multiplication producing a carry flag.
437 def G_UMULO : GenericInstruction {
438 let OutOperandList = (outs type0:$dst, type1:$carry_out);
439 let InOperandList = (ins type0:$src1, type0:$src2);
440 let hasSideEffects = 0;
441 let isCommutable = 1;
444 // Generic signed multiplication producing a carry flag.
445 def G_SMULO : GenericInstruction {
446 let OutOperandList = (outs type0:$dst, type1:$carry_out);
447 let InOperandList = (ins type0:$src1, type0:$src2);
448 let hasSideEffects = 0;
449 let isCommutable = 1;
452 // Multiply two numbers at twice the incoming bit width (unsigned) and return
453 // the high half of the result.
454 def G_UMULH : GenericInstruction {
455 let OutOperandList = (outs type0:$dst);
456 let InOperandList = (ins type0:$src1, type0:$src2);
457 let hasSideEffects = 0;
458 let isCommutable = 1;
461 // Multiply two numbers at twice the incoming bit width (signed) and return
462 // the high half of the result.
463 def G_SMULH : GenericInstruction {
464 let OutOperandList = (outs type0:$dst);
465 let InOperandList = (ins type0:$src1, type0:$src2);
466 let hasSideEffects = 0;
467 let isCommutable = 1;
470 //------------------------------------------------------------------------------
471 // Floating Point Unary Ops.
472 //------------------------------------------------------------------------------
474 def G_FNEG : GenericInstruction {
475 let OutOperandList = (outs type0:$dst);
476 let InOperandList = (ins type0:$src);
477 let hasSideEffects = 0;
480 def G_FPEXT : GenericInstruction {
481 let OutOperandList = (outs type0:$dst);
482 let InOperandList = (ins type1:$src);
483 let hasSideEffects = 0;
486 def G_FPTRUNC : GenericInstruction {
487 let OutOperandList = (outs type0:$dst);
488 let InOperandList = (ins type1:$src);
489 let hasSideEffects = 0;
492 def G_FPTOSI : GenericInstruction {
493 let OutOperandList = (outs type0:$dst);
494 let InOperandList = (ins type1:$src);
495 let hasSideEffects = 0;
498 def G_FPTOUI : GenericInstruction {
499 let OutOperandList = (outs type0:$dst);
500 let InOperandList = (ins type1:$src);
501 let hasSideEffects = 0;
504 def G_SITOFP : GenericInstruction {
505 let OutOperandList = (outs type0:$dst);
506 let InOperandList = (ins type1:$src);
507 let hasSideEffects = 0;
510 def G_UITOFP : GenericInstruction {
511 let OutOperandList = (outs type0:$dst);
512 let InOperandList = (ins type1:$src);
513 let hasSideEffects = 0;
516 def G_FABS : GenericInstruction {
517 let OutOperandList = (outs type0:$dst);
518 let InOperandList = (ins type0:$src);
519 let hasSideEffects = 0;
522 def G_FCOPYSIGN : GenericInstruction {
523 let OutOperandList = (outs type0:$dst);
524 let InOperandList = (ins type0:$src0, type1:$src1);
525 let hasSideEffects = 0;
528 def G_FCANONICALIZE : GenericInstruction {
529 let OutOperandList = (outs type0:$dst);
530 let InOperandList = (ins type0:$src);
531 let hasSideEffects = 0;
534 // FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
537 // In the case where a single input is a NaN (either signaling or quiet),
538 // the non-NaN input is returned.
540 // The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
541 def G_FMINNUM : GenericInstruction {
542 let OutOperandList = (outs type0:$dst);
543 let InOperandList = (ins type0:$src1, type0:$src2);
544 let hasSideEffects = 0;
545 let isCommutable = 1;
548 def G_FMAXNUM : GenericInstruction {
549 let OutOperandList = (outs type0:$dst);
550 let InOperandList = (ins type0:$src1, type0:$src2);
551 let hasSideEffects = 0;
552 let isCommutable = 1;
555 // FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
556 // two values, following the IEEE-754 2008 definition. This differs from
557 // FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
558 // signaling NaN, returns a quiet NaN.
559 def G_FMINNUM_IEEE : GenericInstruction {
560 let OutOperandList = (outs type0:$dst);
561 let InOperandList = (ins type0:$src1, type0:$src2);
562 let hasSideEffects = 0;
563 let isCommutable = 1;
566 def G_FMAXNUM_IEEE : GenericInstruction {
567 let OutOperandList = (outs type0:$dst);
568 let InOperandList = (ins type0:$src1, type0:$src2);
569 let hasSideEffects = 0;
570 let isCommutable = 1;
573 // FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
574 // as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
575 // semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.
576 def G_FMINIMUM : GenericInstruction {
577 let OutOperandList = (outs type0:$dst);
578 let InOperandList = (ins type0:$src1, type0:$src2);
579 let hasSideEffects = 0;
580 let isCommutable = 1;
583 def G_FMAXIMUM : GenericInstruction {
584 let OutOperandList = (outs type0:$dst);
585 let InOperandList = (ins type0:$src1, type0:$src2);
586 let hasSideEffects = 0;
587 let isCommutable = 1;
590 //------------------------------------------------------------------------------
591 // Floating Point Binary ops.
592 //------------------------------------------------------------------------------
594 // Generic FP addition.
595 def G_FADD : GenericInstruction {
596 let OutOperandList = (outs type0:$dst);
597 let InOperandList = (ins type0:$src1, type0:$src2);
598 let hasSideEffects = 0;
599 let isCommutable = 1;
602 // Generic FP subtraction.
603 def G_FSUB : GenericInstruction {
604 let OutOperandList = (outs type0:$dst);
605 let InOperandList = (ins type0:$src1, type0:$src2);
606 let hasSideEffects = 0;
607 let isCommutable = 0;
610 // Generic FP multiplication.
611 def G_FMUL : GenericInstruction {
612 let OutOperandList = (outs type0:$dst);
613 let InOperandList = (ins type0:$src1, type0:$src2);
614 let hasSideEffects = 0;
615 let isCommutable = 1;
618 // Generic fused multiply-add instruction.
619 // Behaves like llvm fma intrinsic ie src1 * src2 + src3
620 def G_FMA : GenericInstruction {
621 let OutOperandList = (outs type0:$dst);
622 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
623 let hasSideEffects = 0;
624 let isCommutable = 0;
627 /// Generic FP multiply and add. Perform a * b + c, while getting the
628 /// same result as the separately rounded operations, unlike G_FMA.
629 def G_FMAD : GenericInstruction {
630 let OutOperandList = (outs type0:$dst);
631 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
632 let hasSideEffects = 0;
633 let isCommutable = 0;
636 // Generic FP division.
637 def G_FDIV : GenericInstruction {
638 let OutOperandList = (outs type0:$dst);
639 let InOperandList = (ins type0:$src1, type0:$src2);
640 let hasSideEffects = 0;
643 // Generic FP remainder.
644 def G_FREM : GenericInstruction {
645 let OutOperandList = (outs type0:$dst);
646 let InOperandList = (ins type0:$src1, type0:$src2);
647 let hasSideEffects = 0;
650 // Floating point exponentiation.
651 def G_FPOW : GenericInstruction {
652 let OutOperandList = (outs type0:$dst);
653 let InOperandList = (ins type0:$src1, type0:$src2);
654 let hasSideEffects = 0;
657 // Floating point base-e exponential of a value.
658 def G_FEXP : GenericInstruction {
659 let OutOperandList = (outs type0:$dst);
660 let InOperandList = (ins type0:$src1);
661 let hasSideEffects = 0;
664 // Floating point base-2 exponential of a value.
665 def G_FEXP2 : GenericInstruction {
666 let OutOperandList = (outs type0:$dst);
667 let InOperandList = (ins type0:$src1);
668 let hasSideEffects = 0;
671 // Floating point base-2 logarithm of a value.
672 def G_FLOG : GenericInstruction {
673 let OutOperandList = (outs type0:$dst);
674 let InOperandList = (ins type0:$src1);
675 let hasSideEffects = 0;
678 // Floating point base-2 logarithm of a value.
679 def G_FLOG2 : GenericInstruction {
680 let OutOperandList = (outs type0:$dst);
681 let InOperandList = (ins type0:$src1);
682 let hasSideEffects = 0;
685 // Floating point base-10 logarithm of a value.
686 def G_FLOG10 : GenericInstruction {
687 let OutOperandList = (outs type0:$dst);
688 let InOperandList = (ins type0:$src1);
689 let hasSideEffects = 0;
692 // Floating point ceiling of a value.
693 def G_FCEIL : GenericInstruction {
694 let OutOperandList = (outs type0:$dst);
695 let InOperandList = (ins type0:$src1);
696 let hasSideEffects = 0;
699 // Floating point cosine of a value.
700 def G_FCOS : GenericInstruction {
701 let OutOperandList = (outs type0:$dst);
702 let InOperandList = (ins type0:$src1);
703 let hasSideEffects = 0;
706 // Floating point sine of a value.
707 def G_FSIN : GenericInstruction {
708 let OutOperandList = (outs type0:$dst);
709 let InOperandList = (ins type0:$src1);
710 let hasSideEffects = 0;
713 // Floating point square root of a value.
714 // This returns NaN for negative nonzero values.
715 // NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
717 def G_FSQRT : GenericInstruction {
718 let OutOperandList = (outs type0:$dst);
719 let InOperandList = (ins type0:$src1);
720 let hasSideEffects = 0;
723 // Floating point floor of a value.
724 def G_FFLOOR : GenericInstruction {
725 let OutOperandList = (outs type0:$dst);
726 let InOperandList = (ins type0:$src1);
727 let hasSideEffects = 0;
730 // Floating point round to next integer.
731 def G_FRINT : GenericInstruction {
732 let OutOperandList = (outs type0:$dst);
733 let InOperandList = (ins type0:$src1);
734 let hasSideEffects = 0;
737 // Floating point round to the nearest integer.
738 def G_FNEARBYINT : GenericInstruction {
739 let OutOperandList = (outs type0:$dst);
740 let InOperandList = (ins type0:$src1);
741 let hasSideEffects = 0;
744 //------------------------------------------------------------------------------
745 // Opcodes for LLVM Intrinsics
746 //------------------------------------------------------------------------------
747 def G_INTRINSIC_TRUNC : GenericInstruction {
748 let OutOperandList = (outs type0:$dst);
749 let InOperandList = (ins type0:$src1);
750 let hasSideEffects = 0;
753 def G_INTRINSIC_ROUND : GenericInstruction {
754 let OutOperandList = (outs type0:$dst);
755 let InOperandList = (ins type0:$src1);
756 let hasSideEffects = 0;
759 //------------------------------------------------------------------------------
761 //------------------------------------------------------------------------------
763 // Generic load. Expects a MachineMemOperand in addition to explicit
764 // operands. If the result size is larger than the memory size, the
765 // high bits are undefined. If the result is a vector type and larger
766 // than the memory size, the high elements are undefined (i.e. this is
767 // not a per-element, vector anyextload)
768 def G_LOAD : GenericInstruction {
769 let OutOperandList = (outs type0:$dst);
770 let InOperandList = (ins ptype1:$addr);
771 let hasSideEffects = 0;
775 // Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
776 def G_SEXTLOAD : GenericInstruction {
777 let OutOperandList = (outs type0:$dst);
778 let InOperandList = (ins ptype1:$addr);
779 let hasSideEffects = 0;
783 // Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
784 def G_ZEXTLOAD : GenericInstruction {
785 let OutOperandList = (outs type0:$dst);
786 let InOperandList = (ins ptype1:$addr);
787 let hasSideEffects = 0;
791 // Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
792 // If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
793 // then the value is loaded from $newaddr.
794 def G_INDEXED_LOAD : GenericInstruction {
795 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
796 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
797 let hasSideEffects = 0;
801 // Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
802 def G_INDEXED_SEXTLOAD : GenericInstruction {
803 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
804 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
805 let hasSideEffects = 0;
809 // Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
810 def G_INDEXED_ZEXTLOAD : GenericInstruction {
811 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
812 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
813 let hasSideEffects = 0;
817 // Generic store. Expects a MachineMemOperand in addition to explicit operands.
818 def G_STORE : GenericInstruction {
819 let OutOperandList = (outs);
820 let InOperandList = (ins type0:$src, ptype1:$addr);
821 let hasSideEffects = 0;
825 // Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
826 def G_INDEXED_STORE : GenericInstruction {
827 let OutOperandList = (outs ptype0:$newaddr);
828 let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
830 let hasSideEffects = 0;
834 // Generic atomic cmpxchg with internal success check. Expects a
835 // MachineMemOperand in addition to explicit operands.
836 def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
837 let OutOperandList = (outs type0:$oldval, type1:$success);
838 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
839 let hasSideEffects = 0;
844 // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
846 def G_ATOMIC_CMPXCHG : GenericInstruction {
847 let OutOperandList = (outs type0:$oldval);
848 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
849 let hasSideEffects = 0;
854 // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
856 class G_ATOMICRMW_OP : GenericInstruction {
857 let OutOperandList = (outs type0:$oldval);
858 let InOperandList = (ins ptype1:$addr, type0:$val);
859 let hasSideEffects = 0;
864 def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
865 def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
866 def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
867 def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
868 def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
869 def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
870 def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
871 def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
872 def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
873 def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
874 def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
875 def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
876 def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
878 def G_FENCE : GenericInstruction {
879 let OutOperandList = (outs);
880 let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
881 let hasSideEffects = 1;
884 //------------------------------------------------------------------------------
886 //------------------------------------------------------------------------------
888 // Extract a register of the specified size, starting from the block given by
889 // index. This will almost certainly be mapped to sub-register COPYs after
890 // register banks have been selected.
891 def G_EXTRACT : GenericInstruction {
892 let OutOperandList = (outs type0:$res);
893 let InOperandList = (ins type1:$src, unknown:$offset);
894 let hasSideEffects = 0;
897 // Extract multiple registers specified size, starting from blocks given by
898 // indexes. This will almost certainly be mapped to sub-register COPYs after
899 // register banks have been selected.
900 // The output operands are always ordered from lowest bits to highest:
901 // %bits_0_7:(s8), %bits_8_15:(s8),
902 // %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
903 def G_UNMERGE_VALUES : GenericInstruction {
904 let OutOperandList = (outs type0:$dst0, variable_ops);
905 let InOperandList = (ins type1:$src);
906 let hasSideEffects = 0;
909 // Insert a smaller register into a larger one at the specified bit-index.
910 def G_INSERT : GenericInstruction {
911 let OutOperandList = (outs type0:$dst);
912 let InOperandList = (ins type0:$src, type1:$op, unknown:$offset);
913 let hasSideEffects = 0;
916 // Concatenate multiple registers of the same size into a wider register.
917 // The input operands are always ordered from lowest bits to highest:
918 // %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
919 // %bits_16_23:(s8), %bits_24_31:(s8)
920 def G_MERGE_VALUES : GenericInstruction {
921 let OutOperandList = (outs type0:$dst);
922 let InOperandList = (ins type1:$src0, variable_ops);
923 let hasSideEffects = 0;
926 /// Create a vector from multiple scalar registers. No implicit
927 /// conversion is performed (i.e. the result element type must be the
928 /// same as all source operands)
929 def G_BUILD_VECTOR : GenericInstruction {
930 let OutOperandList = (outs type0:$dst);
931 let InOperandList = (ins type1:$src0, variable_ops);
932 let hasSideEffects = 0;
935 /// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
936 /// destination vector elt type.
937 def G_BUILD_VECTOR_TRUNC : GenericInstruction {
938 let OutOperandList = (outs type0:$dst);
939 let InOperandList = (ins type1:$src0, variable_ops);
940 let hasSideEffects = 0;
943 /// Create a vector by concatenating vectors together.
944 def G_CONCAT_VECTORS : GenericInstruction {
945 let OutOperandList = (outs type0:$dst);
946 let InOperandList = (ins type1:$src0, variable_ops);
947 let hasSideEffects = 0;
950 // Intrinsic without side effects.
951 def G_INTRINSIC : GenericInstruction {
952 let OutOperandList = (outs);
953 let InOperandList = (ins unknown:$intrin, variable_ops);
954 let hasSideEffects = 0;
957 // Intrinsic with side effects.
958 def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
959 let OutOperandList = (outs);
960 let InOperandList = (ins unknown:$intrin, variable_ops);
961 let hasSideEffects = 1;
966 //------------------------------------------------------------------------------
968 //------------------------------------------------------------------------------
970 // Generic unconditional branch.
971 def G_BR : GenericInstruction {
972 let OutOperandList = (outs);
973 let InOperandList = (ins unknown:$src1);
974 let hasSideEffects = 0;
976 let isTerminator = 1;
980 // Generic conditional branch.
981 def G_BRCOND : GenericInstruction {
982 let OutOperandList = (outs);
983 let InOperandList = (ins type0:$tst, unknown:$truebb);
984 let hasSideEffects = 0;
986 let isTerminator = 1;
989 // Generic indirect branch.
990 def G_BRINDIRECT : GenericInstruction {
991 let OutOperandList = (outs);
992 let InOperandList = (ins type0:$src1);
993 let hasSideEffects = 0;
995 let isTerminator = 1;
998 // Generic branch to jump table entry
999 def G_BRJT : GenericInstruction {
1000 let OutOperandList = (outs);
1001 let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1002 let hasSideEffects = 0;
1004 let isTerminator = 1;
1007 //------------------------------------------------------------------------------
1009 //------------------------------------------------------------------------------
1011 // Generic insertelement.
1012 def G_INSERT_VECTOR_ELT : GenericInstruction {
1013 let OutOperandList = (outs type0:$dst);
1014 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1015 let hasSideEffects = 0;
1018 // Generic extractelement.
1019 def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1020 let OutOperandList = (outs type0:$dst);
1021 let InOperandList = (ins type1:$src, type2:$idx);
1022 let hasSideEffects = 0;
1025 // Generic shufflevector.
1027 // The mask operand should be an IR Constant which exactly matches the
1028 // corresponding mask for the IR shufflevector instruction.
1029 def G_SHUFFLE_VECTOR: GenericInstruction {
1030 let OutOperandList = (outs type0:$dst);
1031 let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1032 let hasSideEffects = 0;
1035 // TODO: Add the other generic opcodes.