This is an archive of the discontinued LLVM Phabricator instance.

[AMDGPU] Really preserve LiveVariables in SILowerControlFlow
ClosedPublic

Authored by foad on Oct 28 2021, 9:15 AM.

Diff Detail

Event Timeline

foad created this revision.Oct 28 2021, 9:15 AM
foad requested review of this revision.Oct 28 2021, 9:15 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 28 2021, 9:15 AM
foad updated this revision to Diff 383061.Oct 28 2021, 9:20 AM

Also update Kills based on existing kill flags.

ruiling added inline comments.Oct 28 2021, 9:34 AM
llvm/lib/CodeGen/LiveVariables.cpp
672

You need to re-compute Kills as well.

686

This sounds like true after Phi elimination? I did not do careful thinking. But it is not true when we have PHI, see the pattern described at line 148 in this file.

ruiling added inline comments.Oct 28 2021, 9:42 AM
llvm/lib/CodeGen/LiveVariables.cpp
691

The caller is required to correctly set the isKill flag before calling this function?

foad updated this revision to Diff 383103.Oct 28 2021, 11:34 AM

Handle phi nodes. Add new dead/kill flags.

arsenm added inline comments.Oct 28 2021, 11:49 AM
llvm/include/llvm/CodeGen/LiveVariables.h
193

Typo nocessary

llvm/lib/CodeGen/LiveVariables.cpp
731–732

Won't this do the right thing if you unconditionally call addRegisterKilled?

foad added inline comments.Oct 28 2021, 11:56 AM
llvm/lib/CodeGen/LiveVariables.cpp
722

Does this work for phi uses? I'm not sure.

731–732

It could give you duplicate entries in the Kills vector which seems undesirable.

ruiling added inline comments.Oct 28 2021, 5:44 PM
llvm/lib/CodeGen/LiveVariables.cpp
672

liveness sounds unnecessary to me. It is better to explicitly say this is for virtual register to align with other public functions of LiveVariables. Something like recomputeForSingleDefVirtReg()?

695–699

This is not quite accurate. if the user is a PHI. we need to handle differently if the user appears in the same block as the define block.

For the pattern drawn at line 148 (incoming block is the same as define block), we don't treat the Reg is alive through the incoming block, it is only alive from the definition to the end. If the incoming block is different from define block, we need to mark the Reg is alive through the incoming block.

731

I think you don't need to require that the isKill flag was correctly setup before calling this function, finding out the new kill after modification is a non-trivial work for general case. It is really handy to find the kill instructions here. Doing a reverse iteration over the instructions will just give you the kill instruction, that is the first instruction we meet.
You can just remove the killsRegister() check here and also stop pushing into Kills when iterating over the uses earlier in this function .

foad updated this revision to Diff 383251.Oct 29 2021, 1:31 AM

Rename function. Recompute dead/kill flags from scratch.

foad marked 7 inline comments as done.Oct 29 2021, 1:38 AM
foad added inline comments.
llvm/lib/CodeGen/LiveVariables.cpp
695–699

I think my code is correct. I am only saying it is live-out of the corresponding predecessor, not live-through. The "Iterate ..." loop below handles the case where Reg is live-out of DefBB.

foad updated this revision to Diff 383292.Oct 29 2021, 4:04 AM

Add dead def MI to Kills. Do not add phi nodes to Kills.

foad added inline comments.Oct 29 2021, 4:06 AM
llvm/lib/CodeGen/LiveVariables.cpp
722

As explained in the comment on struct VarInfo, phi nodes should not be included in Kills, and I think that means that LiveVariables never sets the killed flag on phi use operands.

ruiling added inline comments.Oct 29 2021, 4:28 AM
llvm/lib/CodeGen/LiveVariables.cpp
695–699

I see the problem, your interpretation of live-out does not match what it means in LLVM. You can take a look at LiveVariables::isLiveOut(). We are not saying that a register is live-out of a block if it is only used by a PHI in successor block. I would suggest renaming LiveOutBlocks to LiveToEndBlocks. So we don't have conflicting interpretations of live-out. Please also fix the use of live-out in comments.

foad updated this revision to Diff 383324.Oct 29 2021, 5:42 AM

Change terminology.

foad marked an inline comment as done.Oct 29 2021, 5:45 AM
foad added inline comments.
llvm/lib/CodeGen/LiveVariables.cpp
695–699

Thanks for explaining. I fixed it, but I still think my terminology is better :)

The way I think of it is that phi uses occur on an edge between two blocks. A phi use still means that the value is live-out of the predecessor, since it happens after the end of the predecessor (and before the start of the successor).

