Combining physical registers

The function TII::canCombineSubRegIndices has been gone for a while now, and I was wondering if there is a target-independent way of determining if a certain set of physical registers "adds up" to a larger register. For example, on X86, AL and AH together form AX. On Hexagon, R0 and R1 are D0.
The context here is an attempt to coalesce multiple loads/stores into fewer loads/stores using larger registers.

It is my understanding that register lane masks are not exact in a sense that they will tell me if two register lanes alias, but not necessarily if a set of masks adds up to a full register. Is this correct?

-Krzysztof

The function TII::canCombineSubRegIndices has been gone for a while now, and I was wondering if there is a target-independent way of determining if a certain set of physical registers "adds up" to a larger register. For example, on X86, AL and AH together form AX. On Hexagon, R0 and R1 are D0.
The context here is an attempt to coalesce multiple loads/stores into fewer loads/stores using larger registers.

At the moment, there is no way of determining this, but I have a patch.

It is my understanding that register lane masks are not exact in a sense that they will tell me if two register lanes alias, but not necessarily if a set of masks adds up to a full register. Is this correct?

That’s right.

Would this TRI function solve your problem?

  /// The lane masks returned by getSubRegIndexLaneMask() above can only be
  /// used to determine if sub-registers overlap - they can't be used to
  /// determine if a set of sub-registers completely cover another
  /// sub-register.
  ///
  /// The X86 general purpose registers have two lanes corresponding to the
  /// sub_8bit and sub_8bit_hi sub-registers. Both sub_32bit and sub_16bit have
  /// lane masks '3', but the sub_16bit sub-register doesn't fully cover the
  /// sub_32bit sub-register.
  ///
  /// On the other hand, the ARM NEON lanes fully cover their registers: The
  /// dsub_0 sub-register is completely covered by the ssub_0 and ssub_1 lanes.
  /// This is related to the CoveredBySubRegs property on register definitions.
  ///
  /// This function returns a bit mask of lanes that completely cover their
  /// sub-registers. More precisely, given:
  ///
  /// Covering = getCoveringLanes();
  /// MaskA = getSubRegIndexLaneMask(SubA);
  /// MaskB = getSubRegIndexLaneMask(SubB);
  ///
  /// If (MaskA & ~(MaskB & Covering)) == 0, then SubA is completely covered by
  /// SubB.
  unsigned getCoveringLanes() const { return CoveringLanes; }

/jakob

Yes, this would solve my problem. I'm assuming that if I have subregisters Sub0..SubN (where Sub0 could be 0, i.e. the register itself), and corresponding masks Mask0..MaskN, and
   Mask0 & ~((Mask1|Mask2|..|MaskN) & Covering) == 0,
this will imply that the subregisters Sub1..SubN cover Sub0.

Thanks,
-Krzysztof

That’s right.

Currently, there is no way of getting the lane mask of the register itself, only sub-registers have lane masks.

However, getSubRegIndexLaneMask(0) returns ~0u, and any unused lanes are returned as ‘1’ in getCoveringLanes(), so it should all work out.

/jakob