diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 7c30fc25ae0..df0778d3ce6 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -191,9 +191,11 @@ static bool isCDisp8(uint64_t TSFlags, int Value, int& CValue) { unsigned CD8E = (TSFlags >> X86II::EVEX_CD8EShift) & X86II::EVEX_CD8EMask; unsigned CD8V = (TSFlags >> X86II::EVEX_CD8VShift) & X86II::EVEX_CD8VMask; + unsigned CD8_Scale = (TSFlags >> 56) & 0x7f; if (CD8V == 0 && CD8E == 0) { CValue = Value; + assert(CD8_Scale == 0); return isDisp8(Value); } @@ -224,6 +226,8 @@ static bool isCDisp8(uint64_t TSFlags, int Value, int& CValue) { } } + assert(MemObjSize == CD8_Scale); + unsigned MemObjMask = MemObjSize - 1; assert((MemObjSize & MemObjMask) == 0 && "Invalid memory object size."); diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index cc302663d58..0b3e521ddea 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -184,13 +184,18 @@ 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; } + +// 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 { bits<2> EVEX_CD8E = !if(!eq(esize, 8), 0b00, !if(!eq(esize, 16), 0b01, !if(!eq(esize, 32), 0b10, !if(!eq(esize, 64), 0b11, ?)))); + int CD8_EltSize = !srl(esize, 3); bits<3> EVEX_CD8V = form.Value; } + class Has3DNow0F0FOpcode { bit has3DNow0F0FOpcode = 1; } class MemOp4 { bit hasMemOp4Prefix = 1; } class XOP { Encoding OpEnc = EncXOP; } @@ -255,10 +260,31 @@ class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, bit hasEVEX_B = 0; // Does this inst set the EVEX_B field? bits<2> EVEX_CD8E = 0; // Compressed disp8 form - element-size. bits<3> EVEX_CD8V = 0; // Compressed disp8 form - vector-width. + // Declare it int rather than bits<4> so that all bits are defined when + // assigning to bits<7>. + int CD8_EltSize = 0; // Compressed disp8 form - element-size in bytes. bit has3DNow0F0FOpcode =0;// Wacky 3dNow! encoding? bit hasMemOp4Prefix = 0; // Same bit as VEX_W, but used for swapping operands bit hasEVEX_RC = 0; // Explicitly specified rounding control in FP instruction. + bits<2> EVEX_LL; + let EVEX_LL{0} = hasVEX_L; + let EVEX_LL{1} = hasEVEX_L2; + // Vector size in bytes. + bits<7> VectSize = !shl(16, EVEX_LL); + + // The scaling factor for AVX512's compressed displacement is either + // - the size of a power-of-two number of elements or + // - the size of a single element for broadcasts or + // - the total vector size divided by a power-of-two number. + // Possible values are: 0 (non-AVX512 inst), 1, 2, 4, 8, 16, 32 and 64. + bits<7> CD8_Scale = !if (!eq (OpEnc.Value, EncEVEX.Value), + !if (EVEX_CD8V{2}, + !shl(CD8_EltSize, EVEX_CD8V{1-0}), + !if (hasEVEX_B, + CD8_EltSize, + !srl(VectSize, EVEX_CD8V{1-0}))), 0); + // TSFlags layout should be kept in sync with X86InstrInfo.h. let TSFlags{6-0} = FormBits; let TSFlags{8-7} = OpSizeBits; @@ -288,6 +314,10 @@ class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, let TSFlags{53} = has3DNow0F0FOpcode; let TSFlags{54} = hasMemOp4Prefix; let TSFlags{55} = hasEVEX_RC; + + // Temporarily make this available to the backend in order to assert that TD + // and C++ compute the same scaling value. + let TSFlags{62-56} = CD8_Scale; } class PseudoI pattern>