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 // Provide a variant of an instruction with the same operands, but
23 // different instruction flags. This is intended to provide a
24 // convenient way to define strict floating point variants of ordinary
25 // floating point instructions.
26 class ConstrainedIntruction<GenericInstruction baseInst> :
28 let OutOperandList = baseInst.OutOperandList;
29 let InOperandList = baseInst.InOperandList;
30 let isCommutable = baseInst.isCommutable;
32 // TODO: Do we need a better way to mark reads from FP mode than
34 let hasSideEffects = 1;
35 let mayRaiseFPException = 1;
38 // Extend the underlying scalar type of an operation, leaving the high bits
40 def G_ANYEXT : GenericInstruction {
41 let OutOperandList = (outs type0:$dst);
42 let InOperandList = (ins type1:$src);
43 let hasSideEffects = 0;
46 // Sign extend the underlying scalar type of an operation, copying the sign bit
47 // into the newly-created space.
48 def G_SEXT : GenericInstruction {
49 let OutOperandList = (outs type0:$dst);
50 let InOperandList = (ins type1:$src);
51 let hasSideEffects = 0;
54 // Sign extend the a value from an arbitrary bit position, copying the sign bit
55 // into all bits above it. This is equivalent to a shl + ashr pair with an
56 // appropriate shift amount. $sz is an immediate (MachineOperand::isImm()
57 // returns true) to allow targets to have some bitwidths legal and others
58 // lowered. This opcode is particularly useful if the target has sign-extension
59 // instructions that are cheaper than the constituent shifts as the optimizer is
60 // able to make decisions on whether it's better to hang on to the G_SEXT_INREG
61 // or to lower it and optimize the individual shifts.
62 def G_SEXT_INREG : GenericInstruction {
63 let OutOperandList = (outs type0:$dst);
64 let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
65 let hasSideEffects = 0;
68 // Zero extend the underlying scalar type of an operation, putting zero bits
69 // into the newly-created space.
70 def G_ZEXT : GenericInstruction {
71 let OutOperandList = (outs type0:$dst);
72 let InOperandList = (ins type1:$src);
73 let hasSideEffects = 0;
77 // Truncate the underlying scalar type of an operation. This is equivalent to
78 // G_EXTRACT for scalar types, but acts elementwise on vectors.
79 def G_TRUNC : GenericInstruction {
80 let OutOperandList = (outs type0:$dst);
81 let InOperandList = (ins type1:$src);
82 let hasSideEffects = 0;
85 def G_IMPLICIT_DEF : GenericInstruction {
86 let OutOperandList = (outs type0:$dst);
87 let InOperandList = (ins);
88 let hasSideEffects = 0;
91 def G_PHI : GenericInstruction {
92 let OutOperandList = (outs type0:$dst);
93 let InOperandList = (ins variable_ops);
94 let hasSideEffects = 0;
97 def G_FRAME_INDEX : GenericInstruction {
98 let OutOperandList = (outs type0:$dst);
99 let InOperandList = (ins unknown:$src2);
100 let hasSideEffects = 0;
103 def G_GLOBAL_VALUE : GenericInstruction {
104 let OutOperandList = (outs type0:$dst);
105 let InOperandList = (ins unknown:$src);
106 let hasSideEffects = 0;
109 def G_INTTOPTR : GenericInstruction {
110 let OutOperandList = (outs type0:$dst);
111 let InOperandList = (ins type1:$src);
112 let hasSideEffects = 0;
115 def G_PTRTOINT : GenericInstruction {
116 let OutOperandList = (outs type0:$dst);
117 let InOperandList = (ins type1:$src);
118 let hasSideEffects = 0;
121 def G_BITCAST : GenericInstruction {
122 let OutOperandList = (outs type0:$dst);
123 let InOperandList = (ins type1:$src);
124 let hasSideEffects = 0;
127 // Only supports scalar result types
128 def G_CONSTANT : GenericInstruction {
129 let OutOperandList = (outs type0:$dst);
130 let InOperandList = (ins unknown:$imm);
131 let hasSideEffects = 0;
134 // Only supports scalar result types
135 def G_FCONSTANT : GenericInstruction {
136 let OutOperandList = (outs type0:$dst);
137 let InOperandList = (ins unknown:$imm);
138 let hasSideEffects = 0;
141 def G_VASTART : GenericInstruction {
142 let OutOperandList = (outs);
143 let InOperandList = (ins type0:$list);
144 let hasSideEffects = 0;
148 def G_VAARG : GenericInstruction {
149 let OutOperandList = (outs type0:$val);
150 let InOperandList = (ins type1:$list, unknown:$align);
151 let hasSideEffects = 0;
156 def G_CTLZ : GenericInstruction {
157 let OutOperandList = (outs type0:$dst);
158 let InOperandList = (ins type1:$src);
159 let hasSideEffects = 0;
162 def G_CTLZ_ZERO_UNDEF : GenericInstruction {
163 let OutOperandList = (outs type0:$dst);
164 let InOperandList = (ins type1:$src);
165 let hasSideEffects = 0;
168 def G_CTTZ : GenericInstruction {
169 let OutOperandList = (outs type0:$dst);
170 let InOperandList = (ins type1:$src);
171 let hasSideEffects = 0;
174 def G_CTTZ_ZERO_UNDEF : GenericInstruction {
175 let OutOperandList = (outs type0:$dst);
176 let InOperandList = (ins type1:$src);
177 let hasSideEffects = 0;
180 def G_CTPOP : GenericInstruction {
181 let OutOperandList = (outs type0:$dst);
182 let InOperandList = (ins type1:$src);
183 let hasSideEffects = 0;
186 def G_BSWAP : GenericInstruction {
187 let OutOperandList = (outs type0:$dst);
188 let InOperandList = (ins type0:$src);
189 let hasSideEffects = 0;
192 def G_BITREVERSE : GenericInstruction {
193 let OutOperandList = (outs type0:$dst);
194 let InOperandList = (ins type0:$src);
195 let hasSideEffects = 0;
198 def G_ADDRSPACE_CAST : GenericInstruction {
199 let OutOperandList = (outs type0:$dst);
200 let InOperandList = (ins type1:$src);
201 let hasSideEffects = 0;
204 def G_BLOCK_ADDR : GenericInstruction {
205 let OutOperandList = (outs type0:$dst);
206 let InOperandList = (ins unknown:$ba);
207 let hasSideEffects = 0;
210 def G_JUMP_TABLE : GenericInstruction {
211 let OutOperandList = (outs type0:$dst);
212 let InOperandList = (ins unknown:$jti);
213 let hasSideEffects = 0;
216 def G_DYN_STACKALLOC : GenericInstruction {
217 let OutOperandList = (outs ptype0:$dst);
218 let InOperandList = (ins type1:$size, i32imm:$align);
219 let hasSideEffects = 1;
222 def G_FREEZE : GenericInstruction {
223 let OutOperandList = (outs type0:$dst);
224 let InOperandList = (ins type0:$src);
225 let hasSideEffects = 0;
228 //------------------------------------------------------------------------------
230 //------------------------------------------------------------------------------
233 def G_ADD : GenericInstruction {
234 let OutOperandList = (outs type0:$dst);
235 let InOperandList = (ins type0:$src1, type0:$src2);
236 let hasSideEffects = 0;
237 let isCommutable = 1;
240 // Generic subtraction.
241 def G_SUB : 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 multiplication.
249 def G_MUL : GenericInstruction {
250 let OutOperandList = (outs type0:$dst);
251 let InOperandList = (ins type0:$src1, type0:$src2);
252 let hasSideEffects = 0;
253 let isCommutable = 1;
256 // Generic signed division.
257 def G_SDIV : 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 unsigned division.
265 def G_UDIV : GenericInstruction {
266 let OutOperandList = (outs type0:$dst);
267 let InOperandList = (ins type0:$src1, type0:$src2);
268 let hasSideEffects = 0;
269 let isCommutable = 0;
272 // Generic signed remainder.
273 def G_SREM : GenericInstruction {
274 let OutOperandList = (outs type0:$dst);
275 let InOperandList = (ins type0:$src1, type0:$src2);
276 let hasSideEffects = 0;
277 let isCommutable = 0;
280 // Generic unsigned remainder.
281 def G_UREM : GenericInstruction {
282 let OutOperandList = (outs type0:$dst);
283 let InOperandList = (ins type0:$src1, type0:$src2);
284 let hasSideEffects = 0;
285 let isCommutable = 0;
288 // Generic bitwise and.
289 def G_AND : GenericInstruction {
290 let OutOperandList = (outs type0:$dst);
291 let InOperandList = (ins type0:$src1, type0:$src2);
292 let hasSideEffects = 0;
293 let isCommutable = 1;
296 // Generic bitwise or.
297 def G_OR : GenericInstruction {
298 let OutOperandList = (outs type0:$dst);
299 let InOperandList = (ins type0:$src1, type0:$src2);
300 let hasSideEffects = 0;
301 let isCommutable = 1;
304 // Generic bitwise xor.
305 def G_XOR : GenericInstruction {
306 let OutOperandList = (outs type0:$dst);
307 let InOperandList = (ins type0:$src1, type0:$src2);
308 let hasSideEffects = 0;
309 let isCommutable = 1;
312 // Generic left-shift.
313 def G_SHL : GenericInstruction {
314 let OutOperandList = (outs type0:$dst);
315 let InOperandList = (ins type0:$src1, type1:$src2);
316 let hasSideEffects = 0;
319 // Generic logical right-shift.
320 def G_LSHR : GenericInstruction {
321 let OutOperandList = (outs type0:$dst);
322 let InOperandList = (ins type0:$src1, type1:$src2);
323 let hasSideEffects = 0;
326 // Generic arithmetic right-shift.
327 def G_ASHR : GenericInstruction {
328 let OutOperandList = (outs type0:$dst);
329 let InOperandList = (ins type0:$src1, type1:$src2);
330 let hasSideEffects = 0;
333 /// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
334 /// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth)))
335 def G_FSHL : GenericInstruction {
336 let OutOperandList = (outs type0:$dst);
337 let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
338 let hasSideEffects = 0;
341 /// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
342 /// fshr(X,Y,Z): (X << (bitwidth - (Z % bitwidth))) | (Y >> (Z % bitwidth))
343 def G_FSHR : GenericInstruction {
344 let OutOperandList = (outs type0:$dst);
345 let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
346 let hasSideEffects = 0;
349 // Generic integer comparison.
350 def G_ICMP : GenericInstruction {
351 let OutOperandList = (outs type0:$dst);
352 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
353 let hasSideEffects = 0;
356 // Generic floating-point comparison.
357 def G_FCMP : GenericInstruction {
358 let OutOperandList = (outs type0:$dst);
359 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
360 let hasSideEffects = 0;
364 def G_SELECT : GenericInstruction {
365 let OutOperandList = (outs type0:$dst);
366 let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
367 let hasSideEffects = 0;
370 // Generic pointer offset.
371 def G_PTR_ADD : GenericInstruction {
372 let OutOperandList = (outs type0:$dst);
373 let InOperandList = (ins type0:$src1, type1:$src2);
374 let hasSideEffects = 0;
377 // Generic pointer mask. type1 should be an integer with the same
378 // bitwidth as the pointer type.
379 def G_PTRMASK : GenericInstruction {
380 let OutOperandList = (outs ptype0:$dst);
381 let InOperandList = (ins ptype0:$src, type1:$bits);
382 let hasSideEffects = 0;
385 // Generic signed integer minimum.
386 def G_SMIN : GenericInstruction {
387 let OutOperandList = (outs type0:$dst);
388 let InOperandList = (ins type0:$src1, type0:$src2);
389 let hasSideEffects = 0;
390 let isCommutable = 1;
393 // Generic signed integer maximum.
394 def G_SMAX : GenericInstruction {
395 let OutOperandList = (outs type0:$dst);
396 let InOperandList = (ins type0:$src1, type0:$src2);
397 let hasSideEffects = 0;
398 let isCommutable = 1;
401 // Generic unsigned integer minimum.
402 def G_UMIN : GenericInstruction {
403 let OutOperandList = (outs type0:$dst);
404 let InOperandList = (ins type0:$src1, type0:$src2);
405 let hasSideEffects = 0;
406 let isCommutable = 1;
409 // Generic unsigned integer maximum.
410 def G_UMAX : GenericInstruction {
411 let OutOperandList = (outs type0:$dst);
412 let InOperandList = (ins type0:$src1, type0:$src2);
413 let hasSideEffects = 0;
414 let isCommutable = 1;
417 //------------------------------------------------------------------------------
419 //------------------------------------------------------------------------------
421 // Generic unsigned addition producing a carry flag.
422 def G_UADDO : GenericInstruction {
423 let OutOperandList = (outs type0:$dst, type1:$carry_out);
424 let InOperandList = (ins type0:$src1, type0:$src2);
425 let hasSideEffects = 0;
426 let isCommutable = 1;
429 // Generic unsigned addition consuming and producing a carry flag.
430 def G_UADDE : 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 signed addition producing a carry flag.
437 def G_SADDO : 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 addition consuming and producing a carry flag.
445 def G_SADDE : GenericInstruction {
446 let OutOperandList = (outs type0:$dst, type1:$carry_out);
447 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
448 let hasSideEffects = 0;
451 // Generic unsigned subtraction producing a carry flag.
452 def G_USUBO : GenericInstruction {
453 let OutOperandList = (outs type0:$dst, type1:$carry_out);
454 let InOperandList = (ins type0:$src1, type0:$src2);
455 let hasSideEffects = 0;
457 // Generic unsigned subtraction consuming and producing a carry flag.
458 def G_USUBE : GenericInstruction {
459 let OutOperandList = (outs type0:$dst, type1:$carry_out);
460 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
461 let hasSideEffects = 0;
464 // Generic signed subtraction producing a carry flag.
465 def G_SSUBO : GenericInstruction {
466 let OutOperandList = (outs type0:$dst, type1:$carry_out);
467 let InOperandList = (ins type0:$src1, type0:$src2);
468 let hasSideEffects = 0;
471 // Generic signed subtraction consuming and producing a carry flag.
472 def G_SSUBE : GenericInstruction {
473 let OutOperandList = (outs type0:$dst, type1:$carry_out);
474 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
475 let hasSideEffects = 0;
478 // Generic unsigned multiplication producing a carry flag.
479 def G_UMULO : GenericInstruction {
480 let OutOperandList = (outs type0:$dst, type1:$carry_out);
481 let InOperandList = (ins type0:$src1, type0:$src2);
482 let hasSideEffects = 0;
483 let isCommutable = 1;
486 // Generic signed multiplication producing a carry flag.
487 def G_SMULO : GenericInstruction {
488 let OutOperandList = (outs type0:$dst, type1:$carry_out);
489 let InOperandList = (ins type0:$src1, type0:$src2);
490 let hasSideEffects = 0;
491 let isCommutable = 1;
494 // Multiply two numbers at twice the incoming bit width (unsigned) and return
495 // the high half of the result.
496 def G_UMULH : GenericInstruction {
497 let OutOperandList = (outs type0:$dst);
498 let InOperandList = (ins type0:$src1, type0:$src2);
499 let hasSideEffects = 0;
500 let isCommutable = 1;
503 // Multiply two numbers at twice the incoming bit width (signed) and return
504 // the high half of the result.
505 def G_SMULH : GenericInstruction {
506 let OutOperandList = (outs type0:$dst);
507 let InOperandList = (ins type0:$src1, type0:$src2);
508 let hasSideEffects = 0;
509 let isCommutable = 1;
512 //------------------------------------------------------------------------------
514 //------------------------------------------------------------------------------
516 // Generic saturating unsigned addition.
517 def G_UADDSAT : GenericInstruction {
518 let OutOperandList = (outs type0:$dst);
519 let InOperandList = (ins type0:$src1, type0:$src2);
520 let hasSideEffects = 0;
521 let isCommutable = 1;
524 // Generic saturating signed addition.
525 def G_SADDSAT : GenericInstruction {
526 let OutOperandList = (outs type0:$dst);
527 let InOperandList = (ins type0:$src1, type0:$src2);
528 let hasSideEffects = 0;
529 let isCommutable = 1;
532 // Generic saturating unsigned subtraction.
533 def G_USUBSAT : GenericInstruction {
534 let OutOperandList = (outs type0:$dst);
535 let InOperandList = (ins type0:$src1, type0:$src2);
536 let hasSideEffects = 0;
537 let isCommutable = 0;
540 // Generic saturating signed subtraction.
541 def G_SSUBSAT : GenericInstruction {
542 let OutOperandList = (outs type0:$dst);
543 let InOperandList = (ins type0:$src1, type0:$src2);
544 let hasSideEffects = 0;
545 let isCommutable = 0;
548 //------------------------------------------------------------------------------
549 // Floating Point Unary Ops.
550 //------------------------------------------------------------------------------
552 def G_FNEG : GenericInstruction {
553 let OutOperandList = (outs type0:$dst);
554 let InOperandList = (ins type0:$src);
555 let hasSideEffects = 0;
558 def G_FPEXT : GenericInstruction {
559 let OutOperandList = (outs type0:$dst);
560 let InOperandList = (ins type1:$src);
561 let hasSideEffects = 0;
564 def G_FPTRUNC : GenericInstruction {
565 let OutOperandList = (outs type0:$dst);
566 let InOperandList = (ins type1:$src);
567 let hasSideEffects = 0;
570 def G_FPTOSI : GenericInstruction {
571 let OutOperandList = (outs type0:$dst);
572 let InOperandList = (ins type1:$src);
573 let hasSideEffects = 0;
576 def G_FPTOUI : GenericInstruction {
577 let OutOperandList = (outs type0:$dst);
578 let InOperandList = (ins type1:$src);
579 let hasSideEffects = 0;
582 def G_SITOFP : GenericInstruction {
583 let OutOperandList = (outs type0:$dst);
584 let InOperandList = (ins type1:$src);
585 let hasSideEffects = 0;
588 def G_UITOFP : GenericInstruction {
589 let OutOperandList = (outs type0:$dst);
590 let InOperandList = (ins type1:$src);
591 let hasSideEffects = 0;
594 def G_FABS : GenericInstruction {
595 let OutOperandList = (outs type0:$dst);
596 let InOperandList = (ins type0:$src);
597 let hasSideEffects = 0;
600 def G_FCOPYSIGN : GenericInstruction {
601 let OutOperandList = (outs type0:$dst);
602 let InOperandList = (ins type0:$src0, type1:$src1);
603 let hasSideEffects = 0;
606 def G_FCANONICALIZE : GenericInstruction {
607 let OutOperandList = (outs type0:$dst);
608 let InOperandList = (ins type0:$src);
609 let hasSideEffects = 0;
612 // FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
615 // In the case where a single input is a NaN (either signaling or quiet),
616 // the non-NaN input is returned.
618 // The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
619 def G_FMINNUM : GenericInstruction {
620 let OutOperandList = (outs type0:$dst);
621 let InOperandList = (ins type0:$src1, type0:$src2);
622 let hasSideEffects = 0;
623 let isCommutable = 1;
626 def G_FMAXNUM : GenericInstruction {
627 let OutOperandList = (outs type0:$dst);
628 let InOperandList = (ins type0:$src1, type0:$src2);
629 let hasSideEffects = 0;
630 let isCommutable = 1;
633 // FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
634 // two values, following the IEEE-754 2008 definition. This differs from
635 // FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
636 // signaling NaN, returns a quiet NaN.
637 def G_FMINNUM_IEEE : GenericInstruction {
638 let OutOperandList = (outs type0:$dst);
639 let InOperandList = (ins type0:$src1, type0:$src2);
640 let hasSideEffects = 0;
641 let isCommutable = 1;
644 def G_FMAXNUM_IEEE : GenericInstruction {
645 let OutOperandList = (outs type0:$dst);
646 let InOperandList = (ins type0:$src1, type0:$src2);
647 let hasSideEffects = 0;
648 let isCommutable = 1;
651 // FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
652 // as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
653 // semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.
654 def G_FMINIMUM : GenericInstruction {
655 let OutOperandList = (outs type0:$dst);
656 let InOperandList = (ins type0:$src1, type0:$src2);
657 let hasSideEffects = 0;
658 let isCommutable = 1;
661 def G_FMAXIMUM : GenericInstruction {
662 let OutOperandList = (outs type0:$dst);
663 let InOperandList = (ins type0:$src1, type0:$src2);
664 let hasSideEffects = 0;
665 let isCommutable = 1;
668 //------------------------------------------------------------------------------
669 // Floating Point Binary ops.
670 //------------------------------------------------------------------------------
672 // Generic FP addition.
673 def G_FADD : GenericInstruction {
674 let OutOperandList = (outs type0:$dst);
675 let InOperandList = (ins type0:$src1, type0:$src2);
676 let hasSideEffects = 0;
677 let isCommutable = 1;
680 // Generic FP subtraction.
681 def G_FSUB : GenericInstruction {
682 let OutOperandList = (outs type0:$dst);
683 let InOperandList = (ins type0:$src1, type0:$src2);
684 let hasSideEffects = 0;
685 let isCommutable = 0;
688 // Generic FP multiplication.
689 def G_FMUL : GenericInstruction {
690 let OutOperandList = (outs type0:$dst);
691 let InOperandList = (ins type0:$src1, type0:$src2);
692 let hasSideEffects = 0;
693 let isCommutable = 1;
696 // Generic fused multiply-add instruction.
697 // Behaves like llvm fma intrinsic ie src1 * src2 + src3
698 def G_FMA : GenericInstruction {
699 let OutOperandList = (outs type0:$dst);
700 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
701 let hasSideEffects = 0;
702 let isCommutable = 0;
705 /// Generic FP multiply and add. Perform a * b + c, while getting the
706 /// same result as the separately rounded operations, unlike G_FMA.
707 def G_FMAD : GenericInstruction {
708 let OutOperandList = (outs type0:$dst);
709 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
710 let hasSideEffects = 0;
711 let isCommutable = 0;
714 // Generic FP division.
715 def G_FDIV : GenericInstruction {
716 let OutOperandList = (outs type0:$dst);
717 let InOperandList = (ins type0:$src1, type0:$src2);
718 let hasSideEffects = 0;
721 // Generic FP remainder.
722 def G_FREM : GenericInstruction {
723 let OutOperandList = (outs type0:$dst);
724 let InOperandList = (ins type0:$src1, type0:$src2);
725 let hasSideEffects = 0;
728 // Floating point exponentiation.
729 def G_FPOW : GenericInstruction {
730 let OutOperandList = (outs type0:$dst);
731 let InOperandList = (ins type0:$src1, type0:$src2);
732 let hasSideEffects = 0;
735 // Floating point base-e exponential of a value.
736 def G_FEXP : GenericInstruction {
737 let OutOperandList = (outs type0:$dst);
738 let InOperandList = (ins type0:$src1);
739 let hasSideEffects = 0;
742 // Floating point base-2 exponential of a value.
743 def G_FEXP2 : GenericInstruction {
744 let OutOperandList = (outs type0:$dst);
745 let InOperandList = (ins type0:$src1);
746 let hasSideEffects = 0;
749 // Floating point base-e logarithm of a value.
750 def G_FLOG : GenericInstruction {
751 let OutOperandList = (outs type0:$dst);
752 let InOperandList = (ins type0:$src1);
753 let hasSideEffects = 0;
756 // Floating point base-2 logarithm of a value.
757 def G_FLOG2 : GenericInstruction {
758 let OutOperandList = (outs type0:$dst);
759 let InOperandList = (ins type0:$src1);
760 let hasSideEffects = 0;
763 // Floating point base-10 logarithm of a value.
764 def G_FLOG10 : GenericInstruction {
765 let OutOperandList = (outs type0:$dst);
766 let InOperandList = (ins type0:$src1);
767 let hasSideEffects = 0;
770 // Floating point ceiling of a value.
771 def G_FCEIL : GenericInstruction {
772 let OutOperandList = (outs type0:$dst);
773 let InOperandList = (ins type0:$src1);
774 let hasSideEffects = 0;
777 // Floating point cosine of a value.
778 def G_FCOS : GenericInstruction {
779 let OutOperandList = (outs type0:$dst);
780 let InOperandList = (ins type0:$src1);
781 let hasSideEffects = 0;
784 // Floating point sine of a value.
785 def G_FSIN : GenericInstruction {
786 let OutOperandList = (outs type0:$dst);
787 let InOperandList = (ins type0:$src1);
788 let hasSideEffects = 0;
791 // Floating point square root of a value.
792 // This returns NaN for negative nonzero values.
793 // NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
795 def G_FSQRT : GenericInstruction {
796 let OutOperandList = (outs type0:$dst);
797 let InOperandList = (ins type0:$src1);
798 let hasSideEffects = 0;
801 // Floating point floor of a value.
802 def G_FFLOOR : GenericInstruction {
803 let OutOperandList = (outs type0:$dst);
804 let InOperandList = (ins type0:$src1);
805 let hasSideEffects = 0;
808 // Floating point round to next integer.
809 def G_FRINT : GenericInstruction {
810 let OutOperandList = (outs type0:$dst);
811 let InOperandList = (ins type0:$src1);
812 let hasSideEffects = 0;
815 // Floating point round to the nearest integer.
816 def G_FNEARBYINT : GenericInstruction {
817 let OutOperandList = (outs type0:$dst);
818 let InOperandList = (ins type0:$src1);
819 let hasSideEffects = 0;
822 //------------------------------------------------------------------------------
823 // Opcodes for LLVM Intrinsics
824 //------------------------------------------------------------------------------
825 def G_INTRINSIC_TRUNC : GenericInstruction {
826 let OutOperandList = (outs type0:$dst);
827 let InOperandList = (ins type0:$src1);
828 let hasSideEffects = 0;
831 def G_INTRINSIC_ROUND : GenericInstruction {
832 let OutOperandList = (outs type0:$dst);
833 let InOperandList = (ins type0:$src1);
834 let hasSideEffects = 0;
837 def G_READCYCLECOUNTER : GenericInstruction {
838 let OutOperandList = (outs type0:$dst);
839 let InOperandList = (ins);
840 let hasSideEffects = 1;
843 //------------------------------------------------------------------------------
845 //------------------------------------------------------------------------------
847 // Generic load. Expects a MachineMemOperand in addition to explicit
848 // operands. If the result size is larger than the memory size, the
849 // high bits are undefined. If the result is a vector type and larger
850 // than the memory size, the high elements are undefined (i.e. this is
851 // not a per-element, vector anyextload)
852 def G_LOAD : GenericInstruction {
853 let OutOperandList = (outs type0:$dst);
854 let InOperandList = (ins ptype1:$addr);
855 let hasSideEffects = 0;
859 // Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
860 def G_SEXTLOAD : GenericInstruction {
861 let OutOperandList = (outs type0:$dst);
862 let InOperandList = (ins ptype1:$addr);
863 let hasSideEffects = 0;
867 // Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
868 def G_ZEXTLOAD : GenericInstruction {
869 let OutOperandList = (outs type0:$dst);
870 let InOperandList = (ins ptype1:$addr);
871 let hasSideEffects = 0;
875 // Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
876 // If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
877 // then the value is loaded from $newaddr.
878 def G_INDEXED_LOAD : GenericInstruction {
879 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
880 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
881 let hasSideEffects = 0;
885 // Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
886 def G_INDEXED_SEXTLOAD : GenericInstruction {
887 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
888 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
889 let hasSideEffects = 0;
893 // Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
894 def G_INDEXED_ZEXTLOAD : GenericInstruction {
895 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
896 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
897 let hasSideEffects = 0;
901 // Generic store. Expects a MachineMemOperand in addition to explicit operands.
902 def G_STORE : GenericInstruction {
903 let OutOperandList = (outs);
904 let InOperandList = (ins type0:$src, ptype1:$addr);
905 let hasSideEffects = 0;
909 // Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
910 def G_INDEXED_STORE : GenericInstruction {
911 let OutOperandList = (outs ptype0:$newaddr);
912 let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
914 let hasSideEffects = 0;
918 // Generic atomic cmpxchg with internal success check. Expects a
919 // MachineMemOperand in addition to explicit operands.
920 def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
921 let OutOperandList = (outs type0:$oldval, type1:$success);
922 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
923 let hasSideEffects = 0;
928 // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
930 def G_ATOMIC_CMPXCHG : GenericInstruction {
931 let OutOperandList = (outs type0:$oldval);
932 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
933 let hasSideEffects = 0;
938 // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
940 class G_ATOMICRMW_OP : GenericInstruction {
941 let OutOperandList = (outs type0:$oldval);
942 let InOperandList = (ins ptype1:$addr, type0:$val);
943 let hasSideEffects = 0;
948 def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
949 def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
950 def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
951 def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
952 def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
953 def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
954 def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
955 def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
956 def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
957 def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
958 def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
959 def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
960 def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
962 def G_FENCE : GenericInstruction {
963 let OutOperandList = (outs);
964 let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
965 let hasSideEffects = 1;
968 //------------------------------------------------------------------------------
970 //------------------------------------------------------------------------------
972 // Extract a register of the specified size, starting from the block given by
973 // index. This will almost certainly be mapped to sub-register COPYs after
974 // register banks have been selected.
975 def G_EXTRACT : GenericInstruction {
976 let OutOperandList = (outs type0:$res);
977 let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
978 let hasSideEffects = 0;
981 // Extract multiple registers specified size, starting from blocks given by
982 // indexes. This will almost certainly be mapped to sub-register COPYs after
983 // register banks have been selected.
984 // The output operands are always ordered from lowest bits to highest:
985 // %bits_0_7:(s8), %bits_8_15:(s8),
986 // %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
987 def G_UNMERGE_VALUES : GenericInstruction {
988 let OutOperandList = (outs type0:$dst0, variable_ops);
989 let InOperandList = (ins type1:$src);
990 let hasSideEffects = 0;
993 // Insert a smaller register into a larger one at the specified bit-index.
994 def G_INSERT : GenericInstruction {
995 let OutOperandList = (outs type0:$dst);
996 let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
997 let hasSideEffects = 0;
1000 // Concatenate multiple registers of the same size into a wider register.
1001 // The input operands are always ordered from lowest bits to highest:
1002 // %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
1003 // %bits_16_23:(s8), %bits_24_31:(s8)
1004 def G_MERGE_VALUES : GenericInstruction {
1005 let OutOperandList = (outs type0:$dst);
1006 let InOperandList = (ins type1:$src0, variable_ops);
1007 let hasSideEffects = 0;
1010 /// Create a vector from multiple scalar registers. No implicit
1011 /// conversion is performed (i.e. the result element type must be the
1012 /// same as all source operands)
1013 def G_BUILD_VECTOR : GenericInstruction {
1014 let OutOperandList = (outs type0:$dst);
1015 let InOperandList = (ins type1:$src0, variable_ops);
1016 let hasSideEffects = 0;
1019 /// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
1020 /// destination vector elt type.
1021 def G_BUILD_VECTOR_TRUNC : GenericInstruction {
1022 let OutOperandList = (outs type0:$dst);
1023 let InOperandList = (ins type1:$src0, variable_ops);
1024 let hasSideEffects = 0;
1027 /// Create a vector by concatenating vectors together.
1028 def G_CONCAT_VECTORS : GenericInstruction {
1029 let OutOperandList = (outs type0:$dst);
1030 let InOperandList = (ins type1:$src0, variable_ops);
1031 let hasSideEffects = 0;
1034 // Intrinsic without side effects.
1035 def G_INTRINSIC : GenericInstruction {
1036 let OutOperandList = (outs);
1037 let InOperandList = (ins unknown:$intrin, variable_ops);
1038 let hasSideEffects = 0;
1040 // Conservatively assume this is convergent. If there turnes out to
1041 // be a need, there should be separate convergent intrinsic opcode.s
1042 let isConvergent = 1;
1045 // Intrinsic with side effects.
1046 def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
1047 let OutOperandList = (outs);
1048 let InOperandList = (ins unknown:$intrin, variable_ops);
1049 let hasSideEffects = 1;
1053 // Conservatively assume this is convergent. If there turnes out to
1054 // be a need, there should be separate convergent intrinsic opcode.s
1055 let isConvergent = 1;
1058 //------------------------------------------------------------------------------
1060 //------------------------------------------------------------------------------
1062 // Generic unconditional branch.
1063 def G_BR : GenericInstruction {
1064 let OutOperandList = (outs);
1065 let InOperandList = (ins unknown:$src1);
1066 let hasSideEffects = 0;
1068 let isTerminator = 1;
1072 // Generic conditional branch.
1073 def G_BRCOND : GenericInstruction {
1074 let OutOperandList = (outs);
1075 let InOperandList = (ins type0:$tst, unknown:$truebb);
1076 let hasSideEffects = 0;
1078 let isTerminator = 1;
1081 // Generic indirect branch.
1082 def G_BRINDIRECT : GenericInstruction {
1083 let OutOperandList = (outs);
1084 let InOperandList = (ins type0:$src1);
1085 let hasSideEffects = 0;
1087 let isTerminator = 1;
1089 let isIndirectBranch = 1;
1092 // Generic branch to jump table entry
1093 def G_BRJT : GenericInstruction {
1094 let OutOperandList = (outs);
1095 let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1096 let hasSideEffects = 0;
1098 let isTerminator = 1;
1100 let isIndirectBranch = 1;
1103 def G_READ_REGISTER : GenericInstruction {
1104 let OutOperandList = (outs type0:$dst);
1105 let InOperandList = (ins unknown:$register);
1106 let hasSideEffects = 1;
1108 // Assume convergent. It's probably not worth the effort of somehow
1109 // modeling convergent and nonconvergent register accesses.
1110 let isConvergent = 1;
1113 def G_WRITE_REGISTER : GenericInstruction {
1114 let OutOperandList = (outs);
1115 let InOperandList = (ins unknown:$register, type0:$value);
1116 let hasSideEffects = 1;
1118 // Assume convergent. It's probably not worth the effort of somehow
1119 // modeling convergent and nonconvergent register accesses.
1120 let isConvergent = 1;
1123 //------------------------------------------------------------------------------
1125 //------------------------------------------------------------------------------
1127 // Generic insertelement.
1128 def G_INSERT_VECTOR_ELT : GenericInstruction {
1129 let OutOperandList = (outs type0:$dst);
1130 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1131 let hasSideEffects = 0;
1134 // Generic extractelement.
1135 def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1136 let OutOperandList = (outs type0:$dst);
1137 let InOperandList = (ins type1:$src, type2:$idx);
1138 let hasSideEffects = 0;
1141 // Generic shufflevector.
1143 // The mask operand should be an IR Constant which exactly matches the
1144 // corresponding mask for the IR shufflevector instruction.
1145 def G_SHUFFLE_VECTOR: GenericInstruction {
1146 let OutOperandList = (outs type0:$dst);
1147 let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1148 let hasSideEffects = 0;
1151 //------------------------------------------------------------------------------
1152 // Constrained floating point ops
1153 //------------------------------------------------------------------------------
1155 def G_STRICT_FADD : ConstrainedIntruction<G_FADD>;
1156 def G_STRICT_FSUB : ConstrainedIntruction<G_FSUB>;
1157 def G_STRICT_FMUL : ConstrainedIntruction<G_FMUL>;
1158 def G_STRICT_FDIV : ConstrainedIntruction<G_FDIV>;
1159 def G_STRICT_FREM : ConstrainedIntruction<G_FREM>;
1160 def G_STRICT_FMA : ConstrainedIntruction<G_FMA>;
1161 def G_STRICT_FSQRT : ConstrainedIntruction<G_FSQRT>;