ruiling accepted this revision.Nov 1 2021, 12:57 AM

To the best of my knowledge, the change looks good. But wait one or two days in case others may have more comments. And one corner case which I think also needs to be updated.

llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp
719–720

Here I think the use of InputReg can be a possible kill. Actually we should inherit the possible KILL state from original pseudo instruction. and also replace the Kills of InputReg.

This revision is now accepted and ready to land.Nov 1 2021, 12:57 AM
foad marked an inline comment as done.Nov 1 2021, 3:43 AM
foad added inline comments.
llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp
719–720

The problem here is that we are inserting new instructions in a different place from the original SI_INIT_EXEC_FROM_INPUT instruction. For example, before this pass:

bb.0.main_body:
  liveins: $sgpr0, $vgpr0
  %1:vgpr_32 = COPY killed $vgpr0
  %0:sgpr_32 = COPY killed $sgpr0
  %3:vgpr_32 = V_ADD_U32_e32 %0:sgpr_32, killed %1:vgpr_32, implicit $exec
  %4:vgpr_32 = V_CVT_F32_I32_e32 killed %3:vgpr_32, implicit $mode, implicit $exec
  SI_INIT_EXEC_FROM_INPUT killed %0:sgpr_32, 19, implicit-def dead $exec
  $vgpr0 = COPY killed %4:vgpr_32
  SI_RETURN_TO_EPILOG killed $vgpr0

Note that SI_INIT_EXEC_FROM_INPUT kills %0. But if we copy the kill flag to the S_BFE_U32 instruction we get this:

bb.0.main_body:
  liveins: $sgpr0, $vgpr0
  %0:sgpr_32 = COPY killed $sgpr0
  %5:sgpr_32 = S_BFE_U32 killed %0:sgpr_32, 458771, implicit-def $scc
  $exec = S_BFM_B64 %5:sgpr_32, 0
  S_CMP_EQ_U32 killed %5:sgpr_32, 64, implicit-def $scc
  $exec = S_CMOV_B64 -1, implicit $scc
  %1:vgpr_32 = COPY killed $vgpr0
  %3:vgpr_32 = V_ADD_U32_e32 %0:sgpr_32, killed %1:vgpr_32, implicit $exec
  %4:vgpr_32 = V_CVT_F32_I32_e32 killed %3:vgpr_32, implicit $mode, implicit $exec
  $vgpr0 = COPY killed %4:vgpr_32
  SI_RETURN_TO_EPILOG killed $vgpr0

which is wrong, because %0 is used in the V_ADD_U32 instruction after the kill.

What do you think we should do here? Is it OK to drop the kill flag?

foad updated this revision to Diff 383768.Nov 1 2021, 4:16 AM

Recompute for InputReg in SILowerControlFlow::lowerInitExec.
Fix adding kills in DefBB.

ruiling added inline comments.Nov 1 2021, 5:00 AM
llvm/lib/CodeGen/LiveVariables.cpp
732

why do we need this?

llvm/lib/Target/AMDGPU/SILowerControlFlow.cpp
719–720

I did not notice that, re-computing like in this new version sounds good idea.

foad added inline comments.Nov 1 2021, 5:17 AM
llvm/lib/CodeGen/LiveVariables.cpp
732

This is the cheapest way I could think of to test whether Reg is live-to-end of DefBB. Note that DefBB never appears in AliveBlocks.

ruiling added inline comments.Nov 1 2021, 5:31 AM
llvm/lib/CodeGen/LiveVariables.cpp
729

I would suggest you check against LiveToEndBlocks instead of AliveBlocks.
Think of one possible situation:
bb0:

%1 = ...

bb1:

... = phi [%1 %bb0], [%2 %bb1]
%2 = ...
 ... = add %2, 1
 br i1 %x, bb1, bb2

The add instruction at bb1 that reads %2 should not be marked as KILL. Sounds like we are not doing it right currently.

732

Does my comment above sound good to you? UseBlocks.count() == 1 does not mean whether the Reg is live-to-end of DefBB.

foad updated this revision to Diff 383788.Nov 1 2021, 6:11 AM

Fix check for live-to-end of DefBB.

foad added inline comments.Nov 1 2021, 6:12 AM
llvm/lib/CodeGen/LiveVariables.cpp
732

You are right of course. I can't use LiveToEndBlocks directly because it is a worklist, and it is empty here, so I introduced a new boolean flag for this.

sounds good to me.

This revision was landed with ongoing or failed builds.Nov 2 2021, 8:03 AM
This revision was automatically updated to reflect the committed changes.
foad added a comment.Nov 2 2021, 8:06 AM

@ruiling thanks for the careful review!