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