This is an archive of the discontinued LLVM Phabricator instance.

RegisterCoalescer: Fix verifier error when merging copy of undef
ClosedPublic

Authored by arsenm on Jun 10 2022, 11:19 AM.

Details

Summary

There's no real read of the register, so the copy introduced a new
live value. Make sure we introduce a replacement implicit_def instead
of just erasing the copy.

Found from llvm-reduce since it tries to set undef on everything.

Diff Detail

Unit TestsFailed

Event Timeline

arsenm created this revision.Jun 10 2022, 11:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 10 2022, 11:19 AM
arsenm requested review of this revision.Jun 10 2022, 11:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 10 2022, 11:19 AM
Herald added a subscriber: wdng. · View Herald Transcript
arsenm updated this revision to Diff 437253.Jun 15 2022, 10:58 AM

Fix missing test update (which I guess is a minor regression)

I am not sure I understand this change... Wasn't the intention of the existing that code that when you have something like:

%2 = COPY undef %1
  USE %2

that you merge the regs to remove the copy and add an undef to the use operands? =>

USE undef %1

Why are we starting to use IMPLICIT_DEFs here? Is this related to subregs?

I am not sure I understand this change... Wasn't the intention of the existing that code that when you have something like:

%2 = COPY undef %1
  USE %2

that you merge the regs to remove the copy and add an undef to the use operands? =>

USE undef %1

Yes, but in this situation the output register was a phi def so we need to keep a phi def in the same block in the coalesced register

Why are we starting to use IMPLICIT_DEFs here? Is this related to subregs?

Because it's a live out value, so you need a phi def in the block. It's not related to subregs. This is analagous to the case where ProcessImplicitDefs won't delete IMPLICIT_DEFs that feed phi uses.

For background: My understanding of IMPLICIT_DEF is that it was a bit of a workaround/hack necessary because for a given VReg on a control flow join you can have different "undef"/"not undef" merge. Unfortunately being out of SSA form we can't just attach an undef flag to the respective PHI operand as there is no PHI anymore. I always felt a bit uneasy with IMPLICIT_DEF getting used in other situations where they are not at the end of a block just for joining with a different definition/live value in the next block...

Though I have a feeling restricting IMPLICIT_DEFs just to this particular use case may be a loosing battle now since I think I've seen them pop-up in other situations... Also I don't remember fully, but I think we also trouble with undef flags being unable to express partially defined registers when subreg liveness is enabled.

MatzeB added inline comments.Jun 27 2022, 11:12 AM
llvm/test/CodeGen/AMDGPU/undef-subreg-use-after-coalesce.mir
35–37

This isn't a case of a live-out value though? Shouldn't it continue to use an undef flag over an IMPLICIT_DEF?

MatzeB added inline comments.Jun 27 2022, 11:31 AM
llvm/lib/CodeGen/RegisterCoalescer.cpp
1648
  • This DstLI.liveAt(Idx) can only really be true if we assign to a subregister, can't it? (Otherwise the fact that we are about to (re-)assign the register means that it wouldn't be alive immediately before the copy (except for degenerate cases where the source and destination register of the COPY is the same)...
  • Can SrcLI.liveAt(Idx) ever be true? Don't we filter for that above in lines 1624-1636?
arsenm added inline comments.Jun 28 2022, 12:17 PM
llvm/lib/CodeGen/RegisterCoalescer.cpp
1648

In this case there are subranges in the destination register, but not the source.

You're right, this works with the SrcLI.liveAt check removed

llvm/test/CodeGen/AMDGPU/undef-subreg-use-after-coalesce.mir
35–37

This is the minor regression I mentioned

arsenm updated this revision to Diff 440794.Jun 28 2022, 3:32 PM

Remove unnecessary check

arsenm added inline comments.Jun 28 2022, 3:33 PM
llvm/test/CodeGen/AMDGPU/undef-subreg-use-after-coalesce.mir
35–37

On second inspection, I think this is arguably better. %0.sub1 is dead in the original MIR. Previously, the use on the S_ENDPGM was made undead by the coalescing. The implicit_def keeps %0.sub1 dead and defs a separate register for the undef use

MatzeB accepted this revision.Sep 13 2022, 1:24 PM

I still feel like I don't fully understand why the change in undef-subreg-use-after-coalesce.mir makes things better, but either way the code changes seem reasonable and in the interest of not blocking this any further, go ahead! LGTM

This revision is now accepted and ready to land.Sep 13 2022, 1:24 PM
qcolombet accepted this revision.Sep 13 2022, 3:05 PM

I think it makes sense to insert an implicit_def here.