Blame | Last modification | View Log | Download | RSS feed
//===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===////// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.// See https://llvm.org/LICENSE.txt for license information.// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception////===----------------------------------------------------------------------===////// This file defines the generic opcodes used with GlobalISel.// After instruction selection, these opcodes should not appear.////===----------------------------------------------------------------------===////------------------------------------------------------------------------------// Unary ops.//------------------------------------------------------------------------------class GenericInstruction : StandardPseudoInstruction {let isPreISelOpcode = true;}// Provide a variant of an instruction with the same operands, but// different instruction flags. This is intended to provide a// convenient way to define strict floating point variants of ordinary// floating point instructions.class ConstrainedIntruction<GenericInstruction baseInst> :GenericInstruction {let OutOperandList = baseInst.OutOperandList;let InOperandList = baseInst.InOperandList;let isCommutable = baseInst.isCommutable;// TODO: Do we need a better way to mark reads from FP mode than// hasSideEffects?let hasSideEffects = true;let mayRaiseFPException = true;}// Extend the underlying scalar type of an operation, leaving the high bits// unspecified.def G_ANYEXT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}// Sign extend the underlying scalar type of an operation, copying the sign bit// into the newly-created space.def G_SEXT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}// Sign extend the a value from an arbitrary bit position, copying the sign bit// into all bits above it. This is equivalent to a shl + ashr pair with an// appropriate shift amount. $sz is an immediate (MachineOperand::isImm()// returns true) to allow targets to have some bitwidths legal and others// lowered. This opcode is particularly useful if the target has sign-extension// instructions that are cheaper than the constituent shifts as the optimizer is// able to make decisions on whether it's better to hang on to the G_SEXT_INREG// or to lower it and optimize the individual shifts.def G_SEXT_INREG : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, untyped_imm_0:$sz);let hasSideEffects = false;}// Zero extend the underlying scalar type of an operation, putting zero bits// into the newly-created space.def G_ZEXT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}// Truncate the underlying scalar type of an operation. This is equivalent to// G_EXTRACT for scalar types, but acts elementwise on vectors.def G_TRUNC : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_IMPLICIT_DEF : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins);let hasSideEffects = false;}def G_PHI : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins variable_ops);let hasSideEffects = false;}def G_FRAME_INDEX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$src2);let hasSideEffects = false;}def G_GLOBAL_VALUE : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$src);let hasSideEffects = false;}def G_INTTOPTR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_PTRTOINT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_BITCAST : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}// Only supports scalar result typesdef G_CONSTANT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$imm);let hasSideEffects = false;}// Only supports scalar result typesdef G_FCONSTANT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$imm);let hasSideEffects = false;}def G_VASTART : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins type0:$list);let hasSideEffects = false;let mayStore = true;}def G_VAARG : GenericInstruction {let OutOperandList = (outs type0:$val);let InOperandList = (ins type1:$list, unknown:$align);let hasSideEffects = false;let mayLoad = true;let mayStore = true;}def G_CTLZ : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_CTLZ_ZERO_UNDEF : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_CTTZ : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_CTTZ_ZERO_UNDEF : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_CTPOP : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_BSWAP : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src);let hasSideEffects = false;}def G_BITREVERSE : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src);let hasSideEffects = false;}def G_ADDRSPACE_CAST : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_BLOCK_ADDR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$ba);let hasSideEffects = false;}def G_JUMP_TABLE : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$jti);let hasSideEffects = false;}def G_DYN_STACKALLOC : GenericInstruction {let OutOperandList = (outs ptype0:$dst);let InOperandList = (ins type1:$size, i32imm:$align);let hasSideEffects = true;}def G_FREEZE : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src);let hasSideEffects = false;}def G_LROUND: GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_LLROUND: GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}//------------------------------------------------------------------------------// Binary ops.//------------------------------------------------------------------------------// Generic addition.def G_ADD : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic subtraction.def G_SUB : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic multiplication.def G_MUL : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic signed division.def G_SDIV : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic unsigned division.def G_UDIV : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic signed remainder.def G_SREM : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic unsigned remainder.def G_UREM : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic signed division and remainder.def G_SDIVREM : GenericInstruction {let OutOperandList = (outs type0:$div, type0:$rem);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic unsigned division and remainder.def G_UDIVREM : GenericInstruction {let OutOperandList = (outs type0:$div, type0:$rem);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic bitwise and.def G_AND : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic bitwise or.def G_OR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic bitwise xor.def G_XOR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic left-shift.def G_SHL : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type1:$src2);let hasSideEffects = false;}// Generic logical right-shift.def G_LSHR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type1:$src2);let hasSideEffects = false;}// Generic arithmetic right-shift.def G_ASHR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type1:$src2);let hasSideEffects = false;}/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount./// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth)))def G_FSHL : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);let hasSideEffects = false;}/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount./// fshr(X,Y,Z): (X << (bitwidth - (Z % bitwidth))) | (Y >> (Z % bitwidth))def G_FSHR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);let hasSideEffects = false;}/// Rotate bits right.def G_ROTR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type1:$src2);let hasSideEffects = false;}/// Rotate bits left.def G_ROTL : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type1:$src2);let hasSideEffects = false;}// Generic integer comparison.def G_ICMP : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);let hasSideEffects = false;}// Generic floating-point comparison.def G_FCMP : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);let hasSideEffects = false;}// Generic selectdef G_SELECT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);let hasSideEffects = false;}// Generic pointer offset.def G_PTR_ADD : GenericInstruction {let OutOperandList = (outs ptype0:$dst);let InOperandList = (ins ptype0:$src1, type1:$src2);let hasSideEffects = false;}// Generic pointer mask. type1 should be an integer with the same// bitwidth as the pointer type.def G_PTRMASK : GenericInstruction {let OutOperandList = (outs ptype0:$dst);let InOperandList = (ins ptype0:$src, type1:$bits);let hasSideEffects = false;}// Generic signed integer minimum.def G_SMIN : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic signed integer maximum.def G_SMAX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic unsigned integer minimum.def G_UMIN : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic unsigned integer maximum.def G_UMAX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic integer absolute value.def G_ABS : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src);let hasSideEffects = false;}//------------------------------------------------------------------------------// Overflow ops//------------------------------------------------------------------------------// Generic unsigned addition producing a carry flag.def G_UADDO : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic unsigned addition consuming and producing a carry flag.def G_UADDE : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);let hasSideEffects = false;}// Generic signed addition producing a carry flag.def G_SADDO : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic signed addition consuming and producing a carry flag.def G_SADDE : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);let hasSideEffects = false;}// Generic unsigned subtraction producing a carry flag.def G_USUBO : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;}// Generic unsigned subtraction consuming and producing a carry flag.def G_USUBE : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);let hasSideEffects = false;}// Generic signed subtraction producing a carry flag.def G_SSUBO : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;}// Generic signed subtraction consuming and producing a carry flag.def G_SSUBE : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);let hasSideEffects = false;}// Generic unsigned multiplication producing a carry flag.def G_UMULO : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic signed multiplication producing a carry flag.def G_SMULO : GenericInstruction {let OutOperandList = (outs type0:$dst, type1:$carry_out);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Multiply two numbers at twice the incoming bit width (unsigned) and return// the high half of the result.def G_UMULH : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Multiply two numbers at twice the incoming bit width (signed) and return// the high half of the result.def G_SMULH : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}//------------------------------------------------------------------------------// Saturating ops//------------------------------------------------------------------------------// Generic saturating unsigned addition.def G_UADDSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic saturating signed addition.def G_SADDSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic saturating unsigned subtraction.def G_USUBSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic saturating signed subtraction.def G_SSUBSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic saturating unsigned left shift.def G_USHLSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type1:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic saturating signed left shift.def G_SSHLSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type1:$src2);let hasSideEffects = false;let isCommutable = false;}/// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point/// multiplication on 2 integers with the same width and scale. SCALE/// represents the scale of both operands as fixed point numbers. This/// SCALE parameter must be a constant integer. A scale of zero is/// effectively performing multiplication on 2 integers.def G_SMULFIX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = true;}def G_UMULFIX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = true;}/// Same as the corresponding unsaturated fixed point instructions, but the/// result is clamped between the min and max values representable by the/// bits of the first 2 operands.def G_SMULFIXSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = true;}def G_UMULFIXSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = true;}/// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on/// 2 integers with the same width and scale. SCALE represents the scale/// of both operands as fixed point numbers. This SCALE parameter must be a/// constant integer.def G_SDIVFIX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = false;}def G_UDIVFIX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = false;}/// Same as the corresponding unsaturated fixed point instructions,/// but the result is clamped between the min and max values/// representable by the bits of the first 2 operands.def G_SDIVFIXSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = false;}def G_UDIVFIXSAT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);let hasSideEffects = false;let isCommutable = false;}//------------------------------------------------------------------------------// Floating Point Unary Ops.//------------------------------------------------------------------------------def G_FNEG : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src);let hasSideEffects = false;}def G_FPEXT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_FPTRUNC : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_FPTOSI : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_FPTOUI : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_SITOFP : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_UITOFP : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_FABS : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src);let hasSideEffects = false;}def G_FCOPYSIGN : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type1:$src1);let hasSideEffects = false;}def G_FCANONICALIZE : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src);let hasSideEffects = false;}// Generic opcode equivalent to the llvm.is_fpclass intrinsic.def G_IS_FPCLASS: GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src, unknown:$test);let hasSideEffects = false;}// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two// values.//// In the case where a single input is a NaN (either signaling or quiet),// the non-NaN input is returned.//// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.def G_FMINNUM : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}def G_FMAXNUM : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on// two values, following the IEEE-754 2008 definition. This differs from// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a// signaling NaN, returns a quiet NaN.def G_FMINNUM_IEEE : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}def G_FMAXNUM_IEEE : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.def G_FMINIMUM : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}def G_FMAXIMUM : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}//------------------------------------------------------------------------------// Floating Point Binary ops.//------------------------------------------------------------------------------// Generic FP addition.def G_FADD : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic FP subtraction.def G_FSUB : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = false;}// Generic FP multiplication.def G_FMUL : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;let isCommutable = true;}// Generic fused multiply-add instruction.// Behaves like llvm fma intrinsic ie src1 * src2 + src3def G_FMA : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);let hasSideEffects = false;let isCommutable = false;}/// Generic FP multiply and add. Perform a * b + c, while getting the/// same result as the separately rounded operations, unlike G_FMA.def G_FMAD : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);let hasSideEffects = false;let isCommutable = false;}// Generic FP division.def G_FDIV : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;}// Generic FP remainder.def G_FREM : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;}// Floating point exponentiation.def G_FPOW : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1, type0:$src2);let hasSideEffects = false;}// Floating point exponentiation, with an integer power.def G_FPOWI : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src0, type1:$src1);let hasSideEffects = false;}// Floating point base-e exponential of a value.def G_FEXP : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point base-2 exponential of a value.def G_FEXP2 : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point base-e logarithm of a value.def G_FLOG : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point base-2 logarithm of a value.def G_FLOG2 : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point base-10 logarithm of a value.def G_FLOG10 : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point ceiling of a value.def G_FCEIL : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point cosine of a value.def G_FCOS : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point sine of a value.def G_FSIN : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point square root of a value.// This returns NaN for negative nonzero values.// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's// libm-conformant.def G_FSQRT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point floor of a value.def G_FFLOOR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point round to next integer.def G_FRINT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}// Floating point round to the nearest integer.def G_FNEARBYINT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}//------------------------------------------------------------------------------// Opcodes for LLVM Intrinsics//------------------------------------------------------------------------------def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src1, i32imm:$round_mode);let hasSideEffects = false;}def G_INTRINSIC_TRUNC : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}def G_INTRINSIC_ROUND : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}def G_INTRINSIC_LRINT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src);let hasSideEffects = false;}def G_INTRINSIC_ROUNDEVEN : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src1);let hasSideEffects = false;}def G_READCYCLECOUNTER : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins);let hasSideEffects = true;}//------------------------------------------------------------------------------// Memory ops//------------------------------------------------------------------------------// Generic load. Expects a MachineMemOperand in addition to explicit// operands. If the result size is larger than the memory size, the// high bits are undefined. If the result is a vector type and larger// than the memory size, the high elements are undefined (i.e. this is// not a per-element, vector anyextload)def G_LOAD : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins ptype1:$addr);let hasSideEffects = false;let mayLoad = true;}// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.def G_SEXTLOAD : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins ptype1:$addr);let hasSideEffects = false;let mayLoad = true;}// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.def G_ZEXTLOAD : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins ptype1:$addr);let hasSideEffects = false;let mayLoad = true;}// Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.// If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)// then the value is loaded from $newaddr.def G_INDEXED_LOAD : GenericInstruction {let OutOperandList = (outs type0:$dst, ptype1:$newaddr);let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);let hasSideEffects = false;let mayLoad = true;}// Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.def G_INDEXED_SEXTLOAD : GenericInstruction {let OutOperandList = (outs type0:$dst, ptype1:$newaddr);let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);let hasSideEffects = false;let mayLoad = true;}// Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.def G_INDEXED_ZEXTLOAD : GenericInstruction {let OutOperandList = (outs type0:$dst, ptype1:$newaddr);let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);let hasSideEffects = false;let mayLoad = true;}// Generic store. Expects a MachineMemOperand in addition to explicit operands.def G_STORE : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins type0:$src, ptype1:$addr);let hasSideEffects = false;let mayStore = true;}// Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.def G_INDEXED_STORE : GenericInstruction {let OutOperandList = (outs ptype0:$newaddr);let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,unknown:$am);let hasSideEffects = false;let mayStore = true;}// Generic atomic cmpxchg with internal success check. Expects a// MachineMemOperand in addition to explicit operands.def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {let OutOperandList = (outs type0:$oldval, type1:$success);let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);let hasSideEffects = false;let mayLoad = true;let mayStore = true;}// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit// operands.def G_ATOMIC_CMPXCHG : GenericInstruction {let OutOperandList = (outs type0:$oldval);let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);let hasSideEffects = false;let mayLoad = true;let mayStore = true;}// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit// operands.class G_ATOMICRMW_OP : GenericInstruction {let OutOperandList = (outs type0:$oldval);let InOperandList = (ins ptype1:$addr, type0:$val);let hasSideEffects = false;let mayLoad = true;let mayStore = true;}def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;def G_ATOMICRMW_AND : G_ATOMICRMW_OP;def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;def G_ATOMICRMW_OR : G_ATOMICRMW_OP;def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP;def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP;def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP;def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP;def G_FENCE : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins i32imm:$ordering, i32imm:$scope);let hasSideEffects = true;}//------------------------------------------------------------------------------// Variadic ops//------------------------------------------------------------------------------// Extract a register of the specified size, starting from the block given by// index. This will almost certainly be mapped to sub-register COPYs after// register banks have been selected.def G_EXTRACT : GenericInstruction {let OutOperandList = (outs type0:$res);let InOperandList = (ins type1:$src, untyped_imm_0:$offset);let hasSideEffects = false;}// Extract multiple registers specified size, starting from blocks given by// indexes. This will almost certainly be mapped to sub-register COPYs after// register banks have been selected.// The output operands are always ordered from lowest bits to highest:// %bits_0_7:(s8), %bits_8_15:(s8),// %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)def G_UNMERGE_VALUES : GenericInstruction {let OutOperandList = (outs type0:$dst0, variable_ops);let InOperandList = (ins type1:$src);let hasSideEffects = false;}// Insert a smaller register into a larger one at the specified bit-index.def G_INSERT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);let hasSideEffects = false;}// Concatenate multiple registers of the same size into a wider register.// The input operands are always ordered from lowest bits to highest:// %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),// %bits_16_23:(s8), %bits_24_31:(s8)def G_MERGE_VALUES : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src0, variable_ops);let hasSideEffects = false;}/// Create a vector from multiple scalar registers. No implicit/// conversion is performed (i.e. the result element type must be the/// same as all source operands)def G_BUILD_VECTOR : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src0, variable_ops);let hasSideEffects = false;}/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the/// destination vector elt type.def G_BUILD_VECTOR_TRUNC : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src0, variable_ops);let hasSideEffects = false;}/// Create a vector by concatenating vectors together.def G_CONCAT_VECTORS : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src0, variable_ops);let hasSideEffects = false;}// Intrinsic without side effects.def G_INTRINSIC : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins unknown:$intrin, variable_ops);let hasSideEffects = false;// Conservatively assume this is convergent. If there turnes out to// be a need, there should be separate convergent intrinsic opcodes.let isConvergent = 1;}// Intrinsic with side effects.def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins unknown:$intrin, variable_ops);let hasSideEffects = true;let mayLoad = true;let mayStore = true;// Conservatively assume this is convergent. If there turnes out to// be a need, there should be separate convergent intrinsic opcodes.let isConvergent = true;}//------------------------------------------------------------------------------// Branches.//------------------------------------------------------------------------------// Generic unconditional branch.def G_BR : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins unknown:$src1);let hasSideEffects = false;let isBranch = true;let isTerminator = true;let isBarrier = true;}// Generic conditional branch.def G_BRCOND : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins type0:$tst, unknown:$truebb);let hasSideEffects = false;let isBranch = true;let isTerminator = true;}// Generic indirect branch.def G_BRINDIRECT : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins type0:$src1);let hasSideEffects = false;let isBranch = true;let isTerminator = true;let isBarrier = true;let isIndirectBranch = true;}// Generic branch to jump table entrydef G_BRJT : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);let hasSideEffects = false;let isBranch = true;let isTerminator = true;let isBarrier = true;let isIndirectBranch = true;}// A marker to signal the following code is an invoke region, that may throw// an exception and therefore not return.def G_INVOKE_REGION_START : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins);let isTerminator = true; // This must be a terminator.let hasSideEffects = false;}def G_READ_REGISTER : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins unknown:$register);let hasSideEffects = true;// Assume convergent. It's probably not worth the effort of somehow// modeling convergent and nonconvergent register accesses.let isConvergent = true;}def G_WRITE_REGISTER : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins unknown:$register, type0:$value);let hasSideEffects = true;// Assume convergent. It's probably not worth the effort of somehow// modeling convergent and nonconvergent register accesses.let isConvergent = true;}//------------------------------------------------------------------------------// Vector ops//------------------------------------------------------------------------------// Generic insertelement.def G_INSERT_VECTOR_ELT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);let hasSideEffects = false;}// Generic extractelement.def G_EXTRACT_VECTOR_ELT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$src, type2:$idx);let hasSideEffects = false;}// Generic shufflevector.//// The mask operand should be an IR Constant which exactly matches the// corresponding mask for the IR shufflevector instruction.def G_SHUFFLE_VECTOR: GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);let hasSideEffects = false;}//------------------------------------------------------------------------------// Vector reductions//------------------------------------------------------------------------------class VectorReduction : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$v);let hasSideEffects = false;}def G_VECREDUCE_SEQ_FADD : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$acc, type2:$v);let hasSideEffects = false;}def G_VECREDUCE_SEQ_FMUL : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type1:$acc, type2:$v);let hasSideEffects = false;}def G_VECREDUCE_FADD : VectorReduction;def G_VECREDUCE_FMUL : VectorReduction;def G_VECREDUCE_FMAX : VectorReduction;def G_VECREDUCE_FMIN : VectorReduction;def G_VECREDUCE_ADD : VectorReduction;def G_VECREDUCE_MUL : VectorReduction;def G_VECREDUCE_AND : VectorReduction;def G_VECREDUCE_OR : VectorReduction;def G_VECREDUCE_XOR : VectorReduction;def G_VECREDUCE_SMAX : VectorReduction;def G_VECREDUCE_SMIN : VectorReduction;def G_VECREDUCE_UMAX : VectorReduction;def G_VECREDUCE_UMIN : VectorReduction;//------------------------------------------------------------------------------// Constrained floating point ops//------------------------------------------------------------------------------def G_STRICT_FADD : ConstrainedIntruction<G_FADD>;def G_STRICT_FSUB : ConstrainedIntruction<G_FSUB>;def G_STRICT_FMUL : ConstrainedIntruction<G_FMUL>;def G_STRICT_FDIV : ConstrainedIntruction<G_FDIV>;def G_STRICT_FREM : ConstrainedIntruction<G_FREM>;def G_STRICT_FMA : ConstrainedIntruction<G_FMA>;def G_STRICT_FSQRT : ConstrainedIntruction<G_FSQRT>;//------------------------------------------------------------------------------// Memory intrinsics//------------------------------------------------------------------------------def G_MEMCPY : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);let hasSideEffects = false;let mayLoad = true;let mayStore = true;}def G_MEMCPY_INLINE : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size);let hasSideEffects = false;let mayLoad = true;let mayStore = true;}def G_MEMMOVE : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);let hasSideEffects = false;let mayLoad = true;let mayStore = true;}def G_MEMSET : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);let hasSideEffects = false;let mayStore = true;}def G_BZERO : GenericInstruction {let OutOperandList = (outs);let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall);let hasSideEffects = false;let mayStore = true;}//------------------------------------------------------------------------------// Bitfield extraction.//------------------------------------------------------------------------------// Generic signed bitfield extraction. The operands are in the range// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.def G_SBFX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);let hasSideEffects = false;}// Generic unsigned bitfield extraction. The operands are in the range// 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.def G_UBFX : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);let hasSideEffects = false;}//------------------------------------------------------------------------------// Optimization hints//------------------------------------------------------------------------------// Asserts that an operation has already been zero-extended from a specific// type.def G_ASSERT_ZEXT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, untyped_imm_0:$sz);let hasSideEffects = false;}// Asserts that an operation has already been sign-extended from a specific// type.def G_ASSERT_SEXT : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, untyped_imm_0:$sz);let hasSideEffects = false;}// Asserts that a value has at least the given alignment.def G_ASSERT_ALIGN : GenericInstruction {let OutOperandList = (outs type0:$dst);let InOperandList = (ins type0:$src, untyped_imm_0:$align);let hasSideEffects = false;}