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 = 1; 20} 21 22// Extend the underlying scalar type of an operation, leaving the high bits 23// unspecified. 24def G_ANYEXT : GenericInstruction { 25 let OutOperandList = (outs type0:$dst); 26 let InOperandList = (ins type1:$src); 27 let hasSideEffects = 0; 28} 29 30// Sign extend the underlying scalar type of an operation, copying the sign bit 31// into the newly-created space. 32def G_SEXT : GenericInstruction { 33 let OutOperandList = (outs type0:$dst); 34 let InOperandList = (ins type1:$src); 35 let hasSideEffects = 0; 36} 37 38// Sign extend the a value from an arbitrary bit position, copying the sign bit 39// into all bits above it. This is equivalent to a shl + ashr pair with an 40// appropriate shift amount. $sz is an immediate (MachineOperand::isImm() 41// returns true) to allow targets to have some bitwidths legal and others 42// lowered. This opcode is particularly useful if the target has sign-extension 43// instructions that are cheaper than the constituent shifts as the optimizer is 44// able to make decisions on whether it's better to hang on to the G_SEXT_INREG 45// or to lower it and optimize the individual shifts. 46def G_SEXT_INREG : GenericInstruction { 47 let OutOperandList = (outs type0:$dst); 48 let InOperandList = (ins type0:$src, untyped_imm_0:$sz); 49 let hasSideEffects = 0; 50} 51 52// Zero extend the underlying scalar type of an operation, putting zero bits 53// into the newly-created space. 54def G_ZEXT : GenericInstruction { 55 let OutOperandList = (outs type0:$dst); 56 let InOperandList = (ins type1:$src); 57 let hasSideEffects = 0; 58} 59 60 61// Truncate the underlying scalar type of an operation. This is equivalent to 62// G_EXTRACT for scalar types, but acts elementwise on vectors. 63def G_TRUNC : GenericInstruction { 64 let OutOperandList = (outs type0:$dst); 65 let InOperandList = (ins type1:$src); 66 let hasSideEffects = 0; 67} 68 69def G_IMPLICIT_DEF : GenericInstruction { 70 let OutOperandList = (outs type0:$dst); 71 let InOperandList = (ins); 72 let hasSideEffects = 0; 73} 74 75def G_PHI : GenericInstruction { 76 let OutOperandList = (outs type0:$dst); 77 let InOperandList = (ins variable_ops); 78 let hasSideEffects = 0; 79} 80 81def G_FRAME_INDEX : GenericInstruction { 82 let OutOperandList = (outs type0:$dst); 83 let InOperandList = (ins unknown:$src2); 84 let hasSideEffects = 0; 85} 86 87def G_GLOBAL_VALUE : GenericInstruction { 88 let OutOperandList = (outs type0:$dst); 89 let InOperandList = (ins unknown:$src); 90 let hasSideEffects = 0; 91} 92 93def G_INTTOPTR : GenericInstruction { 94 let OutOperandList = (outs type0:$dst); 95 let InOperandList = (ins type1:$src); 96 let hasSideEffects = 0; 97} 98 99def G_PTRTOINT : GenericInstruction { 100 let OutOperandList = (outs type0:$dst); 101 let InOperandList = (ins type1:$src); 102 let hasSideEffects = 0; 103} 104 105def G_BITCAST : GenericInstruction { 106 let OutOperandList = (outs type0:$dst); 107 let InOperandList = (ins type1:$src); 108 let hasSideEffects = 0; 109} 110 111// Only supports scalar result types 112def G_CONSTANT : GenericInstruction { 113 let OutOperandList = (outs type0:$dst); 114 let InOperandList = (ins unknown:$imm); 115 let hasSideEffects = 0; 116} 117 118// Only supports scalar result types 119def G_FCONSTANT : GenericInstruction { 120 let OutOperandList = (outs type0:$dst); 121 let InOperandList = (ins unknown:$imm); 122 let hasSideEffects = 0; 123} 124 125def G_VASTART : GenericInstruction { 126 let OutOperandList = (outs); 127 let InOperandList = (ins type0:$list); 128 let hasSideEffects = 0; 129 let mayStore = 1; 130} 131 132def G_VAARG : GenericInstruction { 133 let OutOperandList = (outs type0:$val); 134 let InOperandList = (ins type1:$list, unknown:$align); 135 let hasSideEffects = 0; 136 let mayLoad = 1; 137 let mayStore = 1; 138} 139 140def G_CTLZ : GenericInstruction { 141 let OutOperandList = (outs type0:$dst); 142 let InOperandList = (ins type1:$src); 143 let hasSideEffects = 0; 144} 145 146def G_CTLZ_ZERO_UNDEF : GenericInstruction { 147 let OutOperandList = (outs type0:$dst); 148 let InOperandList = (ins type1:$src); 149 let hasSideEffects = 0; 150} 151 152def G_CTTZ : GenericInstruction { 153 let OutOperandList = (outs type0:$dst); 154 let InOperandList = (ins type1:$src); 155 let hasSideEffects = 0; 156} 157 158def G_CTTZ_ZERO_UNDEF : GenericInstruction { 159 let OutOperandList = (outs type0:$dst); 160 let InOperandList = (ins type1:$src); 161 let hasSideEffects = 0; 162} 163 164def G_CTPOP : GenericInstruction { 165 let OutOperandList = (outs type0:$dst); 166 let InOperandList = (ins type1:$src); 167 let hasSideEffects = 0; 168} 169 170def G_BSWAP : GenericInstruction { 171 let OutOperandList = (outs type0:$dst); 172 let InOperandList = (ins type0:$src); 173 let hasSideEffects = 0; 174} 175 176def G_BITREVERSE : GenericInstruction { 177 let OutOperandList = (outs type0:$dst); 178 let InOperandList = (ins type0:$src); 179 let hasSideEffects = 0; 180} 181 182def G_ADDRSPACE_CAST : GenericInstruction { 183 let OutOperandList = (outs type0:$dst); 184 let InOperandList = (ins type1:$src); 185 let hasSideEffects = 0; 186} 187 188def G_BLOCK_ADDR : GenericInstruction { 189 let OutOperandList = (outs type0:$dst); 190 let InOperandList = (ins unknown:$ba); 191 let hasSideEffects = 0; 192} 193 194def G_JUMP_TABLE : GenericInstruction { 195 let OutOperandList = (outs type0:$dst); 196 let InOperandList = (ins unknown:$jti); 197 let hasSideEffects = 0; 198} 199 200def G_DYN_STACKALLOC : GenericInstruction { 201 let OutOperandList = (outs ptype0:$dst); 202 let InOperandList = (ins type1:$size, i32imm:$align); 203 let hasSideEffects = 1; 204} 205 206//------------------------------------------------------------------------------ 207// Binary ops. 208//------------------------------------------------------------------------------ 209 210// Generic addition. 211def G_ADD : GenericInstruction { 212 let OutOperandList = (outs type0:$dst); 213 let InOperandList = (ins type0:$src1, type0:$src2); 214 let hasSideEffects = 0; 215 let isCommutable = 1; 216} 217 218// Generic subtraction. 219def G_SUB : GenericInstruction { 220 let OutOperandList = (outs type0:$dst); 221 let InOperandList = (ins type0:$src1, type0:$src2); 222 let hasSideEffects = 0; 223 let isCommutable = 0; 224} 225 226// Generic multiplication. 227def G_MUL : GenericInstruction { 228 let OutOperandList = (outs type0:$dst); 229 let InOperandList = (ins type0:$src1, type0:$src2); 230 let hasSideEffects = 0; 231 let isCommutable = 1; 232} 233 234// Generic signed division. 235def G_SDIV : GenericInstruction { 236 let OutOperandList = (outs type0:$dst); 237 let InOperandList = (ins type0:$src1, type0:$src2); 238 let hasSideEffects = 0; 239 let isCommutable = 0; 240} 241 242// Generic unsigned division. 243def G_UDIV : GenericInstruction { 244 let OutOperandList = (outs type0:$dst); 245 let InOperandList = (ins type0:$src1, type0:$src2); 246 let hasSideEffects = 0; 247 let isCommutable = 0; 248} 249 250// Generic signed remainder. 251def G_SREM : GenericInstruction { 252 let OutOperandList = (outs type0:$dst); 253 let InOperandList = (ins type0:$src1, type0:$src2); 254 let hasSideEffects = 0; 255 let isCommutable = 0; 256} 257 258// Generic unsigned remainder. 259def G_UREM : GenericInstruction { 260 let OutOperandList = (outs type0:$dst); 261 let InOperandList = (ins type0:$src1, type0:$src2); 262 let hasSideEffects = 0; 263 let isCommutable = 0; 264} 265 266// Generic bitwise and. 267def G_AND : GenericInstruction { 268 let OutOperandList = (outs type0:$dst); 269 let InOperandList = (ins type0:$src1, type0:$src2); 270 let hasSideEffects = 0; 271 let isCommutable = 1; 272} 273 274// Generic bitwise or. 275def G_OR : GenericInstruction { 276 let OutOperandList = (outs type0:$dst); 277 let InOperandList = (ins type0:$src1, type0:$src2); 278 let hasSideEffects = 0; 279 let isCommutable = 1; 280} 281 282// Generic bitwise xor. 283def G_XOR : GenericInstruction { 284 let OutOperandList = (outs type0:$dst); 285 let InOperandList = (ins type0:$src1, type0:$src2); 286 let hasSideEffects = 0; 287 let isCommutable = 1; 288} 289 290// Generic left-shift. 291def G_SHL : GenericInstruction { 292 let OutOperandList = (outs type0:$dst); 293 let InOperandList = (ins type0:$src1, type1:$src2); 294 let hasSideEffects = 0; 295} 296 297// Generic logical right-shift. 298def G_LSHR : GenericInstruction { 299 let OutOperandList = (outs type0:$dst); 300 let InOperandList = (ins type0:$src1, type1:$src2); 301 let hasSideEffects = 0; 302} 303 304// Generic arithmetic right-shift. 305def G_ASHR : GenericInstruction { 306 let OutOperandList = (outs type0:$dst); 307 let InOperandList = (ins type0:$src1, type1:$src2); 308 let hasSideEffects = 0; 309} 310 311// Generic integer comparison. 312def G_ICMP : GenericInstruction { 313 let OutOperandList = (outs type0:$dst); 314 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); 315 let hasSideEffects = 0; 316} 317 318// Generic floating-point comparison. 319def G_FCMP : GenericInstruction { 320 let OutOperandList = (outs type0:$dst); 321 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); 322 let hasSideEffects = 0; 323} 324 325// Generic select 326def G_SELECT : GenericInstruction { 327 let OutOperandList = (outs type0:$dst); 328 let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2); 329 let hasSideEffects = 0; 330} 331 332// Generic pointer offset. 333def G_PTR_ADD : GenericInstruction { 334 let OutOperandList = (outs type0:$dst); 335 let InOperandList = (ins type0:$src1, type1:$src2); 336 let hasSideEffects = 0; 337} 338 339def G_PTR_MASK : GenericInstruction { 340 let OutOperandList = (outs type0:$dst); 341 let InOperandList = (ins type0:$src, unknown:$bits); 342 let hasSideEffects = 0; 343} 344 345// Generic signed integer minimum. 346def G_SMIN : GenericInstruction { 347 let OutOperandList = (outs type0:$dst); 348 let InOperandList = (ins type0:$src1, type0:$src2); 349 let hasSideEffects = 0; 350 let isCommutable = 1; 351} 352 353// Generic signed integer maximum. 354def G_SMAX : GenericInstruction { 355 let OutOperandList = (outs type0:$dst); 356 let InOperandList = (ins type0:$src1, type0:$src2); 357 let hasSideEffects = 0; 358 let isCommutable = 1; 359} 360 361// Generic unsigned integer minimum. 362def G_UMIN : GenericInstruction { 363 let OutOperandList = (outs type0:$dst); 364 let InOperandList = (ins type0:$src1, type0:$src2); 365 let hasSideEffects = 0; 366 let isCommutable = 1; 367} 368 369// Generic unsigned integer maximum. 370def G_UMAX : GenericInstruction { 371 let OutOperandList = (outs type0:$dst); 372 let InOperandList = (ins type0:$src1, type0:$src2); 373 let hasSideEffects = 0; 374 let isCommutable = 1; 375} 376 377//------------------------------------------------------------------------------ 378// Overflow ops 379//------------------------------------------------------------------------------ 380 381// Generic unsigned addition producing a carry flag. 382def G_UADDO : GenericInstruction { 383 let OutOperandList = (outs type0:$dst, type1:$carry_out); 384 let InOperandList = (ins type0:$src1, type0:$src2); 385 let hasSideEffects = 0; 386 let isCommutable = 1; 387} 388 389// Generic unsigned addition consuming and producing a carry flag. 390def G_UADDE : GenericInstruction { 391 let OutOperandList = (outs type0:$dst, type1:$carry_out); 392 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 393 let hasSideEffects = 0; 394} 395 396// Generic signed addition producing a carry flag. 397def G_SADDO : GenericInstruction { 398 let OutOperandList = (outs type0:$dst, type1:$carry_out); 399 let InOperandList = (ins type0:$src1, type0:$src2); 400 let hasSideEffects = 0; 401 let isCommutable = 1; 402} 403 404// Generic signed addition consuming and producing a carry flag. 405def G_SADDE : GenericInstruction { 406 let OutOperandList = (outs type0:$dst, type1:$carry_out); 407 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 408 let hasSideEffects = 0; 409} 410 411// Generic unsigned subtraction producing a carry flag. 412def G_USUBO : GenericInstruction { 413 let OutOperandList = (outs type0:$dst, type1:$carry_out); 414 let InOperandList = (ins type0:$src1, type0:$src2); 415 let hasSideEffects = 0; 416} 417// Generic unsigned subtraction consuming and producing a carry flag. 418def G_USUBE : GenericInstruction { 419 let OutOperandList = (outs type0:$dst, type1:$carry_out); 420 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 421 let hasSideEffects = 0; 422} 423 424// Generic signed subtraction producing a carry flag. 425def G_SSUBO : GenericInstruction { 426 let OutOperandList = (outs type0:$dst, type1:$carry_out); 427 let InOperandList = (ins type0:$src1, type0:$src2); 428 let hasSideEffects = 0; 429} 430 431// Generic signed subtraction consuming and producing a carry flag. 432def G_SSUBE : GenericInstruction { 433 let OutOperandList = (outs type0:$dst, type1:$carry_out); 434 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 435 let hasSideEffects = 0; 436} 437 438// Generic unsigned multiplication producing a carry flag. 439def G_UMULO : GenericInstruction { 440 let OutOperandList = (outs type0:$dst, type1:$carry_out); 441 let InOperandList = (ins type0:$src1, type0:$src2); 442 let hasSideEffects = 0; 443 let isCommutable = 1; 444} 445 446// Generic signed multiplication producing a carry flag. 447def G_SMULO : GenericInstruction { 448 let OutOperandList = (outs type0:$dst, type1:$carry_out); 449 let InOperandList = (ins type0:$src1, type0:$src2); 450 let hasSideEffects = 0; 451 let isCommutable = 1; 452} 453 454// Multiply two numbers at twice the incoming bit width (unsigned) and return 455// the high half of the result. 456def G_UMULH : GenericInstruction { 457 let OutOperandList = (outs type0:$dst); 458 let InOperandList = (ins type0:$src1, type0:$src2); 459 let hasSideEffects = 0; 460 let isCommutable = 1; 461} 462 463// Multiply two numbers at twice the incoming bit width (signed) and return 464// the high half of the result. 465def G_SMULH : GenericInstruction { 466 let OutOperandList = (outs type0:$dst); 467 let InOperandList = (ins type0:$src1, type0:$src2); 468 let hasSideEffects = 0; 469 let isCommutable = 1; 470} 471 472//------------------------------------------------------------------------------ 473// Floating Point Unary Ops. 474//------------------------------------------------------------------------------ 475 476def G_FNEG : GenericInstruction { 477 let OutOperandList = (outs type0:$dst); 478 let InOperandList = (ins type0:$src); 479 let hasSideEffects = 0; 480} 481 482def G_FPEXT : GenericInstruction { 483 let OutOperandList = (outs type0:$dst); 484 let InOperandList = (ins type1:$src); 485 let hasSideEffects = 0; 486} 487 488def G_FPTRUNC : GenericInstruction { 489 let OutOperandList = (outs type0:$dst); 490 let InOperandList = (ins type1:$src); 491 let hasSideEffects = 0; 492} 493 494def G_FPTOSI : GenericInstruction { 495 let OutOperandList = (outs type0:$dst); 496 let InOperandList = (ins type1:$src); 497 let hasSideEffects = 0; 498} 499 500def G_FPTOUI : GenericInstruction { 501 let OutOperandList = (outs type0:$dst); 502 let InOperandList = (ins type1:$src); 503 let hasSideEffects = 0; 504} 505 506def G_SITOFP : GenericInstruction { 507 let OutOperandList = (outs type0:$dst); 508 let InOperandList = (ins type1:$src); 509 let hasSideEffects = 0; 510} 511 512def G_UITOFP : GenericInstruction { 513 let OutOperandList = (outs type0:$dst); 514 let InOperandList = (ins type1:$src); 515 let hasSideEffects = 0; 516} 517 518def G_FABS : GenericInstruction { 519 let OutOperandList = (outs type0:$dst); 520 let InOperandList = (ins type0:$src); 521 let hasSideEffects = 0; 522} 523 524def G_FCOPYSIGN : GenericInstruction { 525 let OutOperandList = (outs type0:$dst); 526 let InOperandList = (ins type0:$src0, type1:$src1); 527 let hasSideEffects = 0; 528} 529 530def G_FCANONICALIZE : GenericInstruction { 531 let OutOperandList = (outs type0:$dst); 532 let InOperandList = (ins type0:$src); 533 let hasSideEffects = 0; 534} 535 536// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two 537// values. 538// 539// In the case where a single input is a NaN (either signaling or quiet), 540// the non-NaN input is returned. 541// 542// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. 543def G_FMINNUM : GenericInstruction { 544 let OutOperandList = (outs type0:$dst); 545 let InOperandList = (ins type0:$src1, type0:$src2); 546 let hasSideEffects = 0; 547 let isCommutable = 1; 548} 549 550def G_FMAXNUM : GenericInstruction { 551 let OutOperandList = (outs type0:$dst); 552 let InOperandList = (ins type0:$src1, type0:$src2); 553 let hasSideEffects = 0; 554 let isCommutable = 1; 555} 556 557// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on 558// two values, following the IEEE-754 2008 definition. This differs from 559// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a 560// signaling NaN, returns a quiet NaN. 561def G_FMINNUM_IEEE : GenericInstruction { 562 let OutOperandList = (outs type0:$dst); 563 let InOperandList = (ins type0:$src1, type0:$src2); 564 let hasSideEffects = 0; 565 let isCommutable = 1; 566} 567 568def G_FMAXNUM_IEEE : GenericInstruction { 569 let OutOperandList = (outs type0:$dst); 570 let InOperandList = (ins type0:$src1, type0:$src2); 571 let hasSideEffects = 0; 572 let isCommutable = 1; 573} 574 575// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 576// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 577// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics. 578def G_FMINIMUM : GenericInstruction { 579 let OutOperandList = (outs type0:$dst); 580 let InOperandList = (ins type0:$src1, type0:$src2); 581 let hasSideEffects = 0; 582 let isCommutable = 1; 583} 584 585def G_FMAXIMUM : GenericInstruction { 586 let OutOperandList = (outs type0:$dst); 587 let InOperandList = (ins type0:$src1, type0:$src2); 588 let hasSideEffects = 0; 589 let isCommutable = 1; 590} 591 592//------------------------------------------------------------------------------ 593// Floating Point Binary ops. 594//------------------------------------------------------------------------------ 595 596// Generic FP addition. 597def G_FADD : GenericInstruction { 598 let OutOperandList = (outs type0:$dst); 599 let InOperandList = (ins type0:$src1, type0:$src2); 600 let hasSideEffects = 0; 601 let isCommutable = 1; 602} 603 604// Generic FP subtraction. 605def G_FSUB : GenericInstruction { 606 let OutOperandList = (outs type0:$dst); 607 let InOperandList = (ins type0:$src1, type0:$src2); 608 let hasSideEffects = 0; 609 let isCommutable = 0; 610} 611 612// Generic FP multiplication. 613def G_FMUL : GenericInstruction { 614 let OutOperandList = (outs type0:$dst); 615 let InOperandList = (ins type0:$src1, type0:$src2); 616 let hasSideEffects = 0; 617 let isCommutable = 1; 618} 619 620// Generic fused multiply-add instruction. 621// Behaves like llvm fma intrinsic ie src1 * src2 + src3 622def G_FMA : GenericInstruction { 623 let OutOperandList = (outs type0:$dst); 624 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); 625 let hasSideEffects = 0; 626 let isCommutable = 0; 627} 628 629/// Generic FP multiply and add. Perform a * b + c, while getting the 630/// same result as the separately rounded operations, unlike G_FMA. 631def G_FMAD : GenericInstruction { 632 let OutOperandList = (outs type0:$dst); 633 let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); 634 let hasSideEffects = 0; 635 let isCommutable = 0; 636} 637 638// Generic FP division. 639def G_FDIV : GenericInstruction { 640 let OutOperandList = (outs type0:$dst); 641 let InOperandList = (ins type0:$src1, type0:$src2); 642 let hasSideEffects = 0; 643} 644 645// Generic FP remainder. 646def G_FREM : GenericInstruction { 647 let OutOperandList = (outs type0:$dst); 648 let InOperandList = (ins type0:$src1, type0:$src2); 649 let hasSideEffects = 0; 650} 651 652// Floating point exponentiation. 653def G_FPOW : GenericInstruction { 654 let OutOperandList = (outs type0:$dst); 655 let InOperandList = (ins type0:$src1, type0:$src2); 656 let hasSideEffects = 0; 657} 658 659// Floating point base-e exponential of a value. 660def G_FEXP : GenericInstruction { 661 let OutOperandList = (outs type0:$dst); 662 let InOperandList = (ins type0:$src1); 663 let hasSideEffects = 0; 664} 665 666// Floating point base-2 exponential of a value. 667def G_FEXP2 : GenericInstruction { 668 let OutOperandList = (outs type0:$dst); 669 let InOperandList = (ins type0:$src1); 670 let hasSideEffects = 0; 671} 672 673// Floating point base-e logarithm of a value. 674def G_FLOG : GenericInstruction { 675 let OutOperandList = (outs type0:$dst); 676 let InOperandList = (ins type0:$src1); 677 let hasSideEffects = 0; 678} 679 680// Floating point base-2 logarithm of a value. 681def G_FLOG2 : GenericInstruction { 682 let OutOperandList = (outs type0:$dst); 683 let InOperandList = (ins type0:$src1); 684 let hasSideEffects = 0; 685} 686 687// Floating point base-10 logarithm of a value. 688def G_FLOG10 : GenericInstruction { 689 let OutOperandList = (outs type0:$dst); 690 let InOperandList = (ins type0:$src1); 691 let hasSideEffects = 0; 692} 693 694// Floating point ceiling of a value. 695def G_FCEIL : GenericInstruction { 696 let OutOperandList = (outs type0:$dst); 697 let InOperandList = (ins type0:$src1); 698 let hasSideEffects = 0; 699} 700 701// Floating point cosine of a value. 702def G_FCOS : GenericInstruction { 703 let OutOperandList = (outs type0:$dst); 704 let InOperandList = (ins type0:$src1); 705 let hasSideEffects = 0; 706} 707 708// Floating point sine of a value. 709def G_FSIN : GenericInstruction { 710 let OutOperandList = (outs type0:$dst); 711 let InOperandList = (ins type0:$src1); 712 let hasSideEffects = 0; 713} 714 715// Floating point square root of a value. 716// This returns NaN for negative nonzero values. 717// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's 718// libm-conformant. 719def G_FSQRT : GenericInstruction { 720 let OutOperandList = (outs type0:$dst); 721 let InOperandList = (ins type0:$src1); 722 let hasSideEffects = 0; 723} 724 725// Floating point floor of a value. 726def G_FFLOOR : GenericInstruction { 727 let OutOperandList = (outs type0:$dst); 728 let InOperandList = (ins type0:$src1); 729 let hasSideEffects = 0; 730} 731 732// Floating point round to next integer. 733def G_FRINT : GenericInstruction { 734 let OutOperandList = (outs type0:$dst); 735 let InOperandList = (ins type0:$src1); 736 let hasSideEffects = 0; 737} 738 739// Floating point round to the nearest integer. 740def G_FNEARBYINT : GenericInstruction { 741 let OutOperandList = (outs type0:$dst); 742 let InOperandList = (ins type0:$src1); 743 let hasSideEffects = 0; 744} 745 746//------------------------------------------------------------------------------ 747// Opcodes for LLVM Intrinsics 748//------------------------------------------------------------------------------ 749def G_INTRINSIC_TRUNC : GenericInstruction { 750 let OutOperandList = (outs type0:$dst); 751 let InOperandList = (ins type0:$src1); 752 let hasSideEffects = 0; 753} 754 755def G_INTRINSIC_ROUND : GenericInstruction { 756 let OutOperandList = (outs type0:$dst); 757 let InOperandList = (ins type0:$src1); 758 let hasSideEffects = 0; 759} 760 761def G_READCYCLECOUNTER : GenericInstruction { 762 let OutOperandList = (outs type0:$dst); 763 let InOperandList = (ins); 764 let hasSideEffects = 1; 765} 766 767//------------------------------------------------------------------------------ 768// Memory ops 769//------------------------------------------------------------------------------ 770 771// Generic load. Expects a MachineMemOperand in addition to explicit 772// operands. If the result size is larger than the memory size, the 773// high bits are undefined. If the result is a vector type and larger 774// than the memory size, the high elements are undefined (i.e. this is 775// not a per-element, vector anyextload) 776def G_LOAD : GenericInstruction { 777 let OutOperandList = (outs type0:$dst); 778 let InOperandList = (ins ptype1:$addr); 779 let hasSideEffects = 0; 780 let mayLoad = 1; 781} 782 783// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands. 784def G_SEXTLOAD : GenericInstruction { 785 let OutOperandList = (outs type0:$dst); 786 let InOperandList = (ins ptype1:$addr); 787 let hasSideEffects = 0; 788 let mayLoad = 1; 789} 790 791// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands. 792def G_ZEXTLOAD : GenericInstruction { 793 let OutOperandList = (outs type0:$dst); 794 let InOperandList = (ins ptype1:$addr); 795 let hasSideEffects = 0; 796 let mayLoad = 1; 797} 798 799// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset. 800// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed) 801// then the value is loaded from $newaddr. 802def G_INDEXED_LOAD : GenericInstruction { 803 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 804 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 805 let hasSideEffects = 0; 806 let mayLoad = 1; 807} 808 809// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD. 810def G_INDEXED_SEXTLOAD : GenericInstruction { 811 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 812 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 813 let hasSideEffects = 0; 814 let mayLoad = 1; 815} 816 817// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD. 818def G_INDEXED_ZEXTLOAD : GenericInstruction { 819 let OutOperandList = (outs type0:$dst, ptype1:$newaddr); 820 let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am); 821 let hasSideEffects = 0; 822 let mayLoad = 1; 823} 824 825// Generic store. Expects a MachineMemOperand in addition to explicit operands. 826def G_STORE : GenericInstruction { 827 let OutOperandList = (outs); 828 let InOperandList = (ins type0:$src, ptype1:$addr); 829 let hasSideEffects = 0; 830 let mayStore = 1; 831} 832 833// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour. 834def G_INDEXED_STORE : GenericInstruction { 835 let OutOperandList = (outs ptype0:$newaddr); 836 let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset, 837 unknown:$am); 838 let hasSideEffects = 0; 839 let mayStore = 1; 840} 841 842// Generic atomic cmpxchg with internal success check. Expects a 843// MachineMemOperand in addition to explicit operands. 844def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction { 845 let OutOperandList = (outs type0:$oldval, type1:$success); 846 let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval); 847 let hasSideEffects = 0; 848 let mayLoad = 1; 849 let mayStore = 1; 850} 851 852// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit 853// operands. 854def G_ATOMIC_CMPXCHG : GenericInstruction { 855 let OutOperandList = (outs type0:$oldval); 856 let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval); 857 let hasSideEffects = 0; 858 let mayLoad = 1; 859 let mayStore = 1; 860} 861 862// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit 863// operands. 864class G_ATOMICRMW_OP : GenericInstruction { 865 let OutOperandList = (outs type0:$oldval); 866 let InOperandList = (ins ptype1:$addr, type0:$val); 867 let hasSideEffects = 0; 868 let mayLoad = 1; 869 let mayStore = 1; 870} 871 872def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP; 873def G_ATOMICRMW_ADD : G_ATOMICRMW_OP; 874def G_ATOMICRMW_SUB : G_ATOMICRMW_OP; 875def G_ATOMICRMW_AND : G_ATOMICRMW_OP; 876def G_ATOMICRMW_NAND : G_ATOMICRMW_OP; 877def G_ATOMICRMW_OR : G_ATOMICRMW_OP; 878def G_ATOMICRMW_XOR : G_ATOMICRMW_OP; 879def G_ATOMICRMW_MAX : G_ATOMICRMW_OP; 880def G_ATOMICRMW_MIN : G_ATOMICRMW_OP; 881def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP; 882def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP; 883def G_ATOMICRMW_FADD : G_ATOMICRMW_OP; 884def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP; 885 886def G_FENCE : GenericInstruction { 887 let OutOperandList = (outs); 888 let InOperandList = (ins i32imm:$ordering, i32imm:$scope); 889 let hasSideEffects = 1; 890} 891 892//------------------------------------------------------------------------------ 893// Variadic ops 894//------------------------------------------------------------------------------ 895 896// Extract a register of the specified size, starting from the block given by 897// index. This will almost certainly be mapped to sub-register COPYs after 898// register banks have been selected. 899def G_EXTRACT : GenericInstruction { 900 let OutOperandList = (outs type0:$res); 901 let InOperandList = (ins type1:$src, unknown:$offset); 902 let hasSideEffects = 0; 903} 904 905// Extract multiple registers specified size, starting from blocks given by 906// indexes. This will almost certainly be mapped to sub-register COPYs after 907// register banks have been selected. 908// The output operands are always ordered from lowest bits to highest: 909// %bits_0_7:(s8), %bits_8_15:(s8), 910// %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32) 911def G_UNMERGE_VALUES : GenericInstruction { 912 let OutOperandList = (outs type0:$dst0, variable_ops); 913 let InOperandList = (ins type1:$src); 914 let hasSideEffects = 0; 915} 916 917// Insert a smaller register into a larger one at the specified bit-index. 918def G_INSERT : GenericInstruction { 919 let OutOperandList = (outs type0:$dst); 920 let InOperandList = (ins type0:$src, type1:$op, unknown:$offset); 921 let hasSideEffects = 0; 922} 923 924// Concatenate multiple registers of the same size into a wider register. 925// The input operands are always ordered from lowest bits to highest: 926// %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8), 927// %bits_16_23:(s8), %bits_24_31:(s8) 928def G_MERGE_VALUES : GenericInstruction { 929 let OutOperandList = (outs type0:$dst); 930 let InOperandList = (ins type1:$src0, variable_ops); 931 let hasSideEffects = 0; 932} 933 934/// Create a vector from multiple scalar registers. No implicit 935/// conversion is performed (i.e. the result element type must be the 936/// same as all source operands) 937def G_BUILD_VECTOR : GenericInstruction { 938 let OutOperandList = (outs type0:$dst); 939 let InOperandList = (ins type1:$src0, variable_ops); 940 let hasSideEffects = 0; 941} 942 943/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the 944/// destination vector elt type. 945def G_BUILD_VECTOR_TRUNC : GenericInstruction { 946 let OutOperandList = (outs type0:$dst); 947 let InOperandList = (ins type1:$src0, variable_ops); 948 let hasSideEffects = 0; 949} 950 951/// Create a vector by concatenating vectors together. 952def G_CONCAT_VECTORS : GenericInstruction { 953 let OutOperandList = (outs type0:$dst); 954 let InOperandList = (ins type1:$src0, variable_ops); 955 let hasSideEffects = 0; 956} 957 958// Intrinsic without side effects. 959def G_INTRINSIC : GenericInstruction { 960 let OutOperandList = (outs); 961 let InOperandList = (ins unknown:$intrin, variable_ops); 962 let hasSideEffects = 0; 963} 964 965// Intrinsic with side effects. 966def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction { 967 let OutOperandList = (outs); 968 let InOperandList = (ins unknown:$intrin, variable_ops); 969 let hasSideEffects = 1; 970 let mayLoad = 1; 971 let mayStore = 1; 972} 973 974//------------------------------------------------------------------------------ 975// Branches. 976//------------------------------------------------------------------------------ 977 978// Generic unconditional branch. 979def G_BR : GenericInstruction { 980 let OutOperandList = (outs); 981 let InOperandList = (ins unknown:$src1); 982 let hasSideEffects = 0; 983 let isBranch = 1; 984 let isTerminator = 1; 985 let isBarrier = 1; 986} 987 988// Generic conditional branch. 989def G_BRCOND : GenericInstruction { 990 let OutOperandList = (outs); 991 let InOperandList = (ins type0:$tst, unknown:$truebb); 992 let hasSideEffects = 0; 993 let isBranch = 1; 994 let isTerminator = 1; 995} 996 997// Generic indirect branch. 998def G_BRINDIRECT : GenericInstruction { 999 let OutOperandList = (outs); 1000 let InOperandList = (ins type0:$src1); 1001 let hasSideEffects = 0; 1002 let isBranch = 1; 1003 let isTerminator = 1; 1004} 1005 1006// Generic branch to jump table entry 1007def G_BRJT : GenericInstruction { 1008 let OutOperandList = (outs); 1009 let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx); 1010 let hasSideEffects = 0; 1011 let isBranch = 1; 1012 let isTerminator = 1; 1013} 1014 1015def G_READ_REGISTER : GenericInstruction { 1016 let OutOperandList = (outs type0:$dst); 1017 let InOperandList = (ins unknown:$register); 1018 let hasSideEffects = 1; 1019 1020 // Assume convergent. It's probably not worth the effort of somehow 1021 // modeling convergent and nonconvergent register accesses. 1022 let isConvergent = 1; 1023} 1024 1025def G_WRITE_REGISTER : GenericInstruction { 1026 let OutOperandList = (outs); 1027 let InOperandList = (ins unknown:$register, type0:$value); 1028 let hasSideEffects = 1; 1029 1030 // Assume convergent. It's probably not worth the effort of somehow 1031 // modeling convergent and nonconvergent register accesses. 1032 let isConvergent = 1; 1033} 1034 1035//------------------------------------------------------------------------------ 1036// Vector ops 1037//------------------------------------------------------------------------------ 1038 1039// Generic insertelement. 1040def G_INSERT_VECTOR_ELT : GenericInstruction { 1041 let OutOperandList = (outs type0:$dst); 1042 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); 1043 let hasSideEffects = 0; 1044} 1045 1046// Generic extractelement. 1047def G_EXTRACT_VECTOR_ELT : GenericInstruction { 1048 let OutOperandList = (outs type0:$dst); 1049 let InOperandList = (ins type1:$src, type2:$idx); 1050 let hasSideEffects = 0; 1051} 1052 1053// Generic shufflevector. 1054// 1055// The mask operand should be an IR Constant which exactly matches the 1056// corresponding mask for the IR shufflevector instruction. 1057def G_SHUFFLE_VECTOR: GenericInstruction { 1058 let OutOperandList = (outs type0:$dst); 1059 let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask); 1060 let hasSideEffects = 0; 1061} 1062 1063// TODO: Add the other generic opcodes. 1064