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