Does anyone know exactly what ComposerIndices in is all about?

I see just one place where it's used in X86 but it's not clear from the comments in and it's one usage, exactly what this feature is about.



TableGen uses them when flattening the sub-register graph. The best example is the ARM NEON registers:

  D0 = { ssub0:S0, ssub1:S1 }
  D1 = { ssub0:S2, ssub1:S3 }

  Q0 = { dsub0:D0, dsub1:D1 }

The flattening means that Q0 has all six sub-registers:

  Q0 = { dsub0:D0, dsub1:D1, ssub0:S0, ssub1:S1, ?:S2, ?:S3 }

Each sub-register must have a unique sub-register index. If you don't specify any CompositeIndices, TableGen will invent names like dsub0_then_ssub_0. The CompositeIndices allows you to name the composite indices:

  CompositeIndices = [(ssub2 dsub_0, ssub_0), (ssub3 dsub_0, ssub_1)]

With that declaration, TableGen infers these sub-register names:

  Q0 = { dsub0:D0, dsub1:D1, ssub0:S0, ssub1:S1, ssub2:S2, ssub3:S3 }

It will also emit a composeSubRegIndices() function that tells you dsub1+ssub0 = ssub2 etc.

Sub-register indices are supposed to compose identically in all registers, so I found it was more convenient to specify the composition as part of the SubRegIndex def itself:

  def ssub_0 : SubRegIndex;
  def ssub_1 : SubRegIndex;
  def ssub_2 : SubRegIndex<[dsub_1, ssub_0]>;
  def ssub_3 : SubRegIndex<[dsub_1, ssub_1]>;

When you do that, it is no longer necessary to set CompositeIndices in the register definitions. I wanted to eliminate CompositeIndices completely, but there is one remaining use: The idempotent sub_ss and sub_sd indices on the XMM registers.

It is possible we can get away with this instead:

  let SubRegIndices = [sub_ss, sub_sd] in
  def XMM0: RegisterWithSubRegs<"xmm0", [XMM0, XMM0]>;

That would allow us to completely remove CompositeIndices.