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 minimumNumber or 799// maximumNumber on two values, following IEEE-754 definitions. This 800// differs from FMINNUM/FMAXNUM in the handling of signaling NaNs, and 801// signed zero. 802// 803// If one input is a signaling NaN, returns a quiet NaN. This matches 804// IEEE-754 2008's minnum/maxnum behavior for signaling NaNs (which 805// differs from 2019). 806// 807// These treat -0 as ordered less than +0, matching the behavior of 808// IEEE-754 2019's minimumNumber/maximumNumber. 809def G_FMINNUM_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 816def G_FMAXNUM_IEEE : GenericInstruction { 817 let OutOperandList = (outs type0:$dst); 818 let InOperandList = (ins type0:$src1, type0:$src2); 819 let hasSideEffects = false; 820 let isCommutable = true; 821} 822 823// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 824// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 825// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2019 semantics. 826def G_FMINIMUM : 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 833def G_FMAXIMUM : GenericInstruction { 834 let OutOperandList = (outs type0:$dst); 835 let InOperandList = (ins type0:$src1, type0:$src2); 836 let hasSideEffects = false; 837 let isCommutable = true; 838} 839 840//------------------------------------------------------------------------------ 841// Floating Point Binary ops. 842//------------------------------------------------------------------------------ 843 844// Generic FP addition. 845def G_FADD : GenericInstruction { 846 let OutOperandList = (outs type0:$dst); 847 let InOperandList = (ins type0:$src1, type0:$src2); 848 let hasSideEffects = false; 849 let isCommutable = true; 850} 851 852// Generic FP subtraction. 853def G_FSUB : GenericInstruction { 854 let OutOperandList = (outs type0:$dst); 855 let InOperandList = (ins type0:$src1, type0:$src2); 856 let hasSideEffects = false; 857 let isCommutable = false; 858} 859 860// Generic FP multiplication. 861def G_FMUL : GenericInstruction { 862 let OutOperandList = (outs type0:$dst); 863 let InOperandList = (ins type0:$src1, type0:$src2); 864 let hasSideEffects = false; 865 let isCommutable = true; 866} 867 868// Generic fused multiply-add instruction. 869// Behaves like llvm fma intrinsic ie src1 * src2 + src3 870def G_FMA : GenericInstruction { 871 let OutOperandList = (outs type0:$dst); 872 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); 873 let hasSideEffects = false; 874 let isCommutable = false; 875} 876 877/// Generic FP multiply and add. Perform a * b + c, while getting the 878/// same result as the separately rounded operations, unlike G_FMA. 879def G_FMAD : GenericInstruction { 880 let OutOperandList = (outs type0:$dst); 881 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); 882 let hasSideEffects = false; 883 let isCommutable = false; 884} 885 886// Generic FP division. 887def G_FDIV : GenericInstruction { 888 let OutOperandList = (outs type0:$dst); 889 let InOperandList = (ins type0:$src1, type0:$src2); 890 let hasSideEffects = false; 891} 892 893// Generic FP remainder. 894def G_FREM : 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. 901def G_FPOW : GenericInstruction { 902 let OutOperandList = (outs type0:$dst); 903 let InOperandList = (ins type0:$src1, type0:$src2); 904 let hasSideEffects = false; 905} 906 907// Floating point exponentiation, with an integer power. 908def G_FPOWI : GenericInstruction { 909 let OutOperandList = (outs type0:$dst); 910 let InOperandList = (ins type0:$src0, type1:$src1); 911 let hasSideEffects = false; 912} 913 914// Floating point base-e exponential of a value. 915def G_FEXP : GenericInstruction { 916 let OutOperandList = (outs type0:$dst); 917 let InOperandList = (ins type0:$src1); 918 let hasSideEffects = false; 919} 920 921// Floating point base-2 exponential of a value. 922def G_FEXP2 : GenericInstruction { 923 let OutOperandList = (outs type0:$dst); 924 let InOperandList = (ins type0:$src1); 925 let hasSideEffects = false; 926} 927 928// Floating point base-10 exponential of a value. 929def G_FEXP10 : GenericInstruction { 930 let OutOperandList = (outs type0:$dst); 931 let InOperandList = (ins type0:$src1); 932 let hasSideEffects = false; 933} 934 935// Floating point base-e logarithm of a value. 936def G_FLOG : GenericInstruction { 937 let OutOperandList = (outs type0:$dst); 938 let InOperandList = (ins type0:$src1); 939 let hasSideEffects = false; 940} 941 942// Floating point base-2 logarithm of a value. 943def G_FLOG2 : GenericInstruction { 944 let OutOperandList = (outs type0:$dst); 945 let InOperandList = (ins type0:$src1); 946 let hasSideEffects = false; 947} 948 949// Floating point base-10 logarithm of a value. 950def G_FLOG10 : GenericInstruction { 951 let OutOperandList = (outs type0:$dst); 952 let InOperandList = (ins type0:$src1); 953 let hasSideEffects = false; 954} 955 956// Floating point x * 2^n 957def G_FLDEXP : GenericInstruction { 958 let OutOperandList = (outs type0:$dst); 959 let InOperandList = (ins type0:$src0, type1:$src1); 960 let hasSideEffects = false; 961} 962 963// Floating point frexp 964def G_FFREXP : GenericInstruction { 965 let OutOperandList = (outs type0:$dst0, type1:$dst1); 966 let InOperandList = (ins type0:$src0); 967 let hasSideEffects = false; 968} 969 970// Floating point ceiling of a value. 971def G_FCEIL : GenericInstruction { 972 let OutOperandList = (outs type0:$dst); 973 let InOperandList = (ins type0:$src1); 974 let hasSideEffects = false; 975} 976 977// Floating point cosine of a value. 978def G_FCOS : GenericInstruction { 979 let OutOperandList = (outs type0:$dst); 980 let InOperandList = (ins type0:$src1); 981 let hasSideEffects = false; 982} 983 984// Floating point sine of a value. 985def G_FSIN : GenericInstruction { 986 let OutOperandList = (outs type0:$dst); 987 let InOperandList = (ins type0:$src1); 988 let hasSideEffects = false; 989} 990 991// Floating point tangent of a value. 992def G_FTAN : GenericInstruction { 993 let OutOperandList = (outs type0:$dst); 994 let InOperandList = (ins type0:$src1); 995 let hasSideEffects = false; 996} 997 998// Floating point square root of a value. 999// This returns NaN for negative nonzero values. 1000// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's 1001// libm-conformant. 1002def G_FSQRT : GenericInstruction { 1003 let OutOperandList = (outs type0:$dst); 1004 let InOperandList = (ins type0:$src1); 1005 let hasSideEffects = false; 1006} 1007 1008// Floating point floor of a value. 1009def G_FFLOOR : GenericInstruction { 1010 let OutOperandList = (outs type0:$dst); 1011 let InOperandList = (ins type0:$src1); 1012 let hasSideEffects = false; 1013} 1014 1015// Floating point round to next integer. 1016def G_FRINT : GenericInstruction { 1017 let OutOperandList = (outs type0:$dst); 1018 let InOperandList = (ins type0:$src1); 1019 let hasSideEffects = false; 1020} 1021 1022// Floating point round to the nearest integer. 1023def G_FNEARBYINT : GenericInstruction { 1024 let OutOperandList = (outs type0:$dst); 1025 let InOperandList = (ins type0:$src1); 1026 let hasSideEffects = false; 1027} 1028 1029//------------------------------------------------------------------------------ 1030// Access to floating-point environment. 1031//------------------------------------------------------------------------------ 1032 1033// These operations read/write floating-point environment. The interaction with 1034// it is modeled as a side effect, because constrained intrinsics use the same 1035// method. 1036 1037// Reading floating-point environment. 1038def G_GET_FPENV : GenericInstruction { 1039 let OutOperandList = (outs type0:$dst); 1040 let InOperandList = (ins); 1041 let hasSideEffects = true; 1042} 1043 1044// Setting floating-point environment. 1045def G_SET_FPENV : GenericInstruction { 1046 let OutOperandList = (outs); 1047 let InOperandList = (ins type0:$src); 1048 let hasSideEffects = true; 1049} 1050 1051// Setting default floating-point environment. 1052def G_RESET_FPENV : GenericInstruction { 1053 let OutOperandList = (outs); 1054 let InOperandList = (ins); 1055 let hasSideEffects = true; 1056} 1057 1058// Reading floating-point control modes. 1059def G_GET_FPMODE : GenericInstruction { 1060 let OutOperandList = (outs type0:$dst); 1061 let InOperandList = (ins); 1062 let hasSideEffects = true; 1063} 1064 1065// Setting floating-point control modes. 1066def G_SET_FPMODE : GenericInstruction { 1067 let OutOperandList = (outs); 1068 let InOperandList = (ins type0:$src); 1069 let hasSideEffects = true; 1070} 1071 1072// Setting floating-point control modes to default state. 1073def G_RESET_FPMODE : GenericInstruction { 1074 let OutOperandList = (outs); 1075 let InOperandList = (ins); 1076 let hasSideEffects = true; 1077} 1078 1079//------------------------------------------------------------------------------ 1080// Opcodes for LLVM Intrinsics 1081//------------------------------------------------------------------------------ 1082def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction { 1083 let OutOperandList = (outs type0:$dst); 1084 let InOperandList = (ins type1:$src1, i32imm:$round_mode); 1085 let hasSideEffects = false; 1086} 1087 1088def G_INTRINSIC_TRUNC : GenericInstruction { 1089 let OutOperandList = (outs type0:$dst); 1090 let InOperandList = (ins type0:$src1); 1091 let hasSideEffects = false; 1092} 1093 1094def G_INTRINSIC_ROUND : GenericInstruction { 1095 let OutOperandList = (outs type0:$dst); 1096 let InOperandList = (ins type0:$src1); 1097 let hasSideEffects = false; 1098} 1099 1100def G_INTRINSIC_LRINT : GenericInstruction { 1101 let OutOperandList = (outs type0:$dst); 1102 let InOperandList = (ins type1:$src); 1103 let hasSideEffects = false; 1104} 1105 1106def G_INTRINSIC_LLRINT : GenericInstruction { 1107 let OutOperandList = (outs type0:$dst); 1108 let InOperandList = (ins type1:$src); 1109 let hasSideEffects = false; 1110} 1111 1112def G_INTRINSIC_ROUNDEVEN : GenericInstruction { 1113 let OutOperandList = (outs type0:$dst); 1114 let InOperandList = (ins type0:$src1); 1115 let hasSideEffects = false; 1116} 1117 1118def G_READCYCLECOUNTER : GenericInstruction { 1119 let OutOperandList = (outs type0:$dst); 1120 let InOperandList = (ins); 1121 let hasSideEffects = true; 1122} 1123 1124def G_READSTEADYCOUNTER : GenericInstruction { 1125 let OutOperandList = (outs type0:$dst); 1126 let InOperandList = (ins); 1127 let hasSideEffects = true; 1128} 1129 1130//------------------------------------------------------------------------------ 1131// Memory ops 1132//------------------------------------------------------------------------------ 1133 1134// Generic load. Expects a MachineMemOperand in addition to explicit 1135// operands. If the result size is larger than the memory size, the 1136// high bits are undefined. If the result is a vector type and larger 1137// than the memory size, the high elements are undefined (i.e. this is 1138// not a per-element, vector anyextload) 1139def G_LOAD : GenericInstruction { 1140 let OutOperandList = (outs type0:$dst); 1141 let InOperandList = (ins ptype1:$addr); 1142 let hasSideEffects = false; 1143 let mayLoad = true; 1144} 1145 1146// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands. 1147def G_SEXTLOAD : GenericInstruction { 1148 let OutOperandList = (outs type0:$dst); 1149 let InOperandList = (ins ptype1:$addr); 1150 let hasSideEffects = false; 1151 let mayLoad = true; 1152} 1153 1154// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands. 1155def G_ZEXTLOAD : GenericInstruction { 1156 let OutOperandList = (outs type0:$dst); 1157 let InOperandList = (ins ptype1:$addr); 1158 let hasSideEffects = false; 1159 let mayLoad = true; 1160} 1161 1162// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset. 1163// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed) 1164// then the value is loaded from $newaddr. 1165def G_INDEXED_LOAD : GenericInstruction { 1166 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1167 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1168 let hasSideEffects = false; 1169 let mayLoad = true; 1170} 1171 1172// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD. 1173def G_INDEXED_SEXTLOAD : GenericInstruction { 1174 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1175 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1176 let hasSideEffects = false; 1177 let mayLoad = true; 1178} 1179 1180// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD. 1181def G_INDEXED_ZEXTLOAD : GenericInstruction { 1182 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 1183 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 1184 let hasSideEffects = false; 1185 let mayLoad = true; 1186} 1187 1188// Generic store. Expects a MachineMemOperand in addition to explicit operands. 1189def G_STORE : GenericInstruction { 1190 let OutOperandList = (outs); 1191 let InOperandList = (ins type0:$src, ptype1:$addr); 1192 let hasSideEffects = false; 1193 let mayStore = true; 1194} 1195 1196// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour. 1197def G_INDEXED_STORE : GenericInstruction { 1198 let OutOperandList = (outs ptype0:$newaddr); 1199 let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset, 1200 unknown:$am); 1201 let hasSideEffects = false; 1202 let mayStore = true; 1203} 1204 1205// Generic atomic cmpxchg with internal success check. Expects a 1206// MachineMemOperand in addition to explicit operands. 1207def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction { 1208 let OutOperandList = (outs type0:$oldval, type1:$success); 1209 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval); 1210 let hasSideEffects = false; 1211 let mayLoad = true; 1212 let mayStore = true; 1213} 1214 1215// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit 1216// operands. 1217def G_ATOMIC_CMPXCHG : GenericInstruction { 1218 let OutOperandList = (outs type0:$oldval); 1219 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval); 1220 let hasSideEffects = false; 1221 let mayLoad = true; 1222 let mayStore = true; 1223} 1224 1225// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit 1226// operands. 1227class G_ATOMICRMW_OP : GenericInstruction { 1228 let OutOperandList = (outs type0:$oldval); 1229 let InOperandList = (ins ptype1:$addr, type0:$val); 1230 let hasSideEffects = false; 1231 let mayLoad = true; 1232 let mayStore = true; 1233} 1234 1235def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP; 1236def G_ATOMICRMW_ADD : G_ATOMICRMW_OP; 1237def G_ATOMICRMW_SUB : G_ATOMICRMW_OP; 1238def G_ATOMICRMW_AND : G_ATOMICRMW_OP; 1239def G_ATOMICRMW_NAND : G_ATOMICRMW_OP; 1240def G_ATOMICRMW_OR : G_ATOMICRMW_OP; 1241def G_ATOMICRMW_XOR : G_ATOMICRMW_OP; 1242def G_ATOMICRMW_MAX : G_ATOMICRMW_OP; 1243def G_ATOMICRMW_MIN : G_ATOMICRMW_OP; 1244def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP; 1245def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP; 1246def G_ATOMICRMW_FADD : G_ATOMICRMW_OP; 1247def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP; 1248def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP; 1249def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP; 1250def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP; 1251def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP; 1252 1253def G_FENCE : GenericInstruction { 1254 let OutOperandList = (outs); 1255 let InOperandList = (ins i32imm:$ordering, i32imm:$scope); 1256 let hasSideEffects = true; 1257} 1258 1259// Generic opcode equivalent to the llvm.prefetch intrinsic. 1260def G_PREFETCH : GenericInstruction { 1261 let OutOperandList = (outs); 1262 let InOperandList = (ins ptype0:$address, i32imm:$rw, i32imm:$locality, i32imm:$cachetype); 1263 let hasSideEffects = true; 1264 let mayLoad = true; 1265 let mayStore = true; 1266} 1267 1268//------------------------------------------------------------------------------ 1269// Variadic ops 1270//------------------------------------------------------------------------------ 1271 1272// Extract a register of the specified size, starting from the block given by 1273// index. This will almost certainly be mapped to sub-register COPYs after 1274// register banks have been selected. 1275def G_EXTRACT : GenericInstruction { 1276 let OutOperandList = (outs type0:$res); 1277 let InOperandList = (ins type1:$src, untyped_imm_0:$offset); 1278 let hasSideEffects = false; 1279} 1280 1281// Extract multiple registers specified size, starting from blocks given by 1282// indexes. This will almost certainly be mapped to sub-register COPYs after 1283// register banks have been selected. 1284// The output operands are always ordered from lowest bits to highest: 1285// %bits_0_7:(s8), %bits_8_15:(s8), 1286// %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32) 1287def G_UNMERGE_VALUES : GenericInstruction { 1288 let OutOperandList = (outs type0:$dst0, variable_ops); 1289 let InOperandList = (ins type1:$src); 1290 let hasSideEffects = false; 1291 let variadicOpsType = type0; 1292} 1293 1294// Insert a smaller register into a larger one at the specified bit-index. 1295def G_INSERT : GenericInstruction { 1296 let OutOperandList = (outs type0:$dst); 1297 let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset); 1298 let hasSideEffects = false; 1299} 1300 1301// Concatenate multiple registers of the same size into a wider register. 1302// The input operands are always ordered from lowest bits to highest: 1303// %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8), 1304// %bits_16_23:(s8), %bits_24_31:(s8) 1305def G_MERGE_VALUES : GenericInstruction { 1306 let OutOperandList = (outs type0:$dst); 1307 let InOperandList = (ins type1:$src0, variable_ops); 1308 let hasSideEffects = false; 1309 let variadicOpsType = type1; 1310} 1311 1312// Generic vscale. 1313// Puts the value of the runtime vscale multiplied by the value in the source 1314// operand into the destination register. 1315def G_VSCALE : GenericInstruction { 1316 let OutOperandList = (outs type0:$dst); 1317 let InOperandList = (ins unknown:$src); 1318 let hasSideEffects = false; 1319} 1320 1321/// Create a vector from multiple scalar registers. No implicit 1322/// conversion is performed (i.e. the result element type must be the 1323/// same as all source operands) 1324def G_BUILD_VECTOR : GenericInstruction { 1325 let OutOperandList = (outs type0:$dst); 1326 let InOperandList = (ins type1:$src0, variable_ops); 1327 let hasSideEffects = false; 1328 let variadicOpsType = type1; 1329} 1330 1331/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the 1332/// destination vector elt type. 1333def G_BUILD_VECTOR_TRUNC : GenericInstruction { 1334 let OutOperandList = (outs type0:$dst); 1335 let InOperandList = (ins type1:$src0, variable_ops); 1336 let hasSideEffects = false; 1337} 1338 1339/// Create a vector by concatenating vectors together. 1340def G_CONCAT_VECTORS : GenericInstruction { 1341 let OutOperandList = (outs type0:$dst); 1342 let InOperandList = (ins type1:$src0, variable_ops); 1343 let hasSideEffects = false; 1344} 1345 1346// Intrinsic without side effects. 1347def G_INTRINSIC : GenericInstruction { 1348 let OutOperandList = (outs); 1349 let InOperandList = (ins unknown:$intrin, variable_ops); 1350 let hasSideEffects = false; 1351} 1352 1353// Intrinsic with side effects. 1354def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction { 1355 let OutOperandList = (outs); 1356 let InOperandList = (ins unknown:$intrin, variable_ops); 1357 let hasSideEffects = true; 1358 let mayLoad = true; 1359 let mayStore = true; 1360} 1361 1362// Convergent intrinsic without side effects. 1363def G_INTRINSIC_CONVERGENT : GenericInstruction { 1364 let OutOperandList = (outs); 1365 let InOperandList = (ins unknown:$intrin, variable_ops); 1366 let hasSideEffects = false; 1367 let isConvergent = true; 1368} 1369 1370// Convergent intrinsic with side effects. 1371def G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS : GenericInstruction { 1372 let OutOperandList = (outs); 1373 let InOperandList = (ins unknown:$intrin, variable_ops); 1374 let hasSideEffects = true; 1375 let mayLoad = true; 1376 let mayStore = true; 1377 let isConvergent = true; 1378} 1379 1380//------------------------------------------------------------------------------ 1381// Branches. 1382//------------------------------------------------------------------------------ 1383 1384// Generic unconditional branch. 1385def G_BR : GenericInstruction { 1386 let OutOperandList = (outs); 1387 let InOperandList = (ins unknown:$src1); 1388 let hasSideEffects = false; 1389 let isBranch = true; 1390 let isTerminator = true; 1391 let isBarrier = true; 1392} 1393 1394// Generic conditional branch. 1395def G_BRCOND : GenericInstruction { 1396 let OutOperandList = (outs); 1397 let InOperandList = (ins type0:$tst, unknown:$truebb); 1398 let hasSideEffects = false; 1399 let isBranch = true; 1400 let isTerminator = true; 1401} 1402 1403// Generic indirect branch. 1404def G_BRINDIRECT : GenericInstruction { 1405 let OutOperandList = (outs); 1406 let InOperandList = (ins type0:$src1); 1407 let hasSideEffects = false; 1408 let isBranch = true; 1409 let isTerminator = true; 1410 let isBarrier = true; 1411 let isIndirectBranch = true; 1412} 1413 1414// Generic branch to jump table entry 1415def G_BRJT : GenericInstruction { 1416 let OutOperandList = (outs); 1417 let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx); 1418 let hasSideEffects = false; 1419 let isBranch = true; 1420 let isTerminator = true; 1421 let isBarrier = true; 1422 let isIndirectBranch = true; 1423} 1424 1425// A marker to signal the following code is an invoke region, that may throw 1426// an exception and therefore not return. 1427def G_INVOKE_REGION_START : GenericInstruction { 1428 let OutOperandList = (outs); 1429 let InOperandList = (ins); 1430 let isTerminator = true; // This must be a terminator. 1431 let hasSideEffects = false; 1432} 1433 1434def G_READ_REGISTER : GenericInstruction { 1435 let OutOperandList = (outs type0:$dst); 1436 let InOperandList = (ins unknown:$register); 1437 let hasSideEffects = true; 1438 1439 // Assume convergent. It's probably not worth the effort of somehow 1440 // modeling convergent and nonconvergent register accesses. 1441 let isConvergent = true; 1442} 1443 1444def G_WRITE_REGISTER : GenericInstruction { 1445 let OutOperandList = (outs); 1446 let InOperandList = (ins unknown:$register, type0:$value); 1447 let hasSideEffects = true; 1448 1449 // Assume convergent. It's probably not worth the effort of somehow 1450 // modeling convergent and nonconvergent register accesses. 1451 let isConvergent = true; 1452} 1453 1454//------------------------------------------------------------------------------ 1455// Vector ops 1456//------------------------------------------------------------------------------ 1457 1458// Generic insert subvector. 1459def G_INSERT_SUBVECTOR : GenericInstruction { 1460 let OutOperandList = (outs type0:$dst); 1461 let InOperandList = (ins type0:$src0, type1:$src1, untyped_imm_0:$idx); 1462 let hasSideEffects = false; 1463} 1464 1465// Generic extract subvector. 1466def G_EXTRACT_SUBVECTOR : GenericInstruction { 1467 let OutOperandList = (outs type0:$dst); 1468 let InOperandList = (ins type0:$src, untyped_imm_0:$idx); 1469 let hasSideEffects = false; 1470} 1471 1472// Generic insertelement. 1473def G_INSERT_VECTOR_ELT : GenericInstruction { 1474 let OutOperandList = (outs type0:$dst); 1475 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); 1476 let hasSideEffects = false; 1477} 1478 1479// Generic extractelement. 1480def G_EXTRACT_VECTOR_ELT : GenericInstruction { 1481 let OutOperandList = (outs type0:$dst); 1482 let InOperandList = (ins type1:$src, type2:$idx); 1483 let hasSideEffects = false; 1484} 1485 1486// Generic shufflevector. 1487// 1488// The mask operand should be an IR Constant which exactly matches the 1489// corresponding mask for the IR shufflevector instruction. 1490def G_SHUFFLE_VECTOR: GenericInstruction { 1491 let OutOperandList = (outs type0:$dst); 1492 let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask); 1493 let hasSideEffects = false; 1494} 1495 1496// Generic splatvector. 1497def G_SPLAT_VECTOR: GenericInstruction { 1498 let OutOperandList = (outs type0:$dst); 1499 let InOperandList = (ins type1:$val); 1500 let hasSideEffects = false; 1501} 1502 1503//------------------------------------------------------------------------------ 1504// Vector reductions 1505//------------------------------------------------------------------------------ 1506 1507class VectorReduction : GenericInstruction { 1508 let OutOperandList = (outs type0:$dst); 1509 let InOperandList = (ins type1:$v); 1510 let hasSideEffects = false; 1511} 1512 1513def G_VECREDUCE_SEQ_FADD : GenericInstruction { 1514 let OutOperandList = (outs type0:$dst); 1515 let InOperandList = (ins type1:$acc, type2:$v); 1516 let hasSideEffects = false; 1517} 1518 1519def G_VECREDUCE_SEQ_FMUL : GenericInstruction { 1520 let OutOperandList = (outs type0:$dst); 1521 let InOperandList = (ins type1:$acc, type2:$v); 1522 let hasSideEffects = false; 1523} 1524 1525def G_VECREDUCE_FADD : VectorReduction; 1526def G_VECREDUCE_FMUL : VectorReduction; 1527 1528def G_VECREDUCE_FMAX : VectorReduction; 1529def G_VECREDUCE_FMIN : VectorReduction; 1530def G_VECREDUCE_FMAXIMUM : VectorReduction; 1531def G_VECREDUCE_FMINIMUM : VectorReduction; 1532 1533def G_VECREDUCE_ADD : VectorReduction; 1534def G_VECREDUCE_MUL : VectorReduction; 1535def G_VECREDUCE_AND : VectorReduction; 1536def G_VECREDUCE_OR : VectorReduction; 1537def G_VECREDUCE_XOR : VectorReduction; 1538def G_VECREDUCE_SMAX : VectorReduction; 1539def G_VECREDUCE_SMIN : VectorReduction; 1540def G_VECREDUCE_UMAX : VectorReduction; 1541def G_VECREDUCE_UMIN : VectorReduction; 1542 1543//------------------------------------------------------------------------------ 1544// Constrained floating point ops 1545//------------------------------------------------------------------------------ 1546 1547def G_STRICT_FADD : ConstrainedInstruction<G_FADD>; 1548def G_STRICT_FSUB : ConstrainedInstruction<G_FSUB>; 1549def G_STRICT_FMUL : ConstrainedInstruction<G_FMUL>; 1550def G_STRICT_FDIV : ConstrainedInstruction<G_FDIV>; 1551def G_STRICT_FREM : ConstrainedInstruction<G_FREM>; 1552def G_STRICT_FMA : ConstrainedInstruction<G_FMA>; 1553def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>; 1554def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>; 1555 1556//------------------------------------------------------------------------------ 1557// Memory intrinsics 1558//------------------------------------------------------------------------------ 1559 1560def G_MEMCPY : GenericInstruction { 1561 let OutOperandList = (outs); 1562 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); 1563 let hasSideEffects = false; 1564 let mayLoad = true; 1565 let mayStore = true; 1566} 1567 1568def G_MEMCPY_INLINE : GenericInstruction { 1569 let OutOperandList = (outs); 1570 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size); 1571 let hasSideEffects = false; 1572 let mayLoad = true; 1573 let mayStore = true; 1574} 1575 1576def G_MEMMOVE : GenericInstruction { 1577 let OutOperandList = (outs); 1578 let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall); 1579 let hasSideEffects = false; 1580 let mayLoad = true; 1581 let mayStore = true; 1582} 1583 1584def G_MEMSET : GenericInstruction { 1585 let OutOperandList = (outs); 1586 let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall); 1587 let hasSideEffects = false; 1588 let mayStore = true; 1589} 1590 1591def G_BZERO : GenericInstruction { 1592 let OutOperandList = (outs); 1593 let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall); 1594 let hasSideEffects = false; 1595 let mayStore = true; 1596} 1597 1598//------------------------------------------------------------------------------ 1599// Trap intrinsics 1600//------------------------------------------------------------------------------ 1601def G_TRAP : GenericInstruction { 1602 let OutOperandList = (outs); 1603 let InOperandList = (ins); 1604 let hasSideEffects = true; 1605 let mayStore = true; 1606} 1607 1608def G_DEBUGTRAP : GenericInstruction { 1609 let OutOperandList = (outs); 1610 let InOperandList = (ins); 1611 let hasSideEffects = true; 1612} 1613 1614def G_UBSANTRAP : GenericInstruction { 1615 let OutOperandList = (outs); 1616 let InOperandList = (ins i8imm:$kind); 1617 let hasSideEffects = true; 1618} 1619 1620//------------------------------------------------------------------------------ 1621// Bitfield extraction. 1622//------------------------------------------------------------------------------ 1623 1624// Generic signed bitfield extraction. The operands are in the range 1625// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. 1626def G_SBFX : GenericInstruction { 1627 let OutOperandList = (outs type0:$dst); 1628 let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); 1629 let hasSideEffects = false; 1630} 1631 1632// Generic unsigned bitfield extraction. The operands are in the range 1633// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned. 1634def G_UBFX : GenericInstruction { 1635 let OutOperandList = (outs type0:$dst); 1636 let InOperandList = (ins type0:$src, type1:$lsb, type1:$width); 1637 let hasSideEffects = false; 1638} 1639 1640//------------------------------------------------------------------------------ 1641// Optimization hints 1642//------------------------------------------------------------------------------ 1643 1644// Asserts that an operation has already been zero-extended from a specific 1645// type. 1646def G_ASSERT_ZEXT : GenericInstruction { 1647 let OutOperandList = (outs type0:$dst); 1648 let InOperandList = (ins type0:$src, untyped_imm_0:$sz); 1649 let hasSideEffects = false; 1650} 1651 1652// Asserts that an operation has already been sign-extended from a specific 1653// type. 1654def G_ASSERT_SEXT : GenericInstruction { 1655 let OutOperandList = (outs type0:$dst); 1656 let InOperandList = (ins type0:$src, untyped_imm_0:$sz); 1657 let hasSideEffects = false; 1658} 1659 1660// Asserts that a value has at least the given alignment. 1661def G_ASSERT_ALIGN : GenericInstruction { 1662 let OutOperandList = (outs type0:$dst); 1663 let InOperandList = (ins type0:$src, untyped_imm_0:$align); 1664 let hasSideEffects = false; 1665} 1666 1667// Prevent constant folding of the source value with any users. 1668def G_CONSTANT_FOLD_BARRIER : GenericInstruction { 1669 let OutOperandList = (outs type0:$dst); 1670 let InOperandList = (ins type0:$src); 1671 let hasSideEffects = false; 1672} 1673