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 = true;
20
21  // When all variadic ops share a type with another operand,
22  // this is the type they share. Used by MIR patterns type inference.
23  TypedOperand variadicOpsType = ?;
24}
25
26// Provide a variant of an instruction with the same operands, but
27// different instruction flags. This is intended to provide a
28// convenient way to define strict floating point variants of ordinary
29// floating point instructions.
30class ConstrainedInstruction<GenericInstruction baseInst> :
31  GenericInstruction {
32  let OutOperandList = baseInst.OutOperandList;
33  let InOperandList =  baseInst.InOperandList;
34  let isCommutable = baseInst.isCommutable;
35
36  // TODO: Do we need a better way to mark reads from FP mode than
37  // hasSideEffects?
38  let hasSideEffects = true;
39  let mayRaiseFPException = true;
40}
41
42// Extend the underlying scalar type of an operation, leaving the high bits
43// unspecified.
44def G_ANYEXT : GenericInstruction {
45  let OutOperandList = (outs type0:$dst);
46  let InOperandList = (ins type1:$src);
47  let hasSideEffects = false;
48}
49
50// Sign extend the underlying scalar type of an operation, copying the sign bit
51// into the newly-created space.
52def G_SEXT : GenericInstruction {
53  let OutOperandList = (outs type0:$dst);
54  let InOperandList = (ins type1:$src);
55  let hasSideEffects = false;
56}
57
58// Sign extend the a value from an arbitrary bit position, copying the sign bit
59// into all bits above it. This is equivalent to a shl + ashr pair with an
60// appropriate shift amount. $sz is an immediate (MachineOperand::isImm()
61// returns true) to allow targets to have some bitwidths legal and others
62// lowered. This opcode is particularly useful if the target has sign-extension
63// instructions that are cheaper than the constituent shifts as the optimizer is
64// able to make decisions on whether it's better to hang on to the G_SEXT_INREG
65// or to lower it and optimize the individual shifts.
66def G_SEXT_INREG : GenericInstruction {
67  let OutOperandList = (outs type0:$dst);
68  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
69  let hasSideEffects = false;
70}
71
72// Zero extend the underlying scalar type of an operation, putting zero bits
73// into the newly-created space.
74def G_ZEXT : GenericInstruction {
75  let OutOperandList = (outs type0:$dst);
76  let InOperandList = (ins type1:$src);
77  let hasSideEffects = false;
78}
79
80
81// Truncate the underlying scalar type of an operation. This is equivalent to
82// G_EXTRACT for scalar types, but acts elementwise on vectors.
83def G_TRUNC : GenericInstruction {
84  let OutOperandList = (outs type0:$dst);
85  let InOperandList = (ins type1:$src);
86  let hasSideEffects = false;
87}
88
89def G_IMPLICIT_DEF : GenericInstruction {
90  let OutOperandList = (outs type0:$dst);
91  let InOperandList = (ins);
92  let hasSideEffects = false;
93}
94
95def G_PHI : GenericInstruction {
96  let OutOperandList = (outs type0:$dst);
97  let InOperandList = (ins variable_ops);
98  let hasSideEffects = false;
99}
100
101def G_FRAME_INDEX : GenericInstruction {
102  let OutOperandList = (outs type0:$dst);
103  let InOperandList = (ins unknown:$src2);
104  let hasSideEffects = false;
105}
106
107def G_GLOBAL_VALUE : GenericInstruction {
108  let OutOperandList = (outs type0:$dst);
109  let InOperandList = (ins unknown:$src);
110  let hasSideEffects = false;
111}
112
113def G_CONSTANT_POOL : GenericInstruction {
114  let OutOperandList = (outs type0:$dst);
115  let InOperandList = (ins unknown:$src);
116  let hasSideEffects = false;
117}
118
119def G_INTTOPTR : GenericInstruction {
120  let OutOperandList = (outs type0:$dst);
121  let InOperandList = (ins type1:$src);
122  let hasSideEffects = false;
123}
124
125def G_PTRTOINT : GenericInstruction {
126  let OutOperandList = (outs type0:$dst);
127  let InOperandList = (ins type1:$src);
128  let hasSideEffects = false;
129}
130
131def G_BITCAST : GenericInstruction {
132  let OutOperandList = (outs type0:$dst);
133  let InOperandList = (ins type1:$src);
134  let hasSideEffects = false;
135}
136
137// Only supports scalar result types
138def G_CONSTANT : GenericInstruction {
139  let OutOperandList = (outs type0:$dst);
140  let InOperandList = (ins unknown:$imm);
141  let hasSideEffects = false;
142}
143
144// Only supports scalar result types
145def G_FCONSTANT : GenericInstruction {
146  let OutOperandList = (outs type0:$dst);
147  let InOperandList = (ins unknown:$imm);
148  let hasSideEffects = false;
149}
150
151def G_VASTART : GenericInstruction {
152  let OutOperandList = (outs);
153  let InOperandList = (ins type0:$list);
154  let hasSideEffects = false;
155  let mayStore = true;
156}
157
158def G_VAARG : GenericInstruction {
159  let OutOperandList = (outs type0:$val);
160  let InOperandList = (ins type1:$list, unknown:$align);
161  let hasSideEffects = false;
162  let mayLoad = true;
163  let mayStore = true;
164}
165
166def G_CTLZ : GenericInstruction {
167  let OutOperandList = (outs type0:$dst);
168  let InOperandList = (ins type1:$src);
169  let hasSideEffects = false;
170}
171
172def G_CTLZ_ZERO_UNDEF : GenericInstruction {
173  let OutOperandList = (outs type0:$dst);
174  let InOperandList = (ins type1:$src);
175  let hasSideEffects = false;
176}
177
178def G_CTTZ : GenericInstruction {
179  let OutOperandList = (outs type0:$dst);
180  let InOperandList = (ins type1:$src);
181  let hasSideEffects = false;
182}
183
184def G_CTTZ_ZERO_UNDEF : GenericInstruction {
185  let OutOperandList = (outs type0:$dst);
186  let InOperandList = (ins type1:$src);
187  let hasSideEffects = false;
188}
189
190def G_CTPOP : GenericInstruction {
191  let OutOperandList = (outs type0:$dst);
192  let InOperandList = (ins type1:$src);
193  let hasSideEffects = false;
194}
195
196def G_BSWAP : GenericInstruction {
197  let OutOperandList = (outs type0:$dst);
198  let InOperandList = (ins type0:$src);
199  let hasSideEffects = false;
200}
201
202def G_BITREVERSE : GenericInstruction {
203  let OutOperandList = (outs type0:$dst);
204  let InOperandList = (ins type0:$src);
205  let hasSideEffects = false;
206}
207
208def G_ADDRSPACE_CAST : GenericInstruction {
209  let OutOperandList = (outs type0:$dst);
210  let InOperandList = (ins type1:$src);
211  let hasSideEffects = false;
212}
213
214def G_BLOCK_ADDR : GenericInstruction {
215  let OutOperandList = (outs type0:$dst);
216  let InOperandList = (ins unknown:$ba);
217  let hasSideEffects = false;
218}
219
220def G_JUMP_TABLE : GenericInstruction {
221  let OutOperandList = (outs type0:$dst);
222  let InOperandList = (ins unknown:$jti);
223  let hasSideEffects = false;
224}
225
226def G_DYN_STACKALLOC : GenericInstruction {
227  let OutOperandList = (outs ptype0:$dst);
228  let InOperandList = (ins type1:$size, i32imm:$align);
229  let hasSideEffects = true;
230}
231
232def G_STACKSAVE : GenericInstruction {
233  let OutOperandList = (outs ptype0:$dst);
234  let InOperandList = (ins);
235  let hasSideEffects = true;
236}
237
238def G_STACKRESTORE : GenericInstruction {
239  let OutOperandList = (outs);
240  let InOperandList = (ins ptype0:$src);
241  let hasSideEffects = true;
242}
243
244def G_FREEZE : GenericInstruction {
245  let OutOperandList = (outs type0:$dst);
246  let InOperandList = (ins type0:$src);
247  let hasSideEffects = false;
248}
249
250def G_LROUND: GenericInstruction {
251  let OutOperandList = (outs type0:$dst);
252  let InOperandList = (ins type1:$src);
253  let hasSideEffects = false;
254}
255
256def G_LLROUND: GenericInstruction {
257  let OutOperandList = (outs type0:$dst);
258  let InOperandList = (ins type1:$src);
259  let hasSideEffects = false;
260}
261
262//------------------------------------------------------------------------------
263// Binary ops.
264//------------------------------------------------------------------------------
265
266// Generic addition.
267def G_ADD : GenericInstruction {
268  let OutOperandList = (outs type0:$dst);
269  let InOperandList = (ins type0:$src1, type0:$src2);
270  let hasSideEffects = false;
271  let isCommutable = true;
272}
273
274// Generic subtraction.
275def G_SUB : GenericInstruction {
276  let OutOperandList = (outs type0:$dst);
277  let InOperandList = (ins type0:$src1, type0:$src2);
278  let hasSideEffects = false;
279  let isCommutable = false;
280}
281
282// Generic multiplication.
283def G_MUL : GenericInstruction {
284  let OutOperandList = (outs type0:$dst);
285  let InOperandList = (ins type0:$src1, type0:$src2);
286  let hasSideEffects = false;
287  let isCommutable = true;
288}
289
290// Generic signed division.
291def G_SDIV : GenericInstruction {
292  let OutOperandList = (outs type0:$dst);
293  let InOperandList = (ins type0:$src1, type0:$src2);
294  let hasSideEffects = false;
295  let isCommutable = false;
296}
297
298// Generic unsigned division.
299def G_UDIV : GenericInstruction {
300  let OutOperandList = (outs type0:$dst);
301  let InOperandList = (ins type0:$src1, type0:$src2);
302  let hasSideEffects = false;
303  let isCommutable = false;
304}
305
306// Generic signed remainder.
307def G_SREM : GenericInstruction {
308  let OutOperandList = (outs type0:$dst);
309  let InOperandList = (ins type0:$src1, type0:$src2);
310  let hasSideEffects = false;
311  let isCommutable = false;
312}
313
314// Generic unsigned remainder.
315def G_UREM : GenericInstruction {
316  let OutOperandList = (outs type0:$dst);
317  let InOperandList = (ins type0:$src1, type0:$src2);
318  let hasSideEffects = false;
319  let isCommutable = false;
320}
321
322// Generic signed division and remainder.
323def G_SDIVREM : GenericInstruction {
324  let OutOperandList = (outs type0:$div, type0:$rem);
325  let InOperandList = (ins type0:$src1, type0:$src2);
326  let hasSideEffects = false;
327  let isCommutable = false;
328}
329
330// Generic unsigned division and remainder.
331def G_UDIVREM : GenericInstruction {
332  let OutOperandList = (outs type0:$div, type0:$rem);
333  let InOperandList = (ins type0:$src1, type0:$src2);
334  let hasSideEffects = false;
335  let isCommutable = false;
336}
337
338// Generic bitwise and.
339def G_AND : GenericInstruction {
340  let OutOperandList = (outs type0:$dst);
341  let InOperandList = (ins type0:$src1, type0:$src2);
342  let hasSideEffects = false;
343  let isCommutable = true;
344}
345
346// Generic bitwise or.
347def G_OR : GenericInstruction {
348  let OutOperandList = (outs type0:$dst);
349  let InOperandList = (ins type0:$src1, type0:$src2);
350  let hasSideEffects = false;
351  let isCommutable = true;
352}
353
354// Generic bitwise xor.
355def G_XOR : GenericInstruction {
356  let OutOperandList = (outs type0:$dst);
357  let InOperandList = (ins type0:$src1, type0:$src2);
358  let hasSideEffects = false;
359  let isCommutable = true;
360}
361
362// Generic left-shift.
363def G_SHL : GenericInstruction {
364  let OutOperandList = (outs type0:$dst);
365  let InOperandList = (ins type0:$src1, type1:$src2);
366  let hasSideEffects = false;
367}
368
369// Generic logical right-shift.
370def G_LSHR : GenericInstruction {
371  let OutOperandList = (outs type0:$dst);
372  let InOperandList = (ins type0:$src1, type1:$src2);
373  let hasSideEffects = false;
374}
375
376// Generic arithmetic right-shift.
377def G_ASHR : GenericInstruction {
378  let OutOperandList = (outs type0:$dst);
379  let InOperandList = (ins type0:$src1, type1:$src2);
380  let hasSideEffects = false;
381}
382
383/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
384/// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth)))
385def G_FSHL : GenericInstruction {
386  let OutOperandList = (outs type0:$dst);
387  let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
388  let hasSideEffects = false;
389}
390
391/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
392/// fshr(X,Y,Z): (X << (bitwidth - (Z % bitwidth))) | (Y >> (Z % bitwidth))
393def G_FSHR : GenericInstruction {
394  let OutOperandList = (outs type0:$dst);
395  let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
396  let hasSideEffects = false;
397}
398
399/// Rotate bits right.
400def G_ROTR : GenericInstruction {
401  let OutOperandList = (outs type0:$dst);
402  let InOperandList = (ins type0:$src1, type1:$src2);
403  let hasSideEffects = false;
404}
405
406/// Rotate bits left.
407def G_ROTL : GenericInstruction {
408  let OutOperandList = (outs type0:$dst);
409  let InOperandList = (ins type0:$src1, type1:$src2);
410  let hasSideEffects = false;
411}
412
413// Generic integer comparison.
414def G_ICMP : GenericInstruction {
415  let OutOperandList = (outs type0:$dst);
416  let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
417  let hasSideEffects = false;
418}
419
420// Generic floating-point comparison.
421def G_FCMP : GenericInstruction {
422  let OutOperandList = (outs type0:$dst);
423  let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
424  let hasSideEffects = false;
425}
426
427// Generic select
428def G_SELECT : GenericInstruction {
429  let OutOperandList = (outs type0:$dst);
430  let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
431  let hasSideEffects = false;
432}
433
434// Generic pointer offset.
435def G_PTR_ADD : GenericInstruction {
436  let OutOperandList = (outs ptype0:$dst);
437  let InOperandList = (ins ptype0:$src1, type1:$src2);
438  let hasSideEffects = false;
439}
440
441// Generic pointer mask. type1 should be an integer with the same
442// bitwidth as the pointer type.
443def G_PTRMASK : GenericInstruction {
444  let OutOperandList = (outs ptype0:$dst);
445  let InOperandList = (ins ptype0:$src, type1:$bits);
446  let hasSideEffects = false;
447}
448
449// Generic signed integer minimum.
450def G_SMIN : GenericInstruction {
451  let OutOperandList = (outs type0:$dst);
452  let InOperandList = (ins type0:$src1, type0:$src2);
453  let hasSideEffects = false;
454  let isCommutable = true;
455}
456
457// Generic signed integer maximum.
458def G_SMAX : GenericInstruction {
459  let OutOperandList = (outs type0:$dst);
460  let InOperandList = (ins type0:$src1, type0:$src2);
461  let hasSideEffects = false;
462  let isCommutable = true;
463}
464
465// Generic unsigned integer minimum.
466def G_UMIN : GenericInstruction {
467  let OutOperandList = (outs type0:$dst);
468  let InOperandList = (ins type0:$src1, type0:$src2);
469  let hasSideEffects = false;
470  let isCommutable = true;
471}
472
473// Generic unsigned integer maximum.
474def G_UMAX : GenericInstruction {
475  let OutOperandList = (outs type0:$dst);
476  let InOperandList = (ins type0:$src1, type0:$src2);
477  let hasSideEffects = false;
478  let isCommutable = true;
479}
480
481// Generic integer absolute value.
482def G_ABS : GenericInstruction {
483  let OutOperandList = (outs type0:$dst);
484  let InOperandList = (ins type0:$src);
485  let hasSideEffects = false;
486}
487
488//------------------------------------------------------------------------------
489// Overflow ops
490//------------------------------------------------------------------------------
491
492// Generic unsigned addition producing a carry flag.
493def G_UADDO : GenericInstruction {
494  let OutOperandList = (outs type0:$dst, type1:$carry_out);
495  let InOperandList = (ins type0:$src1, type0:$src2);
496  let hasSideEffects = false;
497  let isCommutable = true;
498}
499
500// Generic unsigned addition consuming and producing a carry flag.
501def G_UADDE : GenericInstruction {
502  let OutOperandList = (outs type0:$dst, type1:$carry_out);
503  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
504  let hasSideEffects = false;
505}
506
507// Generic signed addition producing a carry flag.
508def G_SADDO : GenericInstruction {
509  let OutOperandList = (outs type0:$dst, type1:$carry_out);
510  let InOperandList = (ins type0:$src1, type0:$src2);
511  let hasSideEffects = false;
512  let isCommutable = true;
513}
514
515// Generic signed addition consuming and producing a carry flag.
516def G_SADDE : GenericInstruction {
517  let OutOperandList = (outs type0:$dst, type1:$carry_out);
518  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
519  let hasSideEffects = false;
520}
521
522// Generic unsigned subtraction producing a carry flag.
523def G_USUBO : GenericInstruction {
524  let OutOperandList = (outs type0:$dst, type1:$carry_out);
525  let InOperandList = (ins type0:$src1, type0:$src2);
526  let hasSideEffects = false;
527}
528// Generic unsigned subtraction consuming and producing a carry flag.
529def G_USUBE : GenericInstruction {
530  let OutOperandList = (outs type0:$dst, type1:$carry_out);
531  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
532  let hasSideEffects = false;
533}
534
535// Generic signed subtraction producing a carry flag.
536def G_SSUBO : GenericInstruction {
537  let OutOperandList = (outs type0:$dst, type1:$carry_out);
538  let InOperandList = (ins type0:$src1, type0:$src2);
539  let hasSideEffects = false;
540}
541
542// Generic signed subtraction consuming and producing a carry flag.
543def G_SSUBE : GenericInstruction {
544  let OutOperandList = (outs type0:$dst, type1:$carry_out);
545  let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
546  let hasSideEffects = false;
547}
548
549// Generic unsigned multiplication producing a carry flag.
550def G_UMULO : GenericInstruction {
551  let OutOperandList = (outs type0:$dst, type1:$carry_out);
552  let InOperandList = (ins type0:$src1, type0:$src2);
553  let hasSideEffects = false;
554  let isCommutable = true;
555}
556
557// Generic signed multiplication producing a carry flag.
558def G_SMULO : GenericInstruction {
559  let OutOperandList = (outs type0:$dst, type1:$carry_out);
560  let InOperandList = (ins type0:$src1, type0:$src2);
561  let hasSideEffects = false;
562  let isCommutable = true;
563}
564
565// Multiply two numbers at twice the incoming bit width (unsigned) and return
566// the high half of the result.
567def G_UMULH : GenericInstruction {
568  let OutOperandList = (outs type0:$dst);
569  let InOperandList = (ins type0:$src1, type0:$src2);
570  let hasSideEffects = false;
571  let isCommutable = true;
572}
573
574// Multiply two numbers at twice the incoming bit width (signed) and return
575// the high half of the result.
576def G_SMULH : GenericInstruction {
577  let OutOperandList = (outs type0:$dst);
578  let InOperandList = (ins type0:$src1, type0:$src2);
579  let hasSideEffects = false;
580  let isCommutable = true;
581}
582
583//------------------------------------------------------------------------------
584// Saturating ops
585//------------------------------------------------------------------------------
586
587// Generic saturating unsigned addition.
588def G_UADDSAT : GenericInstruction {
589  let OutOperandList = (outs type0:$dst);
590  let InOperandList = (ins type0:$src1, type0:$src2);
591  let hasSideEffects = false;
592  let isCommutable = true;
593}
594
595// Generic saturating signed addition.
596def G_SADDSAT : GenericInstruction {
597  let OutOperandList = (outs type0:$dst);
598  let InOperandList = (ins type0:$src1, type0:$src2);
599  let hasSideEffects = false;
600  let isCommutable = true;
601}
602
603// Generic saturating unsigned subtraction.
604def G_USUBSAT : GenericInstruction {
605  let OutOperandList = (outs type0:$dst);
606  let InOperandList = (ins type0:$src1, type0:$src2);
607  let hasSideEffects = false;
608  let isCommutable = false;
609}
610
611// Generic saturating signed subtraction.
612def G_SSUBSAT : GenericInstruction {
613  let OutOperandList = (outs type0:$dst);
614  let InOperandList = (ins type0:$src1, type0:$src2);
615  let hasSideEffects = false;
616  let isCommutable = false;
617}
618
619// Generic saturating unsigned left shift.
620def G_USHLSAT : GenericInstruction {
621  let OutOperandList = (outs type0:$dst);
622  let InOperandList = (ins type0:$src1, type1:$src2);
623  let hasSideEffects = false;
624  let isCommutable = false;
625}
626
627// Generic saturating signed left shift.
628def G_SSHLSAT : GenericInstruction {
629  let OutOperandList = (outs type0:$dst);
630  let InOperandList = (ins type0:$src1, type1:$src2);
631  let hasSideEffects = false;
632  let isCommutable = false;
633}
634
635/// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point
636/// multiplication on 2 integers with the same width and scale. SCALE
637/// represents the scale of both operands as fixed point numbers. This
638/// SCALE parameter must be a constant integer. A scale of zero is
639/// effectively performing multiplication on 2 integers.
640def G_SMULFIX : GenericInstruction {
641  let OutOperandList = (outs type0:$dst);
642  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
643  let hasSideEffects = false;
644  let isCommutable = true;
645}
646
647def G_UMULFIX : GenericInstruction {
648  let OutOperandList = (outs type0:$dst);
649  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
650  let hasSideEffects = false;
651  let isCommutable = true;
652}
653
654/// Same as the corresponding unsaturated fixed point instructions, but the
655/// result is clamped between the min and max values representable by the
656/// bits of the first 2 operands.
657def G_SMULFIXSAT : GenericInstruction {
658  let OutOperandList = (outs type0:$dst);
659  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
660  let hasSideEffects = false;
661  let isCommutable = true;
662}
663
664def G_UMULFIXSAT : GenericInstruction {
665  let OutOperandList = (outs type0:$dst);
666  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
667  let hasSideEffects = false;
668  let isCommutable = true;
669}
670
671/// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on
672/// 2 integers with the same width and scale. SCALE represents the scale
673/// of both operands as fixed point numbers. This SCALE parameter must be a
674/// constant integer.
675def G_SDIVFIX : GenericInstruction {
676  let OutOperandList = (outs type0:$dst);
677  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
678  let hasSideEffects = false;
679  let isCommutable = false;
680}
681
682def G_UDIVFIX : GenericInstruction {
683  let OutOperandList = (outs type0:$dst);
684  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
685  let hasSideEffects = false;
686  let isCommutable = false;
687}
688
689/// Same as the corresponding unsaturated fixed point instructions,
690/// but the result is clamped between the min and max values
691/// representable by the bits of the first 2 operands.
692def G_SDIVFIXSAT : GenericInstruction {
693  let OutOperandList = (outs type0:$dst);
694  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
695  let hasSideEffects = false;
696  let isCommutable = false;
697}
698
699def G_UDIVFIXSAT : GenericInstruction {
700  let OutOperandList = (outs type0:$dst);
701  let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
702  let hasSideEffects = false;
703  let isCommutable = false;
704}
705
706//------------------------------------------------------------------------------
707// Floating Point Unary Ops.
708//------------------------------------------------------------------------------
709
710def G_FNEG : GenericInstruction {
711  let OutOperandList = (outs type0:$dst);
712  let InOperandList = (ins type0:$src);
713  let hasSideEffects = false;
714}
715
716def G_FPEXT : GenericInstruction {
717  let OutOperandList = (outs type0:$dst);
718  let InOperandList = (ins type1:$src);
719  let hasSideEffects = false;
720}
721
722def G_FPTRUNC : GenericInstruction {
723  let OutOperandList = (outs type0:$dst);
724  let InOperandList = (ins type1:$src);
725  let hasSideEffects = false;
726}
727
728def G_FPTOSI : GenericInstruction {
729  let OutOperandList = (outs type0:$dst);
730  let InOperandList = (ins type1:$src);
731  let hasSideEffects = false;
732}
733
734def G_FPTOUI : GenericInstruction {
735  let OutOperandList = (outs type0:$dst);
736  let InOperandList = (ins type1:$src);
737  let hasSideEffects = false;
738}
739
740def G_SITOFP : GenericInstruction {
741  let OutOperandList = (outs type0:$dst);
742  let InOperandList = (ins type1:$src);
743  let hasSideEffects = false;
744}
745
746def G_UITOFP : GenericInstruction {
747  let OutOperandList = (outs type0:$dst);
748  let InOperandList = (ins type1:$src);
749  let hasSideEffects = false;
750}
751
752def G_FABS : GenericInstruction {
753  let OutOperandList = (outs type0:$dst);
754  let InOperandList = (ins type0:$src);
755  let hasSideEffects = false;
756}
757
758def G_FCOPYSIGN : GenericInstruction {
759  let OutOperandList = (outs type0:$dst);
760  let InOperandList = (ins type0:$src0, type1:$src1);
761  let hasSideEffects = false;
762}
763
764def G_FCANONICALIZE : GenericInstruction {
765  let OutOperandList = (outs type0:$dst);
766  let InOperandList = (ins type0:$src);
767  let hasSideEffects = false;
768}
769
770// Generic opcode equivalent to the llvm.is_fpclass intrinsic.
771def G_IS_FPCLASS: GenericInstruction {
772  let OutOperandList = (outs type0:$dst);
773  let InOperandList = (ins type1:$src, unknown:$test);
774  let hasSideEffects = false;
775}
776
777// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
778// values.
779//
780// In the case where a single input is a NaN (either signaling or quiet),
781// the non-NaN input is returned.
782//
783// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
784def G_FMINNUM : GenericInstruction {
785  let OutOperandList = (outs type0:$dst);
786  let InOperandList = (ins type0:$src1, type0:$src2);
787  let hasSideEffects = false;
788  let isCommutable = true;
789}
790
791def G_FMAXNUM : GenericInstruction {
792  let OutOperandList = (outs type0:$dst);
793  let InOperandList = (ins type0:$src1, type0:$src2);
794  let hasSideEffects = false;
795  let isCommutable = true;
796}
797
798// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
799// two values, following the IEEE-754 2008 definition. This differs from
800// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
801// signaling NaN, returns a quiet NaN.
802def G_FMINNUM_IEEE : GenericInstruction {
803  let OutOperandList = (outs type0:$dst);
804  let InOperandList = (ins type0:$src1, type0:$src2);
805  let hasSideEffects = false;
806  let isCommutable = true;
807}
808
809def G_FMAXNUM_IEEE : GenericInstruction {
810  let OutOperandList = (outs type0:$dst);
811  let InOperandList = (ins type0:$src1, type0:$src2);
812  let hasSideEffects = false;
813  let isCommutable = true;
814}
815
816// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
817// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
818// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2019 semantics.
819def G_FMINIMUM : GenericInstruction {
820  let OutOperandList = (outs type0:$dst);
821  let InOperandList = (ins type0:$src1, type0:$src2);
822  let hasSideEffects = false;
823  let isCommutable = true;
824}
825
826def G_FMAXIMUM : GenericInstruction {
827  let OutOperandList = (outs type0:$dst);
828  let InOperandList = (ins type0:$src1, type0:$src2);
829  let hasSideEffects = false;
830  let isCommutable = true;
831}
832
833//------------------------------------------------------------------------------
834// Floating Point Binary ops.
835//------------------------------------------------------------------------------
836
837// Generic FP addition.
838def G_FADD : GenericInstruction {
839  let OutOperandList = (outs type0:$dst);
840  let InOperandList = (ins type0:$src1, type0:$src2);
841  let hasSideEffects = false;
842  let isCommutable = true;
843}
844
845// Generic FP subtraction.
846def G_FSUB : GenericInstruction {
847  let OutOperandList = (outs type0:$dst);
848  let InOperandList = (ins type0:$src1, type0:$src2);
849  let hasSideEffects = false;
850  let isCommutable = false;
851}
852
853// Generic FP multiplication.
854def G_FMUL : GenericInstruction {
855  let OutOperandList = (outs type0:$dst);
856  let InOperandList = (ins type0:$src1, type0:$src2);
857  let hasSideEffects = false;
858  let isCommutable = true;
859}
860
861// Generic fused multiply-add instruction.
862// Behaves like llvm fma intrinsic ie src1 * src2 + src3
863def G_FMA : GenericInstruction {
864  let OutOperandList = (outs type0:$dst);
865  let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
866  let hasSideEffects = false;
867  let isCommutable = false;
868}
869
870/// Generic FP multiply and add. Perform a * b + c, while getting the
871/// same result as the separately rounded operations, unlike G_FMA.
872def G_FMAD : GenericInstruction {
873  let OutOperandList = (outs type0:$dst);
874  let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
875  let hasSideEffects = false;
876  let isCommutable = false;
877}
878
879// Generic FP division.
880def G_FDIV : GenericInstruction {
881  let OutOperandList = (outs type0:$dst);
882  let InOperandList = (ins type0:$src1, type0:$src2);
883  let hasSideEffects = false;
884}
885
886// Generic FP remainder.
887def G_FREM : GenericInstruction {
888  let OutOperandList = (outs type0:$dst);
889  let InOperandList = (ins type0:$src1, type0:$src2);
890  let hasSideEffects = false;
891}
892
893// Floating point exponentiation.
894def G_FPOW : GenericInstruction {
895  let OutOperandList = (outs type0:$dst);
896  let InOperandList = (ins type0:$src1, type0:$src2);
897  let hasSideEffects = false;
898}
899
900// Floating point exponentiation, with an integer power.
901def G_FPOWI : GenericInstruction {
902  let OutOperandList = (outs type0:$dst);
903  let InOperandList = (ins type0:$src0, type1:$src1);
904  let hasSideEffects = false;
905}
906
907// Floating point base-e exponential of a value.
908def G_FEXP : GenericInstruction {
909  let OutOperandList = (outs type0:$dst);
910  let InOperandList = (ins type0:$src1);
911  let hasSideEffects = false;
912}
913
914// Floating point base-2 exponential of a value.
915def G_FEXP2 : GenericInstruction {
916  let OutOperandList = (outs type0:$dst);
917  let InOperandList = (ins type0:$src1);
918  let hasSideEffects = false;
919}
920
921// Floating point base-10 exponential of a value.
922def G_FEXP10 : GenericInstruction {
923  let OutOperandList = (outs type0:$dst);
924  let InOperandList = (ins type0:$src1);
925  let hasSideEffects = false;
926}
927
928// Floating point base-e logarithm of a value.
929def G_FLOG : GenericInstruction {
930  let OutOperandList = (outs type0:$dst);
931  let InOperandList = (ins type0:$src1);
932  let hasSideEffects = false;
933}
934
935// Floating point base-2 logarithm of a value.
936def G_FLOG2 : GenericInstruction {
937  let OutOperandList = (outs type0:$dst);
938  let InOperandList = (ins type0:$src1);
939  let hasSideEffects = false;
940}
941
942// Floating point base-10 logarithm of a value.
943def G_FLOG10 : GenericInstruction {
944  let OutOperandList = (outs type0:$dst);
945  let InOperandList = (ins type0:$src1);
946  let hasSideEffects = false;
947}
948
949// Floating point x * 2^n
950def G_FLDEXP : GenericInstruction {
951  let OutOperandList = (outs type0:$dst);
952  let InOperandList = (ins type0:$src0, type1:$src1);
953  let hasSideEffects = false;
954}
955
956// Floating point frexp
957def G_FFREXP : GenericInstruction {
958  let OutOperandList = (outs type0:$dst0, type1:$dst1);
959  let InOperandList = (ins type0:$src0);
960  let hasSideEffects = false;
961}
962
963// Floating point ceiling of a value.
964def G_FCEIL : GenericInstruction {
965  let OutOperandList = (outs type0:$dst);
966  let InOperandList = (ins type0:$src1);
967  let hasSideEffects = false;
968}
969
970// Floating point cosine of a value.
971def G_FCOS : GenericInstruction {
972  let OutOperandList = (outs type0:$dst);
973  let InOperandList = (ins type0:$src1);
974  let hasSideEffects = false;
975}
976
977// Floating point sine of a value.
978def G_FSIN : GenericInstruction {
979  let OutOperandList = (outs type0:$dst);
980  let InOperandList = (ins type0:$src1);
981  let hasSideEffects = false;
982}
983
984// Floating point square root of a value.
985// This returns NaN for negative nonzero values.
986// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
987// libm-conformant.
988def G_FSQRT : GenericInstruction {
989  let OutOperandList = (outs type0:$dst);
990  let InOperandList = (ins type0:$src1);
991  let hasSideEffects = false;
992}
993
994// Floating point floor of a value.
995def G_FFLOOR : GenericInstruction {
996  let OutOperandList = (outs type0:$dst);
997  let InOperandList = (ins type0:$src1);
998  let hasSideEffects = false;
999}
1000
1001// Floating point round to next integer.
1002def G_FRINT : GenericInstruction {
1003  let OutOperandList = (outs type0:$dst);
1004  let InOperandList = (ins type0:$src1);
1005  let hasSideEffects = false;
1006}
1007
1008// Floating point round to the nearest integer.
1009def G_FNEARBYINT : GenericInstruction {
1010  let OutOperandList = (outs type0:$dst);
1011  let InOperandList = (ins type0:$src1);
1012  let hasSideEffects = false;
1013}
1014
1015//------------------------------------------------------------------------------
1016// Access to floating-point environment.
1017//------------------------------------------------------------------------------
1018
1019// These operations read/write floating-point environment. The interaction with
1020// it is modeled as a side effect, because constrained intrinsics use the same
1021// method.
1022
1023// Reading floating-point environment.
1024def G_GET_FPENV : GenericInstruction {
1025  let OutOperandList = (outs type0:$dst);
1026  let InOperandList = (ins);
1027  let hasSideEffects = true;
1028}
1029
1030// Setting floating-point environment.
1031def G_SET_FPENV : GenericInstruction {
1032  let OutOperandList = (outs);
1033  let InOperandList = (ins type0:$src);
1034  let hasSideEffects = true;
1035}
1036
1037// Setting default floating-point environment.
1038def G_RESET_FPENV : GenericInstruction {
1039  let OutOperandList = (outs);
1040  let InOperandList = (ins);
1041  let hasSideEffects = true;
1042}
1043
1044// Reading floating-point control modes.
1045def G_GET_FPMODE : GenericInstruction {
1046  let OutOperandList = (outs type0:$dst);
1047  let InOperandList = (ins);
1048  let hasSideEffects = true;
1049}
1050
1051// Setting floating-point control modes.
1052def G_SET_FPMODE : GenericInstruction {
1053  let OutOperandList = (outs);
1054  let InOperandList = (ins type0:$src);
1055  let hasSideEffects = true;
1056}
1057
1058// Setting floating-point control modes to default state.
1059def G_RESET_FPMODE : GenericInstruction {
1060  let OutOperandList = (outs);
1061  let InOperandList = (ins);
1062  let hasSideEffects = true;
1063}
1064
1065//------------------------------------------------------------------------------
1066// Opcodes for LLVM Intrinsics
1067//------------------------------------------------------------------------------
1068def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction {
1069  let OutOperandList = (outs type0:$dst);
1070  let InOperandList = (ins type1:$src1, i32imm:$round_mode);
1071  let hasSideEffects = false;
1072}
1073
1074def G_INTRINSIC_TRUNC : GenericInstruction {
1075  let OutOperandList = (outs type0:$dst);
1076  let InOperandList = (ins type0:$src1);
1077  let hasSideEffects = false;
1078}
1079
1080def G_INTRINSIC_ROUND : GenericInstruction {
1081  let OutOperandList = (outs type0:$dst);
1082  let InOperandList = (ins type0:$src1);
1083  let hasSideEffects = false;
1084}
1085
1086def G_INTRINSIC_LRINT : GenericInstruction {
1087  let OutOperandList = (outs type0:$dst);
1088  let InOperandList = (ins type1:$src);
1089  let hasSideEffects = false;
1090}
1091
1092def G_INTRINSIC_ROUNDEVEN : GenericInstruction {
1093  let OutOperandList = (outs type0:$dst);
1094  let InOperandList = (ins type0:$src1);
1095  let hasSideEffects = false;
1096}
1097
1098def G_READCYCLECOUNTER : GenericInstruction {
1099  let OutOperandList = (outs type0:$dst);
1100  let InOperandList = (ins);
1101  let hasSideEffects = true;
1102}
1103
1104def G_READSTEADYCOUNTER : GenericInstruction {
1105  let OutOperandList = (outs type0:$dst);
1106  let InOperandList = (ins);
1107  let hasSideEffects = true;
1108}
1109
1110//------------------------------------------------------------------------------
1111// Memory ops
1112//------------------------------------------------------------------------------
1113
1114// Generic load. Expects a MachineMemOperand in addition to explicit
1115// operands. If the result size is larger than the memory size, the
1116// high bits are undefined. If the result is a vector type and larger
1117// than the memory size, the high elements are undefined (i.e. this is
1118// not a per-element, vector anyextload)
1119def G_LOAD : GenericInstruction {
1120  let OutOperandList = (outs type0:$dst);
1121  let InOperandList = (ins ptype1:$addr);
1122  let hasSideEffects = false;
1123  let mayLoad = true;
1124}
1125
1126// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
1127def G_SEXTLOAD : GenericInstruction {
1128  let OutOperandList = (outs type0:$dst);
1129  let InOperandList = (ins ptype1:$addr);
1130  let hasSideEffects = false;
1131  let mayLoad = true;
1132}
1133
1134// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
1135def G_ZEXTLOAD : GenericInstruction {
1136  let OutOperandList = (outs type0:$dst);
1137  let InOperandList = (ins ptype1:$addr);
1138  let hasSideEffects = false;
1139  let mayLoad = true;
1140}
1141
1142// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
1143// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
1144//  then the value is loaded from $newaddr.
1145def G_INDEXED_LOAD : GenericInstruction {
1146  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1147  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1148  let hasSideEffects = false;
1149  let mayLoad = true;
1150}
1151
1152// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
1153def G_INDEXED_SEXTLOAD : GenericInstruction {
1154  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1155  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1156  let hasSideEffects = false;
1157  let mayLoad = true;
1158}
1159
1160// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
1161def G_INDEXED_ZEXTLOAD : GenericInstruction {
1162  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1163  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1164  let hasSideEffects = false;
1165  let mayLoad = true;
1166}
1167
1168// Generic store. Expects a MachineMemOperand in addition to explicit operands.
1169def G_STORE : GenericInstruction {
1170  let OutOperandList = (outs);
1171  let InOperandList = (ins type0:$src, ptype1:$addr);
1172  let hasSideEffects = false;
1173  let mayStore = true;
1174}
1175
1176// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
1177def G_INDEXED_STORE : GenericInstruction {
1178  let OutOperandList = (outs ptype0:$newaddr);
1179  let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
1180                           unknown:$am);
1181  let hasSideEffects = false;
1182  let mayStore = true;
1183}
1184
1185// Generic atomic cmpxchg with internal success check. Expects a
1186// MachineMemOperand in addition to explicit operands.
1187def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
1188  let OutOperandList = (outs type0:$oldval, type1:$success);
1189  let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
1190  let hasSideEffects = false;
1191  let mayLoad = true;
1192  let mayStore = true;
1193}
1194
1195// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
1196// operands.
1197def G_ATOMIC_CMPXCHG : GenericInstruction {
1198  let OutOperandList = (outs type0:$oldval);
1199  let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
1200  let hasSideEffects = false;
1201  let mayLoad = true;
1202  let mayStore = true;
1203}
1204
1205// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
1206// operands.
1207class G_ATOMICRMW_OP : GenericInstruction {
1208  let OutOperandList = (outs type0:$oldval);
1209  let InOperandList = (ins ptype1:$addr, type0:$val);
1210  let hasSideEffects = false;
1211  let mayLoad = true;
1212  let mayStore = true;
1213}
1214
1215def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
1216def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
1217def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
1218def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
1219def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
1220def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
1221def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
1222def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
1223def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
1224def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
1225def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
1226def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
1227def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
1228def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP;
1229def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP;
1230def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP;
1231def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP;
1232
1233def G_FENCE : GenericInstruction {
1234  let OutOperandList = (outs);
1235  let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
1236  let hasSideEffects = true;
1237}
1238
1239// Generic opcode equivalent to the llvm.prefetch intrinsic.
1240def G_PREFETCH : GenericInstruction {
1241  let OutOperandList = (outs);
1242  let InOperandList = (ins ptype0:$address, i32imm:$rw, i32imm:$locality, i32imm:$cachetype);
1243  let hasSideEffects = true;
1244  let mayLoad = true;
1245  let mayStore = true;
1246}
1247
1248//------------------------------------------------------------------------------
1249// Variadic ops
1250//------------------------------------------------------------------------------
1251
1252// Extract a register of the specified size, starting from the block given by
1253// index. This will almost certainly be mapped to sub-register COPYs after
1254// register banks have been selected.
1255def G_EXTRACT : GenericInstruction {
1256  let OutOperandList = (outs type0:$res);
1257  let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
1258  let hasSideEffects = false;
1259}
1260
1261// Extract multiple registers specified size, starting from blocks given by
1262// indexes. This will almost certainly be mapped to sub-register COPYs after
1263// register banks have been selected.
1264// The output operands are always ordered from lowest bits to highest:
1265//   %bits_0_7:(s8), %bits_8_15:(s8),
1266//       %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
1267def G_UNMERGE_VALUES : GenericInstruction {
1268  let OutOperandList = (outs type0:$dst0, variable_ops);
1269  let InOperandList = (ins type1:$src);
1270  let hasSideEffects = false;
1271  let variadicOpsType = type0;
1272}
1273
1274// Insert a smaller register into a larger one at the specified bit-index.
1275def G_INSERT : GenericInstruction {
1276  let OutOperandList = (outs type0:$dst);
1277  let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
1278  let hasSideEffects = false;
1279}
1280
1281// Concatenate multiple registers of the same size into a wider register.
1282// The input operands are always ordered from lowest bits to highest:
1283//   %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
1284//                             %bits_16_23:(s8), %bits_24_31:(s8)
1285def G_MERGE_VALUES : GenericInstruction {
1286  let OutOperandList = (outs type0:$dst);
1287  let InOperandList = (ins type1:$src0, variable_ops);
1288  let hasSideEffects = false;
1289  let variadicOpsType = type1;
1290}
1291
1292// Generic vscale.
1293// Puts the value of the runtime vscale multiplied by the value in the source
1294// operand into the destination register.
1295def G_VSCALE : GenericInstruction {
1296  let OutOperandList = (outs type0:$dst);
1297  let InOperandList = (ins unknown:$src);
1298  let hasSideEffects = false;
1299}
1300
1301/// Create a vector from multiple scalar registers. No implicit
1302/// conversion is performed (i.e. the result element type must be the
1303/// same as all source operands)
1304def G_BUILD_VECTOR : GenericInstruction {
1305  let OutOperandList = (outs type0:$dst);
1306  let InOperandList = (ins type1:$src0, variable_ops);
1307  let hasSideEffects = false;
1308  let variadicOpsType = type1;
1309}
1310
1311/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
1312/// destination vector elt type.
1313def G_BUILD_VECTOR_TRUNC : GenericInstruction {
1314  let OutOperandList = (outs type0:$dst);
1315  let InOperandList = (ins type1:$src0, variable_ops);
1316  let hasSideEffects = false;
1317}
1318
1319/// Create a vector by concatenating vectors together.
1320def G_CONCAT_VECTORS : GenericInstruction {
1321  let OutOperandList = (outs type0:$dst);
1322  let InOperandList = (ins type1:$src0, variable_ops);
1323  let hasSideEffects = false;
1324}
1325
1326// Intrinsic without side effects.
1327def G_INTRINSIC : GenericInstruction {
1328  let OutOperandList = (outs);
1329  let InOperandList = (ins unknown:$intrin, variable_ops);
1330  let hasSideEffects = false;
1331}
1332
1333// Intrinsic with side effects.
1334def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
1335  let OutOperandList = (outs);
1336  let InOperandList = (ins unknown:$intrin, variable_ops);
1337  let hasSideEffects = true;
1338  let mayLoad = true;
1339  let mayStore = true;
1340}
1341
1342// Convergent intrinsic without side effects.
1343def G_INTRINSIC_CONVERGENT : GenericInstruction {
1344  let OutOperandList = (outs);
1345  let InOperandList = (ins unknown:$intrin, variable_ops);
1346  let hasSideEffects = false;
1347  let isConvergent = true;
1348}
1349
1350// Convergent intrinsic with side effects.
1351def G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS : GenericInstruction {
1352  let OutOperandList = (outs);
1353  let InOperandList = (ins unknown:$intrin, variable_ops);
1354  let hasSideEffects = true;
1355  let mayLoad = true;
1356  let mayStore = true;
1357  let isConvergent = true;
1358}
1359
1360//------------------------------------------------------------------------------
1361// Branches.
1362//------------------------------------------------------------------------------
1363
1364// Generic unconditional branch.
1365def G_BR : GenericInstruction {
1366  let OutOperandList = (outs);
1367  let InOperandList = (ins unknown:$src1);
1368  let hasSideEffects = false;
1369  let isBranch = true;
1370  let isTerminator = true;
1371  let isBarrier = true;
1372}
1373
1374// Generic conditional branch.
1375def G_BRCOND : GenericInstruction {
1376  let OutOperandList = (outs);
1377  let InOperandList = (ins type0:$tst, unknown:$truebb);
1378  let hasSideEffects = false;
1379  let isBranch = true;
1380  let isTerminator = true;
1381}
1382
1383// Generic indirect branch.
1384def G_BRINDIRECT : GenericInstruction {
1385  let OutOperandList = (outs);
1386  let InOperandList = (ins type0:$src1);
1387  let hasSideEffects = false;
1388  let isBranch = true;
1389  let isTerminator = true;
1390  let isBarrier = true;
1391  let isIndirectBranch = true;
1392}
1393
1394// Generic branch to jump table entry
1395def G_BRJT : GenericInstruction {
1396  let OutOperandList = (outs);
1397  let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1398  let hasSideEffects = false;
1399  let isBranch = true;
1400  let isTerminator = true;
1401  let isBarrier = true;
1402  let isIndirectBranch = true;
1403}
1404
1405// A marker to signal the following code is an invoke region, that may throw
1406// an exception and therefore not return.
1407def G_INVOKE_REGION_START : GenericInstruction {
1408  let OutOperandList = (outs);
1409  let InOperandList = (ins);
1410  let isTerminator = true; // This must be a terminator.
1411  let hasSideEffects = false;
1412}
1413
1414def G_READ_REGISTER : GenericInstruction {
1415  let OutOperandList = (outs type0:$dst);
1416  let InOperandList = (ins unknown:$register);
1417  let hasSideEffects = true;
1418
1419  // Assume convergent. It's probably not worth the effort of somehow
1420  // modeling convergent and nonconvergent register accesses.
1421  let isConvergent = true;
1422}
1423
1424def G_WRITE_REGISTER : GenericInstruction {
1425  let OutOperandList = (outs);
1426  let InOperandList = (ins unknown:$register, type0:$value);
1427  let hasSideEffects = true;
1428
1429  // Assume convergent. It's probably not worth the effort of somehow
1430  // modeling convergent and nonconvergent register accesses.
1431  let isConvergent = true;
1432}
1433
1434//------------------------------------------------------------------------------
1435// Vector ops
1436//------------------------------------------------------------------------------
1437
1438// Generic insert subvector.
1439def G_INSERT_SUBVECTOR : GenericInstruction {
1440  let OutOperandList = (outs type0:$dst);
1441  let InOperandList = (ins type0:$src0, type1:$src1, untyped_imm_0:$idx);
1442  let hasSideEffects = false;
1443}
1444
1445// Generic extract subvector.
1446def G_EXTRACT_SUBVECTOR : GenericInstruction {
1447  let OutOperandList = (outs type0:$dst);
1448  let InOperandList = (ins type0:$src, untyped_imm_0:$idx);
1449  let hasSideEffects = false;
1450}
1451
1452// Generic insertelement.
1453def G_INSERT_VECTOR_ELT : GenericInstruction {
1454  let OutOperandList = (outs type0:$dst);
1455  let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1456  let hasSideEffects = false;
1457}
1458
1459// Generic extractelement.
1460def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1461  let OutOperandList = (outs type0:$dst);
1462  let InOperandList = (ins type1:$src, type2:$idx);
1463  let hasSideEffects = false;
1464}
1465
1466// Generic shufflevector.
1467//
1468// The mask operand should be an IR Constant which exactly matches the
1469// corresponding mask for the IR shufflevector instruction.
1470def G_SHUFFLE_VECTOR: GenericInstruction {
1471  let OutOperandList = (outs type0:$dst);
1472  let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1473  let hasSideEffects = false;
1474}
1475
1476// Generic splatvector.
1477def G_SPLAT_VECTOR: GenericInstruction {
1478  let OutOperandList = (outs type0:$dst);
1479  let InOperandList = (ins type1:$val);
1480  let hasSideEffects = false;
1481}
1482
1483//------------------------------------------------------------------------------
1484// Vector reductions
1485//------------------------------------------------------------------------------
1486
1487class VectorReduction : GenericInstruction {
1488  let OutOperandList = (outs type0:$dst);
1489  let InOperandList = (ins type1:$v);
1490  let hasSideEffects = false;
1491}
1492
1493def G_VECREDUCE_SEQ_FADD : GenericInstruction {
1494  let OutOperandList = (outs type0:$dst);
1495  let InOperandList = (ins type1:$acc, type2:$v);
1496  let hasSideEffects = false;
1497}
1498
1499def G_VECREDUCE_SEQ_FMUL : GenericInstruction {
1500  let OutOperandList = (outs type0:$dst);
1501  let InOperandList = (ins type1:$acc, type2:$v);
1502  let hasSideEffects = false;
1503}
1504
1505def G_VECREDUCE_FADD : VectorReduction;
1506def G_VECREDUCE_FMUL : VectorReduction;
1507
1508def G_VECREDUCE_FMAX : VectorReduction;
1509def G_VECREDUCE_FMIN : VectorReduction;
1510def G_VECREDUCE_FMAXIMUM : VectorReduction;
1511def G_VECREDUCE_FMINIMUM : VectorReduction;
1512
1513def G_VECREDUCE_ADD : VectorReduction;
1514def G_VECREDUCE_MUL : VectorReduction;
1515def G_VECREDUCE_AND : VectorReduction;
1516def G_VECREDUCE_OR : VectorReduction;
1517def G_VECREDUCE_XOR : VectorReduction;
1518def G_VECREDUCE_SMAX : VectorReduction;
1519def G_VECREDUCE_SMIN : VectorReduction;
1520def G_VECREDUCE_UMAX : VectorReduction;
1521def G_VECREDUCE_UMIN : VectorReduction;
1522
1523//------------------------------------------------------------------------------
1524// Constrained floating point ops
1525//------------------------------------------------------------------------------
1526
1527def G_STRICT_FADD : ConstrainedInstruction<G_FADD>;
1528def G_STRICT_FSUB : ConstrainedInstruction<G_FSUB>;
1529def G_STRICT_FMUL : ConstrainedInstruction<G_FMUL>;
1530def G_STRICT_FDIV : ConstrainedInstruction<G_FDIV>;
1531def G_STRICT_FREM : ConstrainedInstruction<G_FREM>;
1532def G_STRICT_FMA : ConstrainedInstruction<G_FMA>;
1533def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>;
1534def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>;
1535
1536//------------------------------------------------------------------------------
1537// Memory intrinsics
1538//------------------------------------------------------------------------------
1539
1540def G_MEMCPY : GenericInstruction {
1541  let OutOperandList = (outs);
1542  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1543  let hasSideEffects = false;
1544  let mayLoad = true;
1545  let mayStore = true;
1546}
1547
1548def G_MEMCPY_INLINE : GenericInstruction {
1549  let OutOperandList = (outs);
1550  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size);
1551  let hasSideEffects = false;
1552  let mayLoad = true;
1553  let mayStore = true;
1554}
1555
1556def G_MEMMOVE : GenericInstruction {
1557  let OutOperandList = (outs);
1558  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1559  let hasSideEffects = false;
1560  let mayLoad = true;
1561  let mayStore = true;
1562}
1563
1564def G_MEMSET : GenericInstruction {
1565  let OutOperandList = (outs);
1566  let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
1567  let hasSideEffects = false;
1568  let mayStore = true;
1569}
1570
1571def G_BZERO : GenericInstruction {
1572  let OutOperandList = (outs);
1573  let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall);
1574  let hasSideEffects = false;
1575  let mayStore = true;
1576}
1577
1578//------------------------------------------------------------------------------
1579// Bitfield extraction.
1580//------------------------------------------------------------------------------
1581
1582// Generic signed bitfield extraction. The operands are in the range
1583// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1584def G_SBFX : GenericInstruction {
1585  let OutOperandList = (outs type0:$dst);
1586  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1587  let hasSideEffects = false;
1588}
1589
1590// Generic unsigned bitfield extraction. The operands are in the range
1591// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1592def G_UBFX : GenericInstruction {
1593  let OutOperandList = (outs type0:$dst);
1594  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1595  let hasSideEffects = false;
1596}
1597
1598//------------------------------------------------------------------------------
1599// Optimization hints
1600//------------------------------------------------------------------------------
1601
1602// Asserts that an operation has already been zero-extended from a specific
1603// type.
1604def G_ASSERT_ZEXT : GenericInstruction {
1605  let OutOperandList = (outs type0:$dst);
1606  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1607  let hasSideEffects = false;
1608}
1609
1610// Asserts that an operation has already been sign-extended from a specific
1611// type.
1612def G_ASSERT_SEXT : GenericInstruction {
1613  let OutOperandList = (outs type0:$dst);
1614  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1615  let hasSideEffects = false;
1616}
1617
1618// Asserts that a value has at least the given alignment.
1619def G_ASSERT_ALIGN : GenericInstruction {
1620  let OutOperandList = (outs type0:$dst);
1621  let InOperandList = (ins type0:$src, untyped_imm_0:$align);
1622  let hasSideEffects = false;
1623}
1624
1625// Prevent constant folding of the source value with any users.
1626def G_CONSTANT_FOLD_BARRIER : GenericInstruction {
1627  let OutOperandList = (outs type0:$dst);
1628  let InOperandList = (ins type0:$src);
1629  let hasSideEffects = false;
1630}
1631