• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 minimumNumber or
799// maximumNumber on two values, following IEEE-754 definitions. This
800// differs from FMINNUM/FMAXNUM in the handling of signaling NaNs, and
801// signed zero.
802//
803// If one input is a signaling NaN, returns a quiet NaN. This matches
804// IEEE-754 2008's minnum/maxnum behavior for signaling NaNs (which
805// differs from 2019).
806//
807// These treat -0 as ordered less than +0, matching the behavior of
808// IEEE-754 2019's minimumNumber/maximumNumber.
809def G_FMINNUM_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
816def G_FMAXNUM_IEEE : GenericInstruction {
817  let OutOperandList = (outs type0:$dst);
818  let InOperandList = (ins type0:$src1, type0:$src2);
819  let hasSideEffects = false;
820  let isCommutable = true;
821}
822
823// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
824// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
825// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2019 semantics.
826def G_FMINIMUM : 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
833def G_FMAXIMUM : GenericInstruction {
834  let OutOperandList = (outs type0:$dst);
835  let InOperandList = (ins type0:$src1, type0:$src2);
836  let hasSideEffects = false;
837  let isCommutable = true;
838}
839
840//------------------------------------------------------------------------------
841// Floating Point Binary ops.
842//------------------------------------------------------------------------------
843
844// Generic FP addition.
845def G_FADD : GenericInstruction {
846  let OutOperandList = (outs type0:$dst);
847  let InOperandList = (ins type0:$src1, type0:$src2);
848  let hasSideEffects = false;
849  let isCommutable = true;
850}
851
852// Generic FP subtraction.
853def G_FSUB : GenericInstruction {
854  let OutOperandList = (outs type0:$dst);
855  let InOperandList = (ins type0:$src1, type0:$src2);
856  let hasSideEffects = false;
857  let isCommutable = false;
858}
859
860// Generic FP multiplication.
861def G_FMUL : GenericInstruction {
862  let OutOperandList = (outs type0:$dst);
863  let InOperandList = (ins type0:$src1, type0:$src2);
864  let hasSideEffects = false;
865  let isCommutable = true;
866}
867
868// Generic fused multiply-add instruction.
869// Behaves like llvm fma intrinsic ie src1 * src2 + src3
870def G_FMA : GenericInstruction {
871  let OutOperandList = (outs type0:$dst);
872  let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
873  let hasSideEffects = false;
874  let isCommutable = false;
875}
876
877/// Generic FP multiply and add. Perform a * b + c, while getting the
878/// same result as the separately rounded operations, unlike G_FMA.
879def G_FMAD : GenericInstruction {
880  let OutOperandList = (outs type0:$dst);
881  let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
882  let hasSideEffects = false;
883  let isCommutable = false;
884}
885
886// Generic FP division.
887def G_FDIV : GenericInstruction {
888  let OutOperandList = (outs type0:$dst);
889  let InOperandList = (ins type0:$src1, type0:$src2);
890  let hasSideEffects = false;
891}
892
893// Generic FP remainder.
894def G_FREM : 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.
901def G_FPOW : GenericInstruction {
902  let OutOperandList = (outs type0:$dst);
903  let InOperandList = (ins type0:$src1, type0:$src2);
904  let hasSideEffects = false;
905}
906
907// Floating point exponentiation, with an integer power.
908def G_FPOWI : GenericInstruction {
909  let OutOperandList = (outs type0:$dst);
910  let InOperandList = (ins type0:$src0, type1:$src1);
911  let hasSideEffects = false;
912}
913
914// Floating point base-e exponential of a value.
915def G_FEXP : GenericInstruction {
916  let OutOperandList = (outs type0:$dst);
917  let InOperandList = (ins type0:$src1);
918  let hasSideEffects = false;
919}
920
921// Floating point base-2 exponential of a value.
922def G_FEXP2 : GenericInstruction {
923  let OutOperandList = (outs type0:$dst);
924  let InOperandList = (ins type0:$src1);
925  let hasSideEffects = false;
926}
927
928// Floating point base-10 exponential of a value.
929def G_FEXP10 : GenericInstruction {
930  let OutOperandList = (outs type0:$dst);
931  let InOperandList = (ins type0:$src1);
932  let hasSideEffects = false;
933}
934
935// Floating point base-e logarithm of a value.
936def G_FLOG : GenericInstruction {
937  let OutOperandList = (outs type0:$dst);
938  let InOperandList = (ins type0:$src1);
939  let hasSideEffects = false;
940}
941
942// Floating point base-2 logarithm of a value.
943def G_FLOG2 : GenericInstruction {
944  let OutOperandList = (outs type0:$dst);
945  let InOperandList = (ins type0:$src1);
946  let hasSideEffects = false;
947}
948
949// Floating point base-10 logarithm of a value.
950def G_FLOG10 : GenericInstruction {
951  let OutOperandList = (outs type0:$dst);
952  let InOperandList = (ins type0:$src1);
953  let hasSideEffects = false;
954}
955
956// Floating point x * 2^n
957def G_FLDEXP : GenericInstruction {
958  let OutOperandList = (outs type0:$dst);
959  let InOperandList = (ins type0:$src0, type1:$src1);
960  let hasSideEffects = false;
961}
962
963// Floating point frexp
964def G_FFREXP : GenericInstruction {
965  let OutOperandList = (outs type0:$dst0, type1:$dst1);
966  let InOperandList = (ins type0:$src0);
967  let hasSideEffects = false;
968}
969
970// Floating point ceiling of a value.
971def G_FCEIL : GenericInstruction {
972  let OutOperandList = (outs type0:$dst);
973  let InOperandList = (ins type0:$src1);
974  let hasSideEffects = false;
975}
976
977// Floating point cosine of a value.
978def G_FCOS : GenericInstruction {
979  let OutOperandList = (outs type0:$dst);
980  let InOperandList = (ins type0:$src1);
981  let hasSideEffects = false;
982}
983
984// Floating point sine of a value.
985def G_FSIN : GenericInstruction {
986  let OutOperandList = (outs type0:$dst);
987  let InOperandList = (ins type0:$src1);
988  let hasSideEffects = false;
989}
990
991// Floating point tangent of a value.
992def G_FTAN : GenericInstruction {
993  let OutOperandList = (outs type0:$dst);
994  let InOperandList = (ins type0:$src1);
995  let hasSideEffects = false;
996}
997
998// Floating point square root of a value.
999// This returns NaN for negative nonzero values.
1000// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
1001// libm-conformant.
1002def G_FSQRT : GenericInstruction {
1003  let OutOperandList = (outs type0:$dst);
1004  let InOperandList = (ins type0:$src1);
1005  let hasSideEffects = false;
1006}
1007
1008// Floating point floor of a value.
1009def G_FFLOOR : GenericInstruction {
1010  let OutOperandList = (outs type0:$dst);
1011  let InOperandList = (ins type0:$src1);
1012  let hasSideEffects = false;
1013}
1014
1015// Floating point round to next integer.
1016def G_FRINT : GenericInstruction {
1017  let OutOperandList = (outs type0:$dst);
1018  let InOperandList = (ins type0:$src1);
1019  let hasSideEffects = false;
1020}
1021
1022// Floating point round to the nearest integer.
1023def G_FNEARBYINT : GenericInstruction {
1024  let OutOperandList = (outs type0:$dst);
1025  let InOperandList = (ins type0:$src1);
1026  let hasSideEffects = false;
1027}
1028
1029//------------------------------------------------------------------------------
1030// Access to floating-point environment.
1031//------------------------------------------------------------------------------
1032
1033// These operations read/write floating-point environment. The interaction with
1034// it is modeled as a side effect, because constrained intrinsics use the same
1035// method.
1036
1037// Reading floating-point environment.
1038def G_GET_FPENV : GenericInstruction {
1039  let OutOperandList = (outs type0:$dst);
1040  let InOperandList = (ins);
1041  let hasSideEffects = true;
1042}
1043
1044// Setting floating-point environment.
1045def G_SET_FPENV : GenericInstruction {
1046  let OutOperandList = (outs);
1047  let InOperandList = (ins type0:$src);
1048  let hasSideEffects = true;
1049}
1050
1051// Setting default floating-point environment.
1052def G_RESET_FPENV : GenericInstruction {
1053  let OutOperandList = (outs);
1054  let InOperandList = (ins);
1055  let hasSideEffects = true;
1056}
1057
1058// Reading floating-point control modes.
1059def G_GET_FPMODE : GenericInstruction {
1060  let OutOperandList = (outs type0:$dst);
1061  let InOperandList = (ins);
1062  let hasSideEffects = true;
1063}
1064
1065// Setting floating-point control modes.
1066def G_SET_FPMODE : GenericInstruction {
1067  let OutOperandList = (outs);
1068  let InOperandList = (ins type0:$src);
1069  let hasSideEffects = true;
1070}
1071
1072// Setting floating-point control modes to default state.
1073def G_RESET_FPMODE : GenericInstruction {
1074  let OutOperandList = (outs);
1075  let InOperandList = (ins);
1076  let hasSideEffects = true;
1077}
1078
1079//------------------------------------------------------------------------------
1080// Opcodes for LLVM Intrinsics
1081//------------------------------------------------------------------------------
1082def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction {
1083  let OutOperandList = (outs type0:$dst);
1084  let InOperandList = (ins type1:$src1, i32imm:$round_mode);
1085  let hasSideEffects = false;
1086}
1087
1088def G_INTRINSIC_TRUNC : GenericInstruction {
1089  let OutOperandList = (outs type0:$dst);
1090  let InOperandList = (ins type0:$src1);
1091  let hasSideEffects = false;
1092}
1093
1094def G_INTRINSIC_ROUND : GenericInstruction {
1095  let OutOperandList = (outs type0:$dst);
1096  let InOperandList = (ins type0:$src1);
1097  let hasSideEffects = false;
1098}
1099
1100def G_INTRINSIC_LRINT : GenericInstruction {
1101  let OutOperandList = (outs type0:$dst);
1102  let InOperandList = (ins type1:$src);
1103  let hasSideEffects = false;
1104}
1105
1106def G_INTRINSIC_LLRINT : GenericInstruction {
1107  let OutOperandList = (outs type0:$dst);
1108  let InOperandList = (ins type1:$src);
1109  let hasSideEffects = false;
1110}
1111
1112def G_INTRINSIC_ROUNDEVEN : GenericInstruction {
1113  let OutOperandList = (outs type0:$dst);
1114  let InOperandList = (ins type0:$src1);
1115  let hasSideEffects = false;
1116}
1117
1118def G_READCYCLECOUNTER : GenericInstruction {
1119  let OutOperandList = (outs type0:$dst);
1120  let InOperandList = (ins);
1121  let hasSideEffects = true;
1122}
1123
1124def G_READSTEADYCOUNTER : GenericInstruction {
1125  let OutOperandList = (outs type0:$dst);
1126  let InOperandList = (ins);
1127  let hasSideEffects = true;
1128}
1129
1130//------------------------------------------------------------------------------
1131// Memory ops
1132//------------------------------------------------------------------------------
1133
1134// Generic load. Expects a MachineMemOperand in addition to explicit
1135// operands. If the result size is larger than the memory size, the
1136// high bits are undefined. If the result is a vector type and larger
1137// than the memory size, the high elements are undefined (i.e. this is
1138// not a per-element, vector anyextload)
1139def G_LOAD : GenericInstruction {
1140  let OutOperandList = (outs type0:$dst);
1141  let InOperandList = (ins ptype1:$addr);
1142  let hasSideEffects = false;
1143  let mayLoad = true;
1144}
1145
1146// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
1147def G_SEXTLOAD : GenericInstruction {
1148  let OutOperandList = (outs type0:$dst);
1149  let InOperandList = (ins ptype1:$addr);
1150  let hasSideEffects = false;
1151  let mayLoad = true;
1152}
1153
1154// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
1155def G_ZEXTLOAD : GenericInstruction {
1156  let OutOperandList = (outs type0:$dst);
1157  let InOperandList = (ins ptype1:$addr);
1158  let hasSideEffects = false;
1159  let mayLoad = true;
1160}
1161
1162// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
1163// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
1164//  then the value is loaded from $newaddr.
1165def G_INDEXED_LOAD : GenericInstruction {
1166  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1167  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1168  let hasSideEffects = false;
1169  let mayLoad = true;
1170}
1171
1172// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
1173def G_INDEXED_SEXTLOAD : GenericInstruction {
1174  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1175  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1176  let hasSideEffects = false;
1177  let mayLoad = true;
1178}
1179
1180// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
1181def G_INDEXED_ZEXTLOAD : GenericInstruction {
1182  let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1183  let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1184  let hasSideEffects = false;
1185  let mayLoad = true;
1186}
1187
1188// Generic store. Expects a MachineMemOperand in addition to explicit operands.
1189def G_STORE : GenericInstruction {
1190  let OutOperandList = (outs);
1191  let InOperandList = (ins type0:$src, ptype1:$addr);
1192  let hasSideEffects = false;
1193  let mayStore = true;
1194}
1195
1196// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
1197def G_INDEXED_STORE : GenericInstruction {
1198  let OutOperandList = (outs ptype0:$newaddr);
1199  let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
1200                           unknown:$am);
1201  let hasSideEffects = false;
1202  let mayStore = true;
1203}
1204
1205// Generic atomic cmpxchg with internal success check. Expects a
1206// MachineMemOperand in addition to explicit operands.
1207def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
1208  let OutOperandList = (outs type0:$oldval, type1:$success);
1209  let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
1210  let hasSideEffects = false;
1211  let mayLoad = true;
1212  let mayStore = true;
1213}
1214
1215// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
1216// operands.
1217def G_ATOMIC_CMPXCHG : GenericInstruction {
1218  let OutOperandList = (outs type0:$oldval);
1219  let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
1220  let hasSideEffects = false;
1221  let mayLoad = true;
1222  let mayStore = true;
1223}
1224
1225// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
1226// operands.
1227class G_ATOMICRMW_OP : GenericInstruction {
1228  let OutOperandList = (outs type0:$oldval);
1229  let InOperandList = (ins ptype1:$addr, type0:$val);
1230  let hasSideEffects = false;
1231  let mayLoad = true;
1232  let mayStore = true;
1233}
1234
1235def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
1236def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
1237def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
1238def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
1239def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
1240def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
1241def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
1242def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
1243def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
1244def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
1245def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
1246def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
1247def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
1248def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP;
1249def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP;
1250def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP;
1251def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP;
1252
1253def G_FENCE : GenericInstruction {
1254  let OutOperandList = (outs);
1255  let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
1256  let hasSideEffects = true;
1257}
1258
1259// Generic opcode equivalent to the llvm.prefetch intrinsic.
1260def G_PREFETCH : GenericInstruction {
1261  let OutOperandList = (outs);
1262  let InOperandList = (ins ptype0:$address, i32imm:$rw, i32imm:$locality, i32imm:$cachetype);
1263  let hasSideEffects = true;
1264  let mayLoad = true;
1265  let mayStore = true;
1266}
1267
1268//------------------------------------------------------------------------------
1269// Variadic ops
1270//------------------------------------------------------------------------------
1271
1272// Extract a register of the specified size, starting from the block given by
1273// index. This will almost certainly be mapped to sub-register COPYs after
1274// register banks have been selected.
1275def G_EXTRACT : GenericInstruction {
1276  let OutOperandList = (outs type0:$res);
1277  let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
1278  let hasSideEffects = false;
1279}
1280
1281// Extract multiple registers specified size, starting from blocks given by
1282// indexes. This will almost certainly be mapped to sub-register COPYs after
1283// register banks have been selected.
1284// The output operands are always ordered from lowest bits to highest:
1285//   %bits_0_7:(s8), %bits_8_15:(s8),
1286//       %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
1287def G_UNMERGE_VALUES : GenericInstruction {
1288  let OutOperandList = (outs type0:$dst0, variable_ops);
1289  let InOperandList = (ins type1:$src);
1290  let hasSideEffects = false;
1291  let variadicOpsType = type0;
1292}
1293
1294// Insert a smaller register into a larger one at the specified bit-index.
1295def G_INSERT : GenericInstruction {
1296  let OutOperandList = (outs type0:$dst);
1297  let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
1298  let hasSideEffects = false;
1299}
1300
1301// Concatenate multiple registers of the same size into a wider register.
1302// The input operands are always ordered from lowest bits to highest:
1303//   %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
1304//                             %bits_16_23:(s8), %bits_24_31:(s8)
1305def G_MERGE_VALUES : GenericInstruction {
1306  let OutOperandList = (outs type0:$dst);
1307  let InOperandList = (ins type1:$src0, variable_ops);
1308  let hasSideEffects = false;
1309  let variadicOpsType = type1;
1310}
1311
1312// Generic vscale.
1313// Puts the value of the runtime vscale multiplied by the value in the source
1314// operand into the destination register.
1315def G_VSCALE : GenericInstruction {
1316  let OutOperandList = (outs type0:$dst);
1317  let InOperandList = (ins unknown:$src);
1318  let hasSideEffects = false;
1319}
1320
1321/// Create a vector from multiple scalar registers. No implicit
1322/// conversion is performed (i.e. the result element type must be the
1323/// same as all source operands)
1324def G_BUILD_VECTOR : GenericInstruction {
1325  let OutOperandList = (outs type0:$dst);
1326  let InOperandList = (ins type1:$src0, variable_ops);
1327  let hasSideEffects = false;
1328  let variadicOpsType = type1;
1329}
1330
1331/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
1332/// destination vector elt type.
1333def G_BUILD_VECTOR_TRUNC : GenericInstruction {
1334  let OutOperandList = (outs type0:$dst);
1335  let InOperandList = (ins type1:$src0, variable_ops);
1336  let hasSideEffects = false;
1337}
1338
1339/// Create a vector by concatenating vectors together.
1340def G_CONCAT_VECTORS : GenericInstruction {
1341  let OutOperandList = (outs type0:$dst);
1342  let InOperandList = (ins type1:$src0, variable_ops);
1343  let hasSideEffects = false;
1344}
1345
1346// Intrinsic without side effects.
1347def G_INTRINSIC : GenericInstruction {
1348  let OutOperandList = (outs);
1349  let InOperandList = (ins unknown:$intrin, variable_ops);
1350  let hasSideEffects = false;
1351}
1352
1353// Intrinsic with side effects.
1354def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
1355  let OutOperandList = (outs);
1356  let InOperandList = (ins unknown:$intrin, variable_ops);
1357  let hasSideEffects = true;
1358  let mayLoad = true;
1359  let mayStore = true;
1360}
1361
1362// Convergent intrinsic without side effects.
1363def G_INTRINSIC_CONVERGENT : GenericInstruction {
1364  let OutOperandList = (outs);
1365  let InOperandList = (ins unknown:$intrin, variable_ops);
1366  let hasSideEffects = false;
1367  let isConvergent = true;
1368}
1369
1370// Convergent intrinsic with side effects.
1371def G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS : GenericInstruction {
1372  let OutOperandList = (outs);
1373  let InOperandList = (ins unknown:$intrin, variable_ops);
1374  let hasSideEffects = true;
1375  let mayLoad = true;
1376  let mayStore = true;
1377  let isConvergent = true;
1378}
1379
1380//------------------------------------------------------------------------------
1381// Branches.
1382//------------------------------------------------------------------------------
1383
1384// Generic unconditional branch.
1385def G_BR : GenericInstruction {
1386  let OutOperandList = (outs);
1387  let InOperandList = (ins unknown:$src1);
1388  let hasSideEffects = false;
1389  let isBranch = true;
1390  let isTerminator = true;
1391  let isBarrier = true;
1392}
1393
1394// Generic conditional branch.
1395def G_BRCOND : GenericInstruction {
1396  let OutOperandList = (outs);
1397  let InOperandList = (ins type0:$tst, unknown:$truebb);
1398  let hasSideEffects = false;
1399  let isBranch = true;
1400  let isTerminator = true;
1401}
1402
1403// Generic indirect branch.
1404def G_BRINDIRECT : GenericInstruction {
1405  let OutOperandList = (outs);
1406  let InOperandList = (ins type0:$src1);
1407  let hasSideEffects = false;
1408  let isBranch = true;
1409  let isTerminator = true;
1410  let isBarrier = true;
1411  let isIndirectBranch = true;
1412}
1413
1414// Generic branch to jump table entry
1415def G_BRJT : GenericInstruction {
1416  let OutOperandList = (outs);
1417  let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
1418  let hasSideEffects = false;
1419  let isBranch = true;
1420  let isTerminator = true;
1421  let isBarrier = true;
1422  let isIndirectBranch = true;
1423}
1424
1425// A marker to signal the following code is an invoke region, that may throw
1426// an exception and therefore not return.
1427def G_INVOKE_REGION_START : GenericInstruction {
1428  let OutOperandList = (outs);
1429  let InOperandList = (ins);
1430  let isTerminator = true; // This must be a terminator.
1431  let hasSideEffects = false;
1432}
1433
1434def G_READ_REGISTER : GenericInstruction {
1435  let OutOperandList = (outs type0:$dst);
1436  let InOperandList = (ins unknown:$register);
1437  let hasSideEffects = true;
1438
1439  // Assume convergent. It's probably not worth the effort of somehow
1440  // modeling convergent and nonconvergent register accesses.
1441  let isConvergent = true;
1442}
1443
1444def G_WRITE_REGISTER : GenericInstruction {
1445  let OutOperandList = (outs);
1446  let InOperandList = (ins unknown:$register, type0:$value);
1447  let hasSideEffects = true;
1448
1449  // Assume convergent. It's probably not worth the effort of somehow
1450  // modeling convergent and nonconvergent register accesses.
1451  let isConvergent = true;
1452}
1453
1454//------------------------------------------------------------------------------
1455// Vector ops
1456//------------------------------------------------------------------------------
1457
1458// Generic insert subvector.
1459def G_INSERT_SUBVECTOR : GenericInstruction {
1460  let OutOperandList = (outs type0:$dst);
1461  let InOperandList = (ins type0:$src0, type1:$src1, untyped_imm_0:$idx);
1462  let hasSideEffects = false;
1463}
1464
1465// Generic extract subvector.
1466def G_EXTRACT_SUBVECTOR : GenericInstruction {
1467  let OutOperandList = (outs type0:$dst);
1468  let InOperandList = (ins type0:$src, untyped_imm_0:$idx);
1469  let hasSideEffects = false;
1470}
1471
1472// Generic insertelement.
1473def G_INSERT_VECTOR_ELT : GenericInstruction {
1474  let OutOperandList = (outs type0:$dst);
1475  let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
1476  let hasSideEffects = false;
1477}
1478
1479// Generic extractelement.
1480def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1481  let OutOperandList = (outs type0:$dst);
1482  let InOperandList = (ins type1:$src, type2:$idx);
1483  let hasSideEffects = false;
1484}
1485
1486// Generic shufflevector.
1487//
1488// The mask operand should be an IR Constant which exactly matches the
1489// corresponding mask for the IR shufflevector instruction.
1490def G_SHUFFLE_VECTOR: GenericInstruction {
1491  let OutOperandList = (outs type0:$dst);
1492  let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1493  let hasSideEffects = false;
1494}
1495
1496// Generic splatvector.
1497def G_SPLAT_VECTOR: GenericInstruction {
1498  let OutOperandList = (outs type0:$dst);
1499  let InOperandList = (ins type1:$val);
1500  let hasSideEffects = false;
1501}
1502
1503//------------------------------------------------------------------------------
1504// Vector reductions
1505//------------------------------------------------------------------------------
1506
1507class VectorReduction : GenericInstruction {
1508  let OutOperandList = (outs type0:$dst);
1509  let InOperandList = (ins type1:$v);
1510  let hasSideEffects = false;
1511}
1512
1513def G_VECREDUCE_SEQ_FADD : GenericInstruction {
1514  let OutOperandList = (outs type0:$dst);
1515  let InOperandList = (ins type1:$acc, type2:$v);
1516  let hasSideEffects = false;
1517}
1518
1519def G_VECREDUCE_SEQ_FMUL : GenericInstruction {
1520  let OutOperandList = (outs type0:$dst);
1521  let InOperandList = (ins type1:$acc, type2:$v);
1522  let hasSideEffects = false;
1523}
1524
1525def G_VECREDUCE_FADD : VectorReduction;
1526def G_VECREDUCE_FMUL : VectorReduction;
1527
1528def G_VECREDUCE_FMAX : VectorReduction;
1529def G_VECREDUCE_FMIN : VectorReduction;
1530def G_VECREDUCE_FMAXIMUM : VectorReduction;
1531def G_VECREDUCE_FMINIMUM : VectorReduction;
1532
1533def G_VECREDUCE_ADD : VectorReduction;
1534def G_VECREDUCE_MUL : VectorReduction;
1535def G_VECREDUCE_AND : VectorReduction;
1536def G_VECREDUCE_OR : VectorReduction;
1537def G_VECREDUCE_XOR : VectorReduction;
1538def G_VECREDUCE_SMAX : VectorReduction;
1539def G_VECREDUCE_SMIN : VectorReduction;
1540def G_VECREDUCE_UMAX : VectorReduction;
1541def G_VECREDUCE_UMIN : VectorReduction;
1542
1543//------------------------------------------------------------------------------
1544// Constrained floating point ops
1545//------------------------------------------------------------------------------
1546
1547def G_STRICT_FADD : ConstrainedInstruction<G_FADD>;
1548def G_STRICT_FSUB : ConstrainedInstruction<G_FSUB>;
1549def G_STRICT_FMUL : ConstrainedInstruction<G_FMUL>;
1550def G_STRICT_FDIV : ConstrainedInstruction<G_FDIV>;
1551def G_STRICT_FREM : ConstrainedInstruction<G_FREM>;
1552def G_STRICT_FMA : ConstrainedInstruction<G_FMA>;
1553def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>;
1554def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>;
1555
1556//------------------------------------------------------------------------------
1557// Memory intrinsics
1558//------------------------------------------------------------------------------
1559
1560def G_MEMCPY : GenericInstruction {
1561  let OutOperandList = (outs);
1562  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1563  let hasSideEffects = false;
1564  let mayLoad = true;
1565  let mayStore = true;
1566}
1567
1568def G_MEMCPY_INLINE : GenericInstruction {
1569  let OutOperandList = (outs);
1570  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size);
1571  let hasSideEffects = false;
1572  let mayLoad = true;
1573  let mayStore = true;
1574}
1575
1576def G_MEMMOVE : GenericInstruction {
1577  let OutOperandList = (outs);
1578  let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1579  let hasSideEffects = false;
1580  let mayLoad = true;
1581  let mayStore = true;
1582}
1583
1584def G_MEMSET : GenericInstruction {
1585  let OutOperandList = (outs);
1586  let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
1587  let hasSideEffects = false;
1588  let mayStore = true;
1589}
1590
1591def G_BZERO : GenericInstruction {
1592  let OutOperandList = (outs);
1593  let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall);
1594  let hasSideEffects = false;
1595  let mayStore = true;
1596}
1597
1598//------------------------------------------------------------------------------
1599// Trap intrinsics
1600//------------------------------------------------------------------------------
1601def G_TRAP : GenericInstruction {
1602  let OutOperandList = (outs);
1603  let InOperandList = (ins);
1604  let hasSideEffects = true;
1605  let mayStore = true;
1606}
1607
1608def G_DEBUGTRAP : GenericInstruction {
1609  let OutOperandList = (outs);
1610  let InOperandList = (ins);
1611  let hasSideEffects = true;
1612}
1613
1614def G_UBSANTRAP : GenericInstruction {
1615  let OutOperandList = (outs);
1616  let InOperandList = (ins i8imm:$kind);
1617  let hasSideEffects = true;
1618}
1619
1620//------------------------------------------------------------------------------
1621// Bitfield extraction.
1622//------------------------------------------------------------------------------
1623
1624// Generic signed bitfield extraction. The operands are in the range
1625// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1626def G_SBFX : GenericInstruction {
1627  let OutOperandList = (outs type0:$dst);
1628  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1629  let hasSideEffects = false;
1630}
1631
1632// Generic unsigned bitfield extraction. The operands are in the range
1633// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
1634def G_UBFX : GenericInstruction {
1635  let OutOperandList = (outs type0:$dst);
1636  let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
1637  let hasSideEffects = false;
1638}
1639
1640//------------------------------------------------------------------------------
1641// Optimization hints
1642//------------------------------------------------------------------------------
1643
1644// Asserts that an operation has already been zero-extended from a specific
1645// type.
1646def G_ASSERT_ZEXT : GenericInstruction {
1647  let OutOperandList = (outs type0:$dst);
1648  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1649  let hasSideEffects = false;
1650}
1651
1652// Asserts that an operation has already been sign-extended from a specific
1653// type.
1654def G_ASSERT_SEXT : GenericInstruction {
1655  let OutOperandList = (outs type0:$dst);
1656  let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
1657  let hasSideEffects = false;
1658}
1659
1660// Asserts that a value has at least the given alignment.
1661def G_ASSERT_ALIGN : GenericInstruction {
1662  let OutOperandList = (outs type0:$dst);
1663  let InOperandList = (ins type0:$src, untyped_imm_0:$align);
1664  let hasSideEffects = false;
1665}
1666
1667// Prevent constant folding of the source value with any users.
1668def G_CONSTANT_FOLD_BARRIER : GenericInstruction {
1669  let OutOperandList = (outs type0:$dst);
1670  let InOperandList = (ins type0:$src);
1671  let hasSideEffects = false;
1672}
1673