Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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