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