Home | History | Annotate | Download | only in Target
      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