//===-- X86InstrInfo.td - Main X86 Instruction Properties --*- 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 describes the X86 properties of the instructions which are needed // for code generation, machine code emission, and analysis. // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // X86 specific DAG Nodes. // 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]>; //===----------------------------------------------------------------------===// // 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; } //===----------------------------------------------------------------------===// // X86 Complex Pattern 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 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 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 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()">; //===----------------------------------------------------------------------===// // X86 Instruction Format Definitions. // include "X86InstrFormats.td" //===----------------------------------------------------------------------===// // Pattern fragments. // // 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; } //===----------------------------------------------------------------------===// // Subsystems. //===----------------------------------------------------------------------===// include "X86InstrMisc.td" include "X86InstrTBM.td" include "X86InstrArithmetic.td" include "X86InstrCMovSetCC.td" include "X86InstrExtension.td" include "X86InstrControl.td" 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" // XOP include "X86InstrXOP.td" // SSE, MMX and 3DNow! vector support. include "X86InstrSSE.td" include "X86InstrAVX512.td" include "X86InstrMMX.td" include "X86Instr3DNow.td" include "X86InstrVMX.td" include "X86InstrSVM.td" include "X86InstrSNP.td" include "X86InstrTSX.td" include "X86InstrSGX.td" include "X86InstrTDX.td" // Key Locker instructions include "X86InstrKL.td" // AMX instructions include "X86InstrAMX.td" // RAO-INT instructions include "X86InstrRAOINT.td" // System instructions. include "X86InstrSystem.td" // Compiler Pseudo Instructions and Pat Patterns include "X86InstrCompiler.td" include "X86InstrVecCompiler.td" // Assembler mnemonic/instruction aliases include "X86InstrAsmAlias.td"