This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Fixing undefined physical register issue when subreg liveness tracking enabled.
ClosedPublic

Authored by kito-cheng on Jun 13 2022, 7:45 AM.

Details

Summary

RISC-V expand register tuple spilling into series of register spilling after
register allocation phase by the pseudo instruction expansion, however part of
register tuple might be still undefined during spilling, machine verifier will
complain the spill instruction is using an undefined physical register.

Optimal solution should be doing liveness analysis and do not emit spill
and reload for those undefined parts, but accurate liveness info at that point
is not so easy to get.

So the suboptimal solution is still spill and reload those undefined parts, but
adding implicit-use of super register to spill function, then machine
verifier will only report report using undefined physical register if
the when whole super register is undefined, and this behavior are also
documented in MachineVerifier::checkLiveness[1].

Example for demo what happend:

v10m2 = xxx
# v12m2 not define yet
PseudoVSPILL2_M2 v10m2_v12m2
...

After expansion:

v10m2 = xxx
# v12m2 not define yet
# Expand PseudoVSPILL2_M2 v10m2_v12m2 to 2 vs2r
VS2R_V v10m2
VS2R_V v12m2 # Use undef reg!

What this patch did:

v10m2 = xxx
# v12m2 not define yet
# Expand PseudoVSPILL2_M2 v10m2_v12m2 to 2 vs2r
VS2R_V v10m2 implicit v10m2_v12m2
# Use undef reg (v12m2), but v10m2_v12m2 ins't totally undef, so
# that's OK.
VS2R_V v12m2 implicit v10m2_v12m2

[1] https://github.com/llvm-mirror/llvm/blob/master/lib/CodeGen/MachineVerifier.cpp#L2016-L2019

Diff Detail

Event Timeline

kito-cheng created this revision.Jun 13 2022, 7:45 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 13 2022, 7:45 AM
kito-cheng requested review of this revision.Jun 13 2022, 7:45 AM
craig.topper added inline comments.Jun 13 2022, 9:01 AM
llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
318

prevent -> prevents
complain -> complaining

325

can this be .addReg(SrcReg, RegState::Implicit)

llvm/test/CodeGen/RISCV/undef-subreg-range.mir
1

Move to rvv directory since it uses RVV instructions?

Changes:

  • Address @craig.topper's commet:
    • Use addReg rather than add(MachineOperand::CreateReg(...)).
    • Tweak comment in the code.
    • Move test case to rvv directory.
kito-cheng marked 3 inline comments as done.Jun 13 2022, 11:59 PM

The fix LGTM.

As for the test, I'm wondering: maybe it's good to have a "real-world" test case for this, but couldn't we test it far more simply? As it stands I'm finding it hard to find the actual bug in the test case.

Just to see how small the test case could be, I tried and was able to reproduce the issue with this test:

---
name:            foo
tracksRegLiveness: true
stack:
  - { id: 0, name: '', type: spill-slot, offset: 0, size: 32, alignment: 8,
      stack-id: scalable-vector, callee-saved-register: '', callee-saved-restored: true }
body:   |
  bb.0:
    liveins: $v8m2, $x10, $x11
    PseudoVSPILL2_M2 killed $v8m2_v10m2, killed $x10, killed $x11 :: (store unknown-size into %stack.0, align 8)
    PseudoRET
...

Perhaps that's a little too simplistic, but it does show off the issue rather cleanly.

llvm/test/CodeGen/RISCV/rvv/undef-subreg-range.mir
6 ↗(On Diff #436674)

Regardless of my comment below, we probably don't need these ModuleIDs or source_filenames?

Chagnes:

  • Refine testcase.
kito-cheng marked an inline comment as done.Jun 14 2022, 8:24 AM

@frasercrmck thanks your suggestion! that made testcase easier to understand what happened, my habit is generating a reduced C testcase and then use that to generating ll or mir test, I guess that habit is come from my GCC development experiences, I guess I should having some new habit about that for LLVM development :P

craig.topper added inline comments.Jun 14 2022, 9:49 AM
llvm/test/CodeGen/RISCV/rvv/undef-subreg-range.mir
13 ↗(On Diff #436796)

Are all these flags needed? Does generating the test with -simplify-mir remove them?

Changes:

  • Remove unnecessary flags in the testcase.
kito-cheng marked an inline comment as done.Jun 14 2022, 10:08 AM
kito-cheng added inline comments.
llvm/test/CodeGen/RISCV/rvv/undef-subreg-range.mir
13 ↗(On Diff #436796)

I don't use -simplify-mir to generate the testcase, but most flags are unnecessary, I just remove those manually this time, and that's new flag to me, I'll use that next time, thanks!

This revision is now accepted and ready to land.Jun 14 2022, 10:34 AM
This revision was landed with ongoing or failed builds.Jun 15 2022, 1:23 AM
This revision was automatically updated to reflect the committed changes.
kito-cheng marked an inline comment as done.
foad added a subscriber: foad.Jun 28 2022, 2:43 AM

We do this (adding implicit super register operands) in AMDGPU too, but eventually they start getting in the way of other optimizations. I'd really like it if we could agree on another way to fix the physical subreg liveness problem. See: https://discourse.llvm.org/t/physical-subregister-liveness/5994