1 //===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the generic opcodes used with GlobalISel.
11 // After instruction selection, these opcodes should not appear.
13 //===----------------------------------------------------------------------===//
15 //------------------------------------------------------------------------------
17 //------------------------------------------------------------------------------
19 class GenericInstruction : StandardPseudoInstruction;
21 // Extend the underlying scalar type of an operation, leaving the high bits
23 def G_ANYEXT : GenericInstruction {
24 let OutOperandList = (outs type0:$dst);
25 let InOperandList = (ins type1:$src);
26 let hasSideEffects = 0;
29 // Sign extend the underlying scalar type of an operation, copying the sign bit
30 // into the newly-created space.
31 def G_SEXT : GenericInstruction {
32 let OutOperandList = (outs type0:$dst);
33 let InOperandList = (ins type1:$src);
34 let hasSideEffects = 0;
37 // Zero extend the underlying scalar type of an operation, putting zero bits
38 // into the newly-created space.
39 def G_ZEXT : GenericInstruction {
40 let OutOperandList = (outs type0:$dst);
41 let InOperandList = (ins type1:$src);
42 let hasSideEffects = 0;
46 // Truncate the underlying scalar type of an operation. This is equivalent to
47 // G_EXTRACT for scalar types, but acts elementwise on vectors.
48 def G_TRUNC : GenericInstruction {
49 let OutOperandList = (outs type0:$dst);
50 let InOperandList = (ins type1:$src);
51 let hasSideEffects = 0;
54 def G_IMPLICIT_DEF : GenericInstruction {
55 let OutOperandList = (outs type0:$dst);
56 let InOperandList = (ins);
57 let hasSideEffects = 0;
60 def G_PHI : GenericInstruction {
61 let OutOperandList = (outs type0:$dst);
62 let InOperandList = (ins variable_ops);
63 let hasSideEffects = 0;
66 def G_FRAME_INDEX : GenericInstruction {
67 let OutOperandList = (outs type0:$dst);
68 let InOperandList = (ins unknown:$src2);
69 let hasSideEffects = 0;
72 def G_GLOBAL_VALUE : GenericInstruction {
73 let OutOperandList = (outs type0:$dst);
74 let InOperandList = (ins unknown:$src);
75 let hasSideEffects = 0;
78 def G_INTTOPTR : GenericInstruction {
79 let OutOperandList = (outs type0:$dst);
80 let InOperandList = (ins type1:$src);
81 let hasSideEffects = 0;
84 def G_PTRTOINT : GenericInstruction {
85 let OutOperandList = (outs type0:$dst);
86 let InOperandList = (ins type1:$src);
87 let hasSideEffects = 0;
90 def G_BITCAST : GenericInstruction {
91 let OutOperandList = (outs type0:$dst);
92 let InOperandList = (ins type1:$src);
93 let hasSideEffects = 0;
96 def G_CONSTANT : GenericInstruction {
97 let OutOperandList = (outs type0:$dst);
98 let InOperandList = (ins unknown:$imm);
99 let hasSideEffects = 0;
102 def G_FCONSTANT : GenericInstruction {
103 let OutOperandList = (outs type0:$dst);
104 let InOperandList = (ins unknown:$imm);
105 let hasSideEffects = 0;
108 def G_VASTART : GenericInstruction {
109 let OutOperandList = (outs);
110 let InOperandList = (ins type0:$list);
111 let hasSideEffects = 0;
115 def G_VAARG : GenericInstruction {
116 let OutOperandList = (outs type0:$val);
117 let InOperandList = (ins type1:$list, unknown:$align);
118 let hasSideEffects = 0;
123 def G_BSWAP : GenericInstruction {
124 let OutOperandList = (outs type0:$dst);
125 let InOperandList = (ins type0:$src);
126 let hasSideEffects = 0;
129 //------------------------------------------------------------------------------
131 //------------------------------------------------------------------------------
134 def G_ADD : GenericInstruction {
135 let OutOperandList = (outs type0:$dst);
136 let InOperandList = (ins type0:$src1, type0:$src2);
137 let hasSideEffects = 0;
138 let isCommutable = 1;
141 // Generic subtraction.
142 def G_SUB : GenericInstruction {
143 let OutOperandList = (outs type0:$dst);
144 let InOperandList = (ins type0:$src1, type0:$src2);
145 let hasSideEffects = 0;
146 let isCommutable = 0;
149 // Generic multiplication.
150 def G_MUL : GenericInstruction {
151 let OutOperandList = (outs type0:$dst);
152 let InOperandList = (ins type0:$src1, type0:$src2);
153 let hasSideEffects = 0;
154 let isCommutable = 1;
157 // Generic signed division.
158 def G_SDIV : GenericInstruction {
159 let OutOperandList = (outs type0:$dst);
160 let InOperandList = (ins type0:$src1, type0:$src2);
161 let hasSideEffects = 0;
162 let isCommutable = 0;
165 // Generic unsigned division.
166 def G_UDIV : GenericInstruction {
167 let OutOperandList = (outs type0:$dst);
168 let InOperandList = (ins type0:$src1, type0:$src2);
169 let hasSideEffects = 0;
170 let isCommutable = 0;
173 // Generic signed remainder.
174 def G_SREM : GenericInstruction {
175 let OutOperandList = (outs type0:$dst);
176 let InOperandList = (ins type0:$src1, type0:$src2);
177 let hasSideEffects = 0;
178 let isCommutable = 0;
181 // Generic unsigned remainder.
182 def G_UREM : GenericInstruction {
183 let OutOperandList = (outs type0:$dst);
184 let InOperandList = (ins type0:$src1, type0:$src2);
185 let hasSideEffects = 0;
186 let isCommutable = 0;
189 // Generic bitwise and.
190 def G_AND : GenericInstruction {
191 let OutOperandList = (outs type0:$dst);
192 let InOperandList = (ins type0:$src1, type0:$src2);
193 let hasSideEffects = 0;
194 let isCommutable = 1;
197 // Generic bitwise or.
198 def G_OR : GenericInstruction {
199 let OutOperandList = (outs type0:$dst);
200 let InOperandList = (ins type0:$src1, type0:$src2);
201 let hasSideEffects = 0;
202 let isCommutable = 1;
205 // Generic bitwise xor.
206 def G_XOR : GenericInstruction {
207 let OutOperandList = (outs type0:$dst);
208 let InOperandList = (ins type0:$src1, type0:$src2);
209 let hasSideEffects = 0;
210 let isCommutable = 1;
213 // Generic left-shift.
214 def G_SHL : GenericInstruction {
215 let OutOperandList = (outs type0:$dst);
216 let InOperandList = (ins type0:$src1, type0:$src2);
217 let hasSideEffects = 0;
220 // Generic logical right-shift.
221 def G_LSHR : GenericInstruction {
222 let OutOperandList = (outs type0:$dst);
223 let InOperandList = (ins type0:$src1, type0:$src2);
224 let hasSideEffects = 0;
227 // Generic arithmetic right-shift.
228 def G_ASHR : GenericInstruction {
229 let OutOperandList = (outs type0:$dst);
230 let InOperandList = (ins type0:$src1, type0:$src2);
231 let hasSideEffects = 0;
234 // Generic integer comparison.
235 def G_ICMP : GenericInstruction {
236 let OutOperandList = (outs type0:$dst);
237 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
238 let hasSideEffects = 0;
241 // Generic floating-point comparison.
242 def G_FCMP : GenericInstruction {
243 let OutOperandList = (outs type0:$dst);
244 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
245 let hasSideEffects = 0;
249 def G_SELECT : GenericInstruction {
250 let OutOperandList = (outs type0:$dst);
251 let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
252 let hasSideEffects = 0;
255 // Generic pointer offset.
256 def G_GEP : GenericInstruction {
257 let OutOperandList = (outs type0:$dst);
258 let InOperandList = (ins type0:$src1, type1:$src2);
259 let hasSideEffects = 0;
262 def G_PTR_MASK : GenericInstruction {
263 let OutOperandList = (outs type0:$dst);
264 let InOperandList = (ins type0:$src, unknown:$bits);
265 let hasSideEffects = 0;
268 //------------------------------------------------------------------------------
270 //------------------------------------------------------------------------------
272 // Generic unsigned addition consuming and producing a carry flag.
273 def G_UADDE : GenericInstruction {
274 let OutOperandList = (outs type0:$dst, type1:$carry_out);
275 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
276 let hasSideEffects = 0;
279 // Generic signed addition producing a carry flag.
280 def G_SADDO : GenericInstruction {
281 let OutOperandList = (outs type0:$dst, type1:$carry_out);
282 let InOperandList = (ins type0:$src1, type0:$src2);
283 let hasSideEffects = 0;
284 let isCommutable = 1;
287 // Generic unsigned subtraction consuming and producing a carry flag.
288 def G_USUBE : GenericInstruction {
289 let OutOperandList = (outs type0:$dst, type1:$carry_out);
290 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
291 let hasSideEffects = 0;
294 // Generic unsigned subtraction producing a carry flag.
295 def G_SSUBO : GenericInstruction {
296 let OutOperandList = (outs type0:$dst, type1:$carry_out);
297 let InOperandList = (ins type0:$src1, type0:$src2);
298 let hasSideEffects = 0;
301 // Generic unsigned multiplication producing a carry flag.
302 def G_UMULO : GenericInstruction {
303 let OutOperandList = (outs type0:$dst, type1:$carry_out);
304 let InOperandList = (ins type0:$src1, type0:$src2);
305 let hasSideEffects = 0;
306 let isCommutable = 1;
309 // Generic signed multiplication producing a carry flag.
310 def G_SMULO : GenericInstruction {
311 let OutOperandList = (outs type0:$dst, type1:$carry_out);
312 let InOperandList = (ins type0:$src1, type0:$src2);
313 let hasSideEffects = 0;
314 let isCommutable = 1;
317 // Multiply two numbers at twice the incoming bit width (unsigned) and return
318 // the high half of the result.
319 def G_UMULH : GenericInstruction {
320 let OutOperandList = (outs type0:$dst);
321 let InOperandList = (ins type0:$src1, type0:$src2);
322 let hasSideEffects = 0;
323 let isCommutable = 1;
326 // Multiply two numbers at twice the incoming bit width (signed) and return
327 // the high half of the result.
328 def G_SMULH : GenericInstruction {
329 let OutOperandList = (outs type0:$dst);
330 let InOperandList = (ins type0:$src1, type0:$src2);
331 let hasSideEffects = 0;
332 let isCommutable = 1;
335 //------------------------------------------------------------------------------
336 // Floating Point Unary Ops.
337 //------------------------------------------------------------------------------
339 def G_FNEG : GenericInstruction {
340 let OutOperandList = (outs type0:$dst);
341 let InOperandList = (ins type0:$src);
342 let hasSideEffects = 0;
345 def G_FPEXT : GenericInstruction {
346 let OutOperandList = (outs type0:$dst);
347 let InOperandList = (ins type1:$src);
348 let hasSideEffects = 0;
351 def G_FPTRUNC : GenericInstruction {
352 let OutOperandList = (outs type0:$dst);
353 let InOperandList = (ins type1:$src);
354 let hasSideEffects = 0;
357 def G_FPTOSI : GenericInstruction {
358 let OutOperandList = (outs type0:$dst);
359 let InOperandList = (ins type1:$src);
360 let hasSideEffects = 0;
363 def G_FPTOUI : GenericInstruction {
364 let OutOperandList = (outs type0:$dst);
365 let InOperandList = (ins type1:$src);
366 let hasSideEffects = 0;
369 def G_SITOFP : GenericInstruction {
370 let OutOperandList = (outs type0:$dst);
371 let InOperandList = (ins type1:$src);
372 let hasSideEffects = 0;
375 def G_UITOFP : GenericInstruction {
376 let OutOperandList = (outs type0:$dst);
377 let InOperandList = (ins type1:$src);
378 let hasSideEffects = 0;
381 //------------------------------------------------------------------------------
382 // Floating Point Binary ops.
383 //------------------------------------------------------------------------------
385 // Generic FP addition.
386 def G_FADD : GenericInstruction {
387 let OutOperandList = (outs type0:$dst);
388 let InOperandList = (ins type0:$src1, type0:$src2);
389 let hasSideEffects = 0;
390 let isCommutable = 1;
393 // Generic FP subtraction.
394 def G_FSUB : GenericInstruction {
395 let OutOperandList = (outs type0:$dst);
396 let InOperandList = (ins type0:$src1, type0:$src2);
397 let hasSideEffects = 0;
398 let isCommutable = 0;
401 // Generic FP multiplication.
402 def G_FMUL : GenericInstruction {
403 let OutOperandList = (outs type0:$dst);
404 let InOperandList = (ins type0:$src1, type0:$src2);
405 let hasSideEffects = 0;
406 let isCommutable = 1;
409 // Generic fused multiply-add instruction.
410 // Behaves like llvm fma intrinsic ie src1 * src2 + src3
411 def G_FMA : GenericInstruction {
412 let OutOperandList = (outs type0:$dst);
413 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
414 let hasSideEffects = 0;
415 let isCommutable = 0;
418 // Generic FP division.
419 def G_FDIV : GenericInstruction {
420 let OutOperandList = (outs type0:$dst);
421 let InOperandList = (ins type0:$src1, type0:$src2);
422 let hasSideEffects = 0;
425 // Generic FP remainder.
426 def G_FREM : GenericInstruction {
427 let OutOperandList = (outs type0:$dst);
428 let InOperandList = (ins type0:$src1, type0:$src2);
429 let hasSideEffects = 0;
432 // Floating point exponentiation.
433 def G_FPOW : GenericInstruction {
434 let OutOperandList = (outs type0:$dst);
435 let InOperandList = (ins type0:$src1, type0:$src2);
436 let hasSideEffects = 0;
439 // Floating point base-e exponential of a value.
440 def G_FEXP : GenericInstruction {
441 let OutOperandList = (outs type0:$dst);
442 let InOperandList = (ins type0:$src1);
443 let hasSideEffects = 0;
446 // Floating point base-2 exponential of a value.
447 def G_FEXP2 : GenericInstruction {
448 let OutOperandList = (outs type0:$dst);
449 let InOperandList = (ins type0:$src1);
450 let hasSideEffects = 0;
453 // Floating point base-2 logarithm of a value.
454 def G_FLOG : GenericInstruction {
455 let OutOperandList = (outs type0:$dst);
456 let InOperandList = (ins type0:$src1);
457 let hasSideEffects = 0;
460 // Floating point base-2 logarithm of a value.
461 def G_FLOG2 : GenericInstruction {
462 let OutOperandList = (outs type0:$dst);
463 let InOperandList = (ins type0:$src1);
464 let hasSideEffects = 0;
467 //------------------------------------------------------------------------------
469 //------------------------------------------------------------------------------
471 // Generic load. Expects a MachineMemOperand in addition to explicit operands.
472 def G_LOAD : GenericInstruction {
473 let OutOperandList = (outs type0:$dst);
474 let InOperandList = (ins ptype1:$addr);
475 let hasSideEffects = 0;
479 // Generic store. Expects a MachineMemOperand in addition to explicit operands.
480 def G_STORE : GenericInstruction {
481 let OutOperandList = (outs);
482 let InOperandList = (ins type0:$src, ptype1:$addr);
483 let hasSideEffects = 0;
487 // Generic atomic cmpxchg with internal success check. Expects a
488 // MachineMemOperand in addition to explicit operands.
489 def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
490 let OutOperandList = (outs type0:$oldval, type1:$success);
491 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
492 let hasSideEffects = 0;
497 // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
499 def G_ATOMIC_CMPXCHG : GenericInstruction {
500 let OutOperandList = (outs type0:$oldval);
501 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
502 let hasSideEffects = 0;
507 // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
509 class G_ATOMICRMW_OP : GenericInstruction {
510 let OutOperandList = (outs type0:$oldval);
511 let InOperandList = (ins ptype1:$addr, type0:$val);
512 let hasSideEffects = 0;
517 def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
518 def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
519 def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
520 def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
521 def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
522 def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
523 def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
524 def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
525 def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
526 def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
527 def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
529 //------------------------------------------------------------------------------
531 //------------------------------------------------------------------------------
533 // Extract a register of the specified size, starting from the block given by
534 // index. This will almost certainly be mapped to sub-register COPYs after
535 // register banks have been selected.
536 def G_EXTRACT : GenericInstruction {
537 let OutOperandList = (outs type0:$res);
538 let InOperandList = (ins type1:$src, unknown:$offset);
539 let hasSideEffects = 0;
542 // Extract multiple registers specified size, starting from blocks given by
543 // indexes. This will almost certainly be mapped to sub-register COPYs after
544 // register banks have been selected.
545 def G_UNMERGE_VALUES : GenericInstruction {
546 let OutOperandList = (outs type0:$dst0, variable_ops);
547 let InOperandList = (ins type1:$src);
548 let hasSideEffects = 0;
551 // Insert a smaller register into a larger one at the specified bit-index.
552 def G_INSERT : GenericInstruction {
553 let OutOperandList = (outs type0:$dst);
554 let InOperandList = (ins type0:$src, type1:$op, unknown:$offset);
555 let hasSideEffects = 0;
558 /// Concatenate multiple registers of the same size into a wider register.
559 def G_MERGE_VALUES : GenericInstruction {
560 let OutOperandList = (outs type0:$dst);
561 let InOperandList = (ins type1:$src0, variable_ops);
562 let hasSideEffects = 0;
565 // Intrinsic without side effects.
566 def G_INTRINSIC : GenericInstruction {
567 let OutOperandList = (outs);
568 let InOperandList = (ins unknown:$intrin, variable_ops);
569 let hasSideEffects = 0;
572 // Intrinsic with side effects.
573 def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
574 let OutOperandList = (outs);
575 let InOperandList = (ins unknown:$intrin, variable_ops);
576 let hasSideEffects = 1;
581 //------------------------------------------------------------------------------
583 //------------------------------------------------------------------------------
585 // Generic unconditional branch.
586 def G_BR : GenericInstruction {
587 let OutOperandList = (outs);
588 let InOperandList = (ins unknown:$src1);
589 let hasSideEffects = 0;
591 let isTerminator = 1;
595 // Generic conditional branch.
596 def G_BRCOND : GenericInstruction {
597 let OutOperandList = (outs);
598 let InOperandList = (ins type0:$tst, unknown:$truebb);
599 let hasSideEffects = 0;
601 let isTerminator = 1;
604 // Generic indirect branch.
605 def G_BRINDIRECT : GenericInstruction {
606 let OutOperandList = (outs);
607 let InOperandList = (ins type0:$src1);
608 let hasSideEffects = 0;
610 let isTerminator = 1;
613 //------------------------------------------------------------------------------
615 //------------------------------------------------------------------------------
617 // Generic insertelement.
618 def G_INSERT_VECTOR_ELT : GenericInstruction {
619 let OutOperandList = (outs type0:$dst);
620 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
621 let hasSideEffects = 0;
624 // Generic extractelement.
625 def G_EXTRACT_VECTOR_ELT : GenericInstruction {
626 let OutOperandList = (outs type0:$dst);
627 let InOperandList = (ins type1:$src, type2:$idx);
628 let hasSideEffects = 0;
631 // Generic shufflevector.
632 def G_SHUFFLE_VECTOR: GenericInstruction {
633 let OutOperandList = (outs type0:$dst);
634 let InOperandList = (ins type1:$v1, type1:$v2, type2:$mask);
635 let hasSideEffects = 0;
638 // TODO: Add the other generic opcodes.