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