1//===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file defines the generic opcodes used with GlobalISel. 10// After instruction selection, these opcodes should not appear. 11// 12//===----------------------------------------------------------------------===// 13 14//------------------------------------------------------------------------------ 15// Unary ops. 16//------------------------------------------------------------------------------ 17 18class 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 ConstrainedInstruction<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} 37 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); 43 let hasSideEffects = false; 44} 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); 51 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; 66} 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); 73 let hasSideEffects = false; 74} 75 76 77// Truncate the underlying scalar type of an operation. This is equivalent to 78// G_EXTRACT for scalar types, but acts elementwise on vectors. 79def G_TRUNC : GenericInstruction { 80 let OutOperandList = (outs type0:$dst); 81 let InOperandList = (ins type1:$src); 82 let hasSideEffects = false; 83} 84 85def G_IMPLICIT_DEF : GenericInstruction { 86 let OutOperandList = (outs type0:$dst); 87 let InOperandList = (ins); 88 let hasSideEffects = false; 89} 90 91def G_PHI : GenericInstruction { 92 let OutOperandList = (outs type0:$dst); 93 let InOperandList = (ins variable_ops); 94 let hasSideEffects = false; 95} 96 97def G_FRAME_INDEX : GenericInstruction { 98 let OutOperandList = (outs type0:$dst); 99 let InOperandList = (ins unknown:$src2); 100 let hasSideEffects = false; 101} 102 103def G_GLOBAL_VALUE : GenericInstruction { 104 let OutOperandList = (outs type0:$dst); 105 let InOperandList = (ins unknown:$src); 106 let hasSideEffects = false; 107} 108 109def G_CONSTANT_POOL : GenericInstruction { 110 let OutOperandList = (outs type0:$dst); 111 let InOperandList = (ins unknown:$src); 112 let hasSideEffects = false; 113} 114 115def G_INTTOPTR : GenericInstruction { 116 let OutOperandList = (outs type0:$dst); 117 let InOperandList = (ins type1:$src); 118 let hasSideEffects = false; 119} 120 121def G_PTRTOINT : GenericInstruction { 122 let OutOperandList = (outs type0:$dst); 123 let InOperandList = (ins type1:$src); 124 let hasSideEffects = false; 125} 126 127def G_BITCAST : GenericInstruction { 128 let OutOperandList = (outs type0:$dst); 129 let InOperandList = (ins type1:$src); 130 let hasSideEffects = false; 131} 132 133// Only supports scalar result types 134def G_CONSTANT : GenericInstruction { 135 let OutOperandList = (outs type0:$dst); 136 let InOperandList = (ins unknown:$imm); 137 let hasSideEffects = false; 138} 139 140// Only supports scalar result types 141def G_FCONSTANT : GenericInstruction { 142 let OutOperandList = (outs type0:$dst); 143 let InOperandList = (ins unknown:$imm); 144 let hasSideEffects = false; 145} 146 147def G_VASTART : GenericInstruction { 148 let OutOperandList = (outs); 149 let InOperandList = (ins type0:$list); 150 let hasSideEffects = false; 151 let mayStore = true; 152} 153 154def G_VAARG : GenericInstruction { 155 let OutOperandList = (outs type0:$val); 156 let InOperandList = (ins type1:$list, unknown:$align); 157 let hasSideEffects = false; 158 let mayLoad = true; 159 let mayStore = true; 160} 161 162def G_CTLZ : GenericInstruction { 163 let OutOperandList = (outs type0:$dst); 164 let InOperandList = (ins type1:$src); 165 let hasSideEffects = false; 166} 167 168def G_CTLZ_ZERO_UNDEF : GenericInstruction { 169 let OutOperandList = (outs type0:$dst); 170 let InOperandList = (ins type1:$src); 171 let hasSideEffects = false; 172} 173 174def G_CTTZ : GenericInstruction { 175 let OutOperandList = (outs type0:$dst); 176 let InOperandList = (ins type1:$src); 177 let hasSideEffects = false; 178} 179 180def G_CTTZ_ZERO_UNDEF : GenericInstruction { 181 let OutOperandList = (outs type0:$dst); 182 let InOperandList = (ins type1:$src); 183 let hasSideEffects = false; 184} 185 186def G_CTPOP : GenericInstruction { 187 let OutOperandList = (outs type0:$dst); 188 let InOperandList = (ins type1:$src); 189 let hasSideEffects = false; 190} 191 192def G_BSWAP : GenericInstruction { 193 let OutOperandList = (outs type0:$dst); 194 let InOperandList = (ins type0:$src); 195 let hasSideEffects = false; 196} 197 198def G_BITREVERSE : GenericInstruction { 199 let OutOperandList = (outs type0:$dst); 200 let InOperandList = (ins type0:$src); 201 let hasSideEffects = false; 202} 203 204def G_ADDRSPACE_CAST : GenericInstruction { 205 let OutOperandList = (outs type0:$dst); 206 let InOperandList = (ins type1:$src); 207 let hasSideEffects = false; 208} 209 210def G_BLOCK_ADDR : GenericInstruction { 211 let OutOperandList = (outs type0:$dst); 212 let InOperandList = (ins unknown:$ba); 213 let hasSideEffects = false; 214} 215 216def G_JUMP_TABLE : GenericInstruction { 217 let OutOperandList = (outs type0:$dst); 218 let InOperandList = (ins unknown:$jti); 219 let hasSideEffects = false; 220} 221 222def G_DYN_STACKALLOC : GenericInstruction { 223 let OutOperandList = (outs ptype0:$dst); 224 let InOperandList = (ins type1:$size, i32imm:$align); 225 let hasSideEffects = true; 226} 227 228def G_FREEZE : GenericInstruction { 229 let OutOperandList = (outs type0:$dst); 230 let InOperandList = (ins type0:$src); 231 let hasSideEffects = false; 232} 233 234def G_LROUND: GenericInstruction { 235 let OutOperandList = (outs type0:$dst); 236 let InOperandList = (ins type1:$src); 237 let hasSideEffects = false; 238} 239 240def G_LLROUND: GenericInstruction { 241 let OutOperandList = (outs type0:$dst); 242 let InOperandList = (ins type1:$src); 243 let hasSideEffects = false; 244} 245 246//------------------------------------------------------------------------------ 247// Binary ops. 248//------------------------------------------------------------------------------ 249 250// Generic addition. 251def G_ADD : GenericInstruction { 252 let OutOperandList = (outs type0:$dst); 253 let InOperandList = (ins type0:$src1, type0:$src2); 254 let hasSideEffects = false; 255 let isCommutable = true; 256} 257 258// Generic subtraction. 259def G_SUB : GenericInstruction { 260 let OutOperandList = (outs type0:$dst); 261 let InOperandList = (ins type0:$src1, type0:$src2); 262 let hasSideEffects = false; 263 let isCommutable = false; 264} 265 266// Generic multiplication. 267def G_MUL : GenericInstruction { 268 let OutOperandList = (outs type0:$dst); 269 let InOperandList = (ins type0:$src1, type0:$src2); 270 let hasSideEffects = false; 271 let isCommutable = true; 272} 273 274// Generic signed division. 275def G_SDIV : GenericInstruction { 276 let OutOperandList = (outs type0:$dst); 277 let InOperandList = (ins type0:$src1, type0:$src2); 278 let hasSideEffects = false; 279 let isCommutable = false; 280} 281 282// Generic unsigned division. 283def G_UDIV : GenericInstruction { 284 let OutOperandList = (outs type0:$dst); 285 let InOperandList = (ins type0:$src1, type0:$src2); 286 let hasSideEffects = false; 287 let isCommutable = false; 288} 289 290// Generic signed remainder. 291def G_SREM : GenericInstruction { 292 let OutOperandList = (outs type0:$dst); 293 let InOperandList = (ins type0:$src1, type0:$src2); 294 let hasSideEffects = false; 295 let isCommutable = false; 296} 297 298// Generic unsigned remainder. 299def G_UREM : GenericInstruction { 300 let OutOperandList = (outs type0:$dst); 301 let InOperandList = (ins type0:$src1, type0:$src2); 302 let hasSideEffects = false; 303 let isCommutable = false; 304} 305 306// Generic signed division and remainder. 307def G_SDIVREM : GenericInstruction { 308 let OutOperandList = (outs type0:$div, type0:$rem); 309 let InOperandList = (ins type0:$src1, type0:$src2); 310 let hasSideEffects = false; 311 let isCommutable = false; 312} 313 314// Generic unsigned division and remainder. 315def G_UDIVREM : GenericInstruction { 316 let OutOperandList = (outs type0:$div, type0:$rem); 317 let InOperandList = (ins type0:$src1, type0:$src2); 318 let hasSideEffects = false; 319 let isCommutable = false; 320} 321 322// Generic bitwise and. 323def G_AND : GenericInstruction { 324 let OutOperandList = (outs type0:$dst); 325 let InOperandList = (ins type0:$src1, type0:$src2); 326 let hasSideEffects = false; 327 let isCommutable = true; 328} 329 330// Generic bitwise or. 331def G_OR : GenericInstruction { 332 let OutOperandList = (outs type0:$dst); 333 let InOperandList = (ins type0:$src1, type0:$src2); 334 let hasSideEffects = false; 335 let isCommutable = true; 336} 337 338// Generic bitwise xor. 339def G_XOR : GenericInstruction { 340 let OutOperandList = (outs type0:$dst); 341 let InOperandList = (ins type0:$src1, type0:$src2); 342 let hasSideEffects = false; 343 let isCommutable = true; 344} 345 346// Generic left-shift. 347def G_SHL : GenericInstruction { 348 let OutOperandList = (outs type0:$dst); 349 let InOperandList = (ins type0:$src1, type1:$src2); 350 let hasSideEffects = false; 351} 352 353// Generic logical right-shift. 354def G_LSHR : GenericInstruction { 355 let OutOperandList = (outs type0:$dst); 356 let InOperandList = (ins type0:$src1, type1:$src2); 357 let hasSideEffects = false; 358} 359 360// Generic arithmetic right-shift. 361def G_ASHR : GenericInstruction { 362 let OutOperandList = (outs type0:$dst); 363 let InOperandList = (ins type0:$src1, type1:$src2); 364 let hasSideEffects = false; 365} 366 367/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount. 368/// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth))) 369def G_FSHL : GenericInstruction { 370 let OutOperandList = (outs type0:$dst); 371 let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3); 372 let hasSideEffects = false; 373} 374 375/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount. 376/// fshr(X,Y,Z): (X << (bitwidth - (Z % bitwidth))) | (Y >> (Z % bitwidth)) 377def G_FSHR : GenericInstruction { 378 let OutOperandList = (outs type0:$dst); 379 let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3); 380 let hasSideEffects = false; 381} 382 383/// Rotate bits right. 384def G_ROTR : GenericInstruction { 385 let OutOperandList = (outs type0:$dst); 386 let InOperandList = (ins type0:$src1, type1:$src2); 387 let hasSideEffects = false; 388} 389 390/// Rotate bits left. 391def G_ROTL : GenericInstruction { 392 let OutOperandList = (outs type0:$dst); 393 let InOperandList = (ins type0:$src1, type1:$src2); 394 let hasSideEffects = false; 395} 396 397// Generic integer comparison. 398def G_ICMP : GenericInstruction { 399 let OutOperandList = (outs type0:$dst); 400 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); 401 let hasSideEffects = false; 402} 403 404// Generic floating-point comparison. 405def G_FCMP : GenericInstruction { 406 let OutOperandList = (outs type0:$dst); 407 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); 408 let hasSideEffects = false; 409} 410 411// Generic select 412def G_SELECT : GenericInstruction { 413 let OutOperandList = (outs type0:$dst); 414 let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2); 415 let hasSideEffects = false; 416} 417 418// Generic pointer offset. 419def G_PTR_ADD : GenericInstruction { 420 let OutOperandList = (outs ptype0:$dst); 421 let InOperandList = (ins ptype0:$src1, type1:$src2); 422 let hasSideEffects = false; 423} 424 425// Generic pointer mask. type1 should be an integer with the same 426// bitwidth as the pointer type. 427def G_PTRMASK : GenericInstruction { 428 let OutOperandList = (outs ptype0:$dst); 429 let InOperandList = (ins ptype0:$src, type1:$bits); 430 let hasSideEffects = false; 431} 432 433// Generic signed integer minimum. 434def G_SMIN : GenericInstruction { 435 let OutOperandList = (outs type0:$dst); 436 let InOperandList = (ins type0:$src1, type0:$src2); 437 let hasSideEffects = false; 438 let isCommutable = true; 439} 440 441// Generic signed integer maximum. 442def G_SMAX : GenericInstruction { 443 let OutOperandList = (outs type0:$dst); 444 let InOperandList = (ins type0:$src1, type0:$src2); 445 let hasSideEffects = false; 446 let isCommutable = true; 447} 448 449// Generic unsigned integer minimum. 450def G_UMIN : GenericInstruction { 451 let OutOperandList = (outs type0:$dst); 452 let InOperandList = (ins type0:$src1, type0:$src2); 453 let hasSideEffects = false; 454 let isCommutable = true; 455} 456 457// Generic unsigned integer maximum. 458def G_UMAX : GenericInstruction { 459 let OutOperandList = (outs type0:$dst); 460 let InOperandList = (ins type0:$src1, type0:$src2); 461 let hasSideEffects = false; 462 let isCommutable = true; 463} 464 465// Generic integer absolute value. 466def G_ABS : GenericInstruction { 467 let OutOperandList = (outs type0:$dst); 468 let InOperandList = (ins type0:$src); 469 let hasSideEffects = false; 470} 471 472//------------------------------------------------------------------------------ 473// Overflow ops 474//------------------------------------------------------------------------------ 475 476// Generic unsigned addition producing a carry flag. 477def G_UADDO : GenericInstruction { 478 let OutOperandList = (outs type0:$dst, type1:$carry_out); 479 let InOperandList = (ins type0:$src1, type0:$src2); 480 let hasSideEffects = false; 481 let isCommutable = true; 482} 483 484// Generic unsigned addition consuming and producing a carry flag. 485def G_UADDE : GenericInstruction { 486 let OutOperandList = (outs type0:$dst, type1:$carry_out); 487 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 488 let hasSideEffects = false; 489} 490 491// Generic signed addition producing a carry flag. 492def G_SADDO : GenericInstruction { 493 let OutOperandList = (outs type0:$dst, type1:$carry_out); 494 let InOperandList = (ins type0:$src1, type0:$src2); 495 let hasSideEffects = false; 496 let isCommutable = true; 497} 498 499// Generic signed addition consuming and producing a carry flag. 500def G_SADDE : GenericInstruction { 501 let OutOperandList = (outs type0:$dst, type1:$carry_out); 502 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 503 let hasSideEffects = false; 504} 505 506// Generic unsigned subtraction producing a carry flag. 507def G_USUBO : GenericInstruction { 508 let OutOperandList = (outs type0:$dst, type1:$carry_out); 509 let InOperandList = (ins type0:$src1, type0:$src2); 510 let hasSideEffects = false; 511} 512// Generic unsigned subtraction consuming and producing a carry flag. 513def G_USUBE : GenericInstruction { 514 let OutOperandList = (outs type0:$dst, type1:$carry_out); 515 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 516 let hasSideEffects = false; 517} 518 519// Generic signed subtraction producing a carry flag. 520def G_SSUBO : GenericInstruction { 521 let OutOperandList = (outs type0:$dst, type1:$carry_out); 522 let InOperandList = (ins type0:$src1, type0:$src2); 523 let hasSideEffects = false; 524} 525 526// Generic signed subtraction consuming and producing a carry flag. 527def G_SSUBE : GenericInstruction { 528 let OutOperandList = (outs type0:$dst, type1:$carry_out); 529 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 530 let hasSideEffects = false; 531} 532 533// Generic unsigned multiplication producing a carry flag. 534def G_UMULO : GenericInstruction { 535 let OutOperandList = (outs type0:$dst, type1:$carry_out); 536 let InOperandList = (ins type0:$src1, type0:$src2); 537 let hasSideEffects = false; 538 let isCommutable = true; 539} 540 541// Generic signed multiplication producing a carry flag. 542def G_SMULO : GenericInstruction { 543 let OutOperandList = (outs type0:$dst, type1:$carry_out); 544 let InOperandList = (ins type0:$src1, type0:$src2); 545 let hasSideEffects = false; 546 let isCommutable = true; 547} 548 549// Multiply two numbers at twice the incoming bit width (unsigned) and return 550// the high half of the result. 551def G_UMULH : GenericInstruction { 552 let OutOperandList = (outs type0:$dst); 553 let InOperandList = (ins type0:$src1, type0:$src2); 554 let hasSideEffects = false; 555 let isCommutable = true; 556} 557 558// Multiply two numbers at twice the incoming bit width (signed) and return 559// the high half of the result. 560def G_SMULH : GenericInstruction { 561 let OutOperandList = (outs type0:$dst); 562 let InOperandList = (ins type0:$src1, type0:$src2); 563 let hasSideEffects = false; 564 let isCommutable = true; 565} 566 567//------------------------------------------------------------------------------ 568// Saturating ops 569//------------------------------------------------------------------------------ 570 571// Generic saturating unsigned addition. 572def G_UADDSAT : GenericInstruction { 573 let OutOperandList = (outs type0:$dst); 574 let InOperandList = (ins type0:$src1, type0:$src2); 575 let hasSideEffects = false; 576 let isCommutable = true; 577} 578 579// Generic saturating signed addition. 580def G_SADDSAT : GenericInstruction { 581 let OutOperandList = (outs type0:$dst); 582 let InOperandList = (ins type0:$src1, type0:$src2); 583 let hasSideEffects = false; 584 let isCommutable = true; 585} 586 587// Generic saturating unsigned subtraction. 588def G_USUBSAT : GenericInstruction { 589 let OutOperandList = (outs type0:$dst); 590 let InOperandList = (ins type0:$src1, type0:$src2); 591 let hasSideEffects = false; 592 let isCommutable = false; 593} 594 595// Generic saturating signed subtraction. 596def G_SSUBSAT : GenericInstruction { 597 let OutOperandList = (outs type0:$dst); 598 let InOperandList = (ins type0:$src1, type0:$src2); 599 let hasSideEffects = false; 600 let isCommutable = false; 601} 602 603// Generic saturating unsigned left shift. 604def G_USHLSAT : GenericInstruction { 605 let OutOperandList = (outs type0:$dst); 606 let InOperandList = (ins type0:$src1, type1:$src2); 607 let hasSideEffects = false; 608 let isCommutable = false; 609} 610 611// Generic saturating signed left shift. 612def G_SSHLSAT : GenericInstruction { 613 let OutOperandList = (outs type0:$dst); 614 let InOperandList = (ins type0:$src1, type1:$src2); 615 let hasSideEffects = false; 616 let isCommutable = false; 617} 618 619/// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point 620/// multiplication on 2 integers with the same width and scale. SCALE 621/// represents the scale of both operands as fixed point numbers. This 622/// SCALE parameter must be a constant integer. A scale of zero is 623/// effectively performing multiplication on 2 integers. 624def G_SMULFIX : GenericInstruction { 625 let OutOperandList = (outs type0:$dst); 626 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 627 let hasSideEffects = false; 628 let isCommutable = true; 629} 630 631def G_UMULFIX : GenericInstruction { 632 let OutOperandList = (outs type0:$dst); 633 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 634 let hasSideEffects = false; 635 let isCommutable = true; 636} 637 638/// Same as the corresponding unsaturated fixed point instructions, but the 639/// result is clamped between the min and max values representable by the 640/// bits of the first 2 operands. 641def G_SMULFIXSAT : GenericInstruction { 642 let OutOperandList = (outs type0:$dst); 643 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 644 let hasSideEffects = false; 645 let isCommutable = true; 646} 647 648def G_UMULFIXSAT : GenericInstruction { 649 let OutOperandList = (outs type0:$dst); 650 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 651 let hasSideEffects = false; 652 let isCommutable = true; 653} 654 655/// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 656/// 2 integers with the same width and scale. SCALE represents the scale 657/// of both operands as fixed point numbers. This SCALE parameter must be a 658/// constant integer. 659def G_SDIVFIX : GenericInstruction { 660 let OutOperandList = (outs type0:$dst); 661 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 662 let hasSideEffects = false; 663 let isCommutable = false; 664} 665 666def G_UDIVFIX : GenericInstruction { 667 let OutOperandList = (outs type0:$dst); 668 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 669 let hasSideEffects = false; 670 let isCommutable = false; 671} 672 673/// Same as the corresponding unsaturated fixed point instructions, 674/// but the result is clamped between the min and max values 675/// representable by the bits of the first 2 operands. 676def G_SDIVFIXSAT : GenericInstruction { 677 let OutOperandList = (outs type0:$dst); 678 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 679 let hasSideEffects = false; 680 let isCommutable = false; 681} 682 683def G_UDIVFIXSAT : GenericInstruction { 684 let OutOperandList = (outs type0:$dst); 685 let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale); 686 let hasSideEffects = false; 687 let isCommutable = false; 688} 689 690//------------------------------------------------------------------------------ 691// Floating Point Unary Ops. 692//------------------------------------------------------------------------------ 693 694def G_FNEG : GenericInstruction { 695 let OutOperandList = (outs type0:$dst); 696 let InOperandList = (ins type0:$src); 697 let hasSideEffects = false; 698} 699 700def G_FPEXT : GenericInstruction { 701 let OutOperandList = (outs type0:$dst); 702 let InOperandList = (ins type1:$src); 703 let hasSideEffects = false; 704} 705 706def G_FPTRUNC : GenericInstruction { 707 let OutOperandList = (outs type0:$dst); 708 let InOperandList = (ins type1:$src); 709 let hasSideEffects = false; 710} 711 712def G_FPTOSI : GenericInstruction { 713 let OutOperandList = (outs type0:$dst); 714 let InOperandList = (ins type1:$src); 715 let hasSideEffects = false; 716} 717 718def G_FPTOUI : GenericInstruction { 719 let OutOperandList = (outs type0:$dst); 720 let InOperandList = (ins type1:$src); 721 let hasSideEffects = false; 722} 723 724def G_SITOFP : GenericInstruction { 725 let OutOperandList = (outs type0:$dst); 726 let InOperandList = (ins type1:$src); 727 let hasSideEffects = false; 728} 729 730def G_UITOFP : GenericInstruction { 731 let OutOperandList = (outs type0:$dst); 732 let InOperandList = (ins type1:$src); 733 let hasSideEffects = false; 734} 735 736def G_FABS : GenericInstruction { 737 let OutOperandList = (outs type0:$dst); 738 let InOperandList = (ins type0:$src); 739 let hasSideEffects = false; 740} 741 742def G_FCOPYSIGN : GenericInstruction { 743 let OutOperandList = (outs type0:$dst); 744 let InOperandList = (ins type0:$src0, type1:$src1); 745 let hasSideEffects = false; 746} 747 748def G_FCANONICALIZE : GenericInstruction { 749 let OutOperandList = (outs type0:$dst); 750 let InOperandList = (ins type0:$src); 751 let hasSideEffects = false; 752} 753 754// Generic opcode equivalent to the llvm.is_fpclass intrinsic. 755def G_IS_FPCLASS: GenericInstruction { 756 let OutOperandList = (outs type0:$dst); 757 let InOperandList = (ins type1:$src, unknown:$test); 758 let hasSideEffects = false; 759} 760 761// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two 762// values. 763// 764// In the case where a single input is a NaN (either signaling or quiet), 765// the non-NaN input is returned. 766// 767// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. 768def G_FMINNUM : GenericInstruction { 769 let OutOperandList = (outs type0:$dst); 770 let InOperandList = (ins type0:$src1, type0:$src2); 771 let hasSideEffects = false; 772 let isCommutable = true; 773} 774 775def G_FMAXNUM : GenericInstruction { 776 let OutOperandList = (outs type0:$dst); 777 let InOperandList = (ins type0:$src1, type0:$src2); 778 let hasSideEffects = false; 779 let isCommutable = true; 780} 781 782// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on 783// two values, following the IEEE-754 2008 definition. This differs from 784// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a 785// signaling NaN, returns a quiet NaN. 786def G_FMINNUM_IEEE : GenericInstruction { 787 let OutOperandList = (outs type0:$dst); 788 let InOperandList = (ins type0:$src1, type0:$src2); 789 let hasSideEffects = false; 790 let isCommutable = true; 791} 792 793def G_FMAXNUM_IEEE : GenericInstruction { 794 let OutOperandList = (outs type0:$dst); 795 let InOperandList = (ins type0:$src1, type0:$src2); 796 let hasSideEffects = false; 797 let isCommutable = true; 798} 799 800// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 801// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 802// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics. 803def G_FMINIMUM : GenericInstruction { 804 let OutOperandList = (outs type0:$dst); 805 let InOperandList = (ins type0:$src1, type0:$src2); 806 let hasSideEffects = false; 807 let isCommutable = true; 808} 809 810def G_FMAXIMUM : GenericInstruction { 811 let OutOperandList = (outs type0:$dst); 812 let InOperandList = (ins type0:$src1, type0:$src2); 813 let hasSideEffects = false; 814 let isCommutable = true; 815} 816 817//------------------------------------------------------------------------------ 818// Floating Point Binary ops. 819//------------------------------------------------------------------------------ 820 821// Generic FP addition. 822def G_FADD : GenericInstruction { 823 let OutOperandList = (outs type0:$dst); 824 let InOperandList = (ins type0:$src1, type0:$src2); 825 let hasSideEffects = false; 826 let isCommutable = true; 827} 828 829// Generic FP subtraction. 830def G_FSUB : GenericInstruction { 831 let OutOperandList = (outs type0:$dst); 832 let InOperandList = (ins type0:$src1, type0:$src2); 833 let hasSideEffects = false; 834 let isCommutable = false; 835} 836 837// Generic FP multiplication. 838def G_FMUL : GenericInstruction { 839 let OutOperandList = (outs type0:$dst); 840 let InOperandList = (ins type0:$src1, type0:$src2); 841 let hasSideEffects = false; 842 let isCommutable = true; 843} 844 845// Generic fused multiply-add instruction. 846// Behaves like llvm fma intrinsic ie src1 * src2 + src3 847def G_FMA : GenericInstruction { 848 let OutOperandList = (outs type0:$dst); 849 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); 850 let hasSideEffects = false; 851 let isCommutable = false; 852} 853 854/// Generic FP multiply and add. Perform a * b + c, while getting the 855/// same result as the separately rounded operations, unlike G_FMA. 856def G_FMAD : GenericInstruction { 857 let OutOperandList = (outs type0:$dst); 858 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); 859 let hasSideEffects = false; 860 let isCommutable = false; 861} 862 863// Generic FP division. 864def G_FDIV : GenericInstruction { 865 let OutOperandList = (outs type0:$dst); 866 let InOperandList = (ins type0:$src1, type0:$src2); 867 let hasSideEffects = false; 868} 869 870// Generic FP remainder. 871def G_FREM : GenericInstruction { 872 let OutOperandList = (outs type0:$dst); 873 let InOperandList = (ins type0:$src1, type0:$src2); 874 let hasSideEffects = false; 875} 876 877// Floating point exponentiation. 878def G_FPOW : GenericInstruction { 879 let OutOperandList = (outs type0:$dst); 880 let InOperandList = (ins type0:$src1, type0:$src2); 881 let hasSideEffects = false; 882} 883 884// Floating point exponentiation, with an integer power. 885def G_FPOWI : GenericInstruction { 886 let OutOperandList = (outs type0:$dst); 887 let InOperandList = (ins type0:$src0, type1:$src1); 888 let hasSideEffects = false; 889} 890 891// Floating point base-e exponential of a value. 892def G_FEXP : GenericInstruction { 893 let OutOperandList = (outs type0:$dst); 894 let InOperandList = (ins type0:$src1); 895 let hasSideEffects = false; 896} 897 898// Floating point base-2 exponential of a value. 899def G_FEXP2 : GenericInstruction { 900 let OutOperandList = (outs type0:$dst); 901 let InOperandList = (ins type0:$src1); 902 let hasSideEffects = false; 903} 904 905// Floating point base-e logarithm of a value. 906def G_FLOG : GenericInstruction { 907 let OutOperandList = (outs type0:$dst); 908 let InOperandList = (ins type0:$src1); 909 let hasSideEffects = false; 910} 911 912// Floating point base-2 logarithm of a value. 913def G_FLOG2 : GenericInstruction { 914 let OutOperandList = (outs type0:$dst); 915 let InOperandList = (ins type0:$src1); 916 let hasSideEffects = false; 917} 918 919// Floating point base-10 logarithm of a value. 920def G_FLOG10 : GenericInstruction { 921 let OutOperandList = (outs type0:$dst); 922 let InOperandList = (ins type0:$src1); 923 let hasSideEffects = false; 924} 925 926// Floating point x * 2^n 927def G_FLDEXP : GenericInstruction { 928 let OutOperandList = (outs type0:$dst); 929 let InOperandList = (ins type0:$src0, type1:$src1); 930 let hasSideEffects = false; 931} 932 933// Floating point frexp 934def G_FFREXP : GenericInstruction { 935 let OutOperandList = (outs type0:$dst0, type1:$dst1); 936 let InOperandList = (ins type0:$src0); 937 let hasSideEffects = false; 938} 939 940// Floating point ceiling of a value. 941def G_FCEIL : GenericInstruction { 942 let OutOperandList = (outs type0:$dst); 943 let InOperandList = (ins type0:$src1); 944 let hasSideEffects = false; 945} 946 947// Floating point cosine of a value. 948def G_FCOS : GenericInstruction { 949 let OutOperandList = (outs type0:$dst); 950 let InOperandList = (ins type0:$src1); 951 let hasSideEffects = false; 952} 953 954// Floating point sine of a value. 955def G_FSIN : GenericInstruction { 956 let OutOperandList = (outs type0:$dst); 957 let InOperandList = (ins type0:$src1); 958 let hasSideEffects = false; 959} 960 961// Floating point square root of a value. 962// This returns NaN for negative nonzero values. 963// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's 964// libm-conformant. 965def G_FSQRT : GenericInstruction { 966 let OutOperandList = (outs type0:$dst); 967 let InOperandList = (ins type0:$src1); 968 let hasSideEffects = false; 969} 970 971// Floating point floor of a value. 972def G_FFLOOR : GenericInstruction { 973 let OutOperandList = (outs type0:$dst); 974 let InOperandList = (ins type0:$src1); 975 let hasSideEffects = false; 976} 977 978// Floating point round to next integer. 979def G_FRINT : GenericInstruction { 980 let OutOperandList = (outs type0:$dst); 981 let InOperandList = (ins type0:$src1); 982 let hasSideEffects = false; 983} 984 985// Floating point round to the nearest integer. 986def G_FNEARBYINT : GenericInstruction { 987 let OutOperandList = (outs type0:$dst); 988 let InOperandList = (ins type0:$src1); 989 let hasSideEffects = false; 990} 991 992//------------------------------------------------------------------------------ 993// Opcodes for LLVM Intrinsics 994//------------------------------------------------------------------------------ 995def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction { 996 let OutOperandList = (outs type0:$dst); 997 let InOperandList = (ins type1:$src1, i32imm:$round_mode); 998 let hasSideEffects = false; 999} 1000 1001def G_INTRINSIC_TRUNC : GenericInstruction { 1002 let OutOperandList = (outs type0:$dst); 1003 let InOperandList = (ins type0:$src1); 1004 let hasSideEffects = false; 1005} 1006 1007def G_INTRINSIC_ROUND : GenericInstruction { 1008 let OutOperandList = (outs type0:$dst); 1009 let InOperandList = (ins type0:$src1); 1010 let hasSideEffects = false; 1011} 1012 1013def G_INTRINSIC_LRINT : GenericInstruction { 1014 let OutOperandList = (outs type0:$dst); 1015 let InOperandList = (ins type1:$src); 1016 let hasSideEffects = false; 1017} 1018 1019def G_INTRINSIC_ROUNDEVEN : GenericInstruction { 1020 let OutOperandList = (outs type0:$dst); 1021 let InOperandList = (ins type0:$src1); 1022 let hasSideEffects = false; 1023} 1024 1025def G_READCYCLECOUNTER : GenericInstruction { 1026 let OutOperandList = (outs type0:$dst); 1027 let InOperandList = (ins); 1028 let hasSideEffects = true; 1029} 1030 1031//------------------------------------------------------------------------------ 1032// Memory ops 1033//------------------------------------------------------------------------------ 1034 1035// Generic load. Expects a MachineMemOperand in addition to explicit 1036// operands. If the result size is larger than the memory size, the 1037// high bits are undefined. If the result is a vector type and larger 1038// than the memory size, the high elements are undefined (i.e. this is 1039// not a per-element, vector anyextload) 1040def G_LOAD : GenericInstruction { 1041 let OutOperandList = (outs type0:$dst); 1042 let InOperandList = (ins ptype1:$addr); 1043 let hasSideEffects = false; 1044 let mayLoad = true; 1045} 1046 1047// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands. 1048def G_SEXTLOAD : GenericInstruction { 1049 let OutOperandList = (outs type0:$dst); 1050 let InOperandList = (ins ptype1:$addr); 1051 let hasSideEffects = false; 1052 let mayLoad = true; 1053} 1054 1055// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands. 1056def G_ZEXTLOAD : GenericInstruction { 1057 let OutOperandList = (outs type0:$dst); 1058 let InOperandList = (ins ptype1:$addr); 1059 let hasSideEffects = false; 1060 let mayLoad = true; 1061} 1062 1063// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset. 1064// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed) 1065// then the value is loaded from $newaddr. 1066def G_INDEXED_LOAD : GenericInstruction { 1067 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1068 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1069 let hasSideEffects = false; 1070 let mayLoad = true; 1071} 1072 1073// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD. 1074def G_INDEXED_SEXTLOAD : GenericInstruction { 1075 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1076 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1077 let hasSideEffects = false; 1078 let mayLoad = true; 1079} 1080 1081// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD. 1082def G_INDEXED_ZEXTLOAD : GenericInstruction { 1083 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1084 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1085 let hasSideEffects = false; 1086 let mayLoad = true; 1087} 1088 1089// Generic store. Expects a MachineMemOperand in addition to explicit operands. 1090def G_STORE : GenericInstruction { 1091 let OutOperandList = (outs); 1092 let InOperandList = (ins type0:$src, ptype1:$addr); 1093 let hasSideEffects = false; 1094 let mayStore = true; 1095} 1096 1097// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour. 1098def G_INDEXED_STORE : GenericInstruction { 1099 let OutOperandList = (outs ptype0:$newaddr); 1100 let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset, 1101 unknown:$am); 1102 let hasSideEffects = false; 1103 let mayStore = true; 1104} 1105 1106// Generic atomic cmpxchg with internal success check. Expects a 1107// MachineMemOperand in addition to explicit operands. 1108def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction { 1109 let OutOperandList = (outs type0:$oldval, type1:$success); 1110 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval); 1111 let hasSideEffects = false; 1112 let mayLoad = true; 1113 let mayStore = true; 1114} 1115 1116// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit 1117// operands. 1118def G_ATOMIC_CMPXCHG : GenericInstruction { 1119 let OutOperandList = (outs type0:$oldval); 1120 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval); 1121 let hasSideEffects = false; 1122 let mayLoad = true; 1123 let mayStore = true; 1124} 1125 1126// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit 1127// operands. 1128class G_ATOMICRMW_OP : GenericInstruction { 1129 let OutOperandList = (outs type0:$oldval); 1130 let InOperandList = (ins ptype1:$addr, type0:$val); 1131 let hasSideEffects = false; 1132 let mayLoad = true; 1133 let mayStore = true; 1134} 1135 1136def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP; 1137def G_ATOMICRMW_ADD : G_ATOMICRMW_OP; 1138def G_ATOMICRMW_SUB : G_ATOMICRMW_OP; 1139def G_ATOMICRMW_AND : G_ATOMICRMW_OP; 1140def G_ATOMICRMW_NAND : G_ATOMICRMW_OP; 1141def G_ATOMICRMW_OR : G_ATOMICRMW_OP; 1142def G_ATOMICRMW_XOR : G_ATOMICRMW_OP; 1143def G_ATOMICRMW_MAX : G_ATOMICRMW_OP; 1144def G_ATOMICRMW_MIN : G_ATOMICRMW_OP; 1145def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP; 1146def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP; 1147def G_ATOMICRMW_FADD : G_ATOMICRMW_OP; 1148def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP; 1149def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP; 1150def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP; 1151def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP; 1152def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP; 1153 1154def G_FENCE : GenericInstruction { 1155 let OutOperandList = (outs); 1156 let InOperandList = (ins i32imm:$ordering, i32imm:$scope); 1157 let hasSideEffects = true; 1158} 1159 1160//------------------------------------------------------------------------------ 1161// Variadic ops 1162//------------------------------------------------------------------------------ 1163 1164// Extract a register of the specified size, starting from the block given by 1165// index. This will almost certainly be mapped to sub-register COPYs after 1166// register banks have been selected. 1167def G_EXTRACT : GenericInstruction { 1168 let OutOperandList = (outs type0:$res); 1169 let InOperandList = (ins type1:$src, untyped_imm_0:$offset); 1170 let hasSideEffects = false; 1171} 1172 1173// Extract multiple registers specified size, starting from blocks given by 1174// indexes. This will almost certainly be mapped to sub-register COPYs after 1175// register banks have been selected. 1176// The output operands are always ordered from lowest bits to highest: 1177// %bits_0_7:(s8), %bits_8_15:(s8), 1178// %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32) 1179def G_UNMERGE_VALUES : GenericInstruction { 1180 let OutOperandList = (outs type0:$dst0, variable_ops); 1181 let InOperandList = (ins type1:$src); 1182 let hasSideEffects = false; 1183} 1184 1185// Insert a smaller register into a larger one at the specified bit-index. 1186def G_INSERT : GenericInstruction { 1187 let OutOperandList = (outs type0:$dst); 1188 let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset); 1189 let hasSideEffects = false; 1190} 1191 1192// Concatenate multiple registers of the same size into a wider register. 1193// The input operands are always ordered from lowest bits to highest: 1194// %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8), 1195// %bits_16_23:(s8), %bits_24_31:(s8) 1196def G_MERGE_VALUES : GenericInstruction { 1197 let OutOperandList = (outs type0:$dst); 1198 let InOperandList = (ins type1:$src0, variable_ops); 1199 let hasSideEffects = false; 1200} 1201 1202/// Create a vector from multiple scalar registers. No implicit 1203/// conversion is performed (i.e. the result element type must be the 1204/// same as all source operands) 1205def G_BUILD_VECTOR : GenericInstruction { 1206 let OutOperandList = (outs type0:$dst); 1207 let InOperandList = (ins type1:$src0, variable_ops); 1208 let hasSideEffects = false; 1209} 1210 1211/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the 1212/// destination vector elt type. 1213def G_BUILD_VECTOR_TRUNC : GenericInstruction { 1214 let OutOperandList = (outs type0:$dst); 1215 let InOperandList = (ins type1:$src0, variable_ops); 1216 let hasSideEffects = false; 1217} 1218 1219/// Create a vector by concatenating vectors together. 1220def G_CONCAT_VECTORS : GenericInstruction { 1221 let OutOperandList = (outs type0:$dst); 1222 let InOperandList = (ins type1:$src0, variable_ops); 1223 let hasSideEffects = false; 1224} 1225 1226// Intrinsic without side effects. 1227def G_INTRINSIC : GenericInstruction { 1228 let OutOperandList = (outs); 1229 let InOperandList = (ins unknown:$intrin, variable_ops); 1230 let hasSideEffects = false; 1231 1232 // Conservatively assume this is convergent. If there turnes out to 1233 // be a need, there should be separate convergent intrinsic opcodes. 1234 let isConvergent = 1; 1235} 1236 1237// Intrinsic with side effects. 1238def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction { 1239 let OutOperandList = (outs); 1240 let InOperandList = (ins unknown:$intrin, variable_ops); 1241 let hasSideEffects = true; 1242 let mayLoad = true; 1243 let mayStore = true; 1244 1245 // Conservatively assume this is convergent. If there turnes out to 1246 // be a need, there should be separate convergent intrinsic opcodes. 1247 let isConvergent = true; 1248} 1249 1250//------------------------------------------------------------------------------ 1251// Branches. 1252//------------------------------------------------------------------------------ 1253 1254// Generic unconditional branch. 1255def G_BR : GenericInstruction { 1256 let OutOperandList = (outs); 1257 let InOperandList = (ins unknown:$src1); 1258 let hasSideEffects = false; 1259 let isBranch = true; 1260 let isTerminator = true; 1261 let isBarrier = true; 1262} 1263 1264// Generic conditional branch. 1265def G_BRCOND : GenericInstruction { 1266 let OutOperandList = (outs); 1267 let InOperandList = (ins type0:$tst, unknown:$truebb); 1268 let hasSideEffects = false; 1269 let isBranch = true; 1270 let isTerminator = true; 1271} 1272 1273// Generic indirect branch. 1274def G_BRINDIRECT : GenericInstruction { 1275 let OutOperandList = (outs); 1276 let InOperandList = (ins type0:$src1); 1277 let hasSideEffects = false; 1278 let isBranch = true; 1279 let isTerminator = true; 1280 let isBarrier = true; 1281 let isIndirectBranch = true; 1282} 1283 1284// Generic branch to jump table entry 1285def G_BRJT : GenericInstruction { 1286 let OutOperandList = (outs); 1287 let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx); 1288 let hasSideEffects = false; 1289 let isBranch = true; 1290 let isTerminator = true; 1291 let isBarrier = true; 1292 let isIndirectBranch = true; 1293} 1294 1295// A marker to signal the following code is an invoke region, that may throw 1296// an exception and therefore not return. 1297def G_INVOKE_REGION_START : GenericInstruction { 1298 let OutOperandList = (outs); 1299 let InOperandList = (ins); 1300 let isTerminator = true; // This must be a terminator. 1301 let hasSideEffects = false; 1302} 1303 1304def G_READ_REGISTER : GenericInstruction { 1305 let OutOperandList = (outs type0:$dst); 1306 let InOperandList = (ins unknown:$register); 1307 let hasSideEffects = true; 1308 1309 // Assume convergent. It's probably not worth the effort of somehow 1310 // modeling convergent and nonconvergent register accesses. 1311 let isConvergent = true; 1312} 1313 1314def G_WRITE_REGISTER : GenericInstruction { 1315 let OutOperandList = (outs); 1316 let InOperandList = (ins unknown:$register, type0:$value); 1317 let hasSideEffects = true; 1318 1319 // Assume convergent. It's probably not worth the effort of somehow 1320 // modeling convergent and nonconvergent register accesses. 1321 let isConvergent = true; 1322} 1323 1324//------------------------------------------------------------------------------ 1325// Vector ops 1326//------------------------------------------------------------------------------ 1327 1328// Generic insertelement. 1329def G_INSERT_VECTOR_ELT : GenericInstruction { 1330 let OutOperandList = (outs type0:$dst); 1331 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); 1332 let hasSideEffects = false; 1333} 1334 1335// Generic extractelement. 1336def G_EXTRACT_VECTOR_ELT : GenericInstruction { 1337 let OutOperandList = (outs type0:$dst); 1338 let InOperandList = (ins type1:$src, type2:$idx); 1339 let hasSideEffects = false; 1340} 1341 1342// Generic shufflevector. 1343// 1344// The mask operand should be an IR Constant which exactly matches the 1345// corresponding mask for the IR shufflevector instruction. 1346def G_SHUFFLE_VECTOR: GenericInstruction { 1347 let OutOperandList = (outs type0:$dst); 1348 let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask); 1349 let hasSideEffects = false; 1350} 1351 1352//------------------------------------------------------------------------------ 1353// Vector reductions 1354//------------------------------------------------------------------------------ 1355 1356class VectorReduction : GenericInstruction { 1357 let OutOperandList = (outs type0:$dst); 1358 let InOperandList = (ins type1:$v); 1359 let hasSideEffects = false; 1360} 1361 1362def G_VECREDUCE_SEQ_FADD : GenericInstruction { 1363 let OutOperandList = (outs type0:$dst); 1364 let InOperandList = (ins type1:$acc, type2:$v); 1365 let hasSideEffects = false; 1366} 1367 1368def G_VECREDUCE_SEQ_FMUL : GenericInstruction { 1369 let OutOperandList = (outs type0:$dst); 1370 let InOperandList = (ins type1:$acc, type2:$v); 1371 let hasSideEffects = false; 1372} 1373 1374def G_VECREDUCE_FADD : VectorReduction; 1375def G_VECREDUCE_FMUL : VectorReduction; 1376 1377def G_VECREDUCE_FMAX : VectorReduction; 1378def G_VECREDUCE_FMIN : VectorReduction; 1379 1380def G_VECREDUCE_ADD : VectorReduction; 1381def G_VECREDUCE_MUL : VectorReduction; 1382def G_VECREDUCE_AND : VectorReduction; 1383def G_VECREDUCE_OR : VectorReduction; 1384def G_VECREDUCE_XOR : VectorReduction; 1385def G_VECREDUCE_SMAX : VectorReduction; 1386def G_VECREDUCE_SMIN : VectorReduction; 1387def G_VECREDUCE_UMAX : VectorReduction; 1388def G_VECREDUCE_UMIN : VectorReduction; 1389 1390//------------------------------------------------------------------------------ 1391// Constrained floating point ops 1392//------------------------------------------------------------------------------ 1393 1394def G_STRICT_FADD : ConstrainedInstruction<G_FADD>; 1395def G_STRICT_FSUB : ConstrainedInstruction<G_FSUB>; 1396def G_STRICT_FMUL : ConstrainedInstruction<G_FMUL>; 1397def G_STRICT_FDIV : ConstrainedInstruction<G_FDIV>; 1398def G_STRICT_FREM : ConstrainedInstruction<G_FREM>; 1399def G_STRICT_FMA : ConstrainedInstruction<G_FMA>; 1400def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>; 1401def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>; 1402 1403//------------------------------------------------------------------------------ 1404// Memory intrinsics 1405//------------------------------------------------------------------------------ 1406 1407def G_MEMCPY : GenericInstruction { 1408 let OutOperandList = (outs); 1409 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); 1410 let hasSideEffects = false; 1411 let mayLoad = true; 1412 let mayStore = true; 1413} 1414 1415def G_MEMCPY_INLINE : GenericInstruction { 1416 let OutOperandList = (outs); 1417 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size); 1418 let hasSideEffects = false; 1419 let mayLoad = true; 1420 let mayStore = true; 1421} 1422 1423def G_MEMMOVE : GenericInstruction { 1424 let OutOperandList = (outs); 1425 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); 1426 let hasSideEffects = false; 1427 let mayLoad = true; 1428 let mayStore = true; 1429} 1430 1431def G_MEMSET : GenericInstruction { 1432 let OutOperandList = (outs); 1433 let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall); 1434 let hasSideEffects = false; 1435 let mayStore = true; 1436} 1437 1438def G_BZERO : GenericInstruction { 1439 let OutOperandList = (outs); 1440 let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall); 1441 let hasSideEffects = false; 1442 let mayStore = true; 1443} 1444 1445//------------------------------------------------------------------------------ 1446// Bitfield extraction. 1447//------------------------------------------------------------------------------ 1448 1449// Generic signed bitfield extraction. The operands are in the range 1450// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. 1451def G_SBFX : GenericInstruction { 1452 let OutOperandList = (outs type0:$dst); 1453 let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); 1454 let hasSideEffects = false; 1455} 1456 1457// Generic unsigned bitfield extraction. The operands are in the range 1458// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. 1459def G_UBFX : GenericInstruction { 1460 let OutOperandList = (outs type0:$dst); 1461 let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); 1462 let hasSideEffects = false; 1463} 1464 1465//------------------------------------------------------------------------------ 1466// Optimization hints 1467//------------------------------------------------------------------------------ 1468 1469// Asserts that an operation has already been zero-extended from a specific 1470// type. 1471def G_ASSERT_ZEXT : GenericInstruction { 1472 let OutOperandList = (outs type0:$dst); 1473 let InOperandList = (ins type0:$src, untyped_imm_0:$sz); 1474 let hasSideEffects = false; 1475} 1476 1477// Asserts that an operation has already been sign-extended from a specific 1478// type. 1479def G_ASSERT_SEXT : GenericInstruction { 1480 let OutOperandList = (outs type0:$dst); 1481 let InOperandList = (ins type0:$src, untyped_imm_0:$sz); 1482 let hasSideEffects = false; 1483} 1484 1485// Asserts that a value has at least the given alignment. 1486def G_ASSERT_ALIGN : GenericInstruction { 1487 let OutOperandList = (outs type0:$dst); 1488 let InOperandList = (ins type0:$src, untyped_imm_0:$align); 1489 let hasSideEffects = false; 1490} 1491 1492// Prevent constant folding of the source value with any users. 1493def G_CONSTANT_FOLD_BARRIER : GenericInstruction { 1494 let OutOperandList = (outs type0:$dst); 1495 let InOperandList = (ins type0:$src); 1496 let hasSideEffects = false; 1497} 1498