blob: 209925969df3ff3afb5300634520f0be6f024d64 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020018class 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.
26class 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}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010037
38// Extend the underlying scalar type of an operation, leaving the high bits
39// unspecified.
40def G_ANYEXT : GenericInstruction {
41 let OutOperandList = (outs type0:$dst);
42 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020043 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010044}
45
46// Sign extend the underlying scalar type of an operation, copying the sign bit
47// into the newly-created space.
48def G_SEXT : GenericInstruction {
49 let OutOperandList = (outs type0:$dst);
50 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020051 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.
62def G_SEXT_INREG : GenericInstruction {
63 let OutOperandList = (outs type0:$dst);
64 let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
65 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010066}
67
68// Zero extend the underlying scalar type of an operation, putting zero bits
69// into the newly-created space.
70def G_ZEXT : GenericInstruction {
71 let OutOperandList = (outs type0:$dst);
72 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020073 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010074}
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.
79def G_TRUNC : GenericInstruction {
80 let OutOperandList = (outs type0:$dst);
81 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020082 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010083}
84
85def G_IMPLICIT_DEF : GenericInstruction {
86 let OutOperandList = (outs type0:$dst);
87 let InOperandList = (ins);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020088 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010089}
90
91def G_PHI : GenericInstruction {
92 let OutOperandList = (outs type0:$dst);
93 let InOperandList = (ins variable_ops);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020094 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010095}
96
97def G_FRAME_INDEX : GenericInstruction {
98 let OutOperandList = (outs type0:$dst);
99 let InOperandList = (ins unknown:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200100 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100101}
102
103def G_GLOBAL_VALUE : GenericInstruction {
104 let OutOperandList = (outs type0:$dst);
105 let InOperandList = (ins unknown:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200106 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100107}
108
109def G_INTTOPTR : GenericInstruction {
110 let OutOperandList = (outs type0:$dst);
111 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200112 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100113}
114
115def G_PTRTOINT : GenericInstruction {
116 let OutOperandList = (outs type0:$dst);
117 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200118 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100119}
120
121def G_BITCAST : GenericInstruction {
122 let OutOperandList = (outs type0:$dst);
123 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200124 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100125}
126
Andrew Walbran16937d02019-10-22 13:54:20 +0100127// Only supports scalar result types
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100128def G_CONSTANT : GenericInstruction {
129 let OutOperandList = (outs type0:$dst);
130 let InOperandList = (ins unknown:$imm);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200131 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100132}
133
Andrew Walbran16937d02019-10-22 13:54:20 +0100134// Only supports scalar result types
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100135def G_FCONSTANT : GenericInstruction {
136 let OutOperandList = (outs type0:$dst);
137 let InOperandList = (ins unknown:$imm);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200138 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100139}
140
141def G_VASTART : GenericInstruction {
142 let OutOperandList = (outs);
143 let InOperandList = (ins type0:$list);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200144 let hasSideEffects = false;
145 let mayStore = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100146}
147
148def G_VAARG : GenericInstruction {
149 let OutOperandList = (outs type0:$val);
150 let InOperandList = (ins type1:$list, unknown:$align);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200151 let hasSideEffects = false;
152 let mayLoad = true;
153 let mayStore = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154}
155
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100156def G_CTLZ : GenericInstruction {
157 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100158 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200159 let hasSideEffects = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100160}
161
162def G_CTLZ_ZERO_UNDEF : GenericInstruction {
163 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100164 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200165 let hasSideEffects = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100166}
167
168def G_CTTZ : GenericInstruction {
169 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100170 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200171 let hasSideEffects = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100172}
173
174def G_CTTZ_ZERO_UNDEF : GenericInstruction {
175 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100176 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200177 let hasSideEffects = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100178}
179
180def G_CTPOP : GenericInstruction {
181 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100182 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200183 let hasSideEffects = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100184}
185
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100186def G_BSWAP : GenericInstruction {
187 let OutOperandList = (outs type0:$dst);
188 let InOperandList = (ins type0:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200189 let hasSideEffects = false;
190}
191
192def G_BITREVERSE : GenericInstruction {
193 let OutOperandList = (outs type0:$dst);
194 let InOperandList = (ins type0:$src);
195 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100196}
197
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100198def G_ADDRSPACE_CAST : GenericInstruction {
199 let OutOperandList = (outs type0:$dst);
200 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200201 let hasSideEffects = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100202}
203
204def G_BLOCK_ADDR : GenericInstruction {
205 let OutOperandList = (outs type0:$dst);
206 let InOperandList = (ins unknown:$ba);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200207 let hasSideEffects = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100208}
209
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100210def G_JUMP_TABLE : GenericInstruction {
211 let OutOperandList = (outs type0:$dst);
212 let InOperandList = (ins unknown:$jti);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200213 let hasSideEffects = false;
214}
215
216def G_DYN_STACKALLOC : GenericInstruction {
217 let OutOperandList = (outs ptype0:$dst);
218 let InOperandList = (ins type1:$size, i32imm:$align);
219 let hasSideEffects = true;
220}
221
222def G_FREEZE : GenericInstruction {
223 let OutOperandList = (outs type0:$dst);
224 let InOperandList = (ins type0:$src);
225 let hasSideEffects = false;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100226}
227
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100228//------------------------------------------------------------------------------
229// Binary ops.
230//------------------------------------------------------------------------------
231
232// Generic addition.
233def G_ADD : GenericInstruction {
234 let OutOperandList = (outs type0:$dst);
235 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200236 let hasSideEffects = false;
237 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100238}
239
240// Generic subtraction.
241def G_SUB : GenericInstruction {
242 let OutOperandList = (outs type0:$dst);
243 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200244 let hasSideEffects = false;
245 let isCommutable = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100246}
247
248// Generic multiplication.
249def G_MUL : GenericInstruction {
250 let OutOperandList = (outs type0:$dst);
251 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200252 let hasSideEffects = false;
253 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100254}
255
256// Generic signed division.
257def G_SDIV : GenericInstruction {
258 let OutOperandList = (outs type0:$dst);
259 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200260 let hasSideEffects = false;
261 let isCommutable = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100262}
263
264// Generic unsigned division.
265def G_UDIV : GenericInstruction {
266 let OutOperandList = (outs type0:$dst);
267 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200268 let hasSideEffects = false;
269 let isCommutable = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100270}
271
272// Generic signed remainder.
273def G_SREM : GenericInstruction {
274 let OutOperandList = (outs type0:$dst);
275 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200276 let hasSideEffects = false;
277 let isCommutable = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100278}
279
280// Generic unsigned remainder.
281def G_UREM : GenericInstruction {
282 let OutOperandList = (outs type0:$dst);
283 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200284 let hasSideEffects = false;
285 let isCommutable = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100286}
287
288// Generic bitwise and.
289def G_AND : GenericInstruction {
290 let OutOperandList = (outs type0:$dst);
291 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200292 let hasSideEffects = false;
293 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100294}
295
296// Generic bitwise or.
297def G_OR : GenericInstruction {
298 let OutOperandList = (outs type0:$dst);
299 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200300 let hasSideEffects = false;
301 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100302}
303
304// Generic bitwise xor.
305def G_XOR : GenericInstruction {
306 let OutOperandList = (outs type0:$dst);
307 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200308 let hasSideEffects = false;
309 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100310}
311
312// Generic left-shift.
313def G_SHL : GenericInstruction {
314 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100315 let InOperandList = (ins type0:$src1, type1:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200316 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100317}
318
319// Generic logical right-shift.
320def G_LSHR : GenericInstruction {
321 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100322 let InOperandList = (ins type0:$src1, type1:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200323 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100324}
325
326// Generic arithmetic right-shift.
327def G_ASHR : GenericInstruction {
328 let OutOperandList = (outs type0:$dst);
Andrew Walbran16937d02019-10-22 13:54:20 +0100329 let InOperandList = (ins type0:$src1, type1:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200330 let hasSideEffects = false;
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)))
335def G_FSHL : GenericInstruction {
336 let OutOperandList = (outs type0:$dst);
337 let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
338 let hasSideEffects = false;
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))
343def G_FSHR : GenericInstruction {
344 let OutOperandList = (outs type0:$dst);
345 let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
346 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100347}
348
349// Generic integer comparison.
350def G_ICMP : GenericInstruction {
351 let OutOperandList = (outs type0:$dst);
352 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200353 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100354}
355
356// Generic floating-point comparison.
357def G_FCMP : GenericInstruction {
358 let OutOperandList = (outs type0:$dst);
359 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200360 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100361}
362
363// Generic select
364def G_SELECT : GenericInstruction {
365 let OutOperandList = (outs type0:$dst);
366 let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200367 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100368}
369
370// Generic pointer offset.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200371def G_PTR_ADD : GenericInstruction {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100372 let OutOperandList = (outs type0:$dst);
373 let InOperandList = (ins type0:$src1, type1:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200374 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100375}
376
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200377// Generic pointer mask. type1 should be an integer with the same
378// bitwidth as the pointer type.
379def G_PTRMASK : GenericInstruction {
380 let OutOperandList = (outs ptype0:$dst);
381 let InOperandList = (ins ptype0:$src, type1:$bits);
382 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100383}
384
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100385// Generic signed integer minimum.
386def G_SMIN : GenericInstruction {
387 let OutOperandList = (outs type0:$dst);
388 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200389 let hasSideEffects = false;
390 let isCommutable = true;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100391}
392
393// Generic signed integer maximum.
394def G_SMAX : GenericInstruction {
395 let OutOperandList = (outs type0:$dst);
396 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200397 let hasSideEffects = false;
398 let isCommutable = true;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100399}
400
401// Generic unsigned integer minimum.
402def G_UMIN : GenericInstruction {
403 let OutOperandList = (outs type0:$dst);
404 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200405 let hasSideEffects = false;
406 let isCommutable = true;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100407}
408
409// Generic unsigned integer maximum.
410def G_UMAX : GenericInstruction {
411 let OutOperandList = (outs type0:$dst);
412 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200413 let hasSideEffects = false;
414 let isCommutable = true;
415}
416
417// Generic integer absolute value.
418def G_ABS : GenericInstruction {
419 let OutOperandList = (outs type0:$dst);
420 let InOperandList = (ins type0:$src);
421 let hasSideEffects = false;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100422}
423
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100424//------------------------------------------------------------------------------
425// Overflow ops
426//------------------------------------------------------------------------------
427
Andrew Scull0372a572018-11-16 15:47:06 +0000428// Generic unsigned addition producing a carry flag.
429def G_UADDO : GenericInstruction {
430 let OutOperandList = (outs type0:$dst, type1:$carry_out);
431 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200432 let hasSideEffects = false;
433 let isCommutable = true;
Andrew Scull0372a572018-11-16 15:47:06 +0000434}
435
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100436// Generic unsigned addition consuming and producing a carry flag.
437def G_UADDE : GenericInstruction {
438 let OutOperandList = (outs type0:$dst, type1:$carry_out);
439 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200440 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100441}
442
443// Generic signed addition producing a carry flag.
444def G_SADDO : GenericInstruction {
445 let OutOperandList = (outs type0:$dst, type1:$carry_out);
446 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200447 let hasSideEffects = false;
448 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100449}
450
Andrew Scull0372a572018-11-16 15:47:06 +0000451// Generic signed addition consuming and producing a carry flag.
452def G_SADDE : GenericInstruction {
453 let OutOperandList = (outs type0:$dst, type1:$carry_out);
454 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200455 let hasSideEffects = false;
Andrew Scull0372a572018-11-16 15:47:06 +0000456}
457
458// Generic unsigned subtraction producing a carry flag.
459def G_USUBO : GenericInstruction {
460 let OutOperandList = (outs type0:$dst, type1:$carry_out);
461 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200462 let hasSideEffects = false;
Andrew Scull0372a572018-11-16 15:47:06 +0000463}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100464// Generic unsigned subtraction consuming and producing a carry flag.
465def G_USUBE : GenericInstruction {
466 let OutOperandList = (outs type0:$dst, type1:$carry_out);
467 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200468 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100469}
470
Andrew Scull0372a572018-11-16 15:47:06 +0000471// Generic signed subtraction producing a carry flag.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100472def G_SSUBO : GenericInstruction {
473 let OutOperandList = (outs type0:$dst, type1:$carry_out);
474 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200475 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100476}
477
Andrew Scull0372a572018-11-16 15:47:06 +0000478// Generic signed subtraction consuming and producing a carry flag.
479def G_SSUBE : GenericInstruction {
480 let OutOperandList = (outs type0:$dst, type1:$carry_out);
481 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200482 let hasSideEffects = false;
Andrew Scull0372a572018-11-16 15:47:06 +0000483}
484
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100485// Generic unsigned multiplication producing a carry flag.
486def G_UMULO : GenericInstruction {
487 let OutOperandList = (outs type0:$dst, type1:$carry_out);
488 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200489 let hasSideEffects = false;
490 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100491}
492
493// Generic signed multiplication producing a carry flag.
494def G_SMULO : GenericInstruction {
495 let OutOperandList = (outs type0:$dst, type1:$carry_out);
496 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200497 let hasSideEffects = false;
498 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100499}
500
501// Multiply two numbers at twice the incoming bit width (unsigned) and return
502// the high half of the result.
503def G_UMULH : GenericInstruction {
504 let OutOperandList = (outs type0:$dst);
505 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200506 let hasSideEffects = false;
507 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100508}
509
510// Multiply two numbers at twice the incoming bit width (signed) and return
511// the high half of the result.
512def G_SMULH : GenericInstruction {
513 let OutOperandList = (outs type0:$dst);
514 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200515 let hasSideEffects = false;
516 let isCommutable = true;
517}
518
519//------------------------------------------------------------------------------
520// Saturating ops
521//------------------------------------------------------------------------------
522
523// Generic saturating unsigned addition.
524def G_UADDSAT : GenericInstruction {
525 let OutOperandList = (outs type0:$dst);
526 let InOperandList = (ins type0:$src1, type0:$src2);
527 let hasSideEffects = false;
528 let isCommutable = true;
529}
530
531// Generic saturating signed addition.
532def G_SADDSAT : GenericInstruction {
533 let OutOperandList = (outs type0:$dst);
534 let InOperandList = (ins type0:$src1, type0:$src2);
535 let hasSideEffects = false;
536 let isCommutable = true;
537}
538
539// Generic saturating unsigned subtraction.
540def G_USUBSAT : GenericInstruction {
541 let OutOperandList = (outs type0:$dst);
542 let InOperandList = (ins type0:$src1, type0:$src2);
543 let hasSideEffects = false;
544 let isCommutable = false;
545}
546
547// Generic saturating signed subtraction.
548def G_SSUBSAT : GenericInstruction {
549 let OutOperandList = (outs type0:$dst);
550 let InOperandList = (ins type0:$src1, type0:$src2);
551 let hasSideEffects = false;
552 let isCommutable = false;
553}
554
555// Generic saturating unsigned left shift.
556def G_USHLSAT : GenericInstruction {
557 let OutOperandList = (outs type0:$dst);
558 let InOperandList = (ins type0:$src1, type1:$src2);
559 let hasSideEffects = false;
560 let isCommutable = false;
561}
562
563// Generic saturating signed left shift.
564def G_SSHLSAT : GenericInstruction {
565 let OutOperandList = (outs type0:$dst);
566 let InOperandList = (ins type0:$src1, type1:$src2);
567 let hasSideEffects = false;
568 let isCommutable = false;
569}
570
571/// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point
572/// multiplication on 2 integers with the same width and scale. SCALE
573/// represents the scale of both operands as fixed point numbers. This
574/// SCALE parameter must be a constant integer. A scale of zero is
575/// effectively performing multiplication on 2 integers.
576def G_SMULFIX : GenericInstruction {
577 let OutOperandList = (outs type0:$dst);
578 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
579 let hasSideEffects = false;
580 let isCommutable = true;
581}
582
583def G_UMULFIX : GenericInstruction {
584 let OutOperandList = (outs type0:$dst);
585 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
586 let hasSideEffects = false;
587 let isCommutable = true;
588}
589
590/// Same as the corresponding unsaturated fixed point instructions, but the
591/// result is clamped between the min and max values representable by the
592/// bits of the first 2 operands.
593def G_SMULFIXSAT : GenericInstruction {
594 let OutOperandList = (outs type0:$dst);
595 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
596 let hasSideEffects = false;
597 let isCommutable = true;
598}
599
600def G_UMULFIXSAT : GenericInstruction {
601 let OutOperandList = (outs type0:$dst);
602 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
603 let hasSideEffects = false;
604 let isCommutable = true;
605}
606
607/// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on
608/// 2 integers with the same width and scale. SCALE represents the scale
609/// of both operands as fixed point numbers. This SCALE parameter must be a
610/// constant integer.
611def G_SDIVFIX : GenericInstruction {
612 let OutOperandList = (outs type0:$dst);
613 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
614 let hasSideEffects = false;
615 let isCommutable = false;
616}
617
618def G_UDIVFIX : 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 = false;
623}
624
625/// Same as the corresponding unsaturated fixed point instructions,
626/// but the result is clamped between the min and max values
627/// representable by the bits of the first 2 operands.
628def G_SDIVFIXSAT : GenericInstruction {
629 let OutOperandList = (outs type0:$dst);
630 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
631 let hasSideEffects = false;
632 let isCommutable = false;
633}
634
635def G_UDIVFIXSAT : 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 = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100640}
641
642//------------------------------------------------------------------------------
643// Floating Point Unary Ops.
644//------------------------------------------------------------------------------
645
646def G_FNEG : GenericInstruction {
647 let OutOperandList = (outs type0:$dst);
648 let InOperandList = (ins type0:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200649 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100650}
651
652def G_FPEXT : GenericInstruction {
653 let OutOperandList = (outs type0:$dst);
654 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200655 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100656}
657
658def G_FPTRUNC : GenericInstruction {
659 let OutOperandList = (outs type0:$dst);
660 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200661 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100662}
663
664def G_FPTOSI : GenericInstruction {
665 let OutOperandList = (outs type0:$dst);
666 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200667 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100668}
669
670def G_FPTOUI : GenericInstruction {
671 let OutOperandList = (outs type0:$dst);
672 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200673 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100674}
675
676def G_SITOFP : GenericInstruction {
677 let OutOperandList = (outs type0:$dst);
678 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200679 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100680}
681
682def G_UITOFP : GenericInstruction {
683 let OutOperandList = (outs type0:$dst);
684 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200685 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100686}
687
688def G_FABS : GenericInstruction {
689 let OutOperandList = (outs type0:$dst);
690 let InOperandList = (ins type0:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200691 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100692}
693
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100694def G_FCOPYSIGN : GenericInstruction {
695 let OutOperandList = (outs type0:$dst);
696 let InOperandList = (ins type0:$src0, type1:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200697 let hasSideEffects = false;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100698}
699
Andrew Walbran16937d02019-10-22 13:54:20 +0100700def G_FCANONICALIZE : GenericInstruction {
701 let OutOperandList = (outs type0:$dst);
702 let InOperandList = (ins type0:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200703 let hasSideEffects = false;
704}
705
706// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
707// values.
708//
709// In the case where a single input is a NaN (either signaling or quiet),
710// the non-NaN input is returned.
711//
712// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
713def G_FMINNUM : GenericInstruction {
714 let OutOperandList = (outs type0:$dst);
715 let InOperandList = (ins type0:$src1, type0:$src2);
716 let hasSideEffects = false;
717 let isCommutable = true;
718}
719
720def G_FMAXNUM : GenericInstruction {
721 let OutOperandList = (outs type0:$dst);
722 let InOperandList = (ins type0:$src1, type0:$src2);
723 let hasSideEffects = false;
724 let isCommutable = true;
725}
726
727// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
728// two values, following the IEEE-754 2008 definition. This differs from
729// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
730// signaling NaN, returns a quiet NaN.
731def G_FMINNUM_IEEE : GenericInstruction {
732 let OutOperandList = (outs type0:$dst);
733 let InOperandList = (ins type0:$src1, type0:$src2);
734 let hasSideEffects = false;
735 let isCommutable = true;
736}
737
738def G_FMAXNUM_IEEE : GenericInstruction {
739 let OutOperandList = (outs type0:$dst);
740 let InOperandList = (ins type0:$src1, type0:$src2);
741 let hasSideEffects = false;
742 let isCommutable = true;
743}
744
745// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
746// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
747// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.
748def G_FMINIMUM : GenericInstruction {
749 let OutOperandList = (outs type0:$dst);
750 let InOperandList = (ins type0:$src1, type0:$src2);
751 let hasSideEffects = false;
752 let isCommutable = true;
753}
754
755def G_FMAXIMUM : GenericInstruction {
756 let OutOperandList = (outs type0:$dst);
757 let InOperandList = (ins type0:$src1, type0:$src2);
758 let hasSideEffects = false;
759 let isCommutable = true;
Andrew Walbran16937d02019-10-22 13:54:20 +0100760}
761
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100762//------------------------------------------------------------------------------
763// Floating Point Binary ops.
764//------------------------------------------------------------------------------
765
766// Generic FP addition.
767def G_FADD : GenericInstruction {
768 let OutOperandList = (outs type0:$dst);
769 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200770 let hasSideEffects = false;
771 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100772}
773
774// Generic FP subtraction.
775def G_FSUB : GenericInstruction {
776 let OutOperandList = (outs type0:$dst);
777 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200778 let hasSideEffects = false;
779 let isCommutable = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100780}
781
782// Generic FP multiplication.
783def G_FMUL : GenericInstruction {
784 let OutOperandList = (outs type0:$dst);
785 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200786 let hasSideEffects = false;
787 let isCommutable = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100788}
789
790// Generic fused multiply-add instruction.
791// Behaves like llvm fma intrinsic ie src1 * src2 + src3
792def G_FMA : GenericInstruction {
793 let OutOperandList = (outs type0:$dst);
794 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200795 let hasSideEffects = false;
796 let isCommutable = false;
797}
798
799/// Generic FP multiply and add. Perform a * b + c, while getting the
800/// same result as the separately rounded operations, unlike G_FMA.
801def G_FMAD : GenericInstruction {
802 let OutOperandList = (outs type0:$dst);
803 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
804 let hasSideEffects = false;
805 let isCommutable = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100806}
807
808// Generic FP division.
809def G_FDIV : GenericInstruction {
810 let OutOperandList = (outs type0:$dst);
811 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200812 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100813}
814
815// Generic FP remainder.
816def G_FREM : GenericInstruction {
817 let OutOperandList = (outs type0:$dst);
818 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200819 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100820}
821
822// Floating point exponentiation.
823def G_FPOW : GenericInstruction {
824 let OutOperandList = (outs type0:$dst);
825 let InOperandList = (ins type0:$src1, type0:$src2);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200826 let hasSideEffects = false;
827}
828
829// Floating point exponentiation, with an integer power.
830def G_FPOWI : GenericInstruction {
831 let OutOperandList = (outs type0:$dst);
832 let InOperandList = (ins type0:$src0, type1:$src1);
833 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100834}
835
836// Floating point base-e exponential of a value.
837def G_FEXP : GenericInstruction {
838 let OutOperandList = (outs type0:$dst);
839 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200840 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100841}
842
843// Floating point base-2 exponential of a value.
844def G_FEXP2 : GenericInstruction {
845 let OutOperandList = (outs type0:$dst);
846 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200847 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100848}
849
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200850// Floating point base-e logarithm of a value.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100851def G_FLOG : GenericInstruction {
852 let OutOperandList = (outs type0:$dst);
853 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200854 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100855}
856
857// Floating point base-2 logarithm of a value.
858def G_FLOG2 : GenericInstruction {
859 let OutOperandList = (outs type0:$dst);
860 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200861 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100862}
863
Andrew Walbran16937d02019-10-22 13:54:20 +0100864// Floating point base-10 logarithm of a value.
865def G_FLOG10 : GenericInstruction {
866 let OutOperandList = (outs type0:$dst);
867 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200868 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +0100869}
870
871// Floating point ceiling of a value.
872def G_FCEIL : GenericInstruction {
873 let OutOperandList = (outs type0:$dst);
874 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200875 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +0100876}
877
878// Floating point cosine of a value.
879def G_FCOS : GenericInstruction {
880 let OutOperandList = (outs type0:$dst);
881 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200882 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +0100883}
884
885// Floating point sine of a value.
886def G_FSIN : GenericInstruction {
887 let OutOperandList = (outs type0:$dst);
888 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200889 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +0100890}
891
892// Floating point square root of a value.
893// This returns NaN for negative nonzero values.
894// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
895// libm-conformant.
896def G_FSQRT : GenericInstruction {
897 let OutOperandList = (outs type0:$dst);
898 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200899 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +0100900}
901
902// Floating point floor of a value.
903def G_FFLOOR : GenericInstruction {
904 let OutOperandList = (outs type0:$dst);
905 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200906 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +0100907}
908
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100909// Floating point round to next integer.
910def G_FRINT : GenericInstruction {
911 let OutOperandList = (outs type0:$dst);
912 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200913 let hasSideEffects = false;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100914}
915
916// Floating point round to the nearest integer.
917def G_FNEARBYINT : GenericInstruction {
918 let OutOperandList = (outs type0:$dst);
919 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200920 let hasSideEffects = false;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100921}
922
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100923//------------------------------------------------------------------------------
Andrew Scull0372a572018-11-16 15:47:06 +0000924// Opcodes for LLVM Intrinsics
925//------------------------------------------------------------------------------
926def G_INTRINSIC_TRUNC : GenericInstruction {
927 let OutOperandList = (outs type0:$dst);
928 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200929 let hasSideEffects = false;
Andrew Scull0372a572018-11-16 15:47:06 +0000930}
931
932def G_INTRINSIC_ROUND : GenericInstruction {
933 let OutOperandList = (outs type0:$dst);
934 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200935 let hasSideEffects = false;
936}
937
938def G_INTRINSIC_LRINT : GenericInstruction {
939 let OutOperandList = (outs type0:$dst);
940 let InOperandList = (ins type1:$src);
941 let hasSideEffects = false;
942}
943
944def G_INTRINSIC_ROUNDEVEN : GenericInstruction {
945 let OutOperandList = (outs type0:$dst);
946 let InOperandList = (ins type0:$src1);
947 let hasSideEffects = false;
948}
949
950def G_READCYCLECOUNTER : GenericInstruction {
951 let OutOperandList = (outs type0:$dst);
952 let InOperandList = (ins);
953 let hasSideEffects = true;
Andrew Scull0372a572018-11-16 15:47:06 +0000954}
955
956//------------------------------------------------------------------------------
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100957// Memory ops
958//------------------------------------------------------------------------------
959
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200960// Generic load. Expects a MachineMemOperand in addition to explicit
961// operands. If the result size is larger than the memory size, the
962// high bits are undefined. If the result is a vector type and larger
963// than the memory size, the high elements are undefined (i.e. this is
964// not a per-element, vector anyextload)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100965def G_LOAD : GenericInstruction {
966 let OutOperandList = (outs type0:$dst);
967 let InOperandList = (ins ptype1:$addr);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200968 let hasSideEffects = false;
969 let mayLoad = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100970}
971
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100972// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
973def G_SEXTLOAD : GenericInstruction {
974 let OutOperandList = (outs type0:$dst);
975 let InOperandList = (ins ptype1:$addr);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200976 let hasSideEffects = false;
977 let mayLoad = true;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100978}
979
980// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
981def G_ZEXTLOAD : GenericInstruction {
982 let OutOperandList = (outs type0:$dst);
983 let InOperandList = (ins ptype1:$addr);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200984 let hasSideEffects = false;
985 let mayLoad = true;
986}
987
988// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
989// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
990// then the value is loaded from $newaddr.
991def G_INDEXED_LOAD : GenericInstruction {
992 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
993 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
994 let hasSideEffects = false;
995 let mayLoad = true;
996}
997
998// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
999def G_INDEXED_SEXTLOAD : GenericInstruction {
1000 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1001 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1002 let hasSideEffects = false;
1003 let mayLoad = true;
1004}
1005
1006// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
1007def G_INDEXED_ZEXTLOAD : GenericInstruction {
1008 let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
1009 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
1010 let hasSideEffects = false;
1011 let mayLoad = true;
Andrew Scullcdfcccc2018-10-05 20:58:37 +01001012}
1013
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001014// Generic store. Expects a MachineMemOperand in addition to explicit operands.
1015def G_STORE : GenericInstruction {
1016 let OutOperandList = (outs);
1017 let InOperandList = (ins type0:$src, ptype1:$addr);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001018 let hasSideEffects = false;
1019 let mayStore = true;
1020}
1021
1022// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
1023def G_INDEXED_STORE : GenericInstruction {
1024 let OutOperandList = (outs ptype0:$newaddr);
1025 let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
1026 unknown:$am);
1027 let hasSideEffects = false;
1028 let mayStore = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001029}
1030
1031// Generic atomic cmpxchg with internal success check. Expects a
1032// MachineMemOperand in addition to explicit operands.
1033def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
1034 let OutOperandList = (outs type0:$oldval, type1:$success);
1035 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001036 let hasSideEffects = false;
1037 let mayLoad = true;
1038 let mayStore = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001039}
1040
1041// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
1042// operands.
1043def G_ATOMIC_CMPXCHG : GenericInstruction {
1044 let OutOperandList = (outs type0:$oldval);
1045 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001046 let hasSideEffects = false;
1047 let mayLoad = true;
1048 let mayStore = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001049}
1050
1051// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
1052// operands.
1053class G_ATOMICRMW_OP : GenericInstruction {
1054 let OutOperandList = (outs type0:$oldval);
1055 let InOperandList = (ins ptype1:$addr, type0:$val);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001056 let hasSideEffects = false;
1057 let mayLoad = true;
1058 let mayStore = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001059}
1060
1061def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
1062def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
1063def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
1064def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
1065def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
1066def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
1067def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
1068def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
1069def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
1070def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
1071def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001072def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
1073def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001074
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001075def G_FENCE : GenericInstruction {
1076 let OutOperandList = (outs);
1077 let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001078 let hasSideEffects = true;
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001079}
1080
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001081//------------------------------------------------------------------------------
1082// Variadic ops
1083//------------------------------------------------------------------------------
1084
1085// Extract a register of the specified size, starting from the block given by
1086// index. This will almost certainly be mapped to sub-register COPYs after
1087// register banks have been selected.
1088def G_EXTRACT : GenericInstruction {
1089 let OutOperandList = (outs type0:$res);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001090 let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
1091 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001092}
1093
1094// Extract multiple registers specified size, starting from blocks given by
1095// indexes. This will almost certainly be mapped to sub-register COPYs after
1096// register banks have been selected.
Andrew Walbran16937d02019-10-22 13:54:20 +01001097// The output operands are always ordered from lowest bits to highest:
1098// %bits_0_7:(s8), %bits_8_15:(s8),
1099// %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001100def G_UNMERGE_VALUES : GenericInstruction {
1101 let OutOperandList = (outs type0:$dst0, variable_ops);
1102 let InOperandList = (ins type1:$src);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001103 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001104}
1105
1106// Insert a smaller register into a larger one at the specified bit-index.
1107def G_INSERT : GenericInstruction {
1108 let OutOperandList = (outs type0:$dst);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001109 let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
1110 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001111}
1112
Andrew Walbran16937d02019-10-22 13:54:20 +01001113// Concatenate multiple registers of the same size into a wider register.
1114// The input operands are always ordered from lowest bits to highest:
1115// %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
1116// %bits_16_23:(s8), %bits_24_31:(s8)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001117def G_MERGE_VALUES : GenericInstruction {
1118 let OutOperandList = (outs type0:$dst);
1119 let InOperandList = (ins type1:$src0, variable_ops);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001120 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001121}
1122
Andrew Walbran16937d02019-10-22 13:54:20 +01001123/// Create a vector from multiple scalar registers. No implicit
1124/// conversion is performed (i.e. the result element type must be the
1125/// same as all source operands)
1126def G_BUILD_VECTOR : GenericInstruction {
1127 let OutOperandList = (outs type0:$dst);
1128 let InOperandList = (ins type1:$src0, variable_ops);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001129 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +01001130}
1131
1132/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
1133/// destination vector elt type.
1134def G_BUILD_VECTOR_TRUNC : GenericInstruction {
1135 let OutOperandList = (outs type0:$dst);
1136 let InOperandList = (ins type1:$src0, variable_ops);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001137 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +01001138}
1139
1140/// Create a vector by concatenating vectors together.
1141def G_CONCAT_VECTORS : GenericInstruction {
1142 let OutOperandList = (outs type0:$dst);
1143 let InOperandList = (ins type1:$src0, variable_ops);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001144 let hasSideEffects = false;
Andrew Walbran16937d02019-10-22 13:54:20 +01001145}
1146
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001147// Intrinsic without side effects.
1148def G_INTRINSIC : GenericInstruction {
1149 let OutOperandList = (outs);
1150 let InOperandList = (ins unknown:$intrin, variable_ops);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001151 let hasSideEffects = false;
1152
1153 // Conservatively assume this is convergent. If there turnes out to
1154 // be a need, there should be separate convergent intrinsic opcodes.
1155 let isConvergent = 1;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001156}
1157
1158// Intrinsic with side effects.
1159def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
1160 let OutOperandList = (outs);
1161 let InOperandList = (ins unknown:$intrin, variable_ops);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001162 let hasSideEffects = true;
1163 let mayLoad = true;
1164 let mayStore = true;
1165
1166 // Conservatively assume this is convergent. If there turnes out to
1167 // be a need, there should be separate convergent intrinsic opcodes.
1168 let isConvergent = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001169}
1170
1171//------------------------------------------------------------------------------
1172// Branches.
1173//------------------------------------------------------------------------------
1174
1175// Generic unconditional branch.
1176def G_BR : GenericInstruction {
1177 let OutOperandList = (outs);
1178 let InOperandList = (ins unknown:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001179 let hasSideEffects = false;
1180 let isBranch = true;
1181 let isTerminator = true;
1182 let isBarrier = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001183}
1184
1185// Generic conditional branch.
1186def G_BRCOND : GenericInstruction {
1187 let OutOperandList = (outs);
1188 let InOperandList = (ins type0:$tst, unknown:$truebb);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001189 let hasSideEffects = false;
1190 let isBranch = true;
1191 let isTerminator = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001192}
1193
1194// Generic indirect branch.
1195def G_BRINDIRECT : GenericInstruction {
1196 let OutOperandList = (outs);
1197 let InOperandList = (ins type0:$src1);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001198 let hasSideEffects = false;
1199 let isBranch = true;
1200 let isTerminator = true;
1201 let isBarrier = true;
1202 let isIndirectBranch = true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001203}
1204
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001205// Generic branch to jump table entry
1206def G_BRJT : GenericInstruction {
1207 let OutOperandList = (outs);
1208 let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001209 let hasSideEffects = false;
1210 let isBranch = true;
1211 let isTerminator = true;
1212 let isBarrier = true;
1213 let isIndirectBranch = true;
1214}
1215
1216def G_READ_REGISTER : GenericInstruction {
1217 let OutOperandList = (outs type0:$dst);
1218 let InOperandList = (ins unknown:$register);
1219 let hasSideEffects = true;
1220
1221 // Assume convergent. It's probably not worth the effort of somehow
1222 // modeling convergent and nonconvergent register accesses.
1223 let isConvergent = true;
1224}
1225
1226def G_WRITE_REGISTER : GenericInstruction {
1227 let OutOperandList = (outs);
1228 let InOperandList = (ins unknown:$register, type0:$value);
1229 let hasSideEffects = true;
1230
1231 // Assume convergent. It's probably not worth the effort of somehow
1232 // modeling convergent and nonconvergent register accesses.
1233 let isConvergent = true;
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001234}
1235
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001236//------------------------------------------------------------------------------
1237// Vector ops
1238//------------------------------------------------------------------------------
1239
1240// Generic insertelement.
1241def G_INSERT_VECTOR_ELT : GenericInstruction {
1242 let OutOperandList = (outs type0:$dst);
1243 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001244 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001245}
1246
1247// Generic extractelement.
1248def G_EXTRACT_VECTOR_ELT : GenericInstruction {
1249 let OutOperandList = (outs type0:$dst);
1250 let InOperandList = (ins type1:$src, type2:$idx);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001251 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001252}
1253
1254// Generic shufflevector.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001255//
1256// The mask operand should be an IR Constant which exactly matches the
1257// corresponding mask for the IR shufflevector instruction.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001258def G_SHUFFLE_VECTOR: GenericInstruction {
1259 let OutOperandList = (outs type0:$dst);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001260 let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
1261 let hasSideEffects = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001262}
1263
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001264//------------------------------------------------------------------------------
1265// Vector reductions
1266//------------------------------------------------------------------------------
1267
1268class VectorReduction : GenericInstruction {
1269 let OutOperandList = (outs type0:$dst);
1270 let InOperandList = (ins type1:$v);
1271 let hasSideEffects = false;
1272}
1273
1274def G_VECREDUCE_SEQ_FADD : GenericInstruction {
1275 let OutOperandList = (outs type0:$dst);
1276 let InOperandList = (ins type1:$acc, type2:$v);
1277 let hasSideEffects = false;
1278}
1279
1280def G_VECREDUCE_SEQ_FMUL : GenericInstruction {
1281 let OutOperandList = (outs type0:$dst);
1282 let InOperandList = (ins type1:$acc, type2:$v);
1283 let hasSideEffects = false;
1284}
1285
1286def G_VECREDUCE_FADD : VectorReduction;
1287def G_VECREDUCE_FMUL : VectorReduction;
1288
1289def G_VECREDUCE_FMAX : VectorReduction;
1290def G_VECREDUCE_FMIN : VectorReduction;
1291
1292def G_VECREDUCE_ADD : VectorReduction;
1293def G_VECREDUCE_MUL : VectorReduction;
1294def G_VECREDUCE_AND : VectorReduction;
1295def G_VECREDUCE_OR : VectorReduction;
1296def G_VECREDUCE_XOR : VectorReduction;
1297def G_VECREDUCE_SMAX : VectorReduction;
1298def G_VECREDUCE_SMIN : VectorReduction;
1299def G_VECREDUCE_UMAX : VectorReduction;
1300def G_VECREDUCE_UMIN : VectorReduction;
1301
1302//------------------------------------------------------------------------------
1303// Constrained floating point ops
1304//------------------------------------------------------------------------------
1305
1306def G_STRICT_FADD : ConstrainedIntruction<G_FADD>;
1307def G_STRICT_FSUB : ConstrainedIntruction<G_FSUB>;
1308def G_STRICT_FMUL : ConstrainedIntruction<G_FMUL>;
1309def G_STRICT_FDIV : ConstrainedIntruction<G_FDIV>;
1310def G_STRICT_FREM : ConstrainedIntruction<G_FREM>;
1311def G_STRICT_FMA : ConstrainedIntruction<G_FMA>;
1312def G_STRICT_FSQRT : ConstrainedIntruction<G_FSQRT>;
1313
1314//------------------------------------------------------------------------------
1315// Memory intrinsics
1316//------------------------------------------------------------------------------
1317
1318def G_MEMCPY : GenericInstruction {
1319 let OutOperandList = (outs);
1320 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1321 let hasSideEffects = false;
1322 let mayLoad = true;
1323 let mayStore = true;
1324}
1325
1326def G_MEMMOVE : GenericInstruction {
1327 let OutOperandList = (outs);
1328 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
1329 let hasSideEffects = false;
1330 let mayLoad = true;
1331 let mayStore = true;
1332}
1333
1334def G_MEMSET : GenericInstruction {
1335 let OutOperandList = (outs);
1336 let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
1337 let hasSideEffects = false;
1338 let mayStore = true;
1339}