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-2019 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 environment. 1024def G_GET_FPENV : GenericInstruction { 1025 let OutOperandList = (outs type0:$dst); 1026 let InOperandList = (ins); 1027 let hasSideEffects = true; 1028} 1029 1030// Setting floating-point environment. 1031def G_SET_FPENV : GenericInstruction { 1032 let OutOperandList = (outs); 1033 let InOperandList = (ins type0:$src); 1034 let hasSideEffects = true; 1035} 1036 1037// Setting default floating-point environment. 1038def G_RESET_FPENV : GenericInstruction { 1039 let OutOperandList = (outs); 1040 let InOperandList = (ins); 1041 let hasSideEffects = true; 1042} 1043 1044// Reading floating-point control modes. 1045def G_GET_FPMODE : GenericInstruction { 1046 let OutOperandList = (outs type0:$dst); 1047 let InOperandList = (ins); 1048 let hasSideEffects = true; 1049} 1050 1051// Setting floating-point control modes. 1052def G_SET_FPMODE : GenericInstruction { 1053 let OutOperandList = (outs); 1054 let InOperandList = (ins type0:$src); 1055 let hasSideEffects = true; 1056} 1057 1058// Setting floating-point control modes to default state. 1059def G_RESET_FPMODE : GenericInstruction { 1060 let OutOperandList = (outs); 1061 let InOperandList = (ins); 1062 let hasSideEffects = true; 1063} 1064 1065//------------------------------------------------------------------------------ 1066// Opcodes for LLVM Intrinsics 1067//------------------------------------------------------------------------------ 1068def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction { 1069 let OutOperandList = (outs type0:$dst); 1070 let InOperandList = (ins type1:$src1, i32imm:$round_mode); 1071 let hasSideEffects = false; 1072} 1073 1074def G_INTRINSIC_TRUNC : GenericInstruction { 1075 let OutOperandList = (outs type0:$dst); 1076 let InOperandList = (ins type0:$src1); 1077 let hasSideEffects = false; 1078} 1079 1080def G_INTRINSIC_ROUND : GenericInstruction { 1081 let OutOperandList = (outs type0:$dst); 1082 let InOperandList = (ins type0:$src1); 1083 let hasSideEffects = false; 1084} 1085 1086def G_INTRINSIC_LRINT : GenericInstruction { 1087 let OutOperandList = (outs type0:$dst); 1088 let InOperandList = (ins type1:$src); 1089 let hasSideEffects = false; 1090} 1091 1092def G_INTRINSIC_ROUNDEVEN : GenericInstruction { 1093 let OutOperandList = (outs type0:$dst); 1094 let InOperandList = (ins type0:$src1); 1095 let hasSideEffects = false; 1096} 1097 1098def G_READCYCLECOUNTER : GenericInstruction { 1099 let OutOperandList = (outs type0:$dst); 1100 let InOperandList = (ins); 1101 let hasSideEffects = true; 1102} 1103 1104def G_READSTEADYCOUNTER : GenericInstruction { 1105 let OutOperandList = (outs type0:$dst); 1106 let InOperandList = (ins); 1107 let hasSideEffects = true; 1108} 1109 1110//------------------------------------------------------------------------------ 1111// Memory ops 1112//------------------------------------------------------------------------------ 1113 1114// Generic load. Expects a MachineMemOperand in addition to explicit 1115// operands. If the result size is larger than the memory size, the 1116// high bits are undefined. If the result is a vector type and larger 1117// than the memory size, the high elements are undefined (i.e. this is 1118// not a per-element, vector anyextload) 1119def G_LOAD : GenericInstruction { 1120 let OutOperandList = (outs type0:$dst); 1121 let InOperandList = (ins ptype1:$addr); 1122 let hasSideEffects = false; 1123 let mayLoad = true; 1124} 1125 1126// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands. 1127def G_SEXTLOAD : GenericInstruction { 1128 let OutOperandList = (outs type0:$dst); 1129 let InOperandList = (ins ptype1:$addr); 1130 let hasSideEffects = false; 1131 let mayLoad = true; 1132} 1133 1134// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands. 1135def G_ZEXTLOAD : GenericInstruction { 1136 let OutOperandList = (outs type0:$dst); 1137 let InOperandList = (ins ptype1:$addr); 1138 let hasSideEffects = false; 1139 let mayLoad = true; 1140} 1141 1142// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset. 1143// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed) 1144// then the value is loaded from $newaddr. 1145def G_INDEXED_LOAD : GenericInstruction { 1146 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1147 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1148 let hasSideEffects = false; 1149 let mayLoad = true; 1150} 1151 1152// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD. 1153def G_INDEXED_SEXTLOAD : GenericInstruction { 1154 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1155 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1156 let hasSideEffects = false; 1157 let mayLoad = true; 1158} 1159 1160// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD. 1161def G_INDEXED_ZEXTLOAD : GenericInstruction { 1162 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1163 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1164 let hasSideEffects = false; 1165 let mayLoad = true; 1166} 1167 1168// Generic store. Expects a MachineMemOperand in addition to explicit operands. 1169def G_STORE : GenericInstruction { 1170 let OutOperandList = (outs); 1171 let InOperandList = (ins type0:$src, ptype1:$addr); 1172 let hasSideEffects = false; 1173 let mayStore = true; 1174} 1175 1176// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour. 1177def G_INDEXED_STORE : GenericInstruction { 1178 let OutOperandList = (outs ptype0:$newaddr); 1179 let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset, 1180 unknown:$am); 1181 let hasSideEffects = false; 1182 let mayStore = true; 1183} 1184 1185// Generic atomic cmpxchg with internal success check. Expects a 1186// MachineMemOperand in addition to explicit operands. 1187def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction { 1188 let OutOperandList = (outs type0:$oldval, type1:$success); 1189 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval); 1190 let hasSideEffects = false; 1191 let mayLoad = true; 1192 let mayStore = true; 1193} 1194 1195// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit 1196// operands. 1197def G_ATOMIC_CMPXCHG : GenericInstruction { 1198 let OutOperandList = (outs type0:$oldval); 1199 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval); 1200 let hasSideEffects = false; 1201 let mayLoad = true; 1202 let mayStore = true; 1203} 1204 1205// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit 1206// operands. 1207class G_ATOMICRMW_OP : GenericInstruction { 1208 let OutOperandList = (outs type0:$oldval); 1209 let InOperandList = (ins ptype1:$addr, type0:$val); 1210 let hasSideEffects = false; 1211 let mayLoad = true; 1212 let mayStore = true; 1213} 1214 1215def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP; 1216def G_ATOMICRMW_ADD : G_ATOMICRMW_OP; 1217def G_ATOMICRMW_SUB : G_ATOMICRMW_OP; 1218def G_ATOMICRMW_AND : G_ATOMICRMW_OP; 1219def G_ATOMICRMW_NAND : G_ATOMICRMW_OP; 1220def G_ATOMICRMW_OR : G_ATOMICRMW_OP; 1221def G_ATOMICRMW_XOR : G_ATOMICRMW_OP; 1222def G_ATOMICRMW_MAX : G_ATOMICRMW_OP; 1223def G_ATOMICRMW_MIN : G_ATOMICRMW_OP; 1224def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP; 1225def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP; 1226def G_ATOMICRMW_FADD : G_ATOMICRMW_OP; 1227def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP; 1228def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP; 1229def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP; 1230def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP; 1231def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP; 1232 1233def G_FENCE : GenericInstruction { 1234 let OutOperandList = (outs); 1235 let InOperandList = (ins i32imm:$ordering, i32imm:$scope); 1236 let hasSideEffects = true; 1237} 1238 1239// Generic opcode equivalent to the llvm.prefetch intrinsic. 1240def G_PREFETCH : GenericInstruction { 1241 let OutOperandList = (outs); 1242 let InOperandList = (ins ptype0:$address, i32imm:$rw, i32imm:$locality, i32imm:$cachetype); 1243 let hasSideEffects = true; 1244 let mayLoad = true; 1245 let mayStore = true; 1246} 1247 1248//------------------------------------------------------------------------------ 1249// Variadic ops 1250//------------------------------------------------------------------------------ 1251 1252// Extract a register of the specified size, starting from the block given by 1253// index. This will almost certainly be mapped to sub-register COPYs after 1254// register banks have been selected. 1255def G_EXTRACT : GenericInstruction { 1256 let OutOperandList = (outs type0:$res); 1257 let InOperandList = (ins type1:$src, untyped_imm_0:$offset); 1258 let hasSideEffects = false; 1259} 1260 1261// Extract multiple registers specified size, starting from blocks given by 1262// indexes. This will almost certainly be mapped to sub-register COPYs after 1263// register banks have been selected. 1264// The output operands are always ordered from lowest bits to highest: 1265// %bits_0_7:(s8), %bits_8_15:(s8), 1266// %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32) 1267def G_UNMERGE_VALUES : GenericInstruction { 1268 let OutOperandList = (outs type0:$dst0, variable_ops); 1269 let InOperandList = (ins type1:$src); 1270 let hasSideEffects = false; 1271 let variadicOpsType = type0; 1272} 1273 1274// Insert a smaller register into a larger one at the specified bit-index. 1275def G_INSERT : GenericInstruction { 1276 let OutOperandList = (outs type0:$dst); 1277 let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset); 1278 let hasSideEffects = false; 1279} 1280 1281// Concatenate multiple registers of the same size into a wider register. 1282// The input operands are always ordered from lowest bits to highest: 1283// %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8), 1284// %bits_16_23:(s8), %bits_24_31:(s8) 1285def G_MERGE_VALUES : GenericInstruction { 1286 let OutOperandList = (outs type0:$dst); 1287 let InOperandList = (ins type1:$src0, variable_ops); 1288 let hasSideEffects = false; 1289 let variadicOpsType = type1; 1290} 1291 1292// Generic vscale. 1293// Puts the value of the runtime vscale multiplied by the value in the source 1294// operand into the destination register. 1295def G_VSCALE : GenericInstruction { 1296 let OutOperandList = (outs type0:$dst); 1297 let InOperandList = (ins unknown:$src); 1298 let hasSideEffects = false; 1299} 1300 1301/// Create a vector from multiple scalar registers. No implicit 1302/// conversion is performed (i.e. the result element type must be the 1303/// same as all source operands) 1304def G_BUILD_VECTOR : GenericInstruction { 1305 let OutOperandList = (outs type0:$dst); 1306 let InOperandList = (ins type1:$src0, variable_ops); 1307 let hasSideEffects = false; 1308 let variadicOpsType = type1; 1309} 1310 1311/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the 1312/// destination vector elt type. 1313def G_BUILD_VECTOR_TRUNC : GenericInstruction { 1314 let OutOperandList = (outs type0:$dst); 1315 let InOperandList = (ins type1:$src0, variable_ops); 1316 let hasSideEffects = false; 1317} 1318 1319/// Create a vector by concatenating vectors together. 1320def G_CONCAT_VECTORS : GenericInstruction { 1321 let OutOperandList = (outs type0:$dst); 1322 let InOperandList = (ins type1:$src0, variable_ops); 1323 let hasSideEffects = false; 1324} 1325 1326// Intrinsic without side effects. 1327def G_INTRINSIC : GenericInstruction { 1328 let OutOperandList = (outs); 1329 let InOperandList = (ins unknown:$intrin, variable_ops); 1330 let hasSideEffects = false; 1331} 1332 1333// Intrinsic with side effects. 1334def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction { 1335 let OutOperandList = (outs); 1336 let InOperandList = (ins unknown:$intrin, variable_ops); 1337 let hasSideEffects = true; 1338 let mayLoad = true; 1339 let mayStore = true; 1340} 1341 1342// Convergent intrinsic without side effects. 1343def G_INTRINSIC_CONVERGENT : GenericInstruction { 1344 let OutOperandList = (outs); 1345 let InOperandList = (ins unknown:$intrin, variable_ops); 1346 let hasSideEffects = false; 1347 let isConvergent = true; 1348} 1349 1350// Convergent intrinsic with side effects. 1351def G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS : GenericInstruction { 1352 let OutOperandList = (outs); 1353 let InOperandList = (ins unknown:$intrin, variable_ops); 1354 let hasSideEffects = true; 1355 let mayLoad = true; 1356 let mayStore = true; 1357 let isConvergent = true; 1358} 1359 1360//------------------------------------------------------------------------------ 1361// Branches. 1362//------------------------------------------------------------------------------ 1363 1364// Generic unconditional branch. 1365def G_BR : GenericInstruction { 1366 let OutOperandList = (outs); 1367 let InOperandList = (ins unknown:$src1); 1368 let hasSideEffects = false; 1369 let isBranch = true; 1370 let isTerminator = true; 1371 let isBarrier = true; 1372} 1373 1374// Generic conditional branch. 1375def G_BRCOND : GenericInstruction { 1376 let OutOperandList = (outs); 1377 let InOperandList = (ins type0:$tst, unknown:$truebb); 1378 let hasSideEffects = false; 1379 let isBranch = true; 1380 let isTerminator = true; 1381} 1382 1383// Generic indirect branch. 1384def G_BRINDIRECT : GenericInstruction { 1385 let OutOperandList = (outs); 1386 let InOperandList = (ins type0:$src1); 1387 let hasSideEffects = false; 1388 let isBranch = true; 1389 let isTerminator = true; 1390 let isBarrier = true; 1391 let isIndirectBranch = true; 1392} 1393 1394// Generic branch to jump table entry 1395def G_BRJT : GenericInstruction { 1396 let OutOperandList = (outs); 1397 let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx); 1398 let hasSideEffects = false; 1399 let isBranch = true; 1400 let isTerminator = true; 1401 let isBarrier = true; 1402 let isIndirectBranch = true; 1403} 1404 1405// A marker to signal the following code is an invoke region, that may throw 1406// an exception and therefore not return. 1407def G_INVOKE_REGION_START : GenericInstruction { 1408 let OutOperandList = (outs); 1409 let InOperandList = (ins); 1410 let isTerminator = true; // This must be a terminator. 1411 let hasSideEffects = false; 1412} 1413 1414def G_READ_REGISTER : GenericInstruction { 1415 let OutOperandList = (outs type0:$dst); 1416 let InOperandList = (ins unknown:$register); 1417 let hasSideEffects = true; 1418 1419 // Assume convergent. It's probably not worth the effort of somehow 1420 // modeling convergent and nonconvergent register accesses. 1421 let isConvergent = true; 1422} 1423 1424def G_WRITE_REGISTER : GenericInstruction { 1425 let OutOperandList = (outs); 1426 let InOperandList = (ins unknown:$register, type0:$value); 1427 let hasSideEffects = true; 1428 1429 // Assume convergent. It's probably not worth the effort of somehow 1430 // modeling convergent and nonconvergent register accesses. 1431 let isConvergent = true; 1432} 1433 1434//------------------------------------------------------------------------------ 1435// Vector ops 1436//------------------------------------------------------------------------------ 1437 1438// Generic insert subvector. 1439def G_INSERT_SUBVECTOR : GenericInstruction { 1440 let OutOperandList = (outs type0:$dst); 1441 let InOperandList = (ins type0:$src0, type1:$src1, untyped_imm_0:$idx); 1442 let hasSideEffects = false; 1443} 1444 1445// Generic extract subvector. 1446def G_EXTRACT_SUBVECTOR : GenericInstruction { 1447 let OutOperandList = (outs type0:$dst); 1448 let InOperandList = (ins type0:$src, untyped_imm_0:$idx); 1449 let hasSideEffects = false; 1450} 1451 1452// Generic insertelement. 1453def G_INSERT_VECTOR_ELT : GenericInstruction { 1454 let OutOperandList = (outs type0:$dst); 1455 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); 1456 let hasSideEffects = false; 1457} 1458 1459// Generic extractelement. 1460def G_EXTRACT_VECTOR_ELT : GenericInstruction { 1461 let OutOperandList = (outs type0:$dst); 1462 let InOperandList = (ins type1:$src, type2:$idx); 1463 let hasSideEffects = false; 1464} 1465 1466// Generic shufflevector. 1467// 1468// The mask operand should be an IR Constant which exactly matches the 1469// corresponding mask for the IR shufflevector instruction. 1470def G_SHUFFLE_VECTOR: GenericInstruction { 1471 let OutOperandList = (outs type0:$dst); 1472 let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask); 1473 let hasSideEffects = false; 1474} 1475 1476// Generic splatvector. 1477def G_SPLAT_VECTOR: GenericInstruction { 1478 let OutOperandList = (outs type0:$dst); 1479 let InOperandList = (ins type1:$val); 1480 let hasSideEffects = false; 1481} 1482 1483//------------------------------------------------------------------------------ 1484// Vector reductions 1485//------------------------------------------------------------------------------ 1486 1487class VectorReduction : GenericInstruction { 1488 let OutOperandList = (outs type0:$dst); 1489 let InOperandList = (ins type1:$v); 1490 let hasSideEffects = false; 1491} 1492 1493def G_VECREDUCE_SEQ_FADD : GenericInstruction { 1494 let OutOperandList = (outs type0:$dst); 1495 let InOperandList = (ins type1:$acc, type2:$v); 1496 let hasSideEffects = false; 1497} 1498 1499def G_VECREDUCE_SEQ_FMUL : GenericInstruction { 1500 let OutOperandList = (outs type0:$dst); 1501 let InOperandList = (ins type1:$acc, type2:$v); 1502 let hasSideEffects = false; 1503} 1504 1505def G_VECREDUCE_FADD : VectorReduction; 1506def G_VECREDUCE_FMUL : VectorReduction; 1507 1508def G_VECREDUCE_FMAX : VectorReduction; 1509def G_VECREDUCE_FMIN : VectorReduction; 1510def G_VECREDUCE_FMAXIMUM : VectorReduction; 1511def G_VECREDUCE_FMINIMUM : VectorReduction; 1512 1513def G_VECREDUCE_ADD : VectorReduction; 1514def G_VECREDUCE_MUL : VectorReduction; 1515def G_VECREDUCE_AND : VectorReduction; 1516def G_VECREDUCE_OR : VectorReduction; 1517def G_VECREDUCE_XOR : VectorReduction; 1518def G_VECREDUCE_SMAX : VectorReduction; 1519def G_VECREDUCE_SMIN : VectorReduction; 1520def G_VECREDUCE_UMAX : VectorReduction; 1521def G_VECREDUCE_UMIN : VectorReduction; 1522 1523//------------------------------------------------------------------------------ 1524// Constrained floating point ops 1525//------------------------------------------------------------------------------ 1526 1527def G_STRICT_FADD : ConstrainedInstruction<G_FADD>; 1528def G_STRICT_FSUB : ConstrainedInstruction<G_FSUB>; 1529def G_STRICT_FMUL : ConstrainedInstruction<G_FMUL>; 1530def G_STRICT_FDIV : ConstrainedInstruction<G_FDIV>; 1531def G_STRICT_FREM : ConstrainedInstruction<G_FREM>; 1532def G_STRICT_FMA : ConstrainedInstruction<G_FMA>; 1533def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>; 1534def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>; 1535 1536//------------------------------------------------------------------------------ 1537// Memory intrinsics 1538//------------------------------------------------------------------------------ 1539 1540def G_MEMCPY : GenericInstruction { 1541 let OutOperandList = (outs); 1542 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); 1543 let hasSideEffects = false; 1544 let mayLoad = true; 1545 let mayStore = true; 1546} 1547 1548def G_MEMCPY_INLINE : GenericInstruction { 1549 let OutOperandList = (outs); 1550 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size); 1551 let hasSideEffects = false; 1552 let mayLoad = true; 1553 let mayStore = true; 1554} 1555 1556def G_MEMMOVE : GenericInstruction { 1557 let OutOperandList = (outs); 1558 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); 1559 let hasSideEffects = false; 1560 let mayLoad = true; 1561 let mayStore = true; 1562} 1563 1564def G_MEMSET : GenericInstruction { 1565 let OutOperandList = (outs); 1566 let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall); 1567 let hasSideEffects = false; 1568 let mayStore = true; 1569} 1570 1571def G_BZERO : GenericInstruction { 1572 let OutOperandList = (outs); 1573 let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall); 1574 let hasSideEffects = false; 1575 let mayStore = true; 1576} 1577 1578//------------------------------------------------------------------------------ 1579// Bitfield extraction. 1580//------------------------------------------------------------------------------ 1581 1582// Generic signed bitfield extraction. The operands are in the range 1583// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. 1584def G_SBFX : GenericInstruction { 1585 let OutOperandList = (outs type0:$dst); 1586 let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); 1587 let hasSideEffects = false; 1588} 1589 1590// Generic unsigned bitfield extraction. The operands are in the range 1591// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. 1592def G_UBFX : GenericInstruction { 1593 let OutOperandList = (outs type0:$dst); 1594 let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); 1595 let hasSideEffects = false; 1596} 1597 1598//------------------------------------------------------------------------------ 1599// Optimization hints 1600//------------------------------------------------------------------------------ 1601 1602// Asserts that an operation has already been zero-extended from a specific 1603// type. 1604def G_ASSERT_ZEXT : GenericInstruction { 1605 let OutOperandList = (outs type0:$dst); 1606 let InOperandList = (ins type0:$src, untyped_imm_0:$sz); 1607 let hasSideEffects = false; 1608} 1609 1610// Asserts that an operation has already been sign-extended from a specific 1611// type. 1612def G_ASSERT_SEXT : GenericInstruction { 1613 let OutOperandList = (outs type0:$dst); 1614 let InOperandList = (ins type0:$src, untyped_imm_0:$sz); 1615 let hasSideEffects = false; 1616} 1617 1618// Asserts that a value has at least the given alignment. 1619def G_ASSERT_ALIGN : GenericInstruction { 1620 let OutOperandList = (outs type0:$dst); 1621 let InOperandList = (ins type0:$src, untyped_imm_0:$align); 1622 let hasSideEffects = false; 1623} 1624 1625// Prevent constant folding of the source value with any users. 1626def G_CONSTANT_FOLD_BARRIER : GenericInstruction { 1627 let OutOperandList = (outs type0:$dst); 1628 let InOperandList = (ins type0:$src); 1629 let hasSideEffects = false; 1630} 1631