[all-commits] [llvm/llvm-project] ccb3c8: [RegisterCoalescer] Update empty subranges when re...

qcolombet via All-commits all-commits at lists.llvm.org
Wed Jun 3 17:14:04 PDT 2020


  Branch: refs/heads/master
  Home:   https://github.com/llvm/llvm-project
  Commit: ccb3c8e8613413846d6c2f17cc1c1e2a8b6a98ef
      https://github.com/llvm/llvm-project/commit/ccb3c8e8613413846d6c2f17cc1c1e2a8b6a98ef
  Author: Quentin Colombet <qcolombet at apple.com>
  Date:   2020-06-03 (Wed, 03 Jun 2020)

  Changed paths:
    M llvm/lib/CodeGen/RegisterCoalescer.cpp
    A llvm/test/CodeGen/SystemZ/regcoal_remat_empty_subrange.ll

  Log Message:
  -----------
  [RegisterCoalescer] Update empty subranges when rematerializing

When we rematerialize a value as part of the coalescing, we may
widen the register class of the destination register.
When this happens, updateRegDefUses may create additional subranges
to account for the wider register class.
The created subranges are empty and if they are not defined by
the rematerialized instruction we clean them up.
However, if they are defined by the rematerialized instruction but
unused, we failed to flag them as dead definition and would leave
them as empty live-range.
This is wrong because empty live-ranges don't interfere with anything,
thus if we don't fix them, we would fail to account that the
rematerialized instruction clobbers some lanes.

E.g., let us consider the following pseudo code:
def.lane_low64:reg128 = ldimm
newdef:reg32 = COPY def.lane_low64_low32

When rematerialization happens for newdef, we end up with:
newdef.lane_low64:reg128 = ldimm
 = use newdef.lane_low64_low32

Let's look at the live interval of newdef.
Before rematerialization, we would get:
newdef [defIdx, useIdx:0) 0 at defIdx

Right after updateRegDefUses, newdef register class is widen to reg128
and the subrange definitions will be augmented to fill the subreg that
is used at the definition point, here lane_low64.
The resulting live interval would be:
newdef [newDefIdx, useIdx:0) 0 at newDefIdx
 * lane_low64_high32 EMPTY
 * lane_low64_low32 [newDefIdx, useIdx:0)

Before this patch this would be the final status of the live interval.
Therefore we miss that lane_low64_high32 is actually live on the
definition point of newdef.

With this patch, after rematerializing, we check all the added subranges
and for the ones that are defined but empty, we flag them as dead def.
Thus, in that case, newdef would look like this:
newdef [newDefIdx, useIdx:0) 0 at newDefIdx
 * lane_low64_high32 [newDefIdx, newDefIdxDead) ; <-- instead of EMPTY
 * lane_low64_low32 [newDefIdx, useIdx:0)

This fixes https://www.llvm.org/PR46154




More information about the All-commits mailing list