diff --git a/llvm/lib/Target/X86/X86Instr3DNow.td b/llvm/lib/Target/X86/X86Instr3DNow.td index d5651b6776957..3be03ab0f4332 100644 --- a/llvm/lib/Target/X86/X86Instr3DNow.td +++ b/llvm/lib/Target/X86/X86Instr3DNow.td @@ -79,16 +79,6 @@ let SchedRW = [WriteEMMS], def FEMMS : I3DNow<0x0E, RawFrm, (outs), (ins), "femms", [(int_x86_mmx_femms)]>, TB; -// PREFETCHWT1 is supported we want to use it for everything but T0. -def PrefetchWLevel : PatFrag<(ops), (i32 timm), [{ - return N->getSExtValue() == 3 || !Subtarget->hasPREFETCHWT1(); -}]>; - -// Use PREFETCHWT1 for NTA, T2, T1. -def PrefetchWT1Level : TImmLeaf; - let SchedRW = [WriteLoad] in { let Predicates = [Has3DNow, NoSSEPrefetch] in def PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i8mem:$addr), diff --git a/llvm/lib/Target/X86/X86InstrAVX512.td b/llvm/lib/Target/X86/X86InstrAVX512.td index 77b359e84fbd2..5eb893a82fcc7 100644 --- a/llvm/lib/Target/X86/X86InstrAVX512.td +++ b/llvm/lib/Target/X86/X86InstrAVX512.td @@ -12,194 +12,6 @@ // //===----------------------------------------------------------------------===// -// Group template arguments that can be derived from the vector type (EltNum x -// EltVT). These are things like the register class for the writemask, etc. -// The idea is to pass one of these as the template argument rather than the -// individual arguments. -// The template is also used for scalar types, in this case numelts is 1. -class X86VectorVTInfo { - RegisterClass RC = rc; - ValueType EltVT = eltvt; - int NumElts = numelts; - - // Corresponding mask register class. - RegisterClass KRC = !cast("VK" # NumElts); - - // Corresponding mask register pair class. - RegisterOperand KRPC = !if (!gt(NumElts, 16), ?, - !cast("VK" # NumElts # "Pair")); - - // Corresponding write-mask register class. - RegisterClass KRCWM = !cast("VK" # NumElts # "WM"); - - // The mask VT. - ValueType KVT = !cast("v" # NumElts # "i1"); - - // Suffix used in the instruction mnemonic. - string Suffix = suffix; - - // VTName is a string name for vector VT. For vector types it will be - // v # NumElts # EltVT, so for vector of 8 elements of i32 it will be v8i32 - // It is a little bit complex for scalar types, where NumElts = 1. - // In this case we build v4f32 or v2f64 - string VTName = "v" # !if (!eq (NumElts, 1), - !if (!eq (EltVT.Size, 16), 8, - !if (!eq (EltVT.Size, 32), 4, - !if (!eq (EltVT.Size, 64), 2, NumElts))), NumElts) # EltVT; - - // The vector VT. - ValueType VT = !cast(VTName); - - string EltTypeName = !cast(EltVT); - // Size of the element type in bits, e.g. 32 for v16i32. - string EltSizeName = !subst("i", "", !subst("f", "", !subst("b", "", EltTypeName))); - int EltSize = EltVT.Size; - - // "i" for integer types and "f" for floating-point types - string TypeVariantName = !subst("b", "", !subst(EltSizeName, "", EltTypeName)); - - // Size of RC in bits, e.g. 512 for VR512. - int Size = VT.Size; - - // The corresponding memory operand, e.g. i512mem for VR512. - X86MemOperand MemOp = !cast(TypeVariantName # Size # "mem"); - X86MemOperand ScalarMemOp = !cast(!subst("b", "", EltTypeName) # "mem"); - // FP scalar memory operand for intrinsics - ssmem/sdmem. - Operand IntScalarMemOp = !if (!eq (EltTypeName, "f16"), !cast("shmem"), - !if (!eq (EltTypeName, "bf16"), !cast("shmem"), - !if (!eq (EltTypeName, "f32"), !cast("ssmem"), - !if (!eq (EltTypeName, "f64"), !cast("sdmem"), ?)))); - - // Load patterns - PatFrag LdFrag = !cast("load" # VTName); - - PatFrag AlignedLdFrag = !cast("alignedload" # VTName); - - PatFrag ScalarLdFrag = !cast("load" # !subst("b", "", EltTypeName)); - PatFrag BroadcastLdFrag = !cast("X86VBroadcastld" # EltSizeName); - - PatFrags ScalarIntMemFrags = !if (!eq (EltTypeName, "f16"), !cast("sse_load_f16"), - !if (!eq (EltTypeName, "bf16"), !cast("sse_load_f16"), - !if (!eq (EltTypeName, "f32"), !cast("sse_load_f32"), - !if (!eq (EltTypeName, "f64"), !cast("sse_load_f64"), ?)))); - - // The string to specify embedded broadcast in assembly. - string BroadcastStr = "{1to" # NumElts # "}"; - - // 8-bit compressed displacement tuple/subvector format. This is only - // defined for NumElts <= 8. - CD8VForm CD8TupleForm = !if (!eq (!srl(NumElts, 4), 0), - !cast("CD8VT" # NumElts), ?); - - SubRegIndex SubRegIdx = !if (!eq (Size, 128), sub_xmm, - !if (!eq (Size, 256), sub_ymm, ?)); - - Domain ExeDomain = !if (!eq (EltTypeName, "f32"), SSEPackedSingle, - !if (!eq (EltTypeName, "f64"), SSEPackedDouble, - !if (!eq (EltTypeName, "f16"), SSEPackedSingle, // FIXME? - !if (!eq (EltTypeName, "bf16"), SSEPackedSingle, // FIXME? - SSEPackedInt)))); - - RegisterClass FRC = !if (!eq (EltTypeName, "f32"), FR32X, - !if (!eq (EltTypeName, "f16"), FR16X, - !if (!eq (EltTypeName, "bf16"), FR16X, - FR64X))); - - dag ImmAllZerosV = (VT immAllZerosV); - - string ZSuffix = !if (!eq (Size, 128), "Z128", - !if (!eq (Size, 256), "Z256", "Z")); -} - -def v64i8_info : X86VectorVTInfo<64, i8, VR512, "b">; -def v32i16_info : X86VectorVTInfo<32, i16, VR512, "w">; -def v16i32_info : X86VectorVTInfo<16, i32, VR512, "d">; -def v8i64_info : X86VectorVTInfo<8, i64, VR512, "q">; -def v32f16_info : X86VectorVTInfo<32, f16, VR512, "ph">; -def v32bf16_info: X86VectorVTInfo<32, bf16, VR512, "pbf">; -def v16f32_info : X86VectorVTInfo<16, f32, VR512, "ps">; -def v8f64_info : X86VectorVTInfo<8, f64, VR512, "pd">; - -// "x" in v32i8x_info means RC = VR256X -def v32i8x_info : X86VectorVTInfo<32, i8, VR256X, "b">; -def v16i16x_info : X86VectorVTInfo<16, i16, VR256X, "w">; -def v8i32x_info : X86VectorVTInfo<8, i32, VR256X, "d">; -def v4i64x_info : X86VectorVTInfo<4, i64, VR256X, "q">; -def v16f16x_info : X86VectorVTInfo<16, f16, VR256X, "ph">; -def v16bf16x_info: X86VectorVTInfo<16, bf16, VR256X, "pbf">; -def v8f32x_info : X86VectorVTInfo<8, f32, VR256X, "ps">; -def v4f64x_info : X86VectorVTInfo<4, f64, VR256X, "pd">; - -def v16i8x_info : X86VectorVTInfo<16, i8, VR128X, "b">; -def v8i16x_info : X86VectorVTInfo<8, i16, VR128X, "w">; -def v4i32x_info : X86VectorVTInfo<4, i32, VR128X, "d">; -def v2i64x_info : X86VectorVTInfo<2, i64, VR128X, "q">; -def v8f16x_info : X86VectorVTInfo<8, f16, VR128X, "ph">; -def v8bf16x_info : X86VectorVTInfo<8, bf16, VR128X, "pbf">; -def v4f32x_info : X86VectorVTInfo<4, f32, VR128X, "ps">; -def v2f64x_info : X86VectorVTInfo<2, f64, VR128X, "pd">; - -// We map scalar types to the smallest (128-bit) vector type -// with the appropriate element type. This allows to use the same masking logic. -def i32x_info : X86VectorVTInfo<1, i32, GR32, "si">; -def i64x_info : X86VectorVTInfo<1, i64, GR64, "sq">; -def f16x_info : X86VectorVTInfo<1, f16, VR128X, "sh">; -def bf16x_info : X86VectorVTInfo<1, bf16, VR128X, "sbf">; -def f32x_info : X86VectorVTInfo<1, f32, VR128X, "ss">; -def f64x_info : X86VectorVTInfo<1, f64, VR128X, "sd">; - -class AVX512VLVectorVTInfo { - X86VectorVTInfo info512 = i512; - X86VectorVTInfo info256 = i256; - X86VectorVTInfo info128 = i128; -} - -def avx512vl_i8_info : AVX512VLVectorVTInfo; -def avx512vl_i16_info : AVX512VLVectorVTInfo; -def avx512vl_i32_info : AVX512VLVectorVTInfo; -def avx512vl_i64_info : AVX512VLVectorVTInfo; -def avx512vl_f16_info : AVX512VLVectorVTInfo; -def avx512vl_bf16_info : AVX512VLVectorVTInfo; -def avx512vl_f32_info : AVX512VLVectorVTInfo; -def avx512vl_f64_info : AVX512VLVectorVTInfo; - -class X86KVectorVTInfo { - RegisterClass KRC = _krc; - RegisterClass KRCWM = _krcwm; - ValueType KVT = _vt; -} - -def v1i1_info : X86KVectorVTInfo; -def v2i1_info : X86KVectorVTInfo; -def v4i1_info : X86KVectorVTInfo; -def v8i1_info : X86KVectorVTInfo; -def v16i1_info : X86KVectorVTInfo; -def v32i1_info : X86KVectorVTInfo; -def v64i1_info : X86KVectorVTInfo; - -// Used for matching masked operations. Ensures the operation part only has a -// single use. -def vselect_mask : PatFrag<(ops node:$mask, node:$src1, node:$src2), - (vselect node:$mask, node:$src1, node:$src2), [{ - return isProfitableToFormMaskedOp(N); -}]>; - -def X86selects_mask : PatFrag<(ops node:$mask, node:$src1, node:$src2), - (X86selects node:$mask, node:$src1, node:$src2), [{ - return isProfitableToFormMaskedOp(N); -}]>; - // This multiclass generates the masking variants from the non-masking // variant. It only provides the assembly pieces for the masking variants. // It assumes custom ISel patterns for masking which can be provided as @@ -2157,15 +1969,6 @@ multiclass avx512_cmp_scalarhasOneUse(); -}]>; -def X86cmpmsSAE_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (X86cmpmsSAE node:$src1, node:$src2, node:$cc), [{ - return N->hasOneUse(); -}]>; - let Predicates = [HasAVX512] in { let ExeDomain = SSEPackedSingle in defm VCMPSSZ : avx512_cmp_scalar opc, string OpcodeStr, } } -// This fragment treats X86cmpm as commutable to help match loads in both -// operands for PCMPEQ. -def X86setcc_commute : SDNode<"ISD::SETCC", SDTSetCC, [SDNPCommutative]>; -def X86pcmpgtm : PatFrag<(ops node:$src1, node:$src2), - (setcc node:$src1, node:$src2, SETGT)>; - // AddedComplexity is needed because the explicit SETEQ/SETGT CondCode doesn't // increase the pattern complexity the way an immediate would. let AddedComplexity = 2 in { @@ -2304,20 +2101,6 @@ defm VPCMPGTQ : avx512_icmp_packed_rmb_vl<0x37, "vpcmpgtq", T8PD, REX_W, EVEX_CD8<64, CD8VF>; } -def X86pcmpm_imm : SDNodeXForm(N->getOperand(2))->get(); - uint8_t SSECC = X86::getVPCMPImmForCond(CC); - return getI8Imm(SSECC, SDLoc(N)); -}]>; - -// Swapped operand version of the above. -def X86pcmpm_imm_commute : SDNodeXForm(N->getOperand(2))->get(); - uint8_t SSECC = X86::getVPCMPImmForCond(CC); - SSECC = X86::getSwappedVPCMPImm(SSECC); - return getI8Imm(SSECC, SDLoc(N)); -}]>; - multiclass avx512_icmp_cc opc, string Suffix, PatFrag Frag, PatFrag Frag_su, X86FoldableSchedWrite sched, @@ -2451,30 +2234,6 @@ multiclass avx512_icmp_cc_rmb_vl opc, string Suffix, PatFrag Frag, } } -def X86pcmpm : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return !ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - -def X86pcmpm_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return N->hasOneUse() && !ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - -def X86pcmpum : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - -def X86pcmpum_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (setcc node:$src1, node:$src2, node:$cc), [{ - ISD::CondCode CC = cast(N->getOperand(2))->get(); - return N->hasOneUse() && ISD::isUnsignedIntSetCC(CC); -}], X86pcmpm_imm>; - // FIXME: Is there a better scheduler class for VPCMP/VPCMPU? defm VPCMPB : avx512_icmp_cc_vl<0x3F, "b", X86pcmpm, X86pcmpm_su, SchedWriteVecALU, avx512vl_i8_info, HasBWI>, @@ -2504,16 +2263,6 @@ defm VPCMPUQ : avx512_icmp_cc_rmb_vl<0x1E, "uq", X86pcmpum, X86pcmpum_su, SchedWriteVecALU, avx512vl_i64_info, HasAVX512>, REX_W, EVEX_CD8<64, CD8VF>; -def X86cmpm_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), - (X86cmpm node:$src1, node:$src2, node:$cc), [{ - return N->hasOneUse(); -}]>; - -def X86cmpm_imm_commute : SDNodeXFormgetZExtValue() & 0x1f); - return getI8Imm(Imm, SDLoc(N)); -}]>; - multiclass avx512_vcmp_common { let Uses = [MXCSR], mayRaiseFPException = 1 in { @@ -2679,16 +2428,6 @@ let Predicates = [HasFP16] in { // ---------------------------------------------------------------- // FPClass -def X86Vfpclasss_su : PatFrag<(ops node:$src1, node:$src2), - (X86Vfpclasss node:$src1, node:$src2), [{ - return N->hasOneUse(); -}]>; - -def X86Vfpclass_su : PatFrag<(ops node:$src1, node:$src2), - (X86Vfpclass node:$src1, node:$src2), [{ - return N->hasOneUse(); -}]>; - //handle fpclass instruction mask = op(reg_scalar,imm) // op(mem_scalar,imm) multiclass avx512_scalar_fpclass opc, string OpcodeStr, @@ -3082,10 +2821,6 @@ multiclass avx512_mask_binop_all opc, string OpcodeStr, sched, HasBWI, IsCommutable>, VEX_4V, VEX_L, REX_W, PS; } -// These nodes use 'vnot' instead of 'not' to support vectors. -def vandn : PatFrag<(ops node:$i0, node:$i1), (and (vnot node:$i0), node:$i1)>; -def vxnor : PatFrag<(ops node:$i0, node:$i1), (vnot (xor node:$i0, node:$i1))>; - // TODO - do we need a X86SchedWriteWidths::KMASK type? defm KAND : avx512_mask_binop_all<0x41, "kand", and, SchedWriteVecLogic.XMM, 1>; defm KOR : avx512_mask_binop_all<0x45, "kor", or, SchedWriteVecLogic.XMM, 1>; @@ -9880,19 +9615,6 @@ defm : avx512_masked_scalar; -def select_truncs : PatFrag<(ops node:$src, node:$src0, node:$mask), - (vselect_mask node:$mask, - (X86vtruncs node:$src), node:$src0)>; -def select_truncus : PatFrag<(ops node:$src, node:$src0, node:$mask), - (vselect_mask node:$mask, - (X86vtruncus node:$src), node:$src0)>; - multiclass avx512_trunc_common opc, string OpcodeStr, SDNode OpNode, SDPatternOperator MaskNode, X86FoldableSchedWrite sched, X86VectorVTInfo SrcInfo, @@ -12676,11 +12398,6 @@ defm VPOPCNTW : avx512_unary_rm_vl<0x54, "vpopcntw", ctpop, SchedWriteVecALU, defm : avx512_unary_lowering<"VPOPCNTB", ctpop, avx512vl_i8_info, HasBITALG>; defm : avx512_unary_lowering<"VPOPCNTW", ctpop, avx512vl_i16_info, HasBITALG>; -def X86Vpshufbitqmb_su : PatFrag<(ops node:$src1, node:$src2), - (X86Vpshufbitqmb node:$src1, node:$src2), [{ - return N->hasOneUse(); -}]>; - multiclass VPSHUFBITQMB_rm { defm rr : AVX512_maskable_cmp<0x8F, MRMSrcReg, VTI, (outs VTI.KRC:$dst), (ins VTI.RC:$src1, VTI.RC:$src2), diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td index 56cbc13eaaec8..8c355e84a0659 100644 --- a/llvm/lib/Target/X86/X86InstrArithmetic.td +++ b/llvm/lib/Target/X86/X86InstrArithmetic.td @@ -48,16 +48,6 @@ def PLEA64r : PseudoI<(outs GR64:$dst), (ins anymem:$src), []>; // Fixed-Register Multiplication and Division Instructions. // -// SchedModel info for instruction that loads one value and gets the second -// (and possibly third) value from a register. -// This is used for instructions that put the memory operands before other -// uses. -class SchedLoadReg : Sched<[Sched.Folded, - // Memory operand. - ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault, - // Register reads (implicit or explicit). - Sched.ReadAfterFold, Sched.ReadAfterFold]>; - // BinOpRR - Binary instructions with inputs "reg, reg". class BinOpRR opcode, string mnemonic, X86TypeInfo typeinfo, dag outlist, X86FoldableSchedWrite sched, list pattern> @@ -506,17 +496,6 @@ class IMulOpRMI opcode, string mnemonic, X86TypeInfo info, let ImmT = info.ImmEncoding; } -def X86add_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), - (X86add_flag node:$lhs, node:$rhs), [{ - return hasNoCarryFlagUses(SDValue(N, 1)); -}]>; - -def X86sub_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), - (X86sub_flag node:$lhs, node:$rhs), [{ - // Only use DEC if the result is used. - return !SDValue(N, 0).use_empty() && hasNoCarryFlagUses(SDValue(N, 1)); -}]>; - let Defs = [EFLAGS] in { let Constraints = "$src1 = $dst", SchedRW = [WriteALU] in { // Short forms only valid in 32-bit mode. Selected during MCInst lowering. @@ -1221,9 +1200,6 @@ def : Pat<(store (X86adc_flag i64relocImmSExt32_su:$src, (load addr:$dst), EFLAG // generate a result. From an encoding perspective, they are very different: // they don't have all the usual imm8 and REV forms, and are encoded into a // different space. -def X86testpat : PatFrag<(ops node:$lhs, node:$rhs), - (X86cmp (and_su node:$lhs, node:$rhs), 0)>; - let isCompare = 1 in { let Defs = [EFLAGS] in { let isCommutable = 1 in { diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index 9e99dbd6fe852..457833f8cc331 100644 --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -786,16 +786,6 @@ defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, X86lock_or , "or">; defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, X86lock_and, "and">; defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, X86lock_xor, "xor">; -def X86lock_add_nocf : PatFrag<(ops node:$lhs, node:$rhs), - (X86lock_add node:$lhs, node:$rhs), [{ - return hasNoCarryFlagUses(SDValue(N, 0)); -}]>; - -def X86lock_sub_nocf : PatFrag<(ops node:$lhs, node:$rhs), - (X86lock_sub node:$lhs, node:$rhs), [{ - return hasNoCarryFlagUses(SDValue(N, 0)); -}]>; - let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1, SchedRW = [WriteALURMW] in { let Predicates = [UseIncDec] in { @@ -1304,31 +1294,6 @@ def : Pat<(X86call_rvmarker (i64 tglobaladdr:$rvfunc), (i64 tglobaladdr:$dst)), // %r11. This happens when calling a vararg function with 6 arguments. // // Match an X86tcret that uses less than 7 volatile registers. -def X86tcret_6regs : PatFrag<(ops node:$ptr, node:$off), - (X86tcret node:$ptr, node:$off), [{ - // X86tcret args: (*chain, ptr, imm, regs..., glue) - unsigned NumRegs = 0; - for (unsigned i = 3, e = N->getNumOperands(); i != e; ++i) - if (isa(N->getOperand(i)) && ++NumRegs > 6) - return false; - return true; -}]>; - -def X86tcret_1reg : PatFrag<(ops node:$ptr, node:$off), - (X86tcret node:$ptr, node:$off), [{ - // X86tcret args: (*chain, ptr, imm, regs..., glue) - unsigned NumRegs = 1; - const SDValue& BasePtr = cast(N->getOperand(1))->getBasePtr(); - if (isa(BasePtr)) - NumRegs = 3; - else if (BasePtr->getNumOperands() && isa(BasePtr->getOperand(0))) - NumRegs = 3; - for (unsigned i = 3, e = N->getNumOperands(); i != e; ++i) - if (isa(N->getOperand(i)) && ( NumRegs-- == 0)) - return false; - return true; -}]>; - def : Pat<(X86tcret ptr_rc_tailcall:$dst, timm:$off), (TCRETURNri ptr_rc_tailcall:$dst, timm:$off)>, Requires<[Not64BitMode, NotUseIndirectThunkCalls]>; @@ -1449,32 +1414,8 @@ def : Pat<(i64 (anyext GR16:$src)), def : Pat<(i64 (anyext GR32:$src)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, sub_32bit)>; -// If this is an anyext of the remainder of an 8-bit sdivrem, use a MOVSX -// instead of a MOVZX. The sdivrem lowering will emit emit a MOVSX to move -// %ah to the lower byte of a register. By using a MOVSX here we allow a -// post-isel peephole to merge the two MOVSX instructions into one. -def anyext_sdiv : PatFrag<(ops node:$lhs), (anyext node:$lhs),[{ - return (N->getOperand(0).getOpcode() == ISD::SDIVREM && - N->getOperand(0).getResNo() == 1); -}]>; def : Pat<(i32 (anyext_sdiv GR8:$src)), (MOVSX32rr8 GR8:$src)>; -// Any instruction that defines a 32-bit result leaves the high half of the -// register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may -// be copying from a truncate. AssertSext/AssertZext/AssertAlign aren't saying -// anything about the upper 32 bits, they're probably just qualifying a -// CopyFromReg. FREEZE may be coming from a a truncate. Any other 32-bit -// operation will zero-extend up to 64 bits. -def def32 : PatLeaf<(i32 GR32:$src), [{ - return N->getOpcode() != ISD::TRUNCATE && - N->getOpcode() != TargetOpcode::EXTRACT_SUBREG && - N->getOpcode() != ISD::CopyFromReg && - N->getOpcode() != ISD::AssertSext && - N->getOpcode() != ISD::AssertZext && - N->getOpcode() != ISD::AssertAlign && - N->getOpcode() != ISD::FREEZE; -}]>; - // In the case of a 32-bit def that is known to implicitly zero-extend, // we can use a SUBREG_TO_REG. def : Pat<(i64 (zext def32:$src)), @@ -1492,17 +1433,6 @@ def : Pat<(i64 (and (anyext def32:$src), 0x00000000FFFFFFFF)), // generator to make the generated code easier to read. To do this, we select // into "disjoint bits" pseudo ops. -// Treat an 'or' node is as an 'add' if the or'ed bits are known to be zero. -def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ - if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) - return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue()); - - KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0); - KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0); - return (~Known0.Zero & ~Known1.Zero) == 0; -}]>; - - // (or x1, x2) -> (add x1, x2) if two operands are known not to share bits. // Try this before the selecting to OR. let SchedRW = [WriteALU] in { @@ -1820,23 +1750,6 @@ def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; -def shiftMask8 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ - return isUnneededShiftMask(N, 3); -}]>; - -def shiftMask16 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ - return isUnneededShiftMask(N, 4); -}]>; - -def shiftMask32 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ - return isUnneededShiftMask(N, 5); -}]>; - -def shiftMask64 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ - return isUnneededShiftMask(N, 6); -}]>; - - // Shift amount is implicitly masked. multiclass MaskedShiftAmountPats { // (shift x (and y, 31)) ==> (shift x, y) diff --git a/llvm/lib/Target/X86/X86InstrFPStack.td b/llvm/lib/Target/X86/X86InstrFPStack.td index 66a2d27abf86b..ef4c011c669ad 100644 --- a/llvm/lib/Target/X86/X86InstrFPStack.td +++ b/llvm/lib/Target/X86/X86InstrFPStack.td @@ -12,127 +12,6 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// FPStack specific DAG Nodes. -//===----------------------------------------------------------------------===// - -def SDTX86Fld : SDTypeProfile<1, 1, [SDTCisFP<0>, - SDTCisPtrTy<1>]>; -def SDTX86Fst : SDTypeProfile<0, 2, [SDTCisFP<0>, - SDTCisPtrTy<1>]>; -def SDTX86Fild : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisPtrTy<1>]>; -def SDTX86Fist : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; - -def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; -def SDTX86CwdLoad : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; -def SDTX86FPEnv : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; - -def X86fp80_add : SDNode<"X86ISD::FP80_ADD", SDTFPBinOp, [SDNPCommutative]>; -def X86strict_fp80_add : SDNode<"X86ISD::STRICT_FP80_ADD", SDTFPBinOp, - [SDNPHasChain,SDNPCommutative]>; -def any_X86fp80_add : PatFrags<(ops node:$lhs, node:$rhs), - [(X86strict_fp80_add node:$lhs, node:$rhs), - (X86fp80_add node:$lhs, node:$rhs)]>; - -def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def X86fist : SDNode<"X86ISD::FIST", SDTX86Fist, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_to_mem : SDNode<"X86ISD::FP_TO_INT_IN_MEM", SDTX86Fst, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, - [SDNPHasChain, SDNPMayStore, SDNPSideEffect, - SDNPMemOperand]>; -def X86fp_cwd_set16 : SDNode<"X86ISD::FLDCW16m", SDTX86CwdLoad, - [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, - SDNPMemOperand]>; -def X86fpenv_get : SDNode<"X86ISD::FNSTENVm", SDTX86FPEnv, - [SDNPHasChain, SDNPMayStore, SDNPSideEffect, - SDNPMemOperand]>; -def X86fpenv_set : SDNode<"X86ISD::FLDENVm", SDTX86FPEnv, - [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, - SDNPMemOperand]>; - -def X86fstf32 : PatFrag<(ops node:$val, node:$ptr), - (X86fst node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f32; -}]>; -def X86fstf64 : PatFrag<(ops node:$val, node:$ptr), - (X86fst node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f64; -}]>; -def X86fstf80 : PatFrag<(ops node:$val, node:$ptr), - (X86fst node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f80; -}]>; - -def X86fldf32 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f32; -}]>; -def X86fldf64 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f64; -}]>; -def X86fldf80 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::f80; -}]>; - -def X86fild16 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; -def X86fild32 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; -def X86fild64 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i64; -}]>; - -def X86fist32 : PatFrag<(ops node:$val, node:$ptr), - (X86fist node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; - -def X86fist64 : PatFrag<(ops node:$val, node:$ptr), - (X86fist node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i64; -}]>; - -def X86fp_to_i16mem : PatFrag<(ops node:$val, node:$ptr), - (X86fp_to_mem node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i16; -}]>; -def X86fp_to_i32mem : PatFrag<(ops node:$val, node:$ptr), - (X86fp_to_mem node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i32; -}]>; -def X86fp_to_i64mem : PatFrag<(ops node:$val, node:$ptr), - (X86fp_to_mem node:$val, node:$ptr), [{ - return cast(N)->getMemoryVT() == MVT::i64; -}]>; - -//===----------------------------------------------------------------------===// -// FPStack pattern fragments -//===----------------------------------------------------------------------===// - -def fpimm0 : FPImmLeaf; - -def fpimmneg0 : FPImmLeaf; - -def fpimm1 : FPImmLeaf; - -def fpimmneg1 : FPImmLeaf; - // Some 'special' instructions - expanded after instruction selection. // Clobbers EFLAGS due to OR instruction used internally. // FIXME: Can we model this in SelectionDAG? diff --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td index 68a9bb7053a1c..df05a5788a50a 100644 --- a/llvm/lib/Target/X86/X86InstrFormats.td +++ b/llvm/lib/Target/X86/X86InstrFormats.td @@ -192,91 +192,6 @@ def AdSize16 : AddressSize<1>; // Encodes a 16-bit address. def AdSize32 : AddressSize<2>; // Encodes a 32-bit address. def AdSize64 : AddressSize<3>; // Encodes a 64-bit address. -// Prefix byte classes which are used to indicate to the ad-hoc machine code -// emitter that various prefix bytes are required. -class OpSize16 { OperandSize OpSize = OpSize16; } -class OpSize32 { OperandSize OpSize = OpSize32; } -class AdSize16 { AddressSize AdSize = AdSize16; } -class AdSize32 { AddressSize AdSize = AdSize32; } -class AdSize64 { AddressSize AdSize = AdSize64; } -class REX_W { bit hasREX_W = 1; } -class LOCK { bit hasLockPrefix = 1; } -class REP { bit hasREPPrefix = 1; } -class TB { Map OpMap = TB; } -class T8 { Map OpMap = T8; } -class TA { Map OpMap = TA; } -class XOP8 { Map OpMap = XOP8; Prefix OpPrefix = PS; } -class XOP9 { Map OpMap = XOP9; Prefix OpPrefix = PS; } -class XOPA { Map OpMap = XOPA; Prefix OpPrefix = PS; } -class ThreeDNow { Map OpMap = ThreeDNow; } -class T_MAP4 { Map OpMap = T_MAP4; } -class T_MAP4PS : T_MAP4 { Prefix OpPrefix = PS; } // none -class T_MAP4PD : T_MAP4 { Prefix OpPrefix = PD; } // 0x66 -class T_MAP4XS : T_MAP4 { Prefix OpPrefix = XS; } // 0xF3 -class T_MAP4XD : T_MAP4 { Prefix OpPrefix = XD; } // 0xF2 -class T_MAP5 { Map OpMap = T_MAP5; } -class T_MAP5PS : T_MAP5 { Prefix OpPrefix = PS; } // none -class T_MAP5PD : T_MAP5 { Prefix OpPrefix = PD; } // 0x66 -class T_MAP5XS : T_MAP5 { Prefix OpPrefix = XS; } // 0xF3 -class T_MAP5XD : T_MAP5 { Prefix OpPrefix = XD; } // 0xF2 -class T_MAP6 { Map OpMap = T_MAP6; } -class T_MAP6PS : T_MAP6 { Prefix OpPrefix = PS; } -class T_MAP6PD : T_MAP6 { Prefix OpPrefix = PD; } -class T_MAP6XS : T_MAP6 { Prefix OpPrefix = XS; } -class T_MAP6XD : T_MAP6 { Prefix OpPrefix = XD; } -class T_MAP7 { Map OpMap = T_MAP7; } -class T_MAP7XS : T_MAP7 { Prefix OpPrefix = XS; } // 0xF3 -class T_MAP7XD : T_MAP7 { Prefix OpPrefix = XD; } // 0xF2 -class OBXS { Prefix OpPrefix = XS; } -class PS : TB { Prefix OpPrefix = PS; } -class PD : TB { Prefix OpPrefix = PD; } -class XD : TB { Prefix OpPrefix = XD; } -class XS : TB { Prefix OpPrefix = XS; } -class T8PS : T8 { Prefix OpPrefix = PS; } -class T8PD : T8 { Prefix OpPrefix = PD; } -class T8XD : T8 { Prefix OpPrefix = XD; } -class T8XS : T8 { Prefix OpPrefix = XS; } -class TAPS : TA { Prefix OpPrefix = PS; } -class TAPD : TA { Prefix OpPrefix = PD; } -class TAXD : TA { Prefix OpPrefix = XD; } -class TAXS : TA { Prefix OpPrefix = XS; } -class VEX { Encoding OpEnc = EncVEX; } -class WIG { bit IgnoresW = 1; } -// Special version of REX_W that can be changed to VEX.W==0 for EVEX2VEX. -class VEX_W1X { bit hasREX_W = 1; bit EVEX_W1_VEX_W0 = 1; } -class VEX_4V : VEX { bit hasVEX_4V = 1; } -class VEX_L { bit hasVEX_L = 1; } -class VEX_LIG { bit ignoresVEX_L = 1; } -class EVEX { Encoding OpEnc = EncEVEX; } -class EVEX_4V : EVEX { bit hasVEX_4V = 1; } -class EVEX_K { bit hasEVEX_K = 1; } -class EVEX_KZ : EVEX_K { bit hasEVEX_Z = 1; } -class EVEX_B { bit hasEVEX_B = 1; } -class EVEX_RC { bit hasEVEX_RC = 1; } -class EVEX_V512 { bit hasEVEX_L2 = 1; bit hasVEX_L = 0; } -class EVEX_V256 { bit hasEVEX_L2 = 0; bit hasVEX_L = 1; } -class EVEX_V128 { bit hasEVEX_L2 = 0; bit hasVEX_L = 0; } -class NOTRACK { bit hasNoTrackPrefix = 1; } -class SIMD_EXC { list Uses = [MXCSR]; bit mayRaiseFPException = 1; } - -// Specify AVX512 8-bit compressed displacement encoding based on the vector -// element size in bits (8, 16, 32, 64) and the CDisp8 form. -class EVEX_CD8 { - int CD8_EltSize = !srl(esize, 3); - bits<3> CD8_Form = form.Value; -} - -class XOP { Encoding OpEnc = EncXOP; } -class XOP_4V : XOP { bit hasVEX_4V = 1; } - -// Provide a specific instruction to be used by the EVEX2VEX conversion. -class EVEX2VEXOverride { - string EVEX2VEXOverride = VEXInstrName; -} - -// Prevent EVEX->VEX conversion from considering this instruction. -class NotEVEX2VEXConvertible { bit notEVEX2VEXConvertible = 1; } - // Force the instruction to use REX2/VEX/EVEX encoding. class ExplicitOpPrefix val> { bits<2> Value = val; @@ -285,9 +200,6 @@ def NoExplicitOpPrefix : ExplicitOpPrefix<0>; def ExplicitREX2 : ExplicitOpPrefix<1>; def ExplicitVEX : ExplicitOpPrefix<2>; def ExplicitEVEX : ExplicitOpPrefix<3>; -class ExplicitREX2Prefix { ExplicitOpPrefix explicitOpPrefix = ExplicitREX2; } -class ExplicitVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitVEX; } -class ExplicitEVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitEVEX; } class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, string AsmStr, Domain d = GenericDomain> @@ -397,621 +309,3 @@ class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, let TSFlags{49} = hasNoTrackPrefix; let TSFlags{51-50} = explicitOpPrefixBits; } - -class PseudoI pattern> - : X86Inst<0, Pseudo, NoImm, oops, iops, ""> { - let Pattern = pattern; -} - -class I o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; -} -class Ii8 o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; -} -class Ii8Reg o, Format f, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : X86Inst { - let Pattern = pattern; -} -class Ii8PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} -class Ii16 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} -class Ii32 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} -class Ii32S o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} - -class Ii64 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} - -class Ii16PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} - -class Ii32PCRel o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} - -// FPStack Instruction Templates: -// FPI - Floating Point Instruction template. -class FPI o, Format F, dag outs, dag ins, string asm> - : I { - let Defs = [FPSW]; - let Predicates = [HasX87]; -} - -// FpI_ - Floating Point Pseudo Instruction template. -class FpI_ pattern> - : PseudoI { - let FPForm = fp; - let Defs = [FPSW]; - let Predicates = [HasX87]; -} - -// Templates for instructions that use a 16- or 32-bit segmented address as -// their only operand: lcall (FAR CALL) and ljmp (FAR JMP) -// -// Iseg16 - 16-bit segment selector, 16-bit offset -// Iseg32 - 16-bit segment selector, 32-bit offset - -class Iseg16 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} - -class Iseg32 o, Format f, dag outs, dag ins, string asm, - list pattern> - : X86Inst { - let Pattern = pattern; -} - -// SI - SSE 1 & 2 scalar instructions -class SI o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// SI - SSE 1 & 2 scalar intrinsics - vex form available on AVX512 -class SI_Int o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d = GenericDomain> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} -// SIi8 - SSE 1 & 2 scalar instructions - vex form available on AVX512 -class SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8 { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], - [UseSSE2]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// PI - SSE 1 & 2 packed instructions -class PI o, Format F, dag outs, dag ins, string asm, list pattern, - Domain d> - : I { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// MMXPI - SSE 1 & 2 packed instructions with MMX operands -class MMXPI o, Format F, dag outs, dag ins, string asm, list pattern, - Domain d> - : I { - let Predicates = !if(!eq(OpPrefix.Value, PD.Value), [HasMMX, HasSSE2], - [HasMMX, HasSSE1]); -} - -// PIi8 - SSE 1 & 2 packed instructions with immediate -class PIi8 o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : Ii8 { - let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], - !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], - !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], - [UseSSE1]))); - - // AVX instructions have a 'v' prefix in the mnemonic - let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), - !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), - asm)); -} - -// SSE1 Instruction Templates: -// -// SSI - SSE1 instructions with XS prefix. -// PSI - SSE1 instructions with PS prefix. -// PSIi8 - SSE1 instructions with ImmT == Imm8 and PS prefix. -// VSSI - SSE1 instructions with XS prefix in AVX form. -// VPSI - SSE1 instructions with PS prefix in AVX form, packed single. - -class SSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, Requires<[UseSSE1]>; -class SSIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[UseSSE1]>; -class PSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[UseSSE1]>; -class PSIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PS, - Requires<[UseSSE1]>; -class VSSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX]>; -class VPSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[HasAVX]>; - -// SSE2 Instruction Templates: -// -// SDI - SSE2 instructions with XD prefix. -// SDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix. -// S2SI - SSE2 instructions with XS prefix. -// SSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix. -// PDI - SSE2 instructions with PD prefix, packed double domain. -// PDIi8 - SSE2 instructions with ImmT == Imm8 and PD prefix. -// VSDI - SSE2 scalar instructions with XD prefix in AVX form. -// VPDI - SSE2 vector instructions with PD prefix in AVX form, -// packed double domain. -// VS2I - SSE2 scalar instructions with PD prefix in AVX form. -// S2I - SSE2 scalar instructions with PD prefix. -// MMXSDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix as well as -// MMX operands. -// MMXSSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix as well as -// MMX operands. - -class SDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, Requires<[UseSSE2]>; -class SDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[UseSSE2]>; -class S2SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, Requires<[UseSSE2]>; -class S2SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[UseSSE2]>; -class PDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseSSE2]>; -class PDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PD, - Requires<[UseSSE2]>; -class VSDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[UseAVX]>; -class VS2SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX]>; -class VPDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, - PD, Requires<[HasAVX]>; -class VS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseAVX]>; -class S2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, Requires<[UseSSE2]>; -class MMXSDIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[HasMMX, HasSSE2]>; -class MMXS2SIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[HasMMX, HasSSE2]>; - -// SSE3 Instruction Templates: -// -// S3I - SSE3 instructions with PD prefixes. -// S3SI - SSE3 instructions with XS prefix. -// S3DI - SSE3 instructions with XD prefix. - -class S3SI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[UseSSE3]>; -class S3DI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[UseSSE3]>; -class S3I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[UseSSE3]>; - - -// SSSE3 Instruction Templates: -// -// SS38I - SSSE3 instructions with T8 prefix. -// SS3AI - SSSE3 instructions with TA prefix. -// MMXSS38I - SSSE3 instructions with T8 prefix and MMX operands. -// MMXSS3AI - SSSE3 instructions with TA prefix and MMX operands. -// -// Note: SSSE3 instructions have 64-bit and 128-bit versions. The 64-bit version -// uses the MMX registers. The 64-bit versions are grouped with the MMX -// classes. They need to be enabled even if AVX is enabled. - -class SS38I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSSE3]>; -class SS3AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSSE3]>; -class MMXSS38I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PS, - Requires<[HasMMX, HasSSSE3]>; -class MMXSS3AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPS, - Requires<[HasMMX, HasSSSE3]>; - -// SSE4.1 Instruction Templates: -// -// SS48I - SSE 4.1 instructions with T8 prefix. -// SS41AIi8 - SSE 4.1 instructions with TA prefix and ImmT == Imm8. -// -class SS48I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSE41]>; -class SS4AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSE41]>; - -// SSE4.2 Instruction Templates: -// -// SS428I - SSE 4.2 instructions with T8 prefix. -class SS428I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[UseSSE42]>; - -// SS42AI = SSE 4.2 instructions with TA prefix -class SS42AI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[UseSSE42]>; - -// CRC32I - SSE 4.2 CRC32 instructions. -// NOTE: 'HasCRC32' is used as CRC32 instructions are GPR only and not directly -// controlled by the SSE42 flag. -class CRC32I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8XD, Requires<[HasCRC32]>; - -// AVX Instruction Templates: -// Instructions introduced in AVX (no SSE equivalent forms) -// -// AVX8I - AVX instructions with T8PD prefix. -// AVXAIi8 - AVX instructions with TAPD prefix and ImmT = Imm8. -class AVX8I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX]>; -class AVXAIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX]>; - -// AVX2 Instruction Templates: -// Instructions introduced in AVX2 (no SSE equivalent forms) -// -// AVX28I - AVX2 instructions with T8PD prefix. -// AVX2AIi8 - AVX2 instructions with TAPD prefix and ImmT = Imm8. -class AVX28I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX2]>; -class AVX2AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX2]>; - - -// AVX-512 Instruction Templates: -// Instructions introduced in AVX-512 (no SSE equivalent forms) -// -// AVX5128I - AVX-512 instructions with T8PD prefix. -// AVX512AIi8 - AVX-512 instructions with TAPD prefix and ImmT = Imm8. -// AVX512PDI - AVX-512 instructions with PD, double packed. -// AVX512PSI - AVX-512 instructions with PS, single packed. -// AVX512XS8I - AVX-512 instructions with T8 and XS prefixes. -// AVX512XSI - AVX-512 instructions with XS prefix, generic domain. -// AVX512BI - AVX-512 instructions with PD, int packed domain. -// AVX512SI - AVX-512 scalar instructions with PD prefix. - -class AVX5128I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8PD, - Requires<[HasAVX512]>; -class AVX5128IBase : T8PD { - Domain ExeDomain = SSEPackedInt; -} -class AVX512XS8I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, T8XS, - Requires<[HasAVX512]>; -class AVX512XSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XS, - Requires<[HasAVX512]>; -class AVX512XDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, XD, - Requires<[HasAVX512]>; -class AVX512BI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[HasAVX512]>; -class AVX512BIBase : PD { - Domain ExeDomain = SSEPackedInt; -} -class AVX512BIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PD, - Requires<[HasAVX512]>; -class AVX512BIi8Base : PD { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512XSIi8Base : XS { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512XDIi8Base : XD { - Domain ExeDomain = SSEPackedInt; - ImmType ImmT = Imm8; -} -class AVX512PSIi8Base : PS { - Domain ExeDomain = SSEPackedSingle; - ImmType ImmT = Imm8; -} -class AVX512PDIi8Base : PD { - Domain ExeDomain = SSEPackedDouble; - ImmType ImmT = Imm8; -} -class AVX512AIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[HasAVX512]>; -class AVX512AIi8Base : TAPD { - ImmType ImmT = Imm8; -} -class AVX512Ii8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, - Requires<[HasAVX512]>; -class AVX512PDI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, - Requires<[HasAVX512]>; -class AVX512PSI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, - Requires<[HasAVX512]>; -class AVX512PIi8 o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : Ii8, Requires<[HasAVX512]>; -class AVX512PI o, Format F, dag outs, dag ins, string asm, - list pattern, Domain d> - : I, Requires<[HasAVX512]>; -class AVX512FMA3S o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - EVEX_4V, Requires<[HasAVX512]>; - -class AVX512 o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, Requires<[HasAVX512]>; - -// AES Instruction Templates: -// -// AES8I -// These use the same encoding as the SSE4.2 T8 and TA encodings. -class AES8I o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - Requires<[NoAVX, HasAES]>; - -class AESAI o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, TAPD, - Requires<[NoAVX, HasAES]>; - -// PCLMUL Instruction Templates -class PCLMULIi8 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8, TAPD; - -// FMA3 Instruction Templates -class FMA3 o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoVLX]>; -class FMA3S o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoAVX512]>; -class FMA3S_Int o, Format F, dag outs, dag ins, string asm, - listpattern> - : I, T8PD, - VEX_4V, FMASC, Requires<[HasFMA, NoAVX512]>; - -// FMA4 Instruction Templates -class FMA4 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4, NoVLX]>; -class FMA4S o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4, NoAVX512]>; -class FMA4S_Int o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, FMASC, Requires<[HasFMA4]>; - -// XOP 2, 3 and 4 Operand Instruction Template -class IXOP o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, - XOP9, Requires<[HasXOP]>; - -// XOP 2 and 3 Operand Instruction Templates with imm byte -class IXOPi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, - XOP8, Requires<[HasXOP]>; -// XOP 4 Operand Instruction Templates with imm byte -class IXOPi8Reg o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8Reg, - XOP8, Requires<[HasXOP]>; - -// XOP 5 operand instruction (VEX encoding!) -class IXOP5 o, Format F, dag outs, dag ins, string asm, - listpattern> - : Ii8Reg, TAPD, - VEX_4V, Requires<[HasXOP]>; - -// X86-64 Instruction templates... -// - -class RI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, REX_W; -class RIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, REX_W; -class RIi16 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii16, REX_W; -class RIi32 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii32, REX_W; -class RIi32S o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii32S, REX_W; -class RIi64 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii64, REX_W; - -class RS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : S2I, REX_W; -class VRS2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : VS2I, REX_W; - -// MMX Instruction templates -// - -// MMXI - MMX instructions with TB prefix. -// MMXI32 - MMX instructions with TB prefix valid only in 32 bit mode. -// MMXI64 - MMX instructions with TB prefix valid only in 64 bit mode. -// MMX2I - MMX / SSE2 instructions with PD prefix. -// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. -// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. -// MMXID - MMX instructions with XD prefix. -// MMXIS - MMX instructions with XS prefix. -class MMXI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX]>; -class MMXI32 o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX,Not64BitMode]>; -class MMXI64 o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, Requires<[HasMMX,In64BitMode]>; -class MMXRI o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PS, REX_W, - Requires<[HasMMX,In64BitMode]>; -class MMX2I o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, PD, Requires<[HasMMX]>; -class MMXIi8 o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, PS, Requires<[HasMMX]>; -class MMXID o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XD, Requires<[HasMMX]>; -class MMXIS o, Format F, dag outs, dag ins, string asm, - list pattern> - : Ii8, XS, Requires<[HasMMX]>; diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td new file mode 100644 index 0000000000000..adf527d72f5b4 --- /dev/null +++ b/llvm/lib/Target/X86/X86InstrFragments.td @@ -0,0 +1,841 @@ +//===----------X86InstrFragments - X86 Pattern fragments. --*- 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 +// +//===----------------------------------------------------------------------===// + +// X86-specific DAG node. +def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>, + SDTCisSameAs<1, 2>]>; +def SDTX86FCmp : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisFP<1>, + SDTCisSameAs<1, 2>]>; + +def SDTX86Cmov : SDTypeProfile<1, 4, + [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, + SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; + +// Unary and binary operator instructions that set EFLAGS as a side-effect. +def SDTUnaryArithWithFlags : SDTypeProfile<2, 1, + [SDTCisSameAs<0, 2>, + SDTCisInt<0>, SDTCisVT<1, i32>]>; + +def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, + [SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>, + SDTCisInt<0>, SDTCisVT<1, i32>]>; + +// SDTBinaryArithWithFlagsInOut - RES1, EFLAGS = op LHS, RHS, EFLAGS +def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3, + [SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>, + SDTCisInt<0>, + SDTCisVT<1, i32>, + SDTCisVT<4, i32>]>; +// RES1, RES2, FLAGS = op LHS, RHS +def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2, + [SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>, + SDTCisInt<0>, SDTCisVT<1, i32>]>; +def SDTX86BrCond : SDTypeProfile<0, 3, + [SDTCisVT<0, OtherVT>, + SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; + +def SDTX86SetCC : SDTypeProfile<1, 2, + [SDTCisVT<0, i8>, + SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; +def SDTX86SetCC_C : SDTypeProfile<1, 2, + [SDTCisInt<0>, + SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; + +def SDTX86sahf : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i8>]>; + +def SDTX86rdrand : SDTypeProfile<2, 0, [SDTCisInt<0>, SDTCisVT<1, i32>]>; + +def SDTX86rdpkru : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; +def SDTX86wrpkru : SDTypeProfile<0, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>]>; + +def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, + SDTCisVT<2, i8>]>; +def SDTX86cas8pair : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; +def SDTX86cas16pair : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i64>]>; + +def SDTLockBinaryArithWithFlags : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, + SDTCisPtrTy<1>, + SDTCisInt<2>]>; + +def SDTLockUnaryArithWithFlags : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, + SDTCisPtrTy<1>]>; + +def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; + +def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, + SDTCisVT<1, i32>]>; +def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, + SDTCisVT<1, i32>]>; + +def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; + +def SDT_X86NtBrind : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; + +def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, + SDTCisPtrTy<1>]>; + +def SDT_X86VAARG : SDTypeProfile<1, -1, [SDTCisPtrTy<0>, + SDTCisPtrTy<1>, + SDTCisVT<2, i32>, + SDTCisVT<3, i8>, + SDTCisVT<4, i32>]>; + +def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; + +def SDTX86Void : SDTypeProfile<0, 0, []>; + +def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; + +def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + +def SDT_X86TLSBASEADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + +def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + +def SDT_X86DYN_ALLOCA : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; + +def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; + +def SDT_X86PROBED_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; + +def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + +def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; + +def SDT_X86ENQCMD : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, + SDTCisPtrTy<1>, SDTCisSameAs<1, 2>]>; + +def SDT_X86AESENCDECKL : SDTypeProfile<2, 2, [SDTCisVT<0, v2i64>, + SDTCisVT<1, i32>, + SDTCisVT<2, v2i64>, + SDTCisPtrTy<3>]>; + +def SDTX86Cmpccxadd : SDTypeProfile<1, 4, [SDTCisSameAs<0, 2>, + SDTCisPtrTy<1>, SDTCisSameAs<2, 3>, + SDTCisVT<4, i8>]>; + +def X86MFence : SDNode<"X86ISD::MFENCE", SDTNone, [SDNPHasChain]>; + + +def X86bsf : SDNode<"X86ISD::BSF", SDTUnaryArithWithFlags>; +def X86bsr : SDNode<"X86ISD::BSR", SDTUnaryArithWithFlags>; +def X86fshl : SDNode<"X86ISD::FSHL", SDTIntShiftDOp>; +def X86fshr : SDNode<"X86ISD::FSHR", SDTIntShiftDOp>; + +def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest>; +def X86fcmp : SDNode<"X86ISD::FCMP", SDTX86FCmp>; +def X86strict_fcmp : SDNode<"X86ISD::STRICT_FCMP", SDTX86FCmp, [SDNPHasChain]>; +def X86strict_fcmps : SDNode<"X86ISD::STRICT_FCMPS", SDTX86FCmp, [SDNPHasChain]>; +def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>; + +def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>; +def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, + [SDNPHasChain]>; +def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; +def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; + +def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand, + [SDNPHasChain, SDNPSideEffect]>; + +def X86rdseed : SDNode<"X86ISD::RDSEED", SDTX86rdrand, + [SDNPHasChain, SDNPSideEffect]>; + +def X86rdpkru : SDNode<"X86ISD::RDPKRU", SDTX86rdpkru, + [SDNPHasChain, SDNPSideEffect]>; +def X86wrpkru : SDNode<"X86ISD::WRPKRU", SDTX86wrpkru, + [SDNPHasChain, SDNPSideEffect]>; + +def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, + [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86cas8pair, + [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; +def X86cas16 : SDNode<"X86ISD::LCMPXCHG16_DAG", SDTX86cas16pair, + [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, + SDNPMayLoad, SDNPMemOperand]>; + +def X86retglue : SDNode<"X86ISD::RET_GLUE", SDTX86Ret, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def X86iret : SDNode<"X86ISD::IRET", SDTX86Ret, + [SDNPHasChain, SDNPOptInGlue]>; + +def X86vastart_save_xmm_regs : + SDNode<"X86ISD::VASTART_SAVE_XMM_REGS", + SDT_X86VASTART_SAVE_XMM_REGS, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPVariadic]>; +def X86vaarg64 : + SDNode<"X86ISD::VAARG_64", SDT_X86VAARG, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore, + SDNPMemOperand]>; +def X86vaargx32 : + SDNode<"X86ISD::VAARG_X32", SDT_X86VAARG, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore, + SDNPMemOperand]>; +def X86callseq_start : + SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def X86callseq_end : + SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, + SDNPVariadic]>; + +def X86call_rvmarker : SDNode<"X86ISD::CALL_RVMARKER", SDT_X86Call, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, + SDNPVariadic]>; + + +def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, + SDNPVariadic]>; +def X86NoTrackBrind : SDNode<"X86ISD::NT_BRIND", SDT_X86NtBrind, + [SDNPHasChain]>; + +def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, + [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore]>; +def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, + [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, + SDNPMayLoad]>; + +def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; +def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; + +def X86RecoverFrameAlloc : SDNode<"ISD::LOCAL_RECOVER", + SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, + SDTCisInt<1>]>>; + +def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, + [SDNPHasChain]>; + +def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", + SDTypeProfile<1, 1, [SDTCisInt<0>, + SDTCisPtrTy<1>]>, + [SDNPHasChain, SDNPSideEffect]>; +def X86eh_sjlj_longjmp : SDNode<"X86ISD::EH_SJLJ_LONGJMP", + SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, + [SDNPHasChain, SDNPSideEffect]>; +def X86eh_sjlj_setup_dispatch : SDNode<"X86ISD::EH_SJLJ_SETUP_DISPATCH", + SDTypeProfile<0, 0, []>, + [SDNPHasChain, SDNPSideEffect]>; + +def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + +def X86add_flag : SDNode<"X86ISD::ADD", SDTBinaryArithWithFlags, + [SDNPCommutative]>; +def X86sub_flag : SDNode<"X86ISD::SUB", SDTBinaryArithWithFlags>; +def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags, + [SDNPCommutative]>; +def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags, + [SDNPCommutative]>; +def X86adc_flag : SDNode<"X86ISD::ADC", SDTBinaryArithWithFlagsInOut>; +def X86sbb_flag : SDNode<"X86ISD::SBB", SDTBinaryArithWithFlagsInOut>; + +def X86or_flag : SDNode<"X86ISD::OR", SDTBinaryArithWithFlags, + [SDNPCommutative]>; +def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags, + [SDNPCommutative]>; +def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, + [SDNPCommutative]>; + +def X86lock_add : SDNode<"X86ISD::LADD", SDTLockBinaryArithWithFlags, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, + SDNPMemOperand]>; +def X86lock_sub : SDNode<"X86ISD::LSUB", SDTLockBinaryArithWithFlags, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, + SDNPMemOperand]>; +def X86lock_or : SDNode<"X86ISD::LOR", SDTLockBinaryArithWithFlags, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, + SDNPMemOperand]>; +def X86lock_xor : SDNode<"X86ISD::LXOR", SDTLockBinaryArithWithFlags, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, + SDNPMemOperand]>; +def X86lock_and : SDNode<"X86ISD::LAND", SDTLockBinaryArithWithFlags, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, + SDNPMemOperand]>; + +def X86bextr : SDNode<"X86ISD::BEXTR", SDTIntBinOp>; +def X86bextri : SDNode<"X86ISD::BEXTRI", SDTIntBinOp>; + +def X86bzhi : SDNode<"X86ISD::BZHI", SDTIntBinOp>; + +def X86pdep : SDNode<"X86ISD::PDEP", SDTIntBinOp>; +def X86pext : SDNode<"X86ISD::PEXT", SDTIntBinOp>; + +def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; + +def X86DynAlloca : SDNode<"X86ISD::DYN_ALLOCA", SDT_X86DYN_ALLOCA, + [SDNPHasChain, SDNPOutGlue]>; + +def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA, + [SDNPHasChain]>; + +def X86ProbedAlloca : SDNode<"X86ISD::PROBED_ALLOCA", SDT_X86PROBED_ALLOCA, + [SDNPHasChain]>; + +def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def X86lwpins : SDNode<"X86ISD::LWPINS", + SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, + SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>; + +def X86umwait : SDNode<"X86ISD::UMWAIT", + SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, + SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, + [SDNPHasChain, SDNPSideEffect]>; + +def X86tpause : SDNode<"X86ISD::TPAUSE", + SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, + SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, + [SDNPHasChain, SDNPSideEffect]>; + +def X86enqcmd : SDNode<"X86ISD::ENQCMD", SDT_X86ENQCMD, + [SDNPHasChain, SDNPSideEffect]>; +def X86enqcmds : SDNode<"X86ISD::ENQCMDS", SDT_X86ENQCMD, + [SDNPHasChain, SDNPSideEffect]>; +def X86testui : SDNode<"X86ISD::TESTUI", + SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>, + [SDNPHasChain, SDNPSideEffect]>; + +def X86aesenc128kl : SDNode<"X86ISD::AESENC128KL", SDT_X86AESENCDECKL, + [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, + SDNPMemOperand]>; +def X86aesdec128kl : SDNode<"X86ISD::AESDEC128KL", SDT_X86AESENCDECKL, + [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, + SDNPMemOperand]>; +def X86aesenc256kl : SDNode<"X86ISD::AESENC256KL", SDT_X86AESENCDECKL, + [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, + SDNPMemOperand]>; +def X86aesdec256kl : SDNode<"X86ISD::AESDEC256KL", SDT_X86AESENCDECKL, + [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, + SDNPMemOperand]>; + +def X86cmpccxadd : SDNode<"X86ISD::CMPCCXADD", SDTX86Cmpccxadd, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore, + SDNPMemOperand]>; + +// Define X86-specific addressing mode. +def addr : ComplexPattern; +def lea32addr : ComplexPattern; +// In 64-bit mode 32-bit LEAs can use RIP-relative addressing. +def lea64_32addr : ComplexPattern; + +def tls32addr : ComplexPattern; + +def tls32baseaddr : ComplexPattern; + +def lea64addr : ComplexPattern; + +def tls64addr : ComplexPattern; + +def tls64baseaddr : ComplexPattern; + +def vectoraddr : ComplexPattern; + +// A relocatable immediate is an operand that can be relocated by the linker to +// an immediate, such as a regular symbol in non-PIC code. +def relocImm : ComplexPattern; + +// X86 specific condition code. These correspond to CondCode in +// X86InstrInfo.h. They must be kept in synch. +def X86_COND_O : PatLeaf<(i8 0)>; +def X86_COND_NO : PatLeaf<(i8 1)>; +def X86_COND_B : PatLeaf<(i8 2)>; // alt. COND_C +def X86_COND_AE : PatLeaf<(i8 3)>; // alt. COND_NC +def X86_COND_E : PatLeaf<(i8 4)>; // alt. COND_Z +def X86_COND_NE : PatLeaf<(i8 5)>; // alt. COND_NZ +def X86_COND_BE : PatLeaf<(i8 6)>; // alt. COND_NA +def X86_COND_A : PatLeaf<(i8 7)>; // alt. COND_NBE +def X86_COND_S : PatLeaf<(i8 8)>; +def X86_COND_NS : PatLeaf<(i8 9)>; +def X86_COND_P : PatLeaf<(i8 10)>; // alt. COND_PE +def X86_COND_NP : PatLeaf<(i8 11)>; // alt. COND_PO +def X86_COND_L : PatLeaf<(i8 12)>; // alt. COND_NGE +def X86_COND_GE : PatLeaf<(i8 13)>; // alt. COND_NL +def X86_COND_LE : PatLeaf<(i8 14)>; // alt. COND_NG +def X86_COND_G : PatLeaf<(i8 15)>; // alt. COND_NLE + +def i16immSExt8 : ImmLeaf(Imm); }]>; +def i32immSExt8 : ImmLeaf(Imm); }]>; +def i64immSExt8 : ImmLeaf(Imm); }]>; +def i64immSExt32 : ImmLeaf(Imm); }]>; +def i64timmSExt32 : TImmLeaf(Imm); }]>; + +def i16relocImmSExt8 : PatLeaf<(i16 relocImm), [{ + return isSExtAbsoluteSymbolRef(8, N); +}]>; +def i32relocImmSExt8 : PatLeaf<(i32 relocImm), [{ + return isSExtAbsoluteSymbolRef(8, N); +}]>; +def i64relocImmSExt8 : PatLeaf<(i64 relocImm), [{ + return isSExtAbsoluteSymbolRef(8, N); +}]>; +def i64relocImmSExt32 : PatLeaf<(i64 relocImm), [{ + return isSExtAbsoluteSymbolRef(32, N); +}]>; + +// If we have multiple users of an immediate, it's much smaller to reuse +// the register, rather than encode the immediate in every instruction. +// This has the risk of increasing register pressure from stretched live +// ranges, however, the immediates should be trivial to rematerialize by +// the RA in the event of high register pressure. +// TODO : This is currently enabled for stores and binary ops. There are more +// cases for which this can be enabled, though this catches the bulk of the +// issues. +// TODO2 : This should really also be enabled under O2, but there's currently +// an issue with RA where we don't pull the constants into their users +// when we rematerialize them. I'll follow-up on enabling O2 after we fix that +// issue. +// TODO3 : This is currently limited to single basic blocks (DAG creation +// pulls block immediates to the top and merges them if necessary). +// Eventually, it would be nice to allow ConstantHoisting to merge constants +// globally for potentially added savings. +// +def imm_su : PatLeaf<(imm), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def i64immSExt32_su : PatLeaf<(i64immSExt32), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; + +def relocImm8_su : PatLeaf<(i8 relocImm), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def relocImm16_su : PatLeaf<(i16 relocImm), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def relocImm32_su : PatLeaf<(i32 relocImm), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; + +def i16relocImmSExt8_su : PatLeaf<(i16relocImmSExt8), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def i32relocImmSExt8_su : PatLeaf<(i32relocImmSExt8), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def i64relocImmSExt8_su : PatLeaf<(i64relocImmSExt8), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def i64relocImmSExt32_su : PatLeaf<(i64relocImmSExt32), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; + +def i16immSExt8_su : PatLeaf<(i16immSExt8), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def i32immSExt8_su : PatLeaf<(i32immSExt8), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; +def i64immSExt8_su : PatLeaf<(i64immSExt8), [{ + return !shouldAvoidImmediateInstFormsForSize(N); +}]>; + +// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit +// unsigned field. +def i64immZExt32 : ImmLeaf(Imm); }]>; + +def i64immZExt32SExt8 : ImmLeaf(Imm) && isInt<8>(static_cast(Imm)); +}]>; + +// Helper fragments for loads. + +// It's safe to fold a zextload/extload from i1 as a regular i8 load. The +// upper bits are guaranteed to be zero and we were going to emit a MOV8rm +// which might get folded during peephole anyway. +def loadi8 : PatFrag<(ops node:$ptr), (i8 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + ISD::LoadExtType ExtType = LD->getExtensionType(); + return ExtType == ISD::NON_EXTLOAD || ExtType == ISD::EXTLOAD || + ExtType == ISD::ZEXTLOAD; +}]>; + +// It's always safe to treat a anyext i16 load as a i32 load if the i16 is +// known to be 32-bit aligned or better. Ditto for i8 to i16. +def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::NON_EXTLOAD) + return true; + if (ExtType == ISD::EXTLOAD && EnablePromoteAnyextLoad) + return LD->getAlign() >= 2 && LD->isSimple(); + return false; +}]>; + +def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::NON_EXTLOAD) + return true; + if (ExtType == ISD::EXTLOAD && EnablePromoteAnyextLoad) + return LD->getAlign() >= 4 && LD->isSimple(); + return false; +}]>; + +def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>; +def loadf16 : PatFrag<(ops node:$ptr), (f16 (load node:$ptr))>; +def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>; +def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>; +def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>; +def loadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr))>; +def alignedloadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ + LoadSDNode *Ld = cast(N); + return Ld->getAlign() >= Ld->getMemoryVT().getStoreSize(); +}]>; +def memopf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ + LoadSDNode *Ld = cast(N); + return Subtarget->hasSSEUnalignedMem() || + Ld->getAlign() >= Ld->getMemoryVT().getStoreSize(); +}]>; + +def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; +def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; +def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; +def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>; +def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>; +def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>; + +def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; +def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; +def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; +def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; +def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; +def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; +def zextloadi64i1 : PatFrag<(ops node:$ptr), (i64 (zextloadi1 node:$ptr))>; +def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>; +def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>; +def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>; + +def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; +def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; +def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; +def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; +def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; +def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; +def extloadi64i1 : PatFrag<(ops node:$ptr), (i64 (extloadi1 node:$ptr))>; +def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>; +def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>; + +// We can treat an i8/i16 extending load to i64 as a 32 bit load if its known +// to be 4 byte aligned or better. +def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (unindexedload node:$ptr)), [{ + LoadSDNode *LD = cast(N); + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType != ISD::EXTLOAD) + return false; + if (LD->getMemoryVT() == MVT::i32) + return true; + + return LD->getAlign() >= 4 && LD->isSimple(); +}]>; + +// binary op with only one user +class binop_oneuse + : PatFrag<(ops node:$A, node:$B), + (operator node:$A, node:$B), [{ + return N->hasOneUse(); +}]>; + +def add_su : binop_oneuse; +def and_su : binop_oneuse; +def srl_su : binop_oneuse; + +// unary op with only one user +class unop_oneuse + : PatFrag<(ops node:$A), + (operator node:$A), [{ + return N->hasOneUse(); +}]>; + + +def ineg_su : unop_oneuse; +def trunc_su : unop_oneuse; + +def X86add_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86add_flag node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 1)); +}]>; + +def X86sub_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86sub_flag node:$lhs, node:$rhs), [{ + // Only use DEC if the result is used. + return !SDValue(N, 0).use_empty() && hasNoCarryFlagUses(SDValue(N, 1)); +}]>; + +def X86testpat : PatFrag<(ops node:$lhs, node:$rhs), + (X86cmp (and_su node:$lhs, node:$rhs), 0)>; + + +def X86any_fcmp : PatFrags<(ops node:$lhs, node:$rhs), + [(X86strict_fcmp node:$lhs, node:$rhs), + (X86fcmp node:$lhs, node:$rhs)]>; + +// PREFETCHWT1 is supported we want to use it for everything but T0. +def PrefetchWLevel : PatFrag<(ops), (i32 timm), [{ + return N->getSExtValue() == 3 || !Subtarget->hasPREFETCHWT1(); +}]>; + +// Use PREFETCHWT1 for NTA, T2, T1. +def PrefetchWT1Level : TImmLeaf; + +def X86lock_add_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86lock_add node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 0)); +}]>; + +def X86lock_sub_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86lock_sub node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 0)); +}]>; + +def X86tcret_6regs : PatFrag<(ops node:$ptr, node:$off), + (X86tcret node:$ptr, node:$off), [{ + // X86tcret args: (*chain, ptr, imm, regs..., glue) + unsigned NumRegs = 0; + for (unsigned i = 3, e = N->getNumOperands(); i != e; ++i) + if (isa(N->getOperand(i)) && ++NumRegs > 6) + return false; + return true; +}]>; + +def X86tcret_1reg : PatFrag<(ops node:$ptr, node:$off), + (X86tcret node:$ptr, node:$off), [{ + // X86tcret args: (*chain, ptr, imm, regs..., glue) + unsigned NumRegs = 1; + const SDValue& BasePtr = cast(N->getOperand(1))->getBasePtr(); + if (isa(BasePtr)) + NumRegs = 3; + else if (BasePtr->getNumOperands() && isa(BasePtr->getOperand(0))) + NumRegs = 3; + for (unsigned i = 3, e = N->getNumOperands(); i != e; ++i) + if (isa(N->getOperand(i)) && ( NumRegs-- == 0)) + return false; + return true; +}]>; + +// If this is an anyext of the remainder of an 8-bit sdivrem, use a MOVSX +// instead of a MOVZX. The sdivrem lowering will emit emit a MOVSX to move +// %ah to the lower byte of a register. By using a MOVSX here we allow a +// post-isel peephole to merge the two MOVSX instructions into one. +def anyext_sdiv : PatFrag<(ops node:$lhs), (anyext node:$lhs),[{ + return (N->getOperand(0).getOpcode() == ISD::SDIVREM && + N->getOperand(0).getResNo() == 1); +}]>; + +// Any instruction that defines a 32-bit result leaves the high half of the +// register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may +// be copying from a truncate. AssertSext/AssertZext/AssertAlign aren't saying +// anything about the upper 32 bits, they're probably just qualifying a +// CopyFromReg. FREEZE may be coming from a a truncate. Any other 32-bit +// operation will zero-extend up to 64 bits. +def def32 : PatLeaf<(i32 GR32:$src), [{ + return N->getOpcode() != ISD::TRUNCATE && + N->getOpcode() != TargetOpcode::EXTRACT_SUBREG && + N->getOpcode() != ISD::CopyFromReg && + N->getOpcode() != ISD::AssertSext && + N->getOpcode() != ISD::AssertZext && + N->getOpcode() != ISD::AssertAlign && + N->getOpcode() != ISD::FREEZE; +}]>; + +// Treat an 'or' node is as an 'add' if the or'ed bits are known to be zero. +def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ + if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) + return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue()); + + KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0); + KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0); + return (~Known0.Zero & ~Known1.Zero) == 0; +}]>; + +def shiftMask8 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ + return isUnneededShiftMask(N, 3); +}]>; + +def shiftMask16 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ + return isUnneededShiftMask(N, 4); +}]>; + +def shiftMask32 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ + return isUnneededShiftMask(N, 5); +}]>; + +def shiftMask64 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{ + return isUnneededShiftMask(N, 6); +}]>; + +//===----------------------------------------------------------------------===// +// Pattern fragments to auto generate BMI instructions. +//===----------------------------------------------------------------------===// + +def or_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86or_flag node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 1)); +}]>; + +def xor_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86xor_flag node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 1)); +}]>; + +def and_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), + (X86and_flag node:$lhs, node:$rhs), [{ + return hasNoCarryFlagUses(SDValue(N, 1)); +}]>; + +//===----------------------------------------------------------------------===// +// FPStack specific DAG Nodes. +//===----------------------------------------------------------------------===// + +def SDTX86Fld : SDTypeProfile<1, 1, [SDTCisFP<0>, + SDTCisPtrTy<1>]>; +def SDTX86Fst : SDTypeProfile<0, 2, [SDTCisFP<0>, + SDTCisPtrTy<1>]>; +def SDTX86Fild : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisPtrTy<1>]>; +def SDTX86Fist : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; + +def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; +def SDTX86CwdLoad : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; +def SDTX86FPEnv : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; + +def X86fp80_add : SDNode<"X86ISD::FP80_ADD", SDTFPBinOp, [SDNPCommutative]>; +def X86strict_fp80_add : SDNode<"X86ISD::STRICT_FP80_ADD", SDTFPBinOp, + [SDNPHasChain,SDNPCommutative]>; +def any_X86fp80_add : PatFrags<(ops node:$lhs, node:$rhs), + [(X86strict_fp80_add node:$lhs, node:$rhs), + (X86fp80_add node:$lhs, node:$rhs)]>; + +def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def X86fist : SDNode<"X86ISD::FIST", SDTX86Fist, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def X86fp_to_mem : SDNode<"X86ISD::FP_TO_INT_IN_MEM", SDTX86Fst, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, + [SDNPHasChain, SDNPMayStore, SDNPSideEffect, + SDNPMemOperand]>; +def X86fp_cwd_set16 : SDNode<"X86ISD::FLDCW16m", SDTX86CwdLoad, + [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, + SDNPMemOperand]>; +def X86fpenv_get : SDNode<"X86ISD::FNSTENVm", SDTX86FPEnv, + [SDNPHasChain, SDNPMayStore, SDNPSideEffect, + SDNPMemOperand]>; +def X86fpenv_set : SDNode<"X86ISD::FLDENVm", SDTX86FPEnv, + [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, + SDNPMemOperand]>; + +def X86fstf32 : PatFrag<(ops node:$val, node:$ptr), + (X86fst node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; +def X86fstf64 : PatFrag<(ops node:$val, node:$ptr), + (X86fst node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f64; +}]>; +def X86fstf80 : PatFrag<(ops node:$val, node:$ptr), + (X86fst node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f80; +}]>; + +def X86fldf32 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; +def X86fldf64 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f64; +}]>; +def X86fldf80 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f80; +}]>; + +def X86fild16 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def X86fild32 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def X86fild64 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i64; +}]>; + +def X86fist32 : PatFrag<(ops node:$val, node:$ptr), + (X86fist node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; + +def X86fist64 : PatFrag<(ops node:$val, node:$ptr), + (X86fist node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i64; +}]>; + +def X86fp_to_i16mem : PatFrag<(ops node:$val, node:$ptr), + (X86fp_to_mem node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def X86fp_to_i32mem : PatFrag<(ops node:$val, node:$ptr), + (X86fp_to_mem node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def X86fp_to_i64mem : PatFrag<(ops node:$val, node:$ptr), + (X86fp_to_mem node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i64; +}]>; + +//===----------------------------------------------------------------------===// +// FPStack pattern fragments +//===----------------------------------------------------------------------===// + +def fpimm0 : FPImmLeaf; + +def fpimmneg0 : FPImmLeaf; + +def fpimm1 : FPImmLeaf; + +def fpimmneg1 : FPImmLeaf; diff --git a/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td b/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td index 9c1f33e6f975d..f86e15b3ed5d5 100644 --- a/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td +++ b/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td @@ -1045,10 +1045,6 @@ def sse_load_f64 : PatFrags<(ops node:$ptr), (v2f64 (X86vzload64 node:$ptr)), (v2f64 (scalar_to_vector (loadf64 node:$ptr)))]>; -def shmem : X86MemOperand<"printwordmem", X86Mem16AsmOperand>; -def ssmem : X86MemOperand<"printdwordmem", X86Mem32AsmOperand>; -def sdmem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand>; - def fp16imm0 : PatLeaf<(f16 fpimm), [{ return N->isExactlyValue(+0.0); }]>; @@ -1263,3 +1259,116 @@ def masked_truncstore_us_vi32 : PatFrag<(ops node:$src1, node:$src2, node:$src3) (X86MTruncUSStore node:$src1, node:$src2, node:$src3), [{ return cast(N)->getMemoryVT().getScalarType() == MVT::i32; }]>; + +def X86Vfpclasss_su : PatFrag<(ops node:$src1, node:$src2), + (X86Vfpclasss node:$src1, node:$src2), [{ + return N->hasOneUse(); +}]>; + +def X86Vfpclass_su : PatFrag<(ops node:$src1, node:$src2), + (X86Vfpclass node:$src1, node:$src2), [{ + return N->hasOneUse(); +}]>; + +// These nodes use 'vnot' instead of 'not' to support vectors. +def vandn : PatFrag<(ops node:$i0, node:$i1), (and (vnot node:$i0), node:$i1)>; +def vxnor : PatFrag<(ops node:$i0, node:$i1), (vnot (xor node:$i0, node:$i1))>; + +// Used for matching masked operations. Ensures the operation part only has a +// single use. +def vselect_mask : PatFrag<(ops node:$mask, node:$src1, node:$src2), + (vselect node:$mask, node:$src1, node:$src2), [{ + return isProfitableToFormMaskedOp(N); +}]>; + +def X86selects_mask : PatFrag<(ops node:$mask, node:$src1, node:$src2), + (X86selects node:$mask, node:$src1, node:$src2), [{ + return isProfitableToFormMaskedOp(N); +}]>; + +def X86cmpms_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), + (X86cmpms node:$src1, node:$src2, node:$cc), [{ + return N->hasOneUse(); +}]>; +def X86cmpmsSAE_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), + (X86cmpmsSAE node:$src1, node:$src2, node:$cc), [{ + return N->hasOneUse(); +}]>; + +// PatFrags that contain a select and a truncate op. The take operands in the +// same order as X86vmtrunc, X86vmtruncs, X86vmtruncus. This allows us to pass +// either to the multiclasses. +def select_trunc : PatFrag<(ops node:$src, node:$src0, node:$mask), + (vselect_mask node:$mask, + (trunc node:$src), node:$src0)>; +def select_truncs : PatFrag<(ops node:$src, node:$src0, node:$mask), + (vselect_mask node:$mask, + (X86vtruncs node:$src), node:$src0)>; +def select_truncus : PatFrag<(ops node:$src, node:$src0, node:$mask), + (vselect_mask node:$mask, + (X86vtruncus node:$src), node:$src0)>; + +def X86Vpshufbitqmb_su : PatFrag<(ops node:$src1, node:$src2), + (X86Vpshufbitqmb node:$src1, node:$src2), [{ + return N->hasOneUse(); +}]>; + +// This fragment treats X86cmpm as commutable to help match loads in both +// operands for PCMPEQ. +def X86setcc_commute : SDNode<"ISD::SETCC", SDTSetCC, [SDNPCommutative]>; +def X86pcmpgtm : PatFrag<(ops node:$src1, node:$src2), + (setcc node:$src1, node:$src2, SETGT)>; + +def X86pcmpm_imm : SDNodeXForm(N->getOperand(2))->get(); + uint8_t SSECC = X86::getVPCMPImmForCond(CC); + return getI8Imm(SSECC, SDLoc(N)); +}]>; + +// Swapped operand version of the above. +def X86pcmpm_imm_commute : SDNodeXForm(N->getOperand(2))->get(); + uint8_t SSECC = X86::getVPCMPImmForCond(CC); + SSECC = X86::getSwappedVPCMPImm(SSECC); + return getI8Imm(SSECC, SDLoc(N)); +}]>; + +def X86pcmpm : PatFrag<(ops node:$src1, node:$src2, node:$cc), + (setcc node:$src1, node:$src2, node:$cc), [{ + ISD::CondCode CC = cast(N->getOperand(2))->get(); + return !ISD::isUnsignedIntSetCC(CC); +}], X86pcmpm_imm>; + +def X86pcmpm_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), + (setcc node:$src1, node:$src2, node:$cc), [{ + ISD::CondCode CC = cast(N->getOperand(2))->get(); + return N->hasOneUse() && !ISD::isUnsignedIntSetCC(CC); +}], X86pcmpm_imm>; + +def X86pcmpum : PatFrag<(ops node:$src1, node:$src2, node:$cc), + (setcc node:$src1, node:$src2, node:$cc), [{ + ISD::CondCode CC = cast(N->getOperand(2))->get(); + return ISD::isUnsignedIntSetCC(CC); +}], X86pcmpm_imm>; + +def X86pcmpum_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), + (setcc node:$src1, node:$src2, node:$cc), [{ + ISD::CondCode CC = cast(N->getOperand(2))->get(); + return N->hasOneUse() && ISD::isUnsignedIntSetCC(CC); +}], X86pcmpm_imm>; + +def X86cmpm_su : PatFrag<(ops node:$src1, node:$src2, node:$cc), + (X86cmpm node:$src1, node:$src2, node:$cc), [{ + return N->hasOneUse(); +}]>; + +def X86cmpm_imm_commute : SDNodeXFormgetZExtValue() & 0x1f); + return getI8Imm(Imm, SDLoc(N)); +}]>; + +def X86vpmaddwd_su : PatFrag<(ops node:$lhs, node:$rhs), + (X86vpmaddwd node:$lhs, node:$rhs), [{ + return N->hasOneUse(); +}]>; + diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 9ec09ac3d28e2..ee54796323b82 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -6,1413 +6,36 @@ // //===----------------------------------------------------------------------===// // -// This file describes the X86 properties of the instructions which are needed +// This file describes the X86 properties of the instructions which are needed // for code generation, machine code emission, and analysis. // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -// X86 specific DAG Nodes. +// X86 Pattern fragments. // - -def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisSameAs<1, 2>]>; -def SDTX86FCmp : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisFP<1>, - SDTCisSameAs<1, 2>]>; - -def SDTX86Cmov : SDTypeProfile<1, 4, - [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i8>, SDTCisVT<4, i32>]>; - -// Unary and binary operator instructions that set EFLAGS as a side-effect. -def SDTUnaryArithWithFlags : SDTypeProfile<2, 1, - [SDTCisSameAs<0, 2>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; - -// SDTBinaryArithWithFlagsInOut - RES1, EFLAGS = op LHS, RHS, EFLAGS -def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3, - [SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, - SDTCisVT<1, i32>, - SDTCisVT<4, i32>]>; -// RES1, RES2, FLAGS = op LHS, RHS -def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2, - [SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>, - SDTCisSameAs<0, 3>, - SDTCisInt<0>, SDTCisVT<1, i32>]>; -def SDTX86BrCond : SDTypeProfile<0, 3, - [SDTCisVT<0, OtherVT>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86SetCC : SDTypeProfile<1, 2, - [SDTCisVT<0, i8>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; -def SDTX86SetCC_C : SDTypeProfile<1, 2, - [SDTCisInt<0>, - SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; - -def SDTX86sahf : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i8>]>; - -def SDTX86rdrand : SDTypeProfile<2, 0, [SDTCisInt<0>, SDTCisVT<1, i32>]>; - -def SDTX86rdpkru : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; -def SDTX86wrpkru : SDTypeProfile<0, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, - SDTCisVT<2, i32>]>; - -def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, - SDTCisVT<2, i8>]>; -def SDTX86cas8pair : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; -def SDTX86cas16pair : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i64>]>; - -def SDTLockBinaryArithWithFlags : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>, - SDTCisInt<2>]>; - -def SDTLockUnaryArithWithFlags : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>]>; - -def SDTX86Ret : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; - -def SDT_X86CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; -def SDT_X86CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, - SDTCisVT<1, i32>]>; - -def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86NtBrind : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, - SDTCisPtrTy<1>]>; - -def SDT_X86VAARG : SDTypeProfile<1, -1, [SDTCisPtrTy<0>, - SDTCisPtrTy<1>, - SDTCisVT<2, i32>, - SDTCisVT<3, i8>, - SDTCisVT<4, i32>]>; - -def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; - -def SDTX86Void : SDTypeProfile<0, 0, []>; - -def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; - -def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSBASEADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86DYN_ALLOCA : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; - -def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; - -def SDT_X86PROBED_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; - -def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; - -def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; - -def SDT_X86ENQCMD : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisPtrTy<1>, SDTCisSameAs<1, 2>]>; - -def SDT_X86AESENCDECKL : SDTypeProfile<2, 2, [SDTCisVT<0, v2i64>, - SDTCisVT<1, i32>, - SDTCisVT<2, v2i64>, - SDTCisPtrTy<3>]>; - -def SDTX86Cmpccxadd : SDTypeProfile<1, 4, [SDTCisSameAs<0, 2>, - SDTCisPtrTy<1>, SDTCisSameAs<2, 3>, - SDTCisVT<4, i8>]>; - -def X86MFence : SDNode<"X86ISD::MFENCE", SDTNone, [SDNPHasChain]>; - - -def X86bsf : SDNode<"X86ISD::BSF", SDTUnaryArithWithFlags>; -def X86bsr : SDNode<"X86ISD::BSR", SDTUnaryArithWithFlags>; -def X86fshl : SDNode<"X86ISD::FSHL", SDTIntShiftDOp>; -def X86fshr : SDNode<"X86ISD::FSHR", SDTIntShiftDOp>; - -def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest>; -def X86fcmp : SDNode<"X86ISD::FCMP", SDTX86FCmp>; -def X86strict_fcmp : SDNode<"X86ISD::STRICT_FCMP", SDTX86FCmp, [SDNPHasChain]>; -def X86strict_fcmps : SDNode<"X86ISD::STRICT_FCMPS", SDTX86FCmp, [SDNPHasChain]>; -def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>; - -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>; -def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, - [SDNPHasChain]>; -def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; -def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; - -def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86rdseed : SDNode<"X86ISD::RDSEED", SDTX86rdrand, - [SDNPHasChain, SDNPSideEffect]>; - -def X86rdpkru : SDNode<"X86ISD::RDPKRU", SDTX86rdpkru, - [SDNPHasChain, SDNPSideEffect]>; -def X86wrpkru : SDNode<"X86ISD::WRPKRU", SDTX86wrpkru, - [SDNPHasChain, SDNPSideEffect]>; - -def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86cas8pair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; -def X86cas16 : SDNode<"X86ISD::LCMPXCHG16_DAG", SDTX86cas16pair, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad, SDNPMemOperand]>; - -def X86retglue : SDNode<"X86ISD::RET_GLUE", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def X86iret : SDNode<"X86ISD::IRET", SDTX86Ret, - [SDNPHasChain, SDNPOptInGlue]>; - -def X86vastart_save_xmm_regs : - SDNode<"X86ISD::VASTART_SAVE_XMM_REGS", - SDT_X86VASTART_SAVE_XMM_REGS, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand, SDNPVariadic]>; -def X86vaarg64 : - SDNode<"X86ISD::VAARG_64", SDT_X86VAARG, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; -def X86vaargx32 : - SDNode<"X86ISD::VAARG_X32", SDT_X86VAARG, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; -def X86callseq_start : - SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, - [SDNPHasChain, SDNPOutGlue]>; -def X86callseq_end : - SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; - -def X86call_rvmarker : SDNode<"X86ISD::CALL_RVMARKER", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; - - -def X86NoTrackCall : SDNode<"X86ISD::NT_CALL", SDT_X86Call, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; -def X86NoTrackBrind : SDNode<"X86ISD::NT_BRIND", SDT_X86NtBrind, - [SDNPHasChain]>; - -def X86rep_stos: SDNode<"X86ISD::REP_STOS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore]>; -def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, - SDNPMayLoad]>; - -def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; -def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>; - -def X86RecoverFrameAlloc : SDNode<"ISD::LOCAL_RECOVER", - SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, - SDTCisInt<1>]>>; - -def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, - [SDNPHasChain]>; - -def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", - SDTypeProfile<1, 1, [SDTCisInt<0>, - SDTCisPtrTy<1>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_longjmp : SDNode<"X86ISD::EH_SJLJ_LONGJMP", - SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, - [SDNPHasChain, SDNPSideEffect]>; -def X86eh_sjlj_setup_dispatch : SDNode<"X86ISD::EH_SJLJ_SETUP_DISPATCH", - SDTypeProfile<0, 0, []>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -def X86add_flag : SDNode<"X86ISD::ADD", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86sub_flag : SDNode<"X86ISD::SUB", SDTBinaryArithWithFlags>; -def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags, - [SDNPCommutative]>; -def X86adc_flag : SDNode<"X86ISD::ADC", SDTBinaryArithWithFlagsInOut>; -def X86sbb_flag : SDNode<"X86ISD::SBB", SDTBinaryArithWithFlagsInOut>; - -def X86or_flag : SDNode<"X86ISD::OR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags, - [SDNPCommutative]>; -def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, - [SDNPCommutative]>; - -def X86lock_add : SDNode<"X86ISD::LADD", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_sub : SDNode<"X86ISD::LSUB", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_or : SDNode<"X86ISD::LOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_xor : SDNode<"X86ISD::LXOR", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; -def X86lock_and : SDNode<"X86ISD::LAND", SDTLockBinaryArithWithFlags, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; - -def X86bextr : SDNode<"X86ISD::BEXTR", SDTIntBinOp>; -def X86bextri : SDNode<"X86ISD::BEXTRI", SDTIntBinOp>; - -def X86bzhi : SDNode<"X86ISD::BZHI", SDTIntBinOp>; - -def X86pdep : SDNode<"X86ISD::PDEP", SDTIntBinOp>; -def X86pext : SDNode<"X86ISD::PEXT", SDTIntBinOp>; - -def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; - -def X86DynAlloca : SDNode<"X86ISD::DYN_ALLOCA", SDT_X86DYN_ALLOCA, - [SDNPHasChain, SDNPOutGlue]>; - -def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA, - [SDNPHasChain]>; - -def X86ProbedAlloca : SDNode<"X86ISD::PROBED_ALLOCA", SDT_X86PROBED_ALLOCA, - [SDNPHasChain]>; - -def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def X86lwpins : SDNode<"X86ISD::LWPINS", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPSideEffect]>; - -def X86umwait : SDNode<"X86ISD::UMWAIT", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86tpause : SDNode<"X86ISD::TPAUSE", - SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisInt<1>, - SDTCisVT<2, i32>, SDTCisVT<3, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86enqcmd : SDNode<"X86ISD::ENQCMD", SDT_X86ENQCMD, - [SDNPHasChain, SDNPSideEffect]>; -def X86enqcmds : SDNode<"X86ISD::ENQCMDS", SDT_X86ENQCMD, - [SDNPHasChain, SDNPSideEffect]>; -def X86testui : SDNode<"X86ISD::TESTUI", - SDTypeProfile<1, 0, [SDTCisVT<0, i32>]>, - [SDNPHasChain, SDNPSideEffect]>; - -def X86aesenc128kl : SDNode<"X86ISD::AESENC128KL", SDT_X86AESENCDECKL, - [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, - SDNPMemOperand]>; -def X86aesdec128kl : SDNode<"X86ISD::AESDEC128KL", SDT_X86AESENCDECKL, - [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, - SDNPMemOperand]>; -def X86aesenc256kl : SDNode<"X86ISD::AESENC256KL", SDT_X86AESENCDECKL, - [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, - SDNPMemOperand]>; -def X86aesdec256kl : SDNode<"X86ISD::AESDEC256KL", SDT_X86AESENCDECKL, - [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, - SDNPMemOperand]>; - -def X86cmpccxadd : SDNode<"X86ISD::CMPCCXADD", SDTX86Cmpccxadd, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore, - SDNPMemOperand]>; +include "X86InstrFragments.td" +include "X86InstrFragmentsSIMD.td" //===----------------------------------------------------------------------===// // X86 Operand Definitions. // - -// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for -// the index operand of an address, to conform to x86 encoding restrictions. -def ptr_rc_nosp : PointerLikeRegClass<1>; - -// *mem - Operand definitions for the funky X86 addressing mode operands. -// -def X86MemAsmOperand : AsmOperandClass { - let Name = "Mem"; -} -let RenderMethod = "addMemOperands", SuperClasses = [X86MemAsmOperand] in { - def X86Mem8AsmOperand : AsmOperandClass { let Name = "Mem8"; } - def X86Mem16AsmOperand : AsmOperandClass { let Name = "Mem16"; } - def X86Mem32AsmOperand : AsmOperandClass { let Name = "Mem32"; } - def X86Mem64AsmOperand : AsmOperandClass { let Name = "Mem64"; } - def X86Mem80AsmOperand : AsmOperandClass { let Name = "Mem80"; } - def X86Mem128AsmOperand : AsmOperandClass { let Name = "Mem128"; } - def X86Mem256AsmOperand : AsmOperandClass { let Name = "Mem256"; } - def X86Mem512AsmOperand : AsmOperandClass { let Name = "Mem512"; } - // Gather mem operands - def X86Mem64_RC128Operand : AsmOperandClass { let Name = "Mem64_RC128"; } - def X86Mem128_RC128Operand : AsmOperandClass { let Name = "Mem128_RC128"; } - def X86Mem256_RC128Operand : AsmOperandClass { let Name = "Mem256_RC128"; } - def X86Mem128_RC256Operand : AsmOperandClass { let Name = "Mem128_RC256"; } - def X86Mem256_RC256Operand : AsmOperandClass { let Name = "Mem256_RC256"; } - - def X86Mem64_RC128XOperand : AsmOperandClass { let Name = "Mem64_RC128X"; } - def X86Mem128_RC128XOperand : AsmOperandClass { let Name = "Mem128_RC128X"; } - def X86Mem256_RC128XOperand : AsmOperandClass { let Name = "Mem256_RC128X"; } - def X86Mem128_RC256XOperand : AsmOperandClass { let Name = "Mem128_RC256X"; } - def X86Mem256_RC256XOperand : AsmOperandClass { let Name = "Mem256_RC256X"; } - def X86Mem512_RC256XOperand : AsmOperandClass { let Name = "Mem512_RC256X"; } - def X86Mem256_RC512Operand : AsmOperandClass { let Name = "Mem256_RC512"; } - def X86Mem512_RC512Operand : AsmOperandClass { let Name = "Mem512_RC512"; } - def X86Mem512_GR16Operand : AsmOperandClass { let Name = "Mem512_GR16"; } - def X86Mem512_GR32Operand : AsmOperandClass { let Name = "Mem512_GR32"; } - def X86Mem512_GR64Operand : AsmOperandClass { let Name = "Mem512_GR64"; } - - def X86SibMemOperand : AsmOperandClass { let Name = "SibMem"; } -} - -def X86AbsMemAsmOperand : AsmOperandClass { - let Name = "AbsMem"; - let SuperClasses = [X86MemAsmOperand]; -} - -class X86MemOperand : Operand { - let PrintMethod = printMethod; - let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); - let ParserMatchClass = parserMatchClass; - let OperandType = "OPERAND_MEMORY"; - int Size = size; -} - -// Gather mem operands -class X86VMemOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); -} - -def anymem : X86MemOperand<"printMemReference">; -def X86any_fcmp : PatFrags<(ops node:$lhs, node:$rhs), - [(X86strict_fcmp node:$lhs, node:$rhs), - (X86fcmp node:$lhs, node:$rhs)]>; - -// FIXME: Right now we allow any size during parsing, but we might want to -// restrict to only unsized memory. -def opaquemem : X86MemOperand<"printMemReference">; - -def sibmem: X86MemOperand<"printMemReference", X86SibMemOperand>; - -def i8mem : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8>; -def i16mem : X86MemOperand<"printwordmem", X86Mem16AsmOperand, 16>; -def i32mem : X86MemOperand<"printdwordmem", X86Mem32AsmOperand, 32>; -def i64mem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand, 64>; -def i128mem : X86MemOperand<"printxmmwordmem", X86Mem128AsmOperand, 128>; -def i256mem : X86MemOperand<"printymmwordmem", X86Mem256AsmOperand, 256>; -def i512mem : X86MemOperand<"printzmmwordmem", X86Mem512AsmOperand, 512>; -def f16mem : X86MemOperand<"printwordmem", X86Mem16AsmOperand, 16>; -def f32mem : X86MemOperand<"printdwordmem", X86Mem32AsmOperand, 32>; -def f64mem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand, 64>; -def f80mem : X86MemOperand<"printtbytemem", X86Mem80AsmOperand, 80>; -def f128mem : X86MemOperand<"printxmmwordmem", X86Mem128AsmOperand, 128>; -def f256mem : X86MemOperand<"printymmwordmem", X86Mem256AsmOperand, 256>; -def f512mem : X86MemOperand<"printzmmwordmem", X86Mem512AsmOperand, 512>; - -// 32/64 mode specific mem operands -def i512mem_GR16 : X86MemOperand<"printzmmwordmem", X86Mem512_GR16Operand, 512>; -def i512mem_GR32 : X86MemOperand<"printzmmwordmem", X86Mem512_GR32Operand, 512>; -def i512mem_GR64 : X86MemOperand<"printzmmwordmem", X86Mem512_GR64Operand, 512>; - -// Gather mem operands -def vx64mem : X86VMemOperand; -def vx128mem : X86VMemOperand; -def vx256mem : X86VMemOperand; -def vy128mem : X86VMemOperand; -def vy256mem : X86VMemOperand; - -def vx64xmem : X86VMemOperand; -def vx128xmem : X86VMemOperand; -def vx256xmem : X86VMemOperand; -def vy128xmem : X86VMemOperand; -def vy256xmem : X86VMemOperand; -def vy512xmem : X86VMemOperand; -def vz256mem : X86VMemOperand; -def vz512mem : X86VMemOperand; - -// A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead -// of a plain GPR, so that it doesn't potentially require a REX prefix. -def ptr_rc_norex : PointerLikeRegClass<2>; -def ptr_rc_norex_nosp : PointerLikeRegClass<3>; - -def i8mem_NOREX : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8> { - let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, - SEGMENT_REG); -} - -// GPRs available for tailcall. -// It represents GR32_TC, GR64_TC or GR64_TCW64. -def ptr_rc_tailcall : PointerLikeRegClass<4>; - -// Special i32mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i32mem_TC : X86MemOperand<"printdwordmem", X86Mem32AsmOperand, 32> { - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, ptr_rc_tailcall, - i32imm, SEGMENT_REG); -} - -// Special i64mem for addresses of load folding tail calls. These are not -// allowed to use callee-saved registers since they must be scheduled -// after callee-saved register are popped. -def i64mem_TC : X86MemOperand<"printqwordmem", X86Mem64AsmOperand, 64> { - let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, - ptr_rc_tailcall, i32imm, SEGMENT_REG); -} - -// Special parser to detect 16-bit mode to select 16-bit displacement. -def X86AbsMem16AsmOperand : AsmOperandClass { - let Name = "AbsMem16"; - let RenderMethod = "addAbsMemOperands"; - let SuperClasses = [X86AbsMemAsmOperand]; -} - -// Branch targets print as pc-relative values. -class BranchTargetOperand : Operand { - let OperandType = "OPERAND_PCREL"; - let PrintMethod = "printPCRelImm"; - let ParserMatchClass = X86AbsMemAsmOperand; -} - -def i32imm_brtarget : BranchTargetOperand; -def i16imm_brtarget : BranchTargetOperand; - -// 64-bits but only 32 bits are significant, and those bits are treated as being -// pc relative. -def i64i32imm_brtarget : BranchTargetOperand; - -def brtarget : BranchTargetOperand; -def brtarget8 : BranchTargetOperand; -def brtarget16 : BranchTargetOperand { - let ParserMatchClass = X86AbsMem16AsmOperand; -} -def brtarget32 : BranchTargetOperand; - -let RenderMethod = "addSrcIdxOperands" in { - def X86SrcIdx8Operand : AsmOperandClass { - let Name = "SrcIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86SrcIdx16Operand : AsmOperandClass { - let Name = "SrcIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86SrcIdx32Operand : AsmOperandClass { - let Name = "SrcIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86SrcIdx64Operand : AsmOperandClass { - let Name = "SrcIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addSrcIdxOperands" - -let RenderMethod = "addDstIdxOperands" in { - def X86DstIdx8Operand : AsmOperandClass { - let Name = "DstIdx8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86DstIdx16Operand : AsmOperandClass { - let Name = "DstIdx16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86DstIdx32Operand : AsmOperandClass { - let Name = "DstIdx32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86DstIdx64Operand : AsmOperandClass { - let Name = "DstIdx64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addDstIdxOperands" - -let RenderMethod = "addMemOffsOperands" in { - def X86MemOffs16_8AsmOperand : AsmOperandClass { - let Name = "MemOffs16_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs16_16AsmOperand : AsmOperandClass { - let Name = "MemOffs16_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs16_32AsmOperand : AsmOperandClass { - let Name = "MemOffs16_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_8AsmOperand : AsmOperandClass { - let Name = "MemOffs32_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs32_16AsmOperand : AsmOperandClass { - let Name = "MemOffs32_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs32_32AsmOperand : AsmOperandClass { - let Name = "MemOffs32_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs32_64AsmOperand : AsmOperandClass { - let Name = "MemOffs32_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } - def X86MemOffs64_8AsmOperand : AsmOperandClass { - let Name = "MemOffs64_8"; - let SuperClasses = [X86Mem8AsmOperand]; - } - def X86MemOffs64_16AsmOperand : AsmOperandClass { - let Name = "MemOffs64_16"; - let SuperClasses = [X86Mem16AsmOperand]; - } - def X86MemOffs64_32AsmOperand : AsmOperandClass { - let Name = "MemOffs64_32"; - let SuperClasses = [X86Mem32AsmOperand]; - } - def X86MemOffs64_64AsmOperand : AsmOperandClass { - let Name = "MemOffs64_64"; - let SuperClasses = [X86Mem64AsmOperand]; - } -} // RenderMethod = "addMemOffsOperands" - -class X86SrcIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc, SEGMENT_REG); -} - -class X86DstIdxOperand - : X86MemOperand { - let MIOperandInfo = (ops ptr_rc); -} - -def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>; -def srcidx16 : X86SrcIdxOperand<"printSrcIdx16", X86SrcIdx16Operand>; -def srcidx32 : X86SrcIdxOperand<"printSrcIdx32", X86SrcIdx32Operand>; -def srcidx64 : X86SrcIdxOperand<"printSrcIdx64", X86SrcIdx64Operand>; -def dstidx8 : X86DstIdxOperand<"printDstIdx8", X86DstIdx8Operand>; -def dstidx16 : X86DstIdxOperand<"printDstIdx16", X86DstIdx16Operand>; -def dstidx32 : X86DstIdxOperand<"printDstIdx32", X86DstIdx32Operand>; -def dstidx64 : X86DstIdxOperand<"printDstIdx64", X86DstIdx64Operand>; - -class X86MemOffsOperand - : X86MemOperand { - let MIOperandInfo = (ops immOperand, SEGMENT_REG); -} - -def offset16_8 : X86MemOffsOperand; -def offset16_16 : X86MemOffsOperand; -def offset16_32 : X86MemOffsOperand; -def offset32_8 : X86MemOffsOperand; -def offset32_16 : X86MemOffsOperand; -def offset32_32 : X86MemOffsOperand; -def offset32_64 : X86MemOffsOperand; -def offset64_8 : X86MemOffsOperand; -def offset64_16 : X86MemOffsOperand; -def offset64_32 : X86MemOffsOperand; -def offset64_64 : X86MemOffsOperand; - -def ccode : Operand { - let PrintMethod = "printCondCode"; - let OperandNamespace = "X86"; - let OperandType = "OPERAND_COND_CODE"; -} - -class ImmSExtAsmOperandClass : AsmOperandClass { - let SuperClasses = [ImmAsmOperand]; - let RenderMethod = "addImmOperands"; -} - -def X86GR32orGR64AsmOperand : AsmOperandClass { - let Name = "GR32orGR64"; -} -def GR32orGR64 : RegisterOperand { - let ParserMatchClass = X86GR32orGR64AsmOperand; -} - -def X86GR16orGR32orGR64AsmOperand : AsmOperandClass { - let Name = "GR16orGR32orGR64"; -} -def GR16orGR32orGR64 : RegisterOperand { - let ParserMatchClass = X86GR16orGR32orGR64AsmOperand; -} - -def AVX512RCOperand : AsmOperandClass { - let Name = "AVX512RC"; -} -def AVX512RC : Operand { - let PrintMethod = "printRoundingControl"; - let OperandNamespace = "X86"; - let OperandType = "OPERAND_ROUNDING_CONTROL"; - let ParserMatchClass = AVX512RCOperand; -} - -// Sign-extended immediate classes. We don't need to define the full lattice -// here because there is no instruction with an ambiguity between ImmSExti64i32 -// and ImmSExti32i8. -// -// The strange ranges come from the fact that the assembler always works with -// 64-bit immediates, but for a 16-bit target value we want to accept both "-1" -// (which will be a -1ULL), and "0xFF" (-1 in 16-bits). - -// [0, 0x7FFFFFFF] | -// [0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i32AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i32"; -} - -// [0, 0x0000007F] | [0x000000000000FF80, 0x000000000000FFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti16i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti16i8"; - let SuperClasses = [ImmSExti64i32AsmOperand]; -} - -// [0, 0x0000007F] | [0x00000000FFFFFF80, 0x00000000FFFFFFFF] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti32i8"; -} - -// [0, 0x0000007F] | -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { - let Name = "ImmSExti64i8"; - let SuperClasses = [ImmSExti16i8AsmOperand, ImmSExti32i8AsmOperand, - ImmSExti64i32AsmOperand]; -} - -// 4-bit immediate used by some XOP instructions -// [0, 0xF] -def ImmUnsignedi4AsmOperand : AsmOperandClass { - let Name = "ImmUnsignedi4"; - let RenderMethod = "addImmOperands"; - let DiagnosticType = "InvalidImmUnsignedi4"; -} - -// Unsigned immediate used by SSE/AVX instructions -// [0, 0xFF] -// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] -def ImmUnsignedi8AsmOperand : AsmOperandClass { - let Name = "ImmUnsignedi8"; - let RenderMethod = "addImmOperands"; -} - -// A couple of more descriptive operand definitions. -// 16-bits but only 8 bits are significant. -def i16i8imm : Operand { - let ParserMatchClass = ImmSExti16i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} -// 32-bits but only 8 bits are significant. -def i32i8imm : Operand { - let ParserMatchClass = ImmSExti32i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 32 bits are significant. -def i64i32imm : Operand { - let ParserMatchClass = ImmSExti64i32AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bits but only 8 bits are significant. -def i64i8imm : Operand { - let ParserMatchClass = ImmSExti64i8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// Unsigned 4-bit immediate used by some XOP instructions. -def u4imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi4AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// Unsigned 8-bit immediate used by SSE/AVX instructions. -def u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 16-bit immediate but only 8-bits are significant and they are unsigned. -// Used by BT instructions. -def i16u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 32-bit immediate but only 8-bits are significant and they are unsigned. -// Used by some SSE/AVX instructions that use intrinsics. -def i32u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -// 64-bit immediate but only 8-bits are significant and they are unsigned. -// Used by BT instructions. -def i64u8imm : Operand { - let PrintMethod = "printU8Imm"; - let ParserMatchClass = ImmUnsignedi8AsmOperand; - let OperandType = "OPERAND_IMMEDIATE"; -} - -def lea64_32mem : Operand { - let PrintMethod = "printMemReference"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - -// Memory operands that use 64-bit pointers in both ILP32 and LP64. -def lea64mem : Operand { - let PrintMethod = "printMemReference"; - let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); - let ParserMatchClass = X86MemAsmOperand; -} - -let RenderMethod = "addMaskPairOperands" in { - def VK1PairAsmOperand : AsmOperandClass { let Name = "VK1Pair"; } - def VK2PairAsmOperand : AsmOperandClass { let Name = "VK2Pair"; } - def VK4PairAsmOperand : AsmOperandClass { let Name = "VK4Pair"; } - def VK8PairAsmOperand : AsmOperandClass { let Name = "VK8Pair"; } - def VK16PairAsmOperand : AsmOperandClass { let Name = "VK16Pair"; } -} - -def VK1Pair : RegisterOperand { - let ParserMatchClass = VK1PairAsmOperand; -} - -def VK2Pair : RegisterOperand { - let ParserMatchClass = VK2PairAsmOperand; -} - -def VK4Pair : RegisterOperand { - let ParserMatchClass = VK4PairAsmOperand; -} - -def VK8Pair : RegisterOperand { - let ParserMatchClass = VK8PairAsmOperand; -} - -def VK16Pair : RegisterOperand { - let ParserMatchClass = VK16PairAsmOperand; -} +include "X86InstrOperands.td" //===----------------------------------------------------------------------===// -// X86 Complex Pattern Definitions. +// X86 Predicate Definitions. // - -// Define X86-specific addressing mode. -def addr : ComplexPattern; -def lea32addr : ComplexPattern; -// In 64-bit mode 32-bit LEAs can use RIP-relative addressing. -def lea64_32addr : ComplexPattern; - -def tls32addr : ComplexPattern; - -def tls32baseaddr : ComplexPattern; - -def lea64addr : ComplexPattern; - -def tls64addr : ComplexPattern; - -def tls64baseaddr : ComplexPattern; - -def vectoraddr : ComplexPattern; - -// A relocatable immediate is an operand that can be relocated by the linker to -// an immediate, such as a regular symbol in non-PIC code. -def relocImm : ComplexPattern; - -//===----------------------------------------------------------------------===// -// X86 Instruction Predicate Definitions. -def TruePredicate : Predicate<"true">; - -def HasEGPR : Predicate<"Subtarget->hasEGPR()">; -def NoEGPR : Predicate<"!Subtarget->hasEGPR()">; -def HasCMOV : Predicate<"Subtarget->canUseCMOV()">; -def NoCMOV : Predicate<"!Subtarget->canUseCMOV()">; -def HasNOPL : Predicate<"Subtarget->hasNOPL()">; -def HasMMX : Predicate<"Subtarget->hasMMX()">; -def Has3DNow : Predicate<"Subtarget->hasThreeDNow()">; -def Has3DNowA : Predicate<"Subtarget->hasThreeDNowA()">; -def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; -def UseSSE1 : Predicate<"Subtarget->hasSSE1() && !Subtarget->hasAVX()">; -def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; -def UseSSE2 : Predicate<"Subtarget->hasSSE2() && !Subtarget->hasAVX()">; -def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; -def UseSSE3 : Predicate<"Subtarget->hasSSE3() && !Subtarget->hasAVX()">; -def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">; -def UseSSSE3 : Predicate<"Subtarget->hasSSSE3() && !Subtarget->hasAVX()">; -def HasSSE41 : Predicate<"Subtarget->hasSSE41()">; -def NoSSE41 : Predicate<"!Subtarget->hasSSE41()">; -def UseSSE41 : Predicate<"Subtarget->hasSSE41() && !Subtarget->hasAVX()">; -def HasSSE42 : Predicate<"Subtarget->hasSSE42()">; -def UseSSE42 : Predicate<"Subtarget->hasSSE42() && !Subtarget->hasAVX()">; -def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">; -def NoAVX : Predicate<"!Subtarget->hasAVX()">; -def HasAVX : Predicate<"Subtarget->hasAVX()">; -def HasAVX2 : Predicate<"Subtarget->hasAVX2()">; -def HasAVX1Only : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX2()">; -def HasEVEX512 : Predicate<"Subtarget->hasEVEX512()">; -def HasAVX10_1 : Predicate<"Subtarget->hasAVX10_1()">; -def HasAVX10_1_512 : Predicate<"Subtarget->hasAVX10_1_512()">; -def HasAVX512 : Predicate<"Subtarget->hasAVX512()">; -def UseAVX : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX512()">; -def UseAVX2 : Predicate<"Subtarget->hasAVX2() && !Subtarget->hasAVX512()">; -def NoAVX512 : Predicate<"!Subtarget->hasAVX512()">; -def HasCDI : Predicate<"Subtarget->hasCDI()">; -def HasVPOPCNTDQ : Predicate<"Subtarget->hasVPOPCNTDQ()">; -def HasPFI : Predicate<"Subtarget->hasPFI()">; -def HasERI : Predicate<"Subtarget->hasERI()">; -def HasDQI : Predicate<"Subtarget->hasDQI()">; -def NoDQI : Predicate<"!Subtarget->hasDQI()">; -def HasBWI : Predicate<"Subtarget->hasBWI()">; -def NoBWI : Predicate<"!Subtarget->hasBWI()">; -def HasVLX : Predicate<"Subtarget->hasVLX()">; -def NoVLX : Predicate<"!Subtarget->hasVLX()">; -def NoVLX_Or_NoBWI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasBWI()">; -def NoVLX_Or_NoDQI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasDQI()">; -def HasPKU : Predicate<"Subtarget->hasPKU()">; -def HasVNNI : Predicate<"Subtarget->hasVNNI()">; -def HasVP2INTERSECT : Predicate<"Subtarget->hasVP2INTERSECT()">; -def HasBF16 : Predicate<"Subtarget->hasBF16()">; -def HasFP16 : Predicate<"Subtarget->hasFP16()">; -def HasAVXVNNIINT16 : Predicate<"Subtarget->hasAVXVNNIINT16()">; -def HasAVXVNNIINT8 : Predicate<"Subtarget->hasAVXVNNIINT8()">; -def HasAVXVNNI : Predicate <"Subtarget->hasAVXVNNI()">; -def NoVLX_Or_NoVNNI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVNNI()">; - -def HasBITALG : Predicate<"Subtarget->hasBITALG()">; -def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">; -def HasAES : Predicate<"Subtarget->hasAES()">; -def HasVAES : Predicate<"Subtarget->hasVAES()">; -def NoVLX_Or_NoVAES : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVAES()">; -def HasFXSR : Predicate<"Subtarget->hasFXSR()">; -def HasX87 : Predicate<"Subtarget->hasX87()">; -def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">; -def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">; -def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">; -def HasXSAVES : Predicate<"Subtarget->hasXSAVES()">; -def HasPCLMUL : Predicate<"Subtarget->hasPCLMUL()">; -def NoVLX_Or_NoVPCLMULQDQ : - Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVPCLMULQDQ()">; -def HasVPCLMULQDQ : Predicate<"Subtarget->hasVPCLMULQDQ()">; -def HasGFNI : Predicate<"Subtarget->hasGFNI()">; -def HasFMA : Predicate<"Subtarget->hasFMA()">; -def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; -def NoFMA4 : Predicate<"!Subtarget->hasFMA4()">; -def HasXOP : Predicate<"Subtarget->hasXOP()">; -def HasTBM : Predicate<"Subtarget->hasTBM()">; -def NoTBM : Predicate<"!Subtarget->hasTBM()">; -def HasLWP : Predicate<"Subtarget->hasLWP()">; -def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">; -def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">; -def HasF16C : Predicate<"Subtarget->hasF16C()">; -def HasFSGSBase : Predicate<"Subtarget->hasFSGSBase()">; -def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">; -def HasBMI : Predicate<"Subtarget->hasBMI()">; -def HasBMI2 : Predicate<"Subtarget->hasBMI2()">; -def NoBMI2 : Predicate<"!Subtarget->hasBMI2()">; -def HasVBMI : Predicate<"Subtarget->hasVBMI()">; -def HasVBMI2 : Predicate<"Subtarget->hasVBMI2()">; -def HasIFMA : Predicate<"Subtarget->hasIFMA()">; -def HasAVXIFMA : Predicate<"Subtarget->hasAVXIFMA()">; -def NoVLX_Or_NoIFMA : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasIFMA()">; -def HasRTM : Predicate<"Subtarget->hasRTM()">; -def HasADX : Predicate<"Subtarget->hasADX()">; -def HasSHA : Predicate<"Subtarget->hasSHA()">; -def HasSHA512 : Predicate<"Subtarget->hasSHA512()">; -def HasSGX : Predicate<"Subtarget->hasSGX()">; -def HasSM3 : Predicate<"Subtarget->hasSM3()">; -def HasRDSEED : Predicate<"Subtarget->hasRDSEED()">; -def HasSSEPrefetch : Predicate<"Subtarget->hasSSEPrefetch()">; -def NoSSEPrefetch : Predicate<"!Subtarget->hasSSEPrefetch()">; -def HasPRFCHW : Predicate<"Subtarget->hasPRFCHW()">; -def HasPREFETCHI : Predicate<"Subtarget->hasPREFETCHI()">; -def HasPrefetchW : Predicate<"Subtarget->hasPrefetchW()">; -def HasPREFETCHWT1 : Predicate<"Subtarget->hasPREFETCHWT1()">; -def HasLAHFSAHF : Predicate<"Subtarget->hasLAHFSAHF()">; -def HasLAHFSAHF64 : Predicate<"Subtarget->hasLAHFSAHF64()">; -def HasMWAITX : Predicate<"Subtarget->hasMWAITX()">; -def HasCLZERO : Predicate<"Subtarget->hasCLZERO()">; -def HasCLDEMOTE : Predicate<"Subtarget->hasCLDEMOTE()">; -def HasMOVDIRI : Predicate<"Subtarget->hasMOVDIRI()">; -def HasMOVDIR64B : Predicate<"Subtarget->hasMOVDIR64B()">; -def HasPTWRITE : Predicate<"Subtarget->hasPTWRITE()">; -def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">; -def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">; -def HasSHSTK : Predicate<"Subtarget->hasSHSTK()">; -def HasSM4 : Predicate<"Subtarget->hasSM4()">; -def HasCLFLUSH : Predicate<"Subtarget->hasCLFLUSH()">; -def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; -def HasCLWB : Predicate<"Subtarget->hasCLWB()">; -def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; -def HasRDPID : Predicate<"Subtarget->hasRDPID()">; -def HasRDPRU : Predicate<"Subtarget->hasRDPRU()">; -def HasWAITPKG : Predicate<"Subtarget->hasWAITPKG()">; -def HasINVPCID : Predicate<"Subtarget->hasINVPCID()">; -def HasCX8 : Predicate<"Subtarget->hasCX8()">; -def HasCX16 : Predicate<"Subtarget->hasCX16()">; -def HasPCONFIG : Predicate<"Subtarget->hasPCONFIG()">; -def HasENQCMD : Predicate<"Subtarget->hasENQCMD()">; -def HasAMXFP16 : Predicate<"Subtarget->hasAMXFP16()">; -def HasCMPCCXADD : Predicate<"Subtarget->hasCMPCCXADD()">; -def HasAVXNECONVERT : Predicate<"Subtarget->hasAVXNECONVERT()">; -def HasKL : Predicate<"Subtarget->hasKL()">; -def HasRAOINT : Predicate<"Subtarget->hasRAOINT()">; -def HasWIDEKL : Predicate<"Subtarget->hasWIDEKL()">; -def HasHRESET : Predicate<"Subtarget->hasHRESET()">; -def HasSERIALIZE : Predicate<"Subtarget->hasSERIALIZE()">; -def HasTSXLDTRK : Predicate<"Subtarget->hasTSXLDTRK()">; -def HasAMXTILE : Predicate<"Subtarget->hasAMXTILE()">; -def HasAMXBF16 : Predicate<"Subtarget->hasAMXBF16()">; -def HasAMXINT8 : Predicate<"Subtarget->hasAMXINT8()">; -def HasAMXCOMPLEX : Predicate<"Subtarget->hasAMXCOMPLEX()">; -def HasUINTR : Predicate<"Subtarget->hasUINTR()">; -def HasUSERMSR : Predicate<"Subtarget->hasUSERMSR()">; -def HasCRC32 : Predicate<"Subtarget->hasCRC32()">; - -def HasX86_64 : Predicate<"Subtarget->hasX86_64()">; -def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, - AssemblerPredicate<(all_of (not Is64Bit)), "Not 64-bit mode">; -def In64BitMode : Predicate<"Subtarget->is64Bit()">, - AssemblerPredicate<(all_of Is64Bit), "64-bit mode">; -def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">; -def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">; -def In16BitMode : Predicate<"Subtarget->is16Bit()">, - AssemblerPredicate<(all_of Is16Bit), "16-bit mode">; -def Not16BitMode : Predicate<"!Subtarget->is16Bit()">, - AssemblerPredicate<(all_of (not Is16Bit)), "Not 16-bit mode">; -def In32BitMode : Predicate<"Subtarget->is32Bit()">, - AssemblerPredicate<(all_of Is32Bit), "32-bit mode">; -def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; -def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; -def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||" - "Subtarget->getFrameLowering()->hasFP(*MF)"> { - let RecomputePerFunction = 1; -} -def IsPS : Predicate<"Subtarget->isTargetPS()">; -def NotPS : Predicate<"!Subtarget->isTargetPS()">; -def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; -def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; -def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; -def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">; -def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||" - "TM.getCodeModel() == CodeModel::Kernel">; -def IsNotPIC : Predicate<"!TM.isPositionIndependent()">; - -// We could compute these on a per-module basis but doing so requires accessing -// the Function object through the Subtarget and objections were raised -// to that (see post-commit review comments for r301750). -let RecomputePerFunction = 1 in { - def OptForSize : Predicate<"shouldOptForSize(MF)">; - def OptForMinSize : Predicate<"MF->getFunction().hasMinSize()">; - def OptForSpeed : Predicate<"!shouldOptForSize(MF)">; - def UseIncDec : Predicate<"!Subtarget->slowIncDec() || " - "shouldOptForSize(MF)">; - def NoSSE41_Or_OptForSize : Predicate<"shouldOptForSize(MF) || " - "!Subtarget->hasSSE41()">; -} - -def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">; -def FavorMemIndirectCall : Predicate<"!Subtarget->slowTwoMemOps()">; -def HasFastMem32 : Predicate<"!Subtarget->isUnalignedMem32Slow()">; -def HasFastLZCNT : Predicate<"Subtarget->hasFastLZCNT()">; -def HasFastSHLDRotate : Predicate<"Subtarget->hasFastSHLDRotate()">; -def HasERMSB : Predicate<"Subtarget->hasERMSB()">; -def HasFSRM : Predicate<"Subtarget->hasFSRM()">; -def HasMFence : Predicate<"Subtarget->hasMFence()">; -def UseIndirectThunkCalls : Predicate<"Subtarget->useIndirectThunkCalls()">; -def NotUseIndirectThunkCalls : Predicate<"!Subtarget->useIndirectThunkCalls()">; +include "X86InstrPredicates.td" //===----------------------------------------------------------------------===// // X86 Instruction Format Definitions. // - include "X86InstrFormats.td" //===----------------------------------------------------------------------===// -// Pattern fragments. +// X86 Instruction utilities. // - -// X86 specific condition code. These correspond to CondCode in -// X86InstrInfo.h. They must be kept in synch. -def X86_COND_O : PatLeaf<(i8 0)>; -def X86_COND_NO : PatLeaf<(i8 1)>; -def X86_COND_B : PatLeaf<(i8 2)>; // alt. COND_C -def X86_COND_AE : PatLeaf<(i8 3)>; // alt. COND_NC -def X86_COND_E : PatLeaf<(i8 4)>; // alt. COND_Z -def X86_COND_NE : PatLeaf<(i8 5)>; // alt. COND_NZ -def X86_COND_BE : PatLeaf<(i8 6)>; // alt. COND_NA -def X86_COND_A : PatLeaf<(i8 7)>; // alt. COND_NBE -def X86_COND_S : PatLeaf<(i8 8)>; -def X86_COND_NS : PatLeaf<(i8 9)>; -def X86_COND_P : PatLeaf<(i8 10)>; // alt. COND_PE -def X86_COND_NP : PatLeaf<(i8 11)>; // alt. COND_PO -def X86_COND_L : PatLeaf<(i8 12)>; // alt. COND_NGE -def X86_COND_GE : PatLeaf<(i8 13)>; // alt. COND_NL -def X86_COND_LE : PatLeaf<(i8 14)>; // alt. COND_NG -def X86_COND_G : PatLeaf<(i8 15)>; // alt. COND_NLE - -def i16immSExt8 : ImmLeaf(Imm); }]>; -def i32immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt8 : ImmLeaf(Imm); }]>; -def i64immSExt32 : ImmLeaf(Imm); }]>; -def i64timmSExt32 : TImmLeaf(Imm); }]>; - -def i16relocImmSExt8 : PatLeaf<(i16 relocImm), [{ - return isSExtAbsoluteSymbolRef(8, N); -}]>; -def i32relocImmSExt8 : PatLeaf<(i32 relocImm), [{ - return isSExtAbsoluteSymbolRef(8, N); -}]>; -def i64relocImmSExt8 : PatLeaf<(i64 relocImm), [{ - return isSExtAbsoluteSymbolRef(8, N); -}]>; -def i64relocImmSExt32 : PatLeaf<(i64 relocImm), [{ - return isSExtAbsoluteSymbolRef(32, N); -}]>; - -// If we have multiple users of an immediate, it's much smaller to reuse -// the register, rather than encode the immediate in every instruction. -// This has the risk of increasing register pressure from stretched live -// ranges, however, the immediates should be trivial to rematerialize by -// the RA in the event of high register pressure. -// TODO : This is currently enabled for stores and binary ops. There are more -// cases for which this can be enabled, though this catches the bulk of the -// issues. -// TODO2 : This should really also be enabled under O2, but there's currently -// an issue with RA where we don't pull the constants into their users -// when we rematerialize them. I'll follow-up on enabling O2 after we fix that -// issue. -// TODO3 : This is currently limited to single basic blocks (DAG creation -// pulls block immediates to the top and merges them if necessary). -// Eventually, it would be nice to allow ConstantHoisting to merge constants -// globally for potentially added savings. -// -def imm_su : PatLeaf<(imm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt32_su : PatLeaf<(i64immSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def relocImm8_su : PatLeaf<(i8 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def relocImm16_su : PatLeaf<(i16 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def relocImm32_su : PatLeaf<(i32 relocImm), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i16relocImmSExt8_su : PatLeaf<(i16relocImmSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i32relocImmSExt8_su : PatLeaf<(i32relocImmSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64relocImmSExt8_su : PatLeaf<(i64relocImmSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64relocImmSExt32_su : PatLeaf<(i64relocImmSExt32), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -def i16immSExt8_su : PatLeaf<(i16immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i32immSExt8_su : PatLeaf<(i32immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; -def i64immSExt8_su : PatLeaf<(i64immSExt8), [{ - return !shouldAvoidImmediateInstFormsForSize(N); -}]>; - -// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit -// unsigned field. -def i64immZExt32 : ImmLeaf(Imm); }]>; - -def i64immZExt32SExt8 : ImmLeaf(Imm) && isInt<8>(static_cast(Imm)); -}]>; - -// Helper fragments for loads. - -// It's safe to fold a zextload/extload from i1 as a regular i8 load. The -// upper bits are guaranteed to be zero and we were going to emit a MOV8rm -// which might get folded during peephole anyway. -def loadi8 : PatFrag<(ops node:$ptr), (i8 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - return ExtType == ISD::NON_EXTLOAD || ExtType == ISD::EXTLOAD || - ExtType == ISD::ZEXTLOAD; -}]>; - -// It's always safe to treat a anyext i16 load as a i32 load if the i16 is -// known to be 32-bit aligned or better. Ditto for i8 to i16. -def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD && EnablePromoteAnyextLoad) - return LD->getAlign() >= 2 && LD->isSimple(); - return false; -}]>; - -def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD && EnablePromoteAnyextLoad) - return LD->getAlign() >= 4 && LD->isSimple(); - return false; -}]>; - -def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>; -def loadf16 : PatFrag<(ops node:$ptr), (f16 (load node:$ptr))>; -def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>; -def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>; -def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>; -def loadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr))>; -def alignedloadf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Ld->getAlign() >= Ld->getMemoryVT().getStoreSize(); -}]>; -def memopf128 : PatFrag<(ops node:$ptr), (f128 (load node:$ptr)), [{ - LoadSDNode *Ld = cast(N); - return Subtarget->hasSSEUnalignedMem() || - Ld->getAlign() >= Ld->getMemoryVT().getStoreSize(); -}]>; - -def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; -def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; -def sextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>; -def sextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>; -def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>; -def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>; - -def zextloadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>; -def zextloadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>; -def zextloadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>; -def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; -def zextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>; -def zextloadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>; -def zextloadi64i1 : PatFrag<(ops node:$ptr), (i64 (zextloadi1 node:$ptr))>; -def zextloadi64i8 : PatFrag<(ops node:$ptr), (i64 (zextloadi8 node:$ptr))>; -def zextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (zextloadi16 node:$ptr))>; -def zextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (zextloadi32 node:$ptr))>; - -def extloadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>; -def extloadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>; -def extloadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>; -def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>; -def extloadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>; -def extloadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>; -def extloadi64i1 : PatFrag<(ops node:$ptr), (i64 (extloadi1 node:$ptr))>; -def extloadi64i8 : PatFrag<(ops node:$ptr), (i64 (extloadi8 node:$ptr))>; -def extloadi64i16 : PatFrag<(ops node:$ptr), (i64 (extloadi16 node:$ptr))>; - -// We can treat an i8/i16 extending load to i64 as a 32 bit load if its known -// to be 4 byte aligned or better. -def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType != ISD::EXTLOAD) - return false; - if (LD->getMemoryVT() == MVT::i32) - return true; - - return LD->getAlign() >= 4 && LD->isSimple(); -}]>; - -// binary op with only one user -class binop_oneuse - : PatFrag<(ops node:$A, node:$B), - (operator node:$A, node:$B), [{ - return N->hasOneUse(); -}]>; - -def add_su : binop_oneuse; -def and_su : binop_oneuse; -def srl_su : binop_oneuse; - -// unary op with only one user -class unop_oneuse - : PatFrag<(ops node:$A), - (operator node:$A), [{ - return N->hasOneUse(); -}]>; - - -def ineg_su : unop_oneuse; -def trunc_su : unop_oneuse; - -//===----------------------------------------------------------------------===// -// X86 Type infomation definitions -//===----------------------------------------------------------------------===// - -/// X86TypeInfo - This is a bunch of information that describes relevant X86 -/// information about value types. For example, it can tell you what the -/// register class and preferred load to use. -class X86TypeInfo { - /// VT - This is the value type itself. - ValueType VT = vt; - - /// InstrSuffix - This is the suffix used on instructions with this type. For - /// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q". - string InstrSuffix = instrsuffix; - - /// RegClass - This is the register class associated with this type. For - /// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64. - RegisterClass RegClass = regclass; - - /// LoadNode - This is the load node associated with this type. For - /// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64. - PatFrag LoadNode = loadnode; - - /// MemOperand - This is the memory operand associated with this type. For - /// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem. - X86MemOperand MemOperand = memoperand; - - /// ImmEncoding - This is the encoding of an immediate of this type. For - /// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32. Note that i64 -> Imm32 - /// since the immediate fields of i64 instructions is a 32-bit sign extended - /// value. - ImmType ImmEncoding = immkind; - - /// ImmOperand - This is the operand kind of an immediate of this type. For - /// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm. Note that i64 -> - /// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign - /// extended value. - Operand ImmOperand = immoperand; - - /// ImmOperator - This is the operator that should be used to match an - /// immediate of this kind in a pattern (e.g. imm, or i64immSExt32). - SDPatternOperator ImmOperator = immoperator; - - SDPatternOperator ImmNoSuOperator = immnosuoperator; - - /// Imm8Operand - This is the operand kind to use for an imm8 of this type. - /// For example, i8 -> , i16 -> i16i8imm, i32 -> i32i8imm. This is - /// only used for instructions that have a sign-extended imm8 field form. - Operand Imm8Operand = imm8operand; - - /// Imm8Operator - This is the operator that should be used to match an 8-bit - /// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8). - SDPatternOperator Imm8Operator = imm8operator; - - SDPatternOperator Imm8NoSuOperator = imm8nosuoperator; - - /// HasOddOpcode - This bit is true if the instruction should have an odd (as - /// opposed to even) opcode. Operations on i8 are usually even, operations on - /// other datatypes are odd. - bit HasOddOpcode = hasOddOpcode; - - /// OpSize - Selects whether the instruction needs a 0x66 prefix based on - /// 16-bit vs 32-bit mode. i8/i64 set this to OpSizeFixed. i16 sets this - /// to Opsize16. i32 sets this to OpSize32. - OperandSize OpSize = opSize; - - /// HasREX_W - This bit is set to true if the instruction should have - /// the 0x40 REX prefix. This is set for i64 types. - bit HasREX_W = hasREX_W; -} - -def invalid_node : SDNode<"<>", SDTIntLeaf,[],"<>">; - -def Xi8 : X86TypeInfo; -def Xi16 : X86TypeInfo; -def Xi32 : X86TypeInfo; -def Xi64 : X86TypeInfo; - -/// ITy - This instruction base class takes the type info for the instruction. -/// Using this, it: -/// 1. Concatenates together the instruction mnemonic with the appropriate -/// suffix letter, a tab, and the arguments. -/// 2. Infers whether the instruction should have a 0x66 prefix byte. -/// 3. Infers whether the instruction should have a 0x40 REX_W prefix. -/// 4. Infers whether the low bit of the opcode should be 0 (for i8 operations) -/// or 1 (for i16,i32,i64 operations). -class ITy opcode, Format f, X86TypeInfo typeinfo, dag outs, dag ins, - string mnemonic, string args, list pattern> - : I<{opcode{7}, opcode{6}, opcode{5}, opcode{4}, - opcode{3}, opcode{2}, opcode{1}, typeinfo.HasOddOpcode }, - f, outs, ins, - !strconcat(mnemonic, "{", typeinfo.InstrSuffix, "}\t", args), pattern> { - - // Infer instruction prefixes from type info. - let OpSize = typeinfo.OpSize; - let hasREX_W = typeinfo.HasREX_W; -} +include "X86InstrUtils.td" //===----------------------------------------------------------------------===// // Subsystems. @@ -1429,8 +52,6 @@ include "X86InstrShiftRotate.td" // X87 Floating Point Stack. include "X86InstrFPStack.td" -// SIMD support (SSE, MMX and AVX) -include "X86InstrFragmentsSIMD.td" // FMA - Fused Multiply-Add support (requires FMA) include "X86InstrFMA.td" @@ -1447,10 +68,8 @@ include "X86Instr3DNow.td" include "X86InstrVMX.td" include "X86InstrSVM.td" include "X86InstrSNP.td" - include "X86InstrTSX.td" include "X86InstrSGX.td" - include "X86InstrTDX.td" // Key Locker instructions @@ -1471,4 +90,3 @@ include "X86InstrVecCompiler.td" // Assembler mnemonic/instruction aliases include "X86InstrAsmAlias.td" - diff --git a/llvm/lib/Target/X86/X86InstrMisc.td b/llvm/lib/Target/X86/X86InstrMisc.td index 764d4bd6da2a1..82c079fe2ea82 100644 --- a/llvm/lib/Target/X86/X86InstrMisc.td +++ b/llvm/lib/Target/X86/X86InstrMisc.td @@ -1244,26 +1244,6 @@ let Predicates = [HasBMI, HasEGPR], Defs = [EFLAGS] in { defm BLSI64 : bmi_bls<"blsi{q}", MRM3r, MRM3m, GR64, i64mem, WriteBLS, "_EVEX">, REX_W, EVEX; } -//===----------------------------------------------------------------------===// -// Pattern fragments to auto generate BMI instructions. -//===----------------------------------------------------------------------===// - -def or_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), - (X86or_flag node:$lhs, node:$rhs), [{ - return hasNoCarryFlagUses(SDValue(N, 1)); -}]>; - -def xor_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), - (X86xor_flag node:$lhs, node:$rhs), [{ - return hasNoCarryFlagUses(SDValue(N, 1)); -}]>; - -def and_flag_nocf : PatFrag<(ops node:$lhs, node:$rhs), - (X86and_flag node:$lhs, node:$rhs), [{ - return hasNoCarryFlagUses(SDValue(N, 1)); -}]>; - - let Predicates = [HasBMI] in { // FIXME(1): patterns for the load versions are not implemented // FIXME(2): By only matching `add_su` and `ineg_su` we may emit diff --git a/llvm/lib/Target/X86/X86InstrOperands.td b/llvm/lib/Target/X86/X86InstrOperands.td new file mode 100644 index 0000000000000..761458f9cffc3 --- /dev/null +++ b/llvm/lib/Target/X86/X86InstrOperands.td @@ -0,0 +1,497 @@ +//===------- X86InstrOperands.td - X86 Operand Definitions --*- 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 +// +//===----------------------------------------------------------------------===// + +// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for +// the index operand of an address, to conform to x86 encoding restrictions. +def ptr_rc_nosp : PointerLikeRegClass<1>; + +// *mem - Operand definitions for the funky X86 addressing mode operands. +// +def X86MemAsmOperand : AsmOperandClass { + let Name = "Mem"; +} +let RenderMethod = "addMemOperands", SuperClasses = [X86MemAsmOperand] in { + def X86Mem8AsmOperand : AsmOperandClass { let Name = "Mem8"; } + def X86Mem16AsmOperand : AsmOperandClass { let Name = "Mem16"; } + def X86Mem32AsmOperand : AsmOperandClass { let Name = "Mem32"; } + def X86Mem64AsmOperand : AsmOperandClass { let Name = "Mem64"; } + def X86Mem80AsmOperand : AsmOperandClass { let Name = "Mem80"; } + def X86Mem128AsmOperand : AsmOperandClass { let Name = "Mem128"; } + def X86Mem256AsmOperand : AsmOperandClass { let Name = "Mem256"; } + def X86Mem512AsmOperand : AsmOperandClass { let Name = "Mem512"; } + // Gather mem operands + def X86Mem64_RC128Operand : AsmOperandClass { let Name = "Mem64_RC128"; } + def X86Mem128_RC128Operand : AsmOperandClass { let Name = "Mem128_RC128"; } + def X86Mem256_RC128Operand : AsmOperandClass { let Name = "Mem256_RC128"; } + def X86Mem128_RC256Operand : AsmOperandClass { let Name = "Mem128_RC256"; } + def X86Mem256_RC256Operand : AsmOperandClass { let Name = "Mem256_RC256"; } + + def X86Mem64_RC128XOperand : AsmOperandClass { let Name = "Mem64_RC128X"; } + def X86Mem128_RC128XOperand : AsmOperandClass { let Name = "Mem128_RC128X"; } + def X86Mem256_RC128XOperand : AsmOperandClass { let Name = "Mem256_RC128X"; } + def X86Mem128_RC256XOperand : AsmOperandClass { let Name = "Mem128_RC256X"; } + def X86Mem256_RC256XOperand : AsmOperandClass { let Name = "Mem256_RC256X"; } + def X86Mem512_RC256XOperand : AsmOperandClass { let Name = "Mem512_RC256X"; } + def X86Mem256_RC512Operand : AsmOperandClass { let Name = "Mem256_RC512"; } + def X86Mem512_RC512Operand : AsmOperandClass { let Name = "Mem512_RC512"; } + def X86Mem512_GR16Operand : AsmOperandClass { let Name = "Mem512_GR16"; } + def X86Mem512_GR32Operand : AsmOperandClass { let Name = "Mem512_GR32"; } + def X86Mem512_GR64Operand : AsmOperandClass { let Name = "Mem512_GR64"; } + + def X86SibMemOperand : AsmOperandClass { let Name = "SibMem"; } +} + +def X86AbsMemAsmOperand : AsmOperandClass { + let Name = "AbsMem"; + let SuperClasses = [X86MemAsmOperand]; +} + +class X86MemOperand : Operand { + let PrintMethod = printMethod; + let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG); + let ParserMatchClass = parserMatchClass; + let OperandType = "OPERAND_MEMORY"; + int Size = size; +} + +// Gather mem operands +class X86VMemOperand + : X86MemOperand { + let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG); +} + +def anymem : X86MemOperand<"printMemReference">; + +// FIXME: Right now we allow any size during parsing, but we might want to +// restrict to only unsized memory. +def opaquemem : X86MemOperand<"printMemReference">; + +def sibmem: X86MemOperand<"printMemReference", X86SibMemOperand>; + +def i8mem : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8>; +def i16mem : X86MemOperand<"printwordmem", X86Mem16AsmOperand, 16>; +def i32mem : X86MemOperand<"printdwordmem", X86Mem32AsmOperand, 32>; +def i64mem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand, 64>; +def i128mem : X86MemOperand<"printxmmwordmem", X86Mem128AsmOperand, 128>; +def i256mem : X86MemOperand<"printymmwordmem", X86Mem256AsmOperand, 256>; +def i512mem : X86MemOperand<"printzmmwordmem", X86Mem512AsmOperand, 512>; +def f16mem : X86MemOperand<"printwordmem", X86Mem16AsmOperand, 16>; +def f32mem : X86MemOperand<"printdwordmem", X86Mem32AsmOperand, 32>; +def f64mem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand, 64>; +def f80mem : X86MemOperand<"printtbytemem", X86Mem80AsmOperand, 80>; +def f128mem : X86MemOperand<"printxmmwordmem", X86Mem128AsmOperand, 128>; +def f256mem : X86MemOperand<"printymmwordmem", X86Mem256AsmOperand, 256>; +def f512mem : X86MemOperand<"printzmmwordmem", X86Mem512AsmOperand, 512>; + +// 32/64 mode specific mem operands +def i512mem_GR16 : X86MemOperand<"printzmmwordmem", X86Mem512_GR16Operand, 512>; +def i512mem_GR32 : X86MemOperand<"printzmmwordmem", X86Mem512_GR32Operand, 512>; +def i512mem_GR64 : X86MemOperand<"printzmmwordmem", X86Mem512_GR64Operand, 512>; + +// Gather mem operands +def vx64mem : X86VMemOperand; +def vx128mem : X86VMemOperand; +def vx256mem : X86VMemOperand; +def vy128mem : X86VMemOperand; +def vy256mem : X86VMemOperand; + +def vx64xmem : X86VMemOperand; +def vx128xmem : X86VMemOperand; +def vx256xmem : X86VMemOperand; +def vy128xmem : X86VMemOperand; +def vy256xmem : X86VMemOperand; +def vy512xmem : X86VMemOperand; +def vz256mem : X86VMemOperand; +def vz512mem : X86VMemOperand; + +def shmem : X86MemOperand<"printwordmem", X86Mem16AsmOperand>; +def ssmem : X86MemOperand<"printdwordmem", X86Mem32AsmOperand>; +def sdmem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand>; + +// A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead +// of a plain GPR, so that it doesn't potentially require a REX prefix. +def ptr_rc_norex : PointerLikeRegClass<2>; +def ptr_rc_norex_nosp : PointerLikeRegClass<3>; + +def i8mem_NOREX : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8> { + let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, + SEGMENT_REG); +} + +// GPRs available for tailcall. +// It represents GR32_TC, GR64_TC or GR64_TCW64. +def ptr_rc_tailcall : PointerLikeRegClass<4>; + +// Special i32mem for addresses of load folding tail calls. These are not +// allowed to use callee-saved registers since they must be scheduled +// after callee-saved register are popped. +def i32mem_TC : X86MemOperand<"printdwordmem", X86Mem32AsmOperand, 32> { + let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, ptr_rc_tailcall, + i32imm, SEGMENT_REG); +} + +// Special i64mem for addresses of load folding tail calls. These are not +// allowed to use callee-saved registers since they must be scheduled +// after callee-saved register are popped. +def i64mem_TC : X86MemOperand<"printqwordmem", X86Mem64AsmOperand, 64> { + let MIOperandInfo = (ops ptr_rc_tailcall, i8imm, + ptr_rc_tailcall, i32imm, SEGMENT_REG); +} + +// Special parser to detect 16-bit mode to select 16-bit displacement. +def X86AbsMem16AsmOperand : AsmOperandClass { + let Name = "AbsMem16"; + let RenderMethod = "addAbsMemOperands"; + let SuperClasses = [X86AbsMemAsmOperand]; +} + +// Branch targets print as pc-relative values. +class BranchTargetOperand : Operand { + let OperandType = "OPERAND_PCREL"; + let PrintMethod = "printPCRelImm"; + let ParserMatchClass = X86AbsMemAsmOperand; +} + +def i32imm_brtarget : BranchTargetOperand; +def i16imm_brtarget : BranchTargetOperand; + +// 64-bits but only 32 bits are significant, and those bits are treated as being +// pc relative. +def i64i32imm_brtarget : BranchTargetOperand; + +def brtarget : BranchTargetOperand; +def brtarget8 : BranchTargetOperand; +def brtarget16 : BranchTargetOperand { + let ParserMatchClass = X86AbsMem16AsmOperand; +} +def brtarget32 : BranchTargetOperand; + +let RenderMethod = "addSrcIdxOperands" in { + def X86SrcIdx8Operand : AsmOperandClass { + let Name = "SrcIdx8"; + let SuperClasses = [X86Mem8AsmOperand]; + } + def X86SrcIdx16Operand : AsmOperandClass { + let Name = "SrcIdx16"; + let SuperClasses = [X86Mem16AsmOperand]; + } + def X86SrcIdx32Operand : AsmOperandClass { + let Name = "SrcIdx32"; + let SuperClasses = [X86Mem32AsmOperand]; + } + def X86SrcIdx64Operand : AsmOperandClass { + let Name = "SrcIdx64"; + let SuperClasses = [X86Mem64AsmOperand]; + } +} // RenderMethod = "addSrcIdxOperands" + +let RenderMethod = "addDstIdxOperands" in { + def X86DstIdx8Operand : AsmOperandClass { + let Name = "DstIdx8"; + let SuperClasses = [X86Mem8AsmOperand]; + } + def X86DstIdx16Operand : AsmOperandClass { + let Name = "DstIdx16"; + let SuperClasses = [X86Mem16AsmOperand]; + } + def X86DstIdx32Operand : AsmOperandClass { + let Name = "DstIdx32"; + let SuperClasses = [X86Mem32AsmOperand]; + } + def X86DstIdx64Operand : AsmOperandClass { + let Name = "DstIdx64"; + let SuperClasses = [X86Mem64AsmOperand]; + } +} // RenderMethod = "addDstIdxOperands" + +let RenderMethod = "addMemOffsOperands" in { + def X86MemOffs16_8AsmOperand : AsmOperandClass { + let Name = "MemOffs16_8"; + let SuperClasses = [X86Mem8AsmOperand]; + } + def X86MemOffs16_16AsmOperand : AsmOperandClass { + let Name = "MemOffs16_16"; + let SuperClasses = [X86Mem16AsmOperand]; + } + def X86MemOffs16_32AsmOperand : AsmOperandClass { + let Name = "MemOffs16_32"; + let SuperClasses = [X86Mem32AsmOperand]; + } + def X86MemOffs32_8AsmOperand : AsmOperandClass { + let Name = "MemOffs32_8"; + let SuperClasses = [X86Mem8AsmOperand]; + } + def X86MemOffs32_16AsmOperand : AsmOperandClass { + let Name = "MemOffs32_16"; + let SuperClasses = [X86Mem16AsmOperand]; + } + def X86MemOffs32_32AsmOperand : AsmOperandClass { + let Name = "MemOffs32_32"; + let SuperClasses = [X86Mem32AsmOperand]; + } + def X86MemOffs32_64AsmOperand : AsmOperandClass { + let Name = "MemOffs32_64"; + let SuperClasses = [X86Mem64AsmOperand]; + } + def X86MemOffs64_8AsmOperand : AsmOperandClass { + let Name = "MemOffs64_8"; + let SuperClasses = [X86Mem8AsmOperand]; + } + def X86MemOffs64_16AsmOperand : AsmOperandClass { + let Name = "MemOffs64_16"; + let SuperClasses = [X86Mem16AsmOperand]; + } + def X86MemOffs64_32AsmOperand : AsmOperandClass { + let Name = "MemOffs64_32"; + let SuperClasses = [X86Mem32AsmOperand]; + } + def X86MemOffs64_64AsmOperand : AsmOperandClass { + let Name = "MemOffs64_64"; + let SuperClasses = [X86Mem64AsmOperand]; + } +} // RenderMethod = "addMemOffsOperands" + +class X86SrcIdxOperand + : X86MemOperand { + let MIOperandInfo = (ops ptr_rc, SEGMENT_REG); +} + +class X86DstIdxOperand + : X86MemOperand { + let MIOperandInfo = (ops ptr_rc); +} + +def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>; +def srcidx16 : X86SrcIdxOperand<"printSrcIdx16", X86SrcIdx16Operand>; +def srcidx32 : X86SrcIdxOperand<"printSrcIdx32", X86SrcIdx32Operand>; +def srcidx64 : X86SrcIdxOperand<"printSrcIdx64", X86SrcIdx64Operand>; +def dstidx8 : X86DstIdxOperand<"printDstIdx8", X86DstIdx8Operand>; +def dstidx16 : X86DstIdxOperand<"printDstIdx16", X86DstIdx16Operand>; +def dstidx32 : X86DstIdxOperand<"printDstIdx32", X86DstIdx32Operand>; +def dstidx64 : X86DstIdxOperand<"printDstIdx64", X86DstIdx64Operand>; + +class X86MemOffsOperand + : X86MemOperand { + let MIOperandInfo = (ops immOperand, SEGMENT_REG); +} + +def offset16_8 : X86MemOffsOperand; +def offset16_16 : X86MemOffsOperand; +def offset16_32 : X86MemOffsOperand; +def offset32_8 : X86MemOffsOperand; +def offset32_16 : X86MemOffsOperand; +def offset32_32 : X86MemOffsOperand; +def offset32_64 : X86MemOffsOperand; +def offset64_8 : X86MemOffsOperand; +def offset64_16 : X86MemOffsOperand; +def offset64_32 : X86MemOffsOperand; +def offset64_64 : X86MemOffsOperand; + +def ccode : Operand { + let PrintMethod = "printCondCode"; + let OperandNamespace = "X86"; + let OperandType = "OPERAND_COND_CODE"; +} + +class ImmSExtAsmOperandClass : AsmOperandClass { + let SuperClasses = [ImmAsmOperand]; + let RenderMethod = "addImmOperands"; +} + +def X86GR32orGR64AsmOperand : AsmOperandClass { + let Name = "GR32orGR64"; +} +def GR32orGR64 : RegisterOperand { + let ParserMatchClass = X86GR32orGR64AsmOperand; +} + +def X86GR16orGR32orGR64AsmOperand : AsmOperandClass { + let Name = "GR16orGR32orGR64"; +} +def GR16orGR32orGR64 : RegisterOperand { + let ParserMatchClass = X86GR16orGR32orGR64AsmOperand; +} + +def AVX512RCOperand : AsmOperandClass { + let Name = "AVX512RC"; +} +def AVX512RC : Operand { + let PrintMethod = "printRoundingControl"; + let OperandNamespace = "X86"; + let OperandType = "OPERAND_ROUNDING_CONTROL"; + let ParserMatchClass = AVX512RCOperand; +} + +// Sign-extended immediate classes. We don't need to define the full lattice +// here because there is no instruction with an ambiguity between ImmSExti64i32 +// and ImmSExti32i8. +// +// The strange ranges come from the fact that the assembler always works with +// 64-bit immediates, but for a 16-bit target value we want to accept both "-1" +// (which will be a -1ULL), and "0xFF" (-1 in 16-bits). + +// [0, 0x7FFFFFFF] | +// [0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF] +def ImmSExti64i32AsmOperand : ImmSExtAsmOperandClass { + let Name = "ImmSExti64i32"; +} + +// [0, 0x0000007F] | [0x000000000000FF80, 0x000000000000FFFF] | +// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] +def ImmSExti16i8AsmOperand : ImmSExtAsmOperandClass { + let Name = "ImmSExti16i8"; + let SuperClasses = [ImmSExti64i32AsmOperand]; +} + +// [0, 0x0000007F] | [0x00000000FFFFFF80, 0x00000000FFFFFFFF] | +// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] +def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass { + let Name = "ImmSExti32i8"; +} + +// [0, 0x0000007F] | +// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] +def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { + let Name = "ImmSExti64i8"; + let SuperClasses = [ImmSExti16i8AsmOperand, ImmSExti32i8AsmOperand, + ImmSExti64i32AsmOperand]; +} + +// 4-bit immediate used by some XOP instructions +// [0, 0xF] +def ImmUnsignedi4AsmOperand : AsmOperandClass { + let Name = "ImmUnsignedi4"; + let RenderMethod = "addImmOperands"; + let DiagnosticType = "InvalidImmUnsignedi4"; +} + +// Unsigned immediate used by SSE/AVX instructions +// [0, 0xFF] +// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF] +def ImmUnsignedi8AsmOperand : AsmOperandClass { + let Name = "ImmUnsignedi8"; + let RenderMethod = "addImmOperands"; +} + +// A couple of more descriptive operand definitions. +// 16-bits but only 8 bits are significant. +def i16i8imm : Operand { + let ParserMatchClass = ImmSExti16i8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} +// 32-bits but only 8 bits are significant. +def i32i8imm : Operand { + let ParserMatchClass = ImmSExti32i8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +// 64-bits but only 32 bits are significant. +def i64i32imm : Operand { + let ParserMatchClass = ImmSExti64i32AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +// 64-bits but only 8 bits are significant. +def i64i8imm : Operand { + let ParserMatchClass = ImmSExti64i8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +// Unsigned 4-bit immediate used by some XOP instructions. +def u4imm : Operand { + let PrintMethod = "printU8Imm"; + let ParserMatchClass = ImmUnsignedi4AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +// Unsigned 8-bit immediate used by SSE/AVX instructions. +def u8imm : Operand { + let PrintMethod = "printU8Imm"; + let ParserMatchClass = ImmUnsignedi8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +// 16-bit immediate but only 8-bits are significant and they are unsigned. +// Used by BT instructions. +def i16u8imm : Operand { + let PrintMethod = "printU8Imm"; + let ParserMatchClass = ImmUnsignedi8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +// 32-bit immediate but only 8-bits are significant and they are unsigned. +// Used by some SSE/AVX instructions that use intrinsics. +def i32u8imm : Operand { + let PrintMethod = "printU8Imm"; + let ParserMatchClass = ImmUnsignedi8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +// 64-bit immediate but only 8-bits are significant and they are unsigned. +// Used by BT instructions. +def i64u8imm : Operand { + let PrintMethod = "printU8Imm"; + let ParserMatchClass = ImmUnsignedi8AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +def lea64_32mem : Operand { + let PrintMethod = "printMemReference"; + let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); + let ParserMatchClass = X86MemAsmOperand; +} + +// Memory operands that use 64-bit pointers in both ILP32 and LP64. +def lea64mem : Operand { + let PrintMethod = "printMemReference"; + let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG); + let ParserMatchClass = X86MemAsmOperand; +} + +let RenderMethod = "addMaskPairOperands" in { + def VK1PairAsmOperand : AsmOperandClass { let Name = "VK1Pair"; } + def VK2PairAsmOperand : AsmOperandClass { let Name = "VK2Pair"; } + def VK4PairAsmOperand : AsmOperandClass { let Name = "VK4Pair"; } + def VK8PairAsmOperand : AsmOperandClass { let Name = "VK8Pair"; } + def VK16PairAsmOperand : AsmOperandClass { let Name = "VK16Pair"; } +} + +def VK1Pair : RegisterOperand { + let ParserMatchClass = VK1PairAsmOperand; +} + +def VK2Pair : RegisterOperand { + let ParserMatchClass = VK2PairAsmOperand; +} + +def VK4Pair : RegisterOperand { + let ParserMatchClass = VK4PairAsmOperand; +} + +def VK8Pair : RegisterOperand { + let ParserMatchClass = VK8PairAsmOperand; +} + +def VK16Pair : RegisterOperand { + let ParserMatchClass = VK16PairAsmOperand; +} diff --git a/llvm/lib/Target/X86/X86InstrPredicates.td b/llvm/lib/Target/X86/X86InstrPredicates.td new file mode 100644 index 0000000000000..8653f15d86028 --- /dev/null +++ b/llvm/lib/Target/X86/X86InstrPredicates.td @@ -0,0 +1,207 @@ +//===---X86InstrPredicates.td - X86 Predicate Definitions --*- 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 +// +//===----------------------------------------------------------------------===// + +def TruePredicate : Predicate<"true">; + +def HasEGPR : Predicate<"Subtarget->hasEGPR()">; +def NoEGPR : Predicate<"!Subtarget->hasEGPR()">; +def HasCMOV : Predicate<"Subtarget->canUseCMOV()">; +def NoCMOV : Predicate<"!Subtarget->canUseCMOV()">; +def HasNOPL : Predicate<"Subtarget->hasNOPL()">; +def HasMMX : Predicate<"Subtarget->hasMMX()">; +def Has3DNow : Predicate<"Subtarget->hasThreeDNow()">; +def Has3DNowA : Predicate<"Subtarget->hasThreeDNowA()">; +def HasSSE1 : Predicate<"Subtarget->hasSSE1()">; +def UseSSE1 : Predicate<"Subtarget->hasSSE1() && !Subtarget->hasAVX()">; +def HasSSE2 : Predicate<"Subtarget->hasSSE2()">; +def UseSSE2 : Predicate<"Subtarget->hasSSE2() && !Subtarget->hasAVX()">; +def HasSSE3 : Predicate<"Subtarget->hasSSE3()">; +def UseSSE3 : Predicate<"Subtarget->hasSSE3() && !Subtarget->hasAVX()">; +def HasSSSE3 : Predicate<"Subtarget->hasSSSE3()">; +def UseSSSE3 : Predicate<"Subtarget->hasSSSE3() && !Subtarget->hasAVX()">; +def HasSSE41 : Predicate<"Subtarget->hasSSE41()">; +def NoSSE41 : Predicate<"!Subtarget->hasSSE41()">; +def UseSSE41 : Predicate<"Subtarget->hasSSE41() && !Subtarget->hasAVX()">; +def HasSSE42 : Predicate<"Subtarget->hasSSE42()">; +def UseSSE42 : Predicate<"Subtarget->hasSSE42() && !Subtarget->hasAVX()">; +def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">; +def NoAVX : Predicate<"!Subtarget->hasAVX()">; +def HasAVX : Predicate<"Subtarget->hasAVX()">; +def HasAVX2 : Predicate<"Subtarget->hasAVX2()">; +def HasAVX1Only : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX2()">; +def HasEVEX512 : Predicate<"Subtarget->hasEVEX512()">; +def HasAVX10_1 : Predicate<"Subtarget->hasAVX10_1()">; +def HasAVX10_1_512 : Predicate<"Subtarget->hasAVX10_1_512()">; +def HasAVX512 : Predicate<"Subtarget->hasAVX512()">; +def UseAVX : Predicate<"Subtarget->hasAVX() && !Subtarget->hasAVX512()">; +def UseAVX2 : Predicate<"Subtarget->hasAVX2() && !Subtarget->hasAVX512()">; +def NoAVX512 : Predicate<"!Subtarget->hasAVX512()">; +def HasCDI : Predicate<"Subtarget->hasCDI()">; +def HasVPOPCNTDQ : Predicate<"Subtarget->hasVPOPCNTDQ()">; +def HasPFI : Predicate<"Subtarget->hasPFI()">; +def HasERI : Predicate<"Subtarget->hasERI()">; +def HasDQI : Predicate<"Subtarget->hasDQI()">; +def NoDQI : Predicate<"!Subtarget->hasDQI()">; +def HasBWI : Predicate<"Subtarget->hasBWI()">; +def NoBWI : Predicate<"!Subtarget->hasBWI()">; +def HasVLX : Predicate<"Subtarget->hasVLX()">; +def NoVLX : Predicate<"!Subtarget->hasVLX()">; +def NoVLX_Or_NoBWI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasBWI()">; +def NoVLX_Or_NoDQI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasDQI()">; +def HasPKU : Predicate<"Subtarget->hasPKU()">; +def HasVNNI : Predicate<"Subtarget->hasVNNI()">; +def HasVP2INTERSECT : Predicate<"Subtarget->hasVP2INTERSECT()">; +def HasBF16 : Predicate<"Subtarget->hasBF16()">; +def HasFP16 : Predicate<"Subtarget->hasFP16()">; +def HasAVXVNNIINT16 : Predicate<"Subtarget->hasAVXVNNIINT16()">; +def HasAVXVNNIINT8 : Predicate<"Subtarget->hasAVXVNNIINT8()">; +def HasAVXVNNI : Predicate <"Subtarget->hasAVXVNNI()">; +def NoVLX_Or_NoVNNI : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVNNI()">; + +def HasBITALG : Predicate<"Subtarget->hasBITALG()">; +def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">; +def HasAES : Predicate<"Subtarget->hasAES()">; +def HasVAES : Predicate<"Subtarget->hasVAES()">; +def NoVLX_Or_NoVAES : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVAES()">; +def HasFXSR : Predicate<"Subtarget->hasFXSR()">; +def HasX87 : Predicate<"Subtarget->hasX87()">; +def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">; +def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">; +def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">; +def HasXSAVES : Predicate<"Subtarget->hasXSAVES()">; +def HasPCLMUL : Predicate<"Subtarget->hasPCLMUL()">; +def NoVLX_Or_NoVPCLMULQDQ : + Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVPCLMULQDQ()">; +def HasVPCLMULQDQ : Predicate<"Subtarget->hasVPCLMULQDQ()">; +def HasGFNI : Predicate<"Subtarget->hasGFNI()">; +def HasFMA : Predicate<"Subtarget->hasFMA()">; +def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; +def NoFMA4 : Predicate<"!Subtarget->hasFMA4()">; +def HasXOP : Predicate<"Subtarget->hasXOP()">; +def HasTBM : Predicate<"Subtarget->hasTBM()">; +def NoTBM : Predicate<"!Subtarget->hasTBM()">; +def HasLWP : Predicate<"Subtarget->hasLWP()">; +def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">; +def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">; +def HasF16C : Predicate<"Subtarget->hasF16C()">; +def HasFSGSBase : Predicate<"Subtarget->hasFSGSBase()">; +def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">; +def HasBMI : Predicate<"Subtarget->hasBMI()">; +def HasBMI2 : Predicate<"Subtarget->hasBMI2()">; +def NoBMI2 : Predicate<"!Subtarget->hasBMI2()">; +def HasVBMI : Predicate<"Subtarget->hasVBMI()">; +def HasVBMI2 : Predicate<"Subtarget->hasVBMI2()">; +def HasIFMA : Predicate<"Subtarget->hasIFMA()">; +def HasAVXIFMA : Predicate<"Subtarget->hasAVXIFMA()">; +def NoVLX_Or_NoIFMA : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasIFMA()">; +def HasRTM : Predicate<"Subtarget->hasRTM()">; +def HasADX : Predicate<"Subtarget->hasADX()">; +def HasSHA : Predicate<"Subtarget->hasSHA()">; +def HasSHA512 : Predicate<"Subtarget->hasSHA512()">; +def HasSGX : Predicate<"Subtarget->hasSGX()">; +def HasSM3 : Predicate<"Subtarget->hasSM3()">; +def HasRDSEED : Predicate<"Subtarget->hasRDSEED()">; +def HasSSEPrefetch : Predicate<"Subtarget->hasSSEPrefetch()">; +def NoSSEPrefetch : Predicate<"!Subtarget->hasSSEPrefetch()">; +def HasPRFCHW : Predicate<"Subtarget->hasPRFCHW()">; +def HasPREFETCHI : Predicate<"Subtarget->hasPREFETCHI()">; +def HasPrefetchW : Predicate<"Subtarget->hasPrefetchW()">; +def HasPREFETCHWT1 : Predicate<"Subtarget->hasPREFETCHWT1()">; +def HasLAHFSAHF : Predicate<"Subtarget->hasLAHFSAHF()">; +def HasLAHFSAHF64 : Predicate<"Subtarget->hasLAHFSAHF64()">; +def HasMWAITX : Predicate<"Subtarget->hasMWAITX()">; +def HasCLZERO : Predicate<"Subtarget->hasCLZERO()">; +def HasCLDEMOTE : Predicate<"Subtarget->hasCLDEMOTE()">; +def HasMOVDIRI : Predicate<"Subtarget->hasMOVDIRI()">; +def HasMOVDIR64B : Predicate<"Subtarget->hasMOVDIR64B()">; +def HasPTWRITE : Predicate<"Subtarget->hasPTWRITE()">; +def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">; +def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">; +def HasSHSTK : Predicate<"Subtarget->hasSHSTK()">; +def HasSM4 : Predicate<"Subtarget->hasSM4()">; +def HasCLFLUSH : Predicate<"Subtarget->hasCLFLUSH()">; +def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; +def HasCLWB : Predicate<"Subtarget->hasCLWB()">; +def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; +def HasRDPID : Predicate<"Subtarget->hasRDPID()">; +def HasRDPRU : Predicate<"Subtarget->hasRDPRU()">; +def HasWAITPKG : Predicate<"Subtarget->hasWAITPKG()">; +def HasINVPCID : Predicate<"Subtarget->hasINVPCID()">; +def HasCX8 : Predicate<"Subtarget->hasCX8()">; +def HasCX16 : Predicate<"Subtarget->hasCX16()">; +def HasPCONFIG : Predicate<"Subtarget->hasPCONFIG()">; +def HasENQCMD : Predicate<"Subtarget->hasENQCMD()">; +def HasAMXFP16 : Predicate<"Subtarget->hasAMXFP16()">; +def HasCMPCCXADD : Predicate<"Subtarget->hasCMPCCXADD()">; +def HasAVXNECONVERT : Predicate<"Subtarget->hasAVXNECONVERT()">; +def HasKL : Predicate<"Subtarget->hasKL()">; +def HasRAOINT : Predicate<"Subtarget->hasRAOINT()">; +def HasWIDEKL : Predicate<"Subtarget->hasWIDEKL()">; +def HasHRESET : Predicate<"Subtarget->hasHRESET()">; +def HasSERIALIZE : Predicate<"Subtarget->hasSERIALIZE()">; +def HasTSXLDTRK : Predicate<"Subtarget->hasTSXLDTRK()">; +def HasAMXTILE : Predicate<"Subtarget->hasAMXTILE()">; +def HasAMXBF16 : Predicate<"Subtarget->hasAMXBF16()">; +def HasAMXINT8 : Predicate<"Subtarget->hasAMXINT8()">; +def HasAMXCOMPLEX : Predicate<"Subtarget->hasAMXCOMPLEX()">; +def HasUINTR : Predicate<"Subtarget->hasUINTR()">; +def HasUSERMSR : Predicate<"Subtarget->hasUSERMSR()">; +def HasCRC32 : Predicate<"Subtarget->hasCRC32()">; + +def HasX86_64 : Predicate<"Subtarget->hasX86_64()">; +def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, + AssemblerPredicate<(all_of (not Is64Bit)), "Not 64-bit mode">; +def In64BitMode : Predicate<"Subtarget->is64Bit()">, + AssemblerPredicate<(all_of Is64Bit), "64-bit mode">; +def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">; +def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">; +def In16BitMode : Predicate<"Subtarget->is16Bit()">, + AssemblerPredicate<(all_of Is16Bit), "16-bit mode">; +def Not16BitMode : Predicate<"!Subtarget->is16Bit()">, + AssemblerPredicate<(all_of (not Is16Bit)), "Not 16-bit mode">; +def In32BitMode : Predicate<"Subtarget->is32Bit()">, + AssemblerPredicate<(all_of Is32Bit), "32-bit mode">; +def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; +def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">; +def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||" + "Subtarget->getFrameLowering()->hasFP(*MF)"> { + let RecomputePerFunction = 1; +} +def IsPS : Predicate<"Subtarget->isTargetPS()">; +def NotPS : Predicate<"!Subtarget->isTargetPS()">; +def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; +def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; +def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">; +def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">; +def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||" + "TM.getCodeModel() == CodeModel::Kernel">; +def IsNotPIC : Predicate<"!TM.isPositionIndependent()">; + +// We could compute these on a per-module basis but doing so requires accessing +// the Function object through the Subtarget and objections were raised +// to that (see post-commit review comments for r301750). +let RecomputePerFunction = 1 in { + def OptForSize : Predicate<"shouldOptForSize(MF)">; + def OptForMinSize : Predicate<"MF->getFunction().hasMinSize()">; + def OptForSpeed : Predicate<"!shouldOptForSize(MF)">; + def UseIncDec : Predicate<"!Subtarget->slowIncDec() || " + "shouldOptForSize(MF)">; + def NoSSE41_Or_OptForSize : Predicate<"shouldOptForSize(MF) || " + "!Subtarget->hasSSE41()">; +} + +def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">; +def FavorMemIndirectCall : Predicate<"!Subtarget->slowTwoMemOps()">; +def HasFastMem32 : Predicate<"!Subtarget->isUnalignedMem32Slow()">; +def HasFastLZCNT : Predicate<"Subtarget->hasFastLZCNT()">; +def HasFastSHLDRotate : Predicate<"Subtarget->hasFastSHLDRotate()">; +def HasERMSB : Predicate<"Subtarget->hasERMSB()">; +def HasFSRM : Predicate<"Subtarget->hasFSRM()">; +def HasMFence : Predicate<"Subtarget->hasMFence()">; +def UseIndirectThunkCalls : Predicate<"Subtarget->useIndirectThunkCalls()">; +def NotUseIndirectThunkCalls : Predicate<"!Subtarget->useIndirectThunkCalls()">; diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index ef6db2d45d661..34eb17af1033d 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -7359,11 +7359,6 @@ defm VPDPBUSDS : avx_vnni_rm<0x51, "vpdpbusds", X86Vpdpbusds, 0>; defm VPDPWSSD : avx_vnni_rm<0x52, "vpdpwssd", X86Vpdpwssd, 1>; defm VPDPWSSDS : avx_vnni_rm<0x53, "vpdpwssds", X86Vpdpwssds, 1>; -def X86vpmaddwd_su : PatFrag<(ops node:$lhs, node:$rhs), - (X86vpmaddwd node:$lhs, node:$rhs), [{ - return N->hasOneUse(); -}]>; - let Predicates = [HasAVXVNNI, NoVLX_Or_NoVNNI] in { def : Pat<(v8i32 (add VR256:$src1, (X86vpmaddwd_su VR256:$src2, VR256:$src3))), diff --git a/llvm/lib/Target/X86/X86InstrUtils.td b/llvm/lib/Target/X86/X86InstrUtils.td new file mode 100644 index 0000000000000..071c41da67220 --- /dev/null +++ b/llvm/lib/Target/X86/X86InstrUtils.td @@ -0,0 +1,1014 @@ +//===-- X86InstrUtils.td - X86 Instruction Utilities --------*- 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 provides utilities for simplifying the instruction definitions. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Classes for setting the fields of X86Inst +//===----------------------------------------------------------------------===// + +// Prefix byte classes which are used to indicate to the ad-hoc machine code +// emitter that various prefix bytes are required. +class OpSize16 { OperandSize OpSize = OpSize16; } +class OpSize32 { OperandSize OpSize = OpSize32; } +class AdSize16 { AddressSize AdSize = AdSize16; } +class AdSize32 { AddressSize AdSize = AdSize32; } +class AdSize64 { AddressSize AdSize = AdSize64; } +class REX_W { bit hasREX_W = 1; } +class LOCK { bit hasLockPrefix = 1; } +class REP { bit hasREPPrefix = 1; } +class TB { Map OpMap = TB; } +class T8 { Map OpMap = T8; } +class TA { Map OpMap = TA; } +class XOP8 { Map OpMap = XOP8; Prefix OpPrefix = PS; } +class XOP9 { Map OpMap = XOP9; Prefix OpPrefix = PS; } +class XOPA { Map OpMap = XOPA; Prefix OpPrefix = PS; } +class ThreeDNow { Map OpMap = ThreeDNow; } +class T_MAP4 { Map OpMap = T_MAP4; } +class T_MAP4PS : T_MAP4 { Prefix OpPrefix = PS; } // none +class T_MAP4PD : T_MAP4 { Prefix OpPrefix = PD; } // 0x66 +class T_MAP4XS : T_MAP4 { Prefix OpPrefix = XS; } // 0xF3 +class T_MAP4XD : T_MAP4 { Prefix OpPrefix = XD; } // 0xF2 +class T_MAP5 { Map OpMap = T_MAP5; } +class T_MAP5PS : T_MAP5 { Prefix OpPrefix = PS; } // none +class T_MAP5PD : T_MAP5 { Prefix OpPrefix = PD; } // 0x66 +class T_MAP5XS : T_MAP5 { Prefix OpPrefix = XS; } // 0xF3 +class T_MAP5XD : T_MAP5 { Prefix OpPrefix = XD; } // 0xF2 +class T_MAP6 { Map OpMap = T_MAP6; } +class T_MAP6PS : T_MAP6 { Prefix OpPrefix = PS; } +class T_MAP6PD : T_MAP6 { Prefix OpPrefix = PD; } +class T_MAP6XS : T_MAP6 { Prefix OpPrefix = XS; } +class T_MAP6XD : T_MAP6 { Prefix OpPrefix = XD; } +class T_MAP7 { Map OpMap = T_MAP7; } +class T_MAP7XS : T_MAP7 { Prefix OpPrefix = XS; } // 0xF3 +class T_MAP7XD : T_MAP7 { Prefix OpPrefix = XD; } // 0xF2 +class OBXS { Prefix OpPrefix = XS; } +class PS : TB { Prefix OpPrefix = PS; } +class PD : TB { Prefix OpPrefix = PD; } +class XD : TB { Prefix OpPrefix = XD; } +class XS : TB { Prefix OpPrefix = XS; } +class T8PS : T8 { Prefix OpPrefix = PS; } +class T8PD : T8 { Prefix OpPrefix = PD; } +class T8XD : T8 { Prefix OpPrefix = XD; } +class T8XS : T8 { Prefix OpPrefix = XS; } +class TAPS : TA { Prefix OpPrefix = PS; } +class TAPD : TA { Prefix OpPrefix = PD; } +class TAXD : TA { Prefix OpPrefix = XD; } +class TAXS : TA { Prefix OpPrefix = XS; } +class VEX { Encoding OpEnc = EncVEX; } +class WIG { bit IgnoresW = 1; } +// Special version of REX_W that can be changed to VEX.W==0 for EVEX2VEX. +class VEX_W1X { bit hasREX_W = 1; bit EVEX_W1_VEX_W0 = 1; } +class VEX_4V : VEX { bit hasVEX_4V = 1; } +class VEX_L { bit hasVEX_L = 1; } +class VEX_LIG { bit ignoresVEX_L = 1; } +class EVEX { Encoding OpEnc = EncEVEX; } +class EVEX_4V : EVEX { bit hasVEX_4V = 1; } +class EVEX_K { bit hasEVEX_K = 1; } +class EVEX_KZ : EVEX_K { bit hasEVEX_Z = 1; } +class EVEX_B { bit hasEVEX_B = 1; } +class EVEX_RC { bit hasEVEX_RC = 1; } +class EVEX_V512 { bit hasEVEX_L2 = 1; bit hasVEX_L = 0; } +class EVEX_V256 { bit hasEVEX_L2 = 0; bit hasVEX_L = 1; } +class EVEX_V128 { bit hasEVEX_L2 = 0; bit hasVEX_L = 0; } +class NOTRACK { bit hasNoTrackPrefix = 1; } +class SIMD_EXC { list Uses = [MXCSR]; bit mayRaiseFPException = 1; } +// Specify AVX512 8-bit compressed displacement encoding based on the vector +// element size in bits (8, 16, 32, 64) and the CDisp8 form. +class EVEX_CD8 { + int CD8_EltSize = !srl(esize, 3); + bits<3> CD8_Form = form.Value; +} +class XOP { Encoding OpEnc = EncXOP; } +class XOP_4V : XOP { bit hasVEX_4V = 1; } +class EVEX2VEXOverride { + string EVEX2VEXOverride = VEXInstrName; +} +class AVX512BIi8Base : PD { + Domain ExeDomain = SSEPackedInt; + ImmType ImmT = Imm8; +} +class AVX512XSIi8Base : XS { + Domain ExeDomain = SSEPackedInt; + ImmType ImmT = Imm8; +} +class AVX512XDIi8Base : XD { + Domain ExeDomain = SSEPackedInt; + ImmType ImmT = Imm8; +} +class AVX512PSIi8Base : PS { + Domain ExeDomain = SSEPackedSingle; + ImmType ImmT = Imm8; +} +class AVX512PDIi8Base : PD { + Domain ExeDomain = SSEPackedDouble; + ImmType ImmT = Imm8; +} +class NotEVEX2VEXConvertible { bit notEVEX2VEXConvertible = 1; } +class ExplicitREX2Prefix { ExplicitOpPrefix explicitOpPrefix = ExplicitREX2; } +class ExplicitVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitVEX; } +class ExplicitEVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitEVEX; } + +// SchedModel info for instruction that loads one value and gets the second +// (and possibly third) value from a register. +// This is used for instructions that put the memory operands before other +// uses. +class SchedLoadReg : Sched<[Sched.Folded, + // Memory operand. + ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault, + // Register reads (implicit or explicit). + Sched.ReadAfterFold, Sched.ReadAfterFold]>; + +//===----------------------------------------------------------------------===// +// X86 Type infomation definitions +//===----------------------------------------------------------------------===// + +/// X86TypeInfo - This is a bunch of information that describes relevant X86 +/// information about value types. For example, it can tell you what the +/// register class and preferred load to use. +class X86TypeInfo { + /// VT - This is the value type itself. + ValueType VT = vt; + + /// InstrSuffix - This is the suffix used on instructions with this type. For + /// example, i8 -> "b", i16 -> "w", i32 -> "l", i64 -> "q". + string InstrSuffix = instrsuffix; + + /// RegClass - This is the register class associated with this type. For + /// example, i8 -> GR8, i16 -> GR16, i32 -> GR32, i64 -> GR64. + RegisterClass RegClass = regclass; + + /// LoadNode - This is the load node associated with this type. For + /// example, i8 -> loadi8, i16 -> loadi16, i32 -> loadi32, i64 -> loadi64. + PatFrag LoadNode = loadnode; + + /// MemOperand - This is the memory operand associated with this type. For + /// example, i8 -> i8mem, i16 -> i16mem, i32 -> i32mem, i64 -> i64mem. + X86MemOperand MemOperand = memoperand; + + /// ImmEncoding - This is the encoding of an immediate of this type. For + /// example, i8 -> Imm8, i16 -> Imm16, i32 -> Imm32. Note that i64 -> Imm32 + /// since the immediate fields of i64 instructions is a 32-bit sign extended + /// value. + ImmType ImmEncoding = immkind; + + /// ImmOperand - This is the operand kind of an immediate of this type. For + /// example, i8 -> i8imm, i16 -> i16imm, i32 -> i32imm. Note that i64 -> + /// i64i32imm since the immediate fields of i64 instructions is a 32-bit sign + /// extended value. + Operand ImmOperand = immoperand; + + /// ImmOperator - This is the operator that should be used to match an + /// immediate of this kind in a pattern (e.g. imm, or i64immSExt32). + SDPatternOperator ImmOperator = immoperator; + + SDPatternOperator ImmNoSuOperator = immnosuoperator; + + /// Imm8Operand - This is the operand kind to use for an imm8 of this type. + /// For example, i8 -> , i16 -> i16i8imm, i32 -> i32i8imm. This is + /// only used for instructions that have a sign-extended imm8 field form. + Operand Imm8Operand = imm8operand; + + /// Imm8Operator - This is the operator that should be used to match an 8-bit + /// sign extended immediate of this kind in a pattern (e.g. imm16immSExt8). + SDPatternOperator Imm8Operator = imm8operator; + + SDPatternOperator Imm8NoSuOperator = imm8nosuoperator; + + /// HasOddOpcode - This bit is true if the instruction should have an odd (as + /// opposed to even) opcode. Operations on i8 are usually even, operations on + /// other datatypes are odd. + bit HasOddOpcode = hasOddOpcode; + + /// OpSize - Selects whether the instruction needs a 0x66 prefix based on + /// 16-bit vs 32-bit mode. i8/i64 set this to OpSizeFixed. i16 sets this + /// to Opsize16. i32 sets this to OpSize32. + OperandSize OpSize = opSize; + + /// HasREX_W - This bit is set to true if the instruction should have + /// the 0x40 REX prefix. This is set for i64 types. + bit HasREX_W = hasREX_W; +} + +def invalid_node : SDNode<"<>", SDTIntLeaf,[],"<>">; + +def Xi8 : X86TypeInfo; +def Xi16 : X86TypeInfo; +def Xi32 : X86TypeInfo; +def Xi64 : X86TypeInfo; + +// Group template arguments that can be derived from the vector type (EltNum x +// EltVT). These are things like the register class for the writemask, etc. +// The idea is to pass one of these as the template argument rather than the +// individual arguments. +// The template is also used for scalar types, in this case numelts is 1. +class X86VectorVTInfo { + RegisterClass RC = rc; + ValueType EltVT = eltvt; + int NumElts = numelts; + + // Corresponding mask register class. + RegisterClass KRC = !cast("VK" # NumElts); + + // Corresponding mask register pair class. + RegisterOperand KRPC = !if (!gt(NumElts, 16), ?, + !cast("VK" # NumElts # "Pair")); + + // Corresponding write-mask register class. + RegisterClass KRCWM = !cast("VK" # NumElts # "WM"); + + // The mask VT. + ValueType KVT = !cast("v" # NumElts # "i1"); + + // Suffix used in the instruction mnemonic. + string Suffix = suffix; + + // VTName is a string name for vector VT. For vector types it will be + // v # NumElts # EltVT, so for vector of 8 elements of i32 it will be v8i32 + // It is a little bit complex for scalar types, where NumElts = 1. + // In this case we build v4f32 or v2f64 + string VTName = "v" # !if (!eq (NumElts, 1), + !if (!eq (EltVT.Size, 16), 8, + !if (!eq (EltVT.Size, 32), 4, + !if (!eq (EltVT.Size, 64), 2, NumElts))), NumElts) # EltVT; + + // The vector VT. + ValueType VT = !cast(VTName); + + string EltTypeName = !cast(EltVT); + // Size of the element type in bits, e.g. 32 for v16i32. + string EltSizeName = !subst("i", "", !subst("f", "", !subst("b", "", EltTypeName))); + int EltSize = EltVT.Size; + + // "i" for integer types and "f" for floating-point types + string TypeVariantName = !subst("b", "", !subst(EltSizeName, "", EltTypeName)); + + // Size of RC in bits, e.g. 512 for VR512. + int Size = VT.Size; + + // The corresponding memory operand, e.g. i512mem for VR512. + X86MemOperand MemOp = !cast(TypeVariantName # Size # "mem"); + X86MemOperand ScalarMemOp = !cast(!subst("b", "", EltTypeName) # "mem"); + // FP scalar memory operand for intrinsics - ssmem/sdmem. + Operand IntScalarMemOp = !if (!eq (EltTypeName, "f16"), !cast("shmem"), + !if (!eq (EltTypeName, "bf16"), !cast("shmem"), + !if (!eq (EltTypeName, "f32"), !cast("ssmem"), + !if (!eq (EltTypeName, "f64"), !cast("sdmem"), ?)))); + + // Load patterns + PatFrag LdFrag = !cast("load" # VTName); + + PatFrag AlignedLdFrag = !cast("alignedload" # VTName); + + PatFrag ScalarLdFrag = !cast("load" # !subst("b", "", EltTypeName)); + PatFrag BroadcastLdFrag = !cast("X86VBroadcastld" # EltSizeName); + + PatFrags ScalarIntMemFrags = !if (!eq (EltTypeName, "f16"), !cast("sse_load_f16"), + !if (!eq (EltTypeName, "bf16"), !cast("sse_load_f16"), + !if (!eq (EltTypeName, "f32"), !cast("sse_load_f32"), + !if (!eq (EltTypeName, "f64"), !cast("sse_load_f64"), ?)))); + + // The string to specify embedded broadcast in assembly. + string BroadcastStr = "{1to" # NumElts # "}"; + + // 8-bit compressed displacement tuple/subvector format. This is only + // defined for NumElts <= 8. + CD8VForm CD8TupleForm = !if (!eq (!srl(NumElts, 4), 0), + !cast("CD8VT" # NumElts), ?); + + SubRegIndex SubRegIdx = !if (!eq (Size, 128), sub_xmm, + !if (!eq (Size, 256), sub_ymm, ?)); + + Domain ExeDomain = !if (!eq (EltTypeName, "f32"), SSEPackedSingle, + !if (!eq (EltTypeName, "f64"), SSEPackedDouble, + !if (!eq (EltTypeName, "f16"), SSEPackedSingle, // FIXME? + !if (!eq (EltTypeName, "bf16"), SSEPackedSingle, // FIXME? + SSEPackedInt)))); + + RegisterClass FRC = !if (!eq (EltTypeName, "f32"), FR32X, + !if (!eq (EltTypeName, "f16"), FR16X, + !if (!eq (EltTypeName, "bf16"), FR16X, + FR64X))); + + dag ImmAllZerosV = (VT immAllZerosV); + + string ZSuffix = !if (!eq (Size, 128), "Z128", + !if (!eq (Size, 256), "Z256", "Z")); +} + +def v64i8_info : X86VectorVTInfo<64, i8, VR512, "b">; +def v32i16_info : X86VectorVTInfo<32, i16, VR512, "w">; +def v16i32_info : X86VectorVTInfo<16, i32, VR512, "d">; +def v8i64_info : X86VectorVTInfo<8, i64, VR512, "q">; +def v32f16_info : X86VectorVTInfo<32, f16, VR512, "ph">; +def v32bf16_info: X86VectorVTInfo<32, bf16, VR512, "pbf">; +def v16f32_info : X86VectorVTInfo<16, f32, VR512, "ps">; +def v8f64_info : X86VectorVTInfo<8, f64, VR512, "pd">; + +// "x" in v32i8x_info means RC = VR256X +def v32i8x_info : X86VectorVTInfo<32, i8, VR256X, "b">; +def v16i16x_info : X86VectorVTInfo<16, i16, VR256X, "w">; +def v8i32x_info : X86VectorVTInfo<8, i32, VR256X, "d">; +def v4i64x_info : X86VectorVTInfo<4, i64, VR256X, "q">; +def v16f16x_info : X86VectorVTInfo<16, f16, VR256X, "ph">; +def v16bf16x_info: X86VectorVTInfo<16, bf16, VR256X, "pbf">; +def v8f32x_info : X86VectorVTInfo<8, f32, VR256X, "ps">; +def v4f64x_info : X86VectorVTInfo<4, f64, VR256X, "pd">; + +def v16i8x_info : X86VectorVTInfo<16, i8, VR128X, "b">; +def v8i16x_info : X86VectorVTInfo<8, i16, VR128X, "w">; +def v4i32x_info : X86VectorVTInfo<4, i32, VR128X, "d">; +def v2i64x_info : X86VectorVTInfo<2, i64, VR128X, "q">; +def v8f16x_info : X86VectorVTInfo<8, f16, VR128X, "ph">; +def v8bf16x_info : X86VectorVTInfo<8, bf16, VR128X, "pbf">; +def v4f32x_info : X86VectorVTInfo<4, f32, VR128X, "ps">; +def v2f64x_info : X86VectorVTInfo<2, f64, VR128X, "pd">; + +// We map scalar types to the smallest (128-bit) vector type +// with the appropriate element type. This allows to use the same masking logic. +def i32x_info : X86VectorVTInfo<1, i32, GR32, "si">; +def i64x_info : X86VectorVTInfo<1, i64, GR64, "sq">; +def f16x_info : X86VectorVTInfo<1, f16, VR128X, "sh">; +def bf16x_info : X86VectorVTInfo<1, bf16, VR128X, "sbf">; +def f32x_info : X86VectorVTInfo<1, f32, VR128X, "ss">; +def f64x_info : X86VectorVTInfo<1, f64, VR128X, "sd">; + +class AVX512VLVectorVTInfo { + X86VectorVTInfo info512 = i512; + X86VectorVTInfo info256 = i256; + X86VectorVTInfo info128 = i128; +} + +def avx512vl_i8_info : AVX512VLVectorVTInfo; +def avx512vl_i16_info : AVX512VLVectorVTInfo; +def avx512vl_i32_info : AVX512VLVectorVTInfo; +def avx512vl_i64_info : AVX512VLVectorVTInfo; +def avx512vl_f16_info : AVX512VLVectorVTInfo; +def avx512vl_bf16_info : AVX512VLVectorVTInfo; +def avx512vl_f32_info : AVX512VLVectorVTInfo; +def avx512vl_f64_info : AVX512VLVectorVTInfo; + +class X86KVectorVTInfo { + RegisterClass KRC = _krc; + RegisterClass KRCWM = _krcwm; + ValueType KVT = _vt; +} + +def v1i1_info : X86KVectorVTInfo; +def v2i1_info : X86KVectorVTInfo; +def v4i1_info : X86KVectorVTInfo; +def v8i1_info : X86KVectorVTInfo; +def v16i1_info : X86KVectorVTInfo; +def v32i1_info : X86KVectorVTInfo; +def v64i1_info : X86KVectorVTInfo; + +// Subclasses of X86Inst +class PseudoI pattern> + : X86Inst<0, Pseudo, NoImm, oops, iops, ""> { + let Pattern = pattern; +} + +class I o, Format f, dag outs, dag ins, string asm, + list pattern, Domain d = GenericDomain> + : X86Inst { + let Pattern = pattern; +} +class Ii8 o, Format f, dag outs, dag ins, string asm, + list pattern, Domain d = GenericDomain> + : X86Inst { + let Pattern = pattern; +} +class Ii8Reg o, Format f, dag outs, dag ins, string asm, + list pattern, Domain d = GenericDomain> + : X86Inst { + let Pattern = pattern; +} +class Ii8PCRel o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} +class Ii16 o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} +class Ii32 o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} +class Ii32S o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} + +class Ii64 o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} + +class Ii16PCRel o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} + +class Ii32PCRel o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} + +// FPStack Instruction Templates: +// FPI - Floating Point Instruction template. +class FPI o, Format F, dag outs, dag ins, string asm> + : I { + let Defs = [FPSW]; + let Predicates = [HasX87]; +} + +// FpI_ - Floating Point Pseudo Instruction template. +class FpI_ pattern> + : PseudoI { + let FPForm = fp; + let Defs = [FPSW]; + let Predicates = [HasX87]; +} + +// Templates for instructions that use a 16- or 32-bit segmented address as +// their only operand: lcall (FAR CALL) and ljmp (FAR JMP) +// +// Iseg16 - 16-bit segment selector, 16-bit offset +// Iseg32 - 16-bit segment selector, 32-bit offset + +class Iseg16 o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} + +class Iseg32 o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; +} + +// SI - SSE 1 & 2 scalar instructions +class SI o, Format F, dag outs, dag ins, string asm, + list pattern, Domain d = GenericDomain> + : I { + let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], + !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], + !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], + !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], + !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], + [UseSSE1]))))); + + // AVX instructions have a 'v' prefix in the mnemonic + let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), + !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), + asm)); +} + +// SI - SSE 1 & 2 scalar intrinsics - vex form available on AVX512 +class SI_Int o, Format F, dag outs, dag ins, string asm, + list pattern, Domain d = GenericDomain> + : I { + let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], + !if(!eq(OpEnc.Value, EncVEX.Value), [UseAVX], + !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], + !if(!eq(OpPrefix.Value, XD.Value), [UseSSE2], + !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], + [UseSSE1]))))); + + // AVX instructions have a 'v' prefix in the mnemonic + let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), + !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), + asm)); +} +// SIi8 - SSE 1 & 2 scalar instructions - vex form available on AVX512 +class SIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8 { + let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], + !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], + !if(!eq(OpPrefix.Value, XS.Value), [UseSSE1], + [UseSSE2]))); + + // AVX instructions have a 'v' prefix in the mnemonic + let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), + !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), + asm)); +} + +// PI - SSE 1 & 2 packed instructions +class PI o, Format F, dag outs, dag ins, string asm, list pattern, + Domain d> + : I { + let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], + !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], + !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], + [UseSSE1]))); + + // AVX instructions have a 'v' prefix in the mnemonic + let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), + !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), + asm)); +} + +// MMXPI - SSE 1 & 2 packed instructions with MMX operands +class MMXPI o, Format F, dag outs, dag ins, string asm, list pattern, + Domain d> + : I { + let Predicates = !if(!eq(OpPrefix.Value, PD.Value), [HasMMX, HasSSE2], + [HasMMX, HasSSE1]); +} + +// PIi8 - SSE 1 & 2 packed instructions with immediate +class PIi8 o, Format F, dag outs, dag ins, string asm, + list pattern, Domain d> + : Ii8 { + let Predicates = !if(!eq(OpEnc.Value, EncEVEX.Value), [HasAVX512], + !if(!eq(OpEnc.Value, EncVEX.Value), [HasAVX], + !if(!eq(OpPrefix.Value, PD.Value), [UseSSE2], + [UseSSE1]))); + + // AVX instructions have a 'v' prefix in the mnemonic + let AsmString = !if(!eq(OpEnc.Value, EncEVEX.Value), !strconcat("v", asm), + !if(!eq(OpEnc.Value, EncVEX.Value), !strconcat("v", asm), + asm)); +} + +// SSE1 Instruction Templates: +// +// SSI - SSE1 instructions with XS prefix. +// PSI - SSE1 instructions with PS prefix. +// PSIi8 - SSE1 instructions with ImmT == Imm8 and PS prefix. +// VSSI - SSE1 instructions with XS prefix in AVX form. +// VPSI - SSE1 instructions with PS prefix in AVX form, packed single. + +class SSI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XS, Requires<[UseSSE1]>; +class SSIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XS, Requires<[UseSSE1]>; +class PSI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PS, + Requires<[UseSSE1]>; +class PSIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, PS, + Requires<[UseSSE1]>; +class VSSI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XS, + Requires<[HasAVX]>; +class VPSI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PS, + Requires<[HasAVX]>; + +// SSE2 Instruction Templates: +// +// SDI - SSE2 instructions with XD prefix. +// SDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix. +// S2SI - SSE2 instructions with XS prefix. +// SSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix. +// PDI - SSE2 instructions with PD prefix, packed double domain. +// PDIi8 - SSE2 instructions with ImmT == Imm8 and PD prefix. +// VSDI - SSE2 scalar instructions with XD prefix in AVX form. +// VPDI - SSE2 vector instructions with PD prefix in AVX form, +// packed double domain. +// VS2I - SSE2 scalar instructions with PD prefix in AVX form. +// S2I - SSE2 scalar instructions with PD prefix. +// MMXSDIi8 - SSE2 instructions with ImmT == Imm8 and XD prefix as well as +// MMX operands. +// MMXSSDIi8 - SSE2 instructions with ImmT == Imm8 and XS prefix as well as +// MMX operands. + +class SDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XD, Requires<[UseSSE2]>; +class SDIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XD, Requires<[UseSSE2]>; +class S2SI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XS, Requires<[UseSSE2]>; +class S2SIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XS, Requires<[UseSSE2]>; +class PDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PD, + Requires<[UseSSE2]>; +class PDIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, PD, + Requires<[UseSSE2]>; +class VSDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XD, + Requires<[UseAVX]>; +class VS2SI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XS, + Requires<[HasAVX]>; +class VPDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, + PD, Requires<[HasAVX]>; +class VS2I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PD, + Requires<[UseAVX]>; +class S2I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PD, Requires<[UseSSE2]>; +class MMXSDIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XD, Requires<[HasMMX, HasSSE2]>; +class MMXS2SIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XS, Requires<[HasMMX, HasSSE2]>; + +// SSE3 Instruction Templates: +// +// S3I - SSE3 instructions with PD prefixes. +// S3SI - SSE3 instructions with XS prefix. +// S3DI - SSE3 instructions with XD prefix. + +class S3SI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XS, + Requires<[UseSSE3]>; +class S3DI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XD, + Requires<[UseSSE3]>; +class S3I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PD, + Requires<[UseSSE3]>; + + +// SSSE3 Instruction Templates: +// +// SS38I - SSSE3 instructions with T8 prefix. +// SS3AI - SSSE3 instructions with TA prefix. +// MMXSS38I - SSSE3 instructions with T8 prefix and MMX operands. +// MMXSS3AI - SSSE3 instructions with TA prefix and MMX operands. +// +// Note: SSSE3 instructions have 64-bit and 128-bit versions. The 64-bit version +// uses the MMX registers. The 64-bit versions are grouped with the MMX +// classes. They need to be enabled even if AVX is enabled. + +class SS38I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8PD, + Requires<[UseSSSE3]>; +class SS3AI o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPD, + Requires<[UseSSSE3]>; +class MMXSS38I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8PS, + Requires<[HasMMX, HasSSSE3]>; +class MMXSS3AI o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPS, + Requires<[HasMMX, HasSSSE3]>; + +// SSE4.1 Instruction Templates: +// +// SS48I - SSE 4.1 instructions with T8 prefix. +// SS41AIi8 - SSE 4.1 instructions with TA prefix and ImmT == Imm8. +// +class SS48I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8PD, + Requires<[UseSSE41]>; +class SS4AIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPD, + Requires<[UseSSE41]>; + +// SSE4.2 Instruction Templates: +// +// SS428I - SSE 4.2 instructions with T8 prefix. +class SS428I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8PD, + Requires<[UseSSE42]>; + +// SS42AI = SSE 4.2 instructions with TA prefix +class SS42AI o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPD, + Requires<[UseSSE42]>; + +// CRC32I - SSE 4.2 CRC32 instructions. +// NOTE: 'HasCRC32' is used as CRC32 instructions are GPR only and not directly +// controlled by the SSE42 flag. +class CRC32I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8XD, Requires<[HasCRC32]>; + +// AVX Instruction Templates: +// Instructions introduced in AVX (no SSE equivalent forms) +// +// AVX8I - AVX instructions with T8PD prefix. +// AVXAIi8 - AVX instructions with TAPD prefix and ImmT = Imm8. +class AVX8I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8PD, + Requires<[HasAVX]>; +class AVXAIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPD, + Requires<[HasAVX]>; + +// AVX2 Instruction Templates: +// Instructions introduced in AVX2 (no SSE equivalent forms) +// +// AVX28I - AVX2 instructions with T8PD prefix. +// AVX2AIi8 - AVX2 instructions with TAPD prefix and ImmT = Imm8. +class AVX28I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8PD, + Requires<[HasAVX2]>; +class AVX2AIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPD, + Requires<[HasAVX2]>; + + +// AVX-512 Instruction Templates: +// Instructions introduced in AVX-512 (no SSE equivalent forms) +// +// AVX5128I - AVX-512 instructions with T8PD prefix. +// AVX512AIi8 - AVX-512 instructions with TAPD prefix and ImmT = Imm8. +// AVX512PDI - AVX-512 instructions with PD, double packed. +// AVX512PSI - AVX-512 instructions with PS, single packed. +// AVX512XS8I - AVX-512 instructions with T8 and XS prefixes. +// AVX512XSI - AVX-512 instructions with XS prefix, generic domain. +// AVX512BI - AVX-512 instructions with PD, int packed domain. +// AVX512SI - AVX-512 scalar instructions with PD prefix. + +class AVX5128I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8PD, + Requires<[HasAVX512]>; +class AVX5128IBase : T8PD { + Domain ExeDomain = SSEPackedInt; +} +class AVX512XS8I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, T8XS, + Requires<[HasAVX512]>; +class AVX512XSI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XS, + Requires<[HasAVX512]>; +class AVX512XDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, XD, + Requires<[HasAVX512]>; +class AVX512BI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PD, + Requires<[HasAVX512]>; +class AVX512BIBase : PD { + Domain ExeDomain = SSEPackedInt; +} +class AVX512BIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, PD, + Requires<[HasAVX512]>; +class AVX512AIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPD, + Requires<[HasAVX512]>; +class AVX512AIi8Base : TAPD { + ImmType ImmT = Imm8; +} +class AVX512Ii8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, + Requires<[HasAVX512]>; +class AVX512PDI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PD, + Requires<[HasAVX512]>; +class AVX512PSI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PS, + Requires<[HasAVX512]>; +class AVX512PIi8 o, Format F, dag outs, dag ins, string asm, + list pattern, Domain d> + : Ii8, Requires<[HasAVX512]>; +class AVX512PI o, Format F, dag outs, dag ins, string asm, + list pattern, Domain d> + : I, Requires<[HasAVX512]>; +class AVX512FMA3S o, Format F, dag outs, dag ins, string asm, + listpattern> + : I, T8PD, + EVEX_4V, Requires<[HasAVX512]>; + +class AVX512 o, Format F, dag outs, dag ins, string asm, + listpattern> + : I, Requires<[HasAVX512]>; + +// AES Instruction Templates: +// +// AES8I +// These use the same encoding as the SSE4.2 T8 and TA encodings. +class AES8I o, Format F, dag outs, dag ins, string asm, + listpattern> + : I, T8PD, + Requires<[NoAVX, HasAES]>; + +class AESAI o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, TAPD, + Requires<[NoAVX, HasAES]>; + +// PCLMUL Instruction Templates +class PCLMULIi8 o, Format F, dag outs, dag ins, string asm, + listpattern> + : Ii8, TAPD; + +// FMA3 Instruction Templates +class FMA3 o, Format F, dag outs, dag ins, string asm, + listpattern> + : I, T8PD, + VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoVLX]>; +class FMA3S o, Format F, dag outs, dag ins, string asm, + listpattern> + : I, T8PD, + VEX_4V, FMASC, Requires<[HasFMA, NoFMA4, NoAVX512]>; +class FMA3S_Int o, Format F, dag outs, dag ins, string asm, + listpattern> + : I, T8PD, + VEX_4V, FMASC, Requires<[HasFMA, NoAVX512]>; + +// FMA4 Instruction Templates +class FMA4 o, Format F, dag outs, dag ins, string asm, + listpattern> + : Ii8Reg, TAPD, + VEX_4V, FMASC, Requires<[HasFMA4, NoVLX]>; +class FMA4S o, Format F, dag outs, dag ins, string asm, + listpattern> + : Ii8Reg, TAPD, + VEX_4V, FMASC, Requires<[HasFMA4, NoAVX512]>; +class FMA4S_Int o, Format F, dag outs, dag ins, string asm, + listpattern> + : Ii8Reg, TAPD, + VEX_4V, FMASC, Requires<[HasFMA4]>; + +// XOP 2, 3 and 4 Operand Instruction Template +class IXOP o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, + XOP9, Requires<[HasXOP]>; + +// XOP 2 and 3 Operand Instruction Templates with imm byte +class IXOPi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, + XOP8, Requires<[HasXOP]>; +// XOP 4 Operand Instruction Templates with imm byte +class IXOPi8Reg o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8Reg, + XOP8, Requires<[HasXOP]>; + +// XOP 5 operand instruction (VEX encoding!) +class IXOP5 o, Format F, dag outs, dag ins, string asm, + listpattern> + : Ii8Reg, TAPD, + VEX_4V, Requires<[HasXOP]>; + +// X86-64 Instruction templates... +// + +class RI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, REX_W; +class RIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, REX_W; +class RIi16 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii16, REX_W; +class RIi32 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii32, REX_W; +class RIi32S o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii32S, REX_W; +class RIi64 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii64, REX_W; + +class RS2I o, Format F, dag outs, dag ins, string asm, + list pattern> + : S2I, REX_W; +class VRS2I o, Format F, dag outs, dag ins, string asm, + list pattern> + : VS2I, REX_W; + +// MMX Instruction templates +// + +// MMXI - MMX instructions with TB prefix. +// MMXI32 - MMX instructions with TB prefix valid only in 32 bit mode. +// MMXI64 - MMX instructions with TB prefix valid only in 64 bit mode. +// MMX2I - MMX / SSE2 instructions with PD prefix. +// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. +// MMXIi8 - MMX instructions with ImmT == Imm8 and PS prefix. +// MMXID - MMX instructions with XD prefix. +// MMXIS - MMX instructions with XS prefix. +class MMXI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PS, Requires<[HasMMX]>; +class MMXI32 o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PS, Requires<[HasMMX,Not64BitMode]>; +class MMXI64 o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PS, Requires<[HasMMX,In64BitMode]>; +class MMXRI o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PS, REX_W, + Requires<[HasMMX,In64BitMode]>; +class MMX2I o, Format F, dag outs, dag ins, string asm, + list pattern> + : I, PD, Requires<[HasMMX]>; +class MMXIi8 o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, PS, Requires<[HasMMX]>; +class MMXID o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XD, Requires<[HasMMX]>; +class MMXIS o, Format F, dag outs, dag ins, string asm, + list pattern> + : Ii8, XS, Requires<[HasMMX]>; + +/// ITy - This instruction base class takes the type info for the instruction. +/// Using this, it: +/// 1. Concatenates together the instruction mnemonic with the appropriate +/// suffix letter, a tab, and the arguments. +/// 2. Infers whether the instruction should have a 0x66 prefix byte. +/// 3. Infers whether the instruction should have a 0x40 REX_W prefix. +/// 4. Infers whether the low bit of the opcode should be 0 (for i8 operations) +/// or 1 (for i16,i32,i64 operations). +class ITy opcode, Format f, X86TypeInfo typeinfo, dag outs, dag ins, + string mnemonic, string args, list pattern> + : I<{opcode{7}, opcode{6}, opcode{5}, opcode{4}, + opcode{3}, opcode{2}, opcode{1}, typeinfo.HasOddOpcode }, + f, outs, ins, + !strconcat(mnemonic, "{", typeinfo.InstrSuffix, "}\t", args), pattern> { + + // Infer instruction prefixes from type info. + let OpSize = typeinfo.OpSize; + let hasREX_W = typeinfo.HasREX_W; +}