[X86] AVX512: Move compressed displacement logic to TD
authorAdam Nemet <anemet@apple.com>
Thu, 17 Jul 2014 17:04:34 +0000 (17:04 +0000)
committerAdam Nemet <anemet@apple.com>
Thu, 17 Jul 2014 17:04:34 +0000 (17:04 +0000)
This does not actually move the logic yet but reimplements it in the Tablegen
language.  Then asserts that the new implementation results in the same value.

The next patch will remove the assert and the temporary use of the TSFlags and
remove the C++ implementation.

The formula requires a limited form of the logical left and right operators.
I implemented these with the bit-extract/insert operator (i.e. blah{bits}).

No functional change.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213278 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
lib/Target/X86/X86InstrFormats.td

index 7c30fc25ae0ced0375310ed1ecef54a4590a5cd9..df0778d3ce6513a615eb3cf4ccb80543076fb5f2 100644 (file)
@@ -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.");
 
index cc302663d5890c1082f9d4eca33281e91b5f0deb..0b3e521ddeaa565a398273c09ccb050eeb2bb000 100644 (file)
@@ -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<int esize, CD8VForm form> {
   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<bits<8> 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<bits<8> 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<dag oops, dag iops, list<dag> pattern>