xref: /llvm-project/mlir/include/mlir/Dialect/Index/IR/IndexOps.td (revision 795b4efad0259cbf03fc98e3045621916328ce57)
1//===- IndexOps.td - Index operation definitions -----------*- 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#ifndef INDEX_OPS
10#define INDEX_OPS
11
12include "mlir/Dialect/Index/IR/IndexDialect.td"
13include "mlir/Dialect/Index/IR/IndexEnums.td"
14include "mlir/Interfaces/CastInterfaces.td"
15include "mlir/Interfaces/InferIntRangeInterface.td"
16include "mlir/Interfaces/InferTypeOpInterface.td"
17include "mlir/Interfaces/SideEffectInterfaces.td"
18include "mlir/IR/OpAsmInterface.td"
19include "mlir/IR/OpBase.td"
20
21//===----------------------------------------------------------------------===//
22// IndexOp
23//===----------------------------------------------------------------------===//
24
25/// Base class for Index dialect operations.
26class IndexOp<string mnemonic, list<Trait> traits = []>
27    : Op<IndexDialect, mnemonic,
28      [DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>] # traits>;
29
30//===----------------------------------------------------------------------===//
31// IndexBinaryOp
32//===----------------------------------------------------------------------===//
33
34/// Base class for binary Index dialect operations.
35class IndexBinaryOp<string mnemonic, list<Trait> traits = []>
36    : IndexOp<mnemonic, traits> {
37  let arguments = (ins Index:$lhs, Index:$rhs);
38  let results = (outs Index:$result);
39  let assemblyFormat = "$lhs `,` $rhs attr-dict";
40  let hasFolder = 1;
41}
42
43//===----------------------------------------------------------------------===//
44// AddOp
45//===----------------------------------------------------------------------===//
46
47def Index_AddOp : IndexBinaryOp<"add", [Commutative, Pure]> {
48  let summary = "index addition";
49  let description = [{
50    The `index.add` operation takes two index values and computes their sum.
51
52    Example:
53
54    ```mlir
55    // c = a + b
56    %c = index.add %a, %b
57    ```
58  }];
59
60  let hasCanonicalizeMethod = 1;
61}
62
63//===----------------------------------------------------------------------===//
64// SubOp
65//===----------------------------------------------------------------------===//
66
67def Index_SubOp : IndexBinaryOp<"sub", [Pure]> {
68  let summary = "index subtraction";
69  let description = [{
70    The `index.sub` operation takes two index values and computes the difference
71    of the first from the second operand.
72
73    Example:
74
75    ```mlir
76    // c = a - b
77    %c = index.sub %a, %b
78    ```
79  }];
80}
81
82//===----------------------------------------------------------------------===//
83// MulOp
84//===----------------------------------------------------------------------===//
85
86def Index_MulOp : IndexBinaryOp<"mul", [Commutative, Pure]> {
87  let summary = "index multiplication";
88  let description = [{
89    The `index.mul` operation takes two index values and computes their product.
90
91    Example:
92
93    ```mlir
94    // c = a * b
95    %c = index.mul %a, %b
96    ```
97  }];
98
99  let hasCanonicalizeMethod = 1;
100}
101
102//===----------------------------------------------------------------------===//
103// DivSOp
104//===----------------------------------------------------------------------===//
105
106def Index_DivSOp : IndexBinaryOp<"divs", [NoMemoryEffect]> {
107  let summary = "index signed division";
108  let description = [{
109    The `index.divs` operation takes two index values and computes their signed
110    quotient. Treats the leading bit as the sign and rounds towards zero, i.e.
111    `6 / -2 = -3`.
112
113    Note: division by zero and signed division overflow are undefined behaviour.
114
115    Example:
116
117    ```mlir
118    // c = a / b
119    %c = index.divs %a, %b
120    ```
121  }];
122}
123
124//===----------------------------------------------------------------------===//
125// DivUOp
126//===----------------------------------------------------------------------===//
127
128def Index_DivUOp : IndexBinaryOp<"divu", [NoMemoryEffect]> {
129  let summary = "index unsigned division";
130  let description = [{
131    The `index.divu` operation takes two index values and computes their
132    unsigned quotient. Treats the leading bit as the most significant and rounds
133    towards zero, i.e. `6 / -2 = 0`.
134
135    Note: division by zero is undefined behaviour.
136
137    Example:
138
139    ```mlir
140    // c = a / b
141    %c = index.divu %a, %b
142    ```
143  }];
144}
145
146//===----------------------------------------------------------------------===//
147// CeilDivSOp
148//===----------------------------------------------------------------------===//
149
150def Index_CeilDivSOp : IndexBinaryOp<"ceildivs", [NoMemoryEffect]> {
151  let summary = "index signed ceil division";
152  let description = [{
153    The `index.ceildivs` operation takes two index values and computes their
154    signed quotient. Treats the leading bit as the sign and rounds towards
155    positive infinity, i.e. `7 / -2 = -3`.
156
157    Note: division by zero and signed division overflow are undefined behaviour.
158
159    Example:
160
161    ```mlir
162    // c = ceil(a / b)
163    %c = index.ceildivs %a, %b
164    ```
165  }];
166}
167
168//===----------------------------------------------------------------------===//
169// CeilDivUOp
170//===----------------------------------------------------------------------===//
171
172def Index_CeilDivUOp : IndexBinaryOp<"ceildivu", [NoMemoryEffect]> {
173  let summary = "index unsigned ceil division";
174  let description = [{
175    The `index.ceildivu` operation takes two index values and computes their
176    unsigned quotient. Treats the leading bit as the most significant and rounds
177    towards positive infinity, i.e. `6 / -2 = 1`.
178
179    Note: division by zero is undefined behaviour.
180
181    Example:
182
183    ```mlir
184    // c = ceil(a / b)
185    %c = index.ceildivu %a, %b
186    ```
187  }];
188}
189
190//===----------------------------------------------------------------------===//
191// FloorDivSOp
192//===----------------------------------------------------------------------===//
193
194def Index_FloorDivSOp : IndexBinaryOp<"floordivs", [NoMemoryEffect]> {
195  let summary = "index signed floor division";
196  let description = [{
197    The `index.floordivs` operation takes two index values and computes their
198    signed quotient. Treats the leading bit as the sign and rounds towards
199    negative infinity, i.e. `5 / -2 = -3`.
200
201    Note: division by zero and signed division overflow are undefined behaviour.
202
203    Example:
204
205    ```mlir
206    // c = floor(a / b)
207    %c = index.floordivs %a, %b
208    ```
209  }];
210}
211
212//===----------------------------------------------------------------------===//
213// RemSOp
214//===----------------------------------------------------------------------===//
215
216def Index_RemSOp : IndexBinaryOp<"rems", [NoMemoryEffect]> {
217  let summary = "index signed remainder";
218  let description = [{
219    The `index.rems` operation takes two index values and computes their signed
220    remainder. Treats the leading bit as the sign, i.e. `6 % -2 = 0`.
221
222    Example:
223
224    ```mlir
225    // c = a % b
226    %c = index.rems %a, %b
227    ```
228  }];
229}
230
231//===----------------------------------------------------------------------===//
232// RemUOp
233//===----------------------------------------------------------------------===//
234
235def Index_RemUOp : IndexBinaryOp<"remu", [NoMemoryEffect]> {
236  let summary = "index unsigned remainder";
237  let description = [{
238    The `index.remu` operation takes two index values and computes their
239    unsigned remainder. Treats the leading bit as the most significant, i.e.
240    `6 % -2 = 6`.
241
242    Example:
243
244    ```mlir
245    // c = a % b
246    %c = index.remu %a, %b
247    ```
248  }];
249}
250
251//===----------------------------------------------------------------------===//
252// MaxSOp
253//===----------------------------------------------------------------------===//
254
255def Index_MaxSOp : IndexBinaryOp<"maxs", [Commutative, Pure]> {
256  let summary = "index signed maximum";
257  let description = [{
258    The `index.maxs` operation takes two index values and computes their signed
259    maximum value. Treats the leading bit as the sign, i.e. `max(-2, 6) = 6`.
260
261    Example:
262
263    ```mlir
264    // c = max(a, b)
265    %c = index.maxs %a, %b
266    ```
267  }];
268
269  let hasCanonicalizeMethod = 1;
270}
271
272//===----------------------------------------------------------------------===//
273// MaxUOp
274//===----------------------------------------------------------------------===//
275
276def Index_MaxUOp : IndexBinaryOp<"maxu", [Commutative, Pure]> {
277  let summary = "index unsigned maximum";
278  let description = [{
279    The `index.maxu` operation takes two index values and computes their
280    unsigned maximum value. Treats the leading bit as the most significant, i.e.
281    `max(15, 6) = 15` or `max(-2, 6) = -2`.
282
283    Example:
284
285    ```mlir
286    // c = max(a, b)
287    %c = index.maxu %a, %b
288    ```
289  }];
290
291  let hasCanonicalizeMethod = 1;
292}
293
294//===----------------------------------------------------------------------===//
295// MinSOp
296//===----------------------------------------------------------------------===//
297
298def Index_MinSOp : IndexBinaryOp<"mins", [Commutative, Pure]> {
299  let summary = "index signed minimum";
300  let description = [{
301    The `index.mins` operation takes two index values and computes their signed
302    minimum value. Treats the leading bit as the sign, i.e. `min(-2, 6) = -2`.
303
304    Example:
305
306    ```mlir
307    // c = min(a, b)
308    %c = index.mins %a, %b
309    ```
310  }];
311
312  let hasCanonicalizeMethod = 1;
313}
314
315//===----------------------------------------------------------------------===//
316// MinUOp
317//===----------------------------------------------------------------------===//
318
319def Index_MinUOp : IndexBinaryOp<"minu", [Commutative, Pure]> {
320  let summary = "index unsigned minimum";
321  let description = [{
322    The `index.minu` operation takes two index values and computes their
323    unsigned minimum value. Treats the leading bit as the most significant, i.e.
324    `min(15, 6) = 6` or `min(-2, 6) = 6`.
325
326    Example:
327
328    ```mlir
329    // c = min(a, b)
330    %c = index.minu %a, %b
331    ```
332  }];
333
334  let hasCanonicalizeMethod = 1;
335}
336
337//===----------------------------------------------------------------------===//
338// ShlOp
339//===----------------------------------------------------------------------===//
340
341def Index_ShlOp : IndexBinaryOp<"shl", [Pure]> {
342  let summary = "index shift left";
343  let description = [{
344    The `index.shl` operation shifts an index value to the left by a variable
345    amount. The low order bits are filled with zeroes. The RHS operand is always
346    treated as unsigned. If the RHS operand is equal to or greater than the
347    index bitwidth, the result is a poison value.
348
349    Example:
350
351    ```mlir
352    // c = a << b
353    %c = index.shl %a, %b
354    ```
355  }];
356}
357
358//===----------------------------------------------------------------------===//
359// ShrSOp
360//===----------------------------------------------------------------------===//
361
362def Index_ShrSOp : IndexBinaryOp<"shrs", [Pure]> {
363  let summary = "signed index shift right";
364  let description = [{
365    The `index.shrs` operation shifts an index value to the right by a variable
366    amount. The LHS operand is treated as signed. The high order bits are filled
367    with copies of the most significant bit. If the RHS operand is equal to or
368    greater than the index bitwidth, the result is a poison value.
369
370    Example:
371
372    ```mlir
373    // c = a >> b
374    %c = index.shrs %a, %b
375    ```
376  }];
377}
378
379//===----------------------------------------------------------------------===//
380// ShrUOp
381//===----------------------------------------------------------------------===//
382
383def Index_ShrUOp : IndexBinaryOp<"shru", [Pure]> {
384  let summary = "unsigned index shift right";
385  let description = [{
386    The `index.shru` operation shifts an index value to the right by a variable
387    amount. The LHS operand is treated as unsigned. The high order bits are
388    filled with zeroes. If the RHS operand is equal to or greater than the index
389    bitwidth, the result is a poison value.
390
391    Example:
392
393    ```mlir
394    // c = a >> b
395    %c = index.shru %a, %b
396    ```
397  }];
398}
399
400//===----------------------------------------------------------------------===//
401// AndOp
402//===----------------------------------------------------------------------===//
403
404def Index_AndOp : IndexBinaryOp<"and", [Commutative, Pure]> {
405  let summary = "index bitwise and";
406  let description = [{
407    The `index.and` operation takes two index values and computes their bitwise
408    and.
409
410    Example:
411
412    ```mlir
413    // c = a & b
414    %c = index.and %a, %b
415    ```
416  }];
417
418  let hasCanonicalizeMethod = 1;
419}
420
421//===----------------------------------------------------------------------===//
422// OrOp
423//===----------------------------------------------------------------------===//
424
425def Index_OrOp : IndexBinaryOp<"or", [Commutative, Pure]> {
426  let summary = "index bitwise or";
427  let description = [{
428    The `index.or` operation takes two index values and computes their bitwise
429    or.
430
431    Example:
432
433    ```mlir
434    // c = a | b
435    %c = index.or %a, %b
436    ```
437  }];
438
439  let hasCanonicalizeMethod = 1;
440}
441
442//===----------------------------------------------------------------------===//
443// XorOp
444//===----------------------------------------------------------------------===//
445
446def Index_XOrOp : IndexBinaryOp<"xor", [Commutative, Pure]> {
447  let summary = "index bitwise xor";
448  let description = [{
449    The `index.xor` operation takes two index values and computes their bitwise
450    xor.
451
452    Example:
453
454    ```mlir
455    // c = a ^ b
456    %c = index.xor %a, %b
457    ```
458  }];
459
460  let hasCanonicalizeMethod = 1;
461}
462
463//===----------------------------------------------------------------------===//
464// CastSOp
465//===----------------------------------------------------------------------===//
466
467def Index_CastSOp : IndexOp<"casts", [Pure,
468    DeclareOpInterfaceMethods<CastOpInterface>]> {
469  let summary = "index signed cast";
470  let description = [{
471    The `index.casts` operation enables conversions between values of index type
472    and concrete fixed-width integer types. If casting to a wider integer, the
473    value is sign-extended. If casting to a narrower integer, the value is
474    truncated.
475
476    Example:
477
478    ```mlir
479    // Cast to i32
480    %0 = index.casts %a : index to i32
481
482    // Cast from i64
483    %1 = index.casts %b : i64 to index
484    ```
485  }];
486
487  let arguments = (ins AnyTypeOf<[AnyInteger, Index]>:$input);
488  let results = (outs AnyTypeOf<[AnyInteger, Index]>:$output);
489  let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
490  let hasFolder = 1;
491}
492
493//===----------------------------------------------------------------------===//
494// CastUOp
495//===----------------------------------------------------------------------===//
496
497def Index_CastUOp : IndexOp<"castu", [Pure,
498    DeclareOpInterfaceMethods<CastOpInterface>]> {
499  let summary = "index unsigned cast";
500  let description = [{
501    The `index.castu` operation enables conversions between values of index type
502    and concrete fixed-width integer types. If casting to a wider integer, the
503    value is zero-extended. If casting to a narrower integer, the value is
504    truncated.
505
506    Example:
507
508    ```mlir
509    // Cast to i32
510    %0 = index.castu %a : index to i32
511
512    // Cast from i64
513    %1 = index.castu %b : i64 to index
514    ```
515  }];
516
517  let arguments = (ins AnyTypeOf<[AnyInteger, Index]>:$input);
518  let results = (outs AnyTypeOf<[AnyInteger, Index]>:$output);
519  let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)";
520  let hasFolder = 1;
521}
522
523//===----------------------------------------------------------------------===//
524// CmpOp
525//===----------------------------------------------------------------------===//
526
527def Index_CmpOp : IndexOp<"cmp", [Pure]> {
528  let summary = "index compare";
529  let description = [{
530    The `index.cmp` operation takes two index values and compares them according
531    to the comparison predicate and returns an `i1`. The following comparisons
532    are supported:
533
534    -   `eq`:  equal
535    -   `ne`:  not equal
536    -   `slt`: signed less than
537    -   `sle`: signed less than or equal
538    -   `sgt`: signed greater than
539    -   `sge`: signed greater than or equal
540    -   `ult`: unsigned less than
541    -   `ule`: unsigned less than or equal
542    -   `ugt`: unsigned greater than
543    -   `uge`: unsigned greater than or equal
544
545    The result is `1` if the comparison is true and `0` otherwise.
546
547    Example:
548
549    ```mlir
550    // Signed less than comparison.
551    %0 = index.cmp slt(%a, %b)
552
553    // Unsigned greater than or equal comparison.
554    %1 = index.cmp uge(%a, %b)
555
556    // Not equal comparison.
557    %2 = index.cmp ne(%a, %b)
558    ```
559  }];
560
561  let arguments = (ins IndexCmpPredicateAttr:$pred, Index:$lhs, Index:$rhs);
562  let results = (outs I1:$result);
563  let assemblyFormat = "`` $pred `(` $lhs `,` $rhs `)` attr-dict";
564  let hasFolder = 1;
565  let hasCanonicalizeMethod = 1;
566}
567
568//===----------------------------------------------------------------------===//
569// SizeOfOp
570//===----------------------------------------------------------------------===//
571
572def Index_SizeOfOp : IndexOp<"sizeof", [Pure]> {
573  let summary = "size in bits of the index type";
574  let description = [{
575    The `index.sizeof` operation produces an index-typed SSA value equal to the
576    size in bits of the `index` type. For example, on 32-bit systems, the result
577    is `32 : index`, and on 64-bit systems, the result is `64 : index`.
578
579    Example:
580
581    ```mlir
582    %0 = index.sizeof
583    ```
584  }];
585
586  let results = (outs Index:$result);
587  let assemblyFormat = "attr-dict";
588}
589
590//===----------------------------------------------------------------------===//
591// ConstantOp
592//===----------------------------------------------------------------------===//
593
594def Index_ConstantOp : IndexOp<"constant", [
595    ConstantLike, Pure,
596    DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
597  ]> {
598  let summary = "index constant";
599  let description = [{
600    The `index.constant` operation produces an index-typed SSA value equal to
601    some index-typed integer constant.
602
603    Example:
604
605    ```mlir
606    %0 = index.constant 42
607    ```
608  }];
609
610  let arguments = (ins IndexAttr:$value);
611  let results = (outs Index:$result);
612  let assemblyFormat = "attr-dict $value";
613  let hasFolder = 1;
614
615  let builders = [OpBuilder<(ins "int64_t":$value)>];
616}
617
618//===----------------------------------------------------------------------===//
619// BoolConstantOp
620//===----------------------------------------------------------------------===//
621
622def Index_BoolConstantOp : IndexOp<"bool.constant", [
623    ConstantLike, Pure,
624    DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
625  ]> {
626  let summary = "boolean constant";
627  let description = [{
628    The `index.bool.constant` operation produces an bool-typed SSA value equal
629    to either `true` or `false`.
630
631    This operation is used to materialize bool constants that arise when folding
632    `index.cmp`.
633
634    Example:
635
636    ```mlir
637    %0 = index.bool.constant true
638    ```
639  }];
640
641  let arguments = (ins BoolAttr:$value);
642  let results = (outs I1:$result);
643  let assemblyFormat = "attr-dict $value";
644  let hasFolder = 1;
645}
646
647#endif // INDEX_OPS
648