1 //===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the generic opcodes used with GlobalISel. 11 // After instruction selection, these opcodes should not appear. 12 // 13 //===----------------------------------------------------------------------===// 14 15 //------------------------------------------------------------------------------ 16 // Unary ops. 17 //------------------------------------------------------------------------------ 18 19 // Extend the underlying scalar type of an operation, leaving the high bits 20 // unspecified. 21 def G_ANYEXT : Instruction { 22 let OutOperandList = (outs type0:$dst); 23 let InOperandList = (ins type1:$src); 24 let hasSideEffects = 0; 25 } 26 27 // Sign extend the underlying scalar type of an operation, copying the sign bit 28 // into the newly-created space. 29 def G_SEXT : Instruction { 30 let OutOperandList = (outs type0:$dst); 31 let InOperandList = (ins type1:$src); 32 let hasSideEffects = 0; 33 } 34 35 // Zero extend the underlying scalar type of an operation, putting zero bits 36 // into the newly-created space. 37 def G_ZEXT : Instruction { 38 let OutOperandList = (outs type0:$dst); 39 let InOperandList = (ins type1:$src); 40 let hasSideEffects = 0; 41 } 42 43 44 // Truncate the underlying scalar type of an operation. This is equivalent to 45 // G_EXTRACT for scalar types, but acts elementwise on vectors. 46 def G_TRUNC : Instruction { 47 let OutOperandList = (outs type0:$dst); 48 let InOperandList = (ins type1:$src); 49 let hasSideEffects = 0; 50 } 51 52 def G_FRAME_INDEX : Instruction { 53 let OutOperandList = (outs type0:$dst); 54 let InOperandList = (ins unknown:$src2); 55 let hasSideEffects = 0; 56 } 57 58 def G_GLOBAL_VALUE : Instruction { 59 let OutOperandList = (outs type0:$dst); 60 let InOperandList = (ins unknown:$src); 61 let hasSideEffects = 0; 62 } 63 64 def G_INTTOPTR : Instruction { 65 let OutOperandList = (outs type0:$dst); 66 let InOperandList = (ins type1:$src); 67 let hasSideEffects = 0; 68 } 69 70 def G_PTRTOINT : Instruction { 71 let OutOperandList = (outs type0:$dst); 72 let InOperandList = (ins type1:$src); 73 let hasSideEffects = 0; 74 } 75 76 def G_BITCAST : Instruction { 77 let OutOperandList = (outs type0:$dst); 78 let InOperandList = (ins type1:$src); 79 let hasSideEffects = 0; 80 } 81 82 def G_CONSTANT : Instruction { 83 let OutOperandList = (outs type0:$dst); 84 let InOperandList = (ins unknown:$imm); 85 let hasSideEffects = 0; 86 } 87 88 def G_FCONSTANT : Instruction { 89 let OutOperandList = (outs type0:$dst); 90 let InOperandList = (ins unknown:$imm); 91 let hasSideEffects = 0; 92 } 93 94 def G_VASTART : Instruction { 95 let OutOperandList = (outs); 96 let InOperandList = (ins type0:$list); 97 let hasSideEffects = 0; 98 let mayStore = 1; 99 } 100 101 def G_VAARG : Instruction { 102 let OutOperandList = (outs type0:$val); 103 let InOperandList = (ins type1:$list, unknown:$align); 104 let hasSideEffects = 0; 105 let mayLoad = 1; 106 let mayStore = 1; 107 } 108 109 //------------------------------------------------------------------------------ 110 // Binary ops. 111 //------------------------------------------------------------------------------ 112 113 // Generic addition. 114 def G_ADD : Instruction { 115 let OutOperandList = (outs type0:$dst); 116 let InOperandList = (ins type0:$src1, type0:$src2); 117 let hasSideEffects = 0; 118 let isCommutable = 1; 119 } 120 121 // Generic subtraction. 122 def G_SUB : Instruction { 123 let OutOperandList = (outs type0:$dst); 124 let InOperandList = (ins type0:$src1, type0:$src2); 125 let hasSideEffects = 0; 126 let isCommutable = 0; 127 } 128 129 // Generic multiplication. 130 def G_MUL : Instruction { 131 let OutOperandList = (outs type0:$dst); 132 let InOperandList = (ins type0:$src1, type0:$src2); 133 let hasSideEffects = 0; 134 let isCommutable = 1; 135 } 136 137 // Generic signed division. 138 def G_SDIV : Instruction { 139 let OutOperandList = (outs type0:$dst); 140 let InOperandList = (ins type0:$src1, type0:$src2); 141 let hasSideEffects = 0; 142 let isCommutable = 0; 143 } 144 145 // Generic unsigned division. 146 def G_UDIV : Instruction { 147 let OutOperandList = (outs type0:$dst); 148 let InOperandList = (ins type0:$src1, type0:$src2); 149 let hasSideEffects = 0; 150 let isCommutable = 0; 151 } 152 153 // Generic signed remainder. 154 def G_SREM : Instruction { 155 let OutOperandList = (outs type0:$dst); 156 let InOperandList = (ins type0:$src1, type0:$src2); 157 let hasSideEffects = 0; 158 let isCommutable = 0; 159 } 160 161 // Generic unsigned remainder. 162 def G_UREM : Instruction { 163 let OutOperandList = (outs type0:$dst); 164 let InOperandList = (ins type0:$src1, type0:$src2); 165 let hasSideEffects = 0; 166 let isCommutable = 0; 167 } 168 169 // Generic bitwise and. 170 def G_AND : Instruction { 171 let OutOperandList = (outs type0:$dst); 172 let InOperandList = (ins type0:$src1, type0:$src2); 173 let hasSideEffects = 0; 174 let isCommutable = 1; 175 } 176 177 // Generic bitwise or. 178 def G_OR : Instruction { 179 let OutOperandList = (outs type0:$dst); 180 let InOperandList = (ins type0:$src1, type0:$src2); 181 let hasSideEffects = 0; 182 let isCommutable = 1; 183 } 184 185 // Generic bitwise xor. 186 def G_XOR : Instruction { 187 let OutOperandList = (outs type0:$dst); 188 let InOperandList = (ins type0:$src1, type0:$src2); 189 let hasSideEffects = 0; 190 let isCommutable = 1; 191 } 192 193 // Generic left-shift. 194 def G_SHL : Instruction { 195 let OutOperandList = (outs type0:$dst); 196 let InOperandList = (ins type0:$src1, type0:$src2); 197 let hasSideEffects = 0; 198 } 199 200 // Generic logical right-shift. 201 def G_LSHR : Instruction { 202 let OutOperandList = (outs type0:$dst); 203 let InOperandList = (ins type0:$src1, type0:$src2); 204 let hasSideEffects = 0; 205 } 206 207 // Generic arithmetic right-shift. 208 def G_ASHR : Instruction { 209 let OutOperandList = (outs type0:$dst); 210 let InOperandList = (ins type0:$src1, type0:$src2); 211 let hasSideEffects = 0; 212 } 213 214 // Generic integer comparison. 215 def G_ICMP : Instruction { 216 let OutOperandList = (outs type0:$dst); 217 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); 218 let hasSideEffects = 0; 219 } 220 221 // Generic floating-point comparison. 222 def G_FCMP : Instruction { 223 let OutOperandList = (outs type0:$dst); 224 let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); 225 let hasSideEffects = 0; 226 } 227 228 // Generic select 229 def G_SELECT : Instruction { 230 let OutOperandList = (outs type0:$dst); 231 let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2); 232 let hasSideEffects = 0; 233 } 234 235 // Generic pointer offset. 236 def G_GEP : Instruction { 237 let OutOperandList = (outs type0:$dst); 238 let InOperandList = (ins type0:$src1, type1:$src2); 239 let hasSideEffects = 0; 240 } 241 242 def G_PTR_MASK : Instruction { 243 let OutOperandList = (outs type0:$dst); 244 let InOperandList = (ins type0:$src, unknown:$bits); 245 let hasSideEffects = 0; 246 } 247 248 //------------------------------------------------------------------------------ 249 // Overflow ops 250 //------------------------------------------------------------------------------ 251 252 // Generic unsigned addition consuming and producing a carry flag. 253 def G_UADDE : Instruction { 254 let OutOperandList = (outs type0:$dst, type1:$carry_out); 255 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 256 let hasSideEffects = 0; 257 } 258 259 // Generic signed addition producing a carry flag. 260 def G_SADDO : Instruction { 261 let OutOperandList = (outs type0:$dst, type1:$carry_out); 262 let InOperandList = (ins type0:$src1, type0:$src2); 263 let hasSideEffects = 0; 264 let isCommutable = 1; 265 } 266 267 // Generic unsigned subtraction consuming and producing a carry flag. 268 def G_USUBE : Instruction { 269 let OutOperandList = (outs type0:$dst, type1:$carry_out); 270 let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); 271 let hasSideEffects = 0; 272 } 273 274 // Generic unsigned subtraction producing a carry flag. 275 def G_SSUBO : Instruction { 276 let OutOperandList = (outs type0:$dst, type1:$carry_out); 277 let InOperandList = (ins type0:$src1, type0:$src2); 278 let hasSideEffects = 0; 279 } 280 281 // Generic unsigned multiplication producing a carry flag. 282 def G_UMULO : Instruction { 283 let OutOperandList = (outs type0:$dst, type1:$carry_out); 284 let InOperandList = (ins type0:$src1, type0:$src2); 285 let hasSideEffects = 0; 286 let isCommutable = 1; 287 } 288 289 // Generic signed multiplication producing a carry flag. 290 def G_SMULO : Instruction { 291 let OutOperandList = (outs type0:$dst, type1:$carry_out); 292 let InOperandList = (ins type0:$src1, type0:$src2); 293 let hasSideEffects = 0; 294 let isCommutable = 1; 295 } 296 297 // Multiply two numbers at twice the incoming bit width (unsigned) and return 298 // the high half of the result. 299 def G_UMULH : Instruction { 300 let OutOperandList = (outs type0:$dst); 301 let InOperandList = (ins type0:$src1, type0:$src2); 302 let hasSideEffects = 0; 303 let isCommutable = 1; 304 } 305 306 // Multiply two numbers at twice the incoming bit width (signed) and return 307 // the high half of the result. 308 def G_SMULH : Instruction { 309 let OutOperandList = (outs type0:$dst); 310 let InOperandList = (ins type0:$src1, type0:$src2); 311 let hasSideEffects = 0; 312 let isCommutable = 1; 313 } 314 315 //------------------------------------------------------------------------------ 316 // Floating Point Unary Ops. 317 //------------------------------------------------------------------------------ 318 319 def G_FNEG : Instruction { 320 let OutOperandList = (outs type0:$dst); 321 let InOperandList = (ins type0:$src); 322 let hasSideEffects = 0; 323 } 324 325 def G_FPEXT : Instruction { 326 let OutOperandList = (outs type0:$dst); 327 let InOperandList = (ins type1:$src); 328 let hasSideEffects = 0; 329 } 330 331 def G_FPTRUNC : Instruction { 332 let OutOperandList = (outs type0:$dst); 333 let InOperandList = (ins type1:$src); 334 let hasSideEffects = 0; 335 } 336 337 def G_FPTOSI : Instruction { 338 let OutOperandList = (outs type0:$dst); 339 let InOperandList = (ins type1:$src); 340 let hasSideEffects = 0; 341 } 342 343 def G_FPTOUI : Instruction { 344 let OutOperandList = (outs type0:$dst); 345 let InOperandList = (ins type1:$src); 346 let hasSideEffects = 0; 347 } 348 349 def G_SITOFP : Instruction { 350 let OutOperandList = (outs type0:$dst); 351 let InOperandList = (ins type1:$src); 352 let hasSideEffects = 0; 353 } 354 355 def G_UITOFP : Instruction { 356 let OutOperandList = (outs type0:$dst); 357 let InOperandList = (ins type1:$src); 358 let hasSideEffects = 0; 359 } 360 361 //------------------------------------------------------------------------------ 362 // Floating Point Binary ops. 363 //------------------------------------------------------------------------------ 364 365 // Generic FP addition. 366 def G_FADD : Instruction { 367 let OutOperandList = (outs type0:$dst); 368 let InOperandList = (ins type0:$src1, type0:$src2); 369 let hasSideEffects = 0; 370 let isCommutable = 1; 371 } 372 373 // Generic FP subtraction. 374 def G_FSUB : Instruction { 375 let OutOperandList = (outs type0:$dst); 376 let InOperandList = (ins type0:$src1, type0:$src2); 377 let hasSideEffects = 0; 378 let isCommutable = 0; 379 } 380 381 // Generic FP multiplication. 382 def G_FMUL : Instruction { 383 let OutOperandList = (outs type0:$dst); 384 let InOperandList = (ins type0:$src1, type0:$src2); 385 let hasSideEffects = 0; 386 let isCommutable = 1; 387 } 388 389 // Generic FP division. 390 def G_FDIV : Instruction { 391 let OutOperandList = (outs type0:$dst); 392 let InOperandList = (ins type0:$src1, type0:$src2); 393 let hasSideEffects = 0; 394 } 395 396 // Generic FP remainder. 397 def G_FREM : Instruction { 398 let OutOperandList = (outs type0:$dst); 399 let InOperandList = (ins type0:$src1, type0:$src2); 400 let hasSideEffects = 0; 401 } 402 403 // Floating point exponentiation. 404 def G_FPOW : Instruction { 405 let OutOperandList = (outs type0:$dst); 406 let InOperandList = (ins type0:$src1, type0:$src2); 407 let hasSideEffects = 0; 408 } 409 410 //------------------------------------------------------------------------------ 411 // Memory ops 412 //------------------------------------------------------------------------------ 413 414 // Generic load. Expects a MachineMemOperand in addition to explicit operands. 415 def G_LOAD : Instruction { 416 let OutOperandList = (outs type0:$dst); 417 let InOperandList = (ins type1:$addr); 418 let hasSideEffects = 0; 419 let mayLoad = 1; 420 } 421 422 // Generic store. Expects a MachineMemOperand in addition to explicit operands. 423 def G_STORE : Instruction { 424 let OutOperandList = (outs); 425 let InOperandList = (ins type0:$src, type1:$addr); 426 let hasSideEffects = 0; 427 let mayStore = 1; 428 } 429 430 //------------------------------------------------------------------------------ 431 // Variadic ops 432 //------------------------------------------------------------------------------ 433 434 // Extract multiple registers specified size, starting from blocks given by 435 // indexes. This will almost certainly be mapped to sub-register COPYs after 436 // register banks have been selected. 437 def G_EXTRACT : Instruction { 438 let OutOperandList = (outs type0:$res); 439 let InOperandList = (ins type1:$src, unknown:$offset); 440 let hasSideEffects = 0; 441 } 442 443 // Extract multiple registers specified size, starting from blocks given by 444 // indexes. This will almost certainly be mapped to sub-register COPYs after 445 // register banks have been selected. 446 def G_UNMERGE_VALUES : Instruction { 447 let OutOperandList = (outs); 448 let InOperandList = (ins variable_ops); 449 let hasSideEffects = 0; 450 } 451 452 // Insert a smaller register into a larger one at the specified bit-index. 453 def G_INSERT : Instruction { 454 let OutOperandList = (outs type0:$dst); 455 let InOperandList = (ins type0:$src, type1:$op, unknown:$offset); 456 let hasSideEffects = 0; 457 } 458 459 // Combine a sequence of generic vregs into a single larger value (starting at 460 // bit 0). Essentially a G_INSERT where $src is an IMPLICIT_DEF, but it's so 461 // important to legalization it probably deserves its own instruction. 462 def G_SEQUENCE : Instruction { 463 let OutOperandList = (outs type0:$dst); 464 let InOperandList = (ins variable_ops); 465 let hasSideEffects = 0; 466 } 467 468 def G_MERGE_VALUES : Instruction { 469 let OutOperandList = (outs type0:$dst); 470 let InOperandList = (ins variable_ops); 471 let hasSideEffects = 0; 472 } 473 474 // Intrinsic without side effects. 475 def G_INTRINSIC : Instruction { 476 let OutOperandList = (outs); 477 let InOperandList = (ins unknown:$intrin, variable_ops); 478 let hasSideEffects = 0; 479 } 480 481 // Intrinsic with side effects. 482 def G_INTRINSIC_W_SIDE_EFFECTS : Instruction { 483 let OutOperandList = (outs); 484 let InOperandList = (ins unknown:$intrin, variable_ops); 485 let hasSideEffects = 1; 486 let mayLoad = 1; 487 let mayStore = 1; 488 } 489 490 //------------------------------------------------------------------------------ 491 // Branches. 492 //------------------------------------------------------------------------------ 493 494 // Generic unconditional branch. 495 def G_BR : Instruction { 496 let OutOperandList = (outs); 497 let InOperandList = (ins unknown:$src1); 498 let hasSideEffects = 0; 499 let isBranch = 1; 500 let isTerminator = 1; 501 let isBarrier = 1; 502 } 503 504 // Generic conditional branch. 505 def G_BRCOND : Instruction { 506 let OutOperandList = (outs); 507 let InOperandList = (ins type0:$tst, unknown:$truebb); 508 let hasSideEffects = 0; 509 let isBranch = 1; 510 let isTerminator = 1; 511 } 512 513 // Generic indirect branch. 514 def G_BRINDIRECT : Instruction { 515 let OutOperandList = (outs); 516 let InOperandList = (ins type0:$src1); 517 let hasSideEffects = 0; 518 let isBranch = 1; 519 let isTerminator = 1; 520 } 521 522 //------------------------------------------------------------------------------ 523 // Vector ops 524 //------------------------------------------------------------------------------ 525 526 // Generic insertelement. 527 def G_INSERT_VECTOR_ELT : Instruction { 528 let OutOperandList = (outs type0:$dst); 529 let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); 530 let hasSideEffects = 0; 531 } 532 533 // Generic extractelement. 534 def G_EXTRACT_VECTOR_ELT : Instruction { 535 let OutOperandList = (outs type0:$dst); 536 let InOperandList = (ins type1:$src, type2:$idx); 537 let hasSideEffects = 0; 538 } 539 540 // Generic shufflevector. 541 def G_SHUFFLE_VECTOR: Instruction { 542 let OutOperandList = (outs type0:$dst); 543 let InOperandList = (ins type1:$v1, type1:$v2, type2:$mask); 544 let hasSideEffects = 0; 545 } 546 547 // TODO: Add the other generic opcodes. 548