This is an archive of the discontinued LLVM Phabricator instance.

[NFC][regalloc] Move ExtraRegInfo and related to LiveRangeStageManager
ClosedPublic

Authored by mtrofin on Nov 30 2021, 4:46 PM.

Details

Summary

This would allow sharing the LiveRangeStageManager between different
RegAllocEvictionAdvisors. One scenario is for ML training, where we want
to capture what the default advisor would do, for bootstrapping (speeds
up training).

RFC: https://lists.llvm.org/pipermail/llvm-dev/2021-November/153639.html

Diff Detail

Event Timeline

mtrofin created this revision.Nov 30 2021, 4:46 PM
mtrofin requested review of this revision.Nov 30 2021, 4:46 PM
Herald added a project: Restricted Project. · View Herald TranscriptNov 30 2021, 4:46 PM

Gentle reminder - thanks!

Is there any way to see a complete stack to make it easier to comment on the approach as a whole?

mtrofin added a comment.EditedDec 2 2021, 11:38 AM

Is there any way to see a complete stack to make it easier to comment on the approach as a whole?

I sent a while back D113525 as an overview for the effort of factoring eviction as an analysis. This particular patch slightly deviates from that patch: rather than mashing the live range state tracking in the analysis, for the reason outlined in the review message, we factor it as its own class.

mtrofin edited the summary of this revision. (Show Details)Dec 2 2021, 11:41 AM

I cannot shake the feeling that we should put the interfaces into a RegAllocGreedy.h, the interface doesn't feel generic enough for anything else (and FWIW I am not advocating to make it more generic, just set the right expectations that this is meant to be used in combination with RegAllocGreedy). And with expectations managed maybe it's good enough to just hand out a reference to ExtraRegInfo to some friend implementations of the eviction interface instead of introducing more abstractions and "Manager" classes. How do others working on the regallocs feel?

llvm/lib/CodeGen/RegAllocEvictionAdvisor.h
89

Add a comment to document the role of this class and try to find a better name (ExtraRegInfos to match the ExtraRegInfo map this is appears to be wrapping?)

102–107

Can we keep the MRI reference out of the interface?

119–137

Wondering if we can go without an MRI reference

llvm/lib/CodeGen/RegAllocGreedy.cpp
176

Is it possible to embed this by value to avoid the extra indirections?

I cannot shake the feeling that we should put the interfaces into a RegAllocGreedy.h, the interface doesn't feel generic enough for anything else (and FWIW I am not advocating to make it more generic, just set the right expectations that this is meant to be used in combination with RegAllocGreedy). And with expectations managed maybe it's good enough to just hand out a reference to ExtraRegInfo to some friend implementations of the eviction interface instead of introducing more abstractions and "Manager" classes. How do others working on the regallocs feel?

We'll want to use ExtraRegInfo & associated APIs in the ML-based implementation, hence the factoring.

mtrofin marked an inline comment as done.Dec 2 2021, 12:36 PM
mtrofin added inline comments.
llvm/lib/CodeGen/RegAllocEvictionAdvisor.h
89

Hmm, I thought both the Stage and the Cascade relate to tracking the transitions of the virtual register through the allocation; but I can see how, if we move this to a RegAllocGreedy.h, and we want to track more state later, ExtraRegInfo may work better. How about we use that and rename the vector to just Info (it's private anyway)?

102–107

The goal was to avoid needing to pass the exact same thing (the MRI->getNumVirtRegs()) at the points where we need to resize.

So I learn: what's the downside of MRI here?

Would passing the VirtRegMap be a reasonable alternative?

119–137

ack (consolidating this in the comment above)

llvm/lib/CodeGen/RegAllocGreedy.cpp
176

Oh, is this the reason for avoiding nondefault ctor? Let me fire up a https://llvm-compile-time-tracker.com/ experiment, if overhead is a concern.

mtrofin marked an inline comment as done.Dec 2 2021, 1:06 PM
mtrofin added inline comments.
llvm/lib/CodeGen/RegAllocGreedy.cpp
176

Here it is - arguably, the indirection has no impact.

mtrofin added inline comments.Dec 2 2021, 1:56 PM
llvm/lib/CodeGen/RegAllocGreedy.cpp
176

Actually - I think we can avoid the heap allocation, and not require default ctor, too, if we used Optional. I'll try that.

mtrofin updated this revision to Diff 391469.Dec 2 2021, 2:44 PM

incorporated feedback:

  • using ExtraRegInfo for type name
  • dropped heap allocation in favor of Optional
MatzeB added a comment.Dec 2 2021, 3:09 PM

We'll want to use ExtraRegInfo & associated APIs in the ML-based implementation, hence the factoring.

I understand that. I am hinting at possible designs on how much or how little we abstract:

  1. Treat "eviction" as a strategy that is part of RegAllocGreedy and specifically embrace the fact that things only work in combination with RegAllocGreedy:
// RegAllocGreedy.h
class RegAllocGreedy;

// This is interface only works for RAGreedy, hence it is in RegAllocGreedy.h. Benefit: we can directly
// re-use datastructures and call methods on RAGreedy.
class EvictionStrategy {
  RegAllocGreedy *RAGreedy;
  EvictionStrategy(RegAllocGreedy* RAGreedy) : RAGreedy(RAGreedy) {}

  void doStuff() {
    // ...
    RAGreedy->setStage(...);
    // ...
  }
};

class RegAllocGreedy {

  void setStage(...);
  friend class EvictionStrategy;
  // ...
  EvictionStrategy *Eviction;
};

This will require fewer abstraction to be built up, with the downside of having a higher entanglement between the two.

  1. The other end of the spectrum is pushing for more abstraction modeling eviction independently of the rest of the register allocator. This usually comes with the goal of having a cleaner separation of concerns and better re-usability of the algorithm (for other regallocs or compilers?).

Now my point is that the current patches appear to aiming more at option 2) while at the same time the interfaces are clearly heavily inspired/only usable for RegAllocGreedy. So I was posing the question if we should rather acknowledge that reality and aim more for a 1) design instead...

While I personally think 1) is the better choice in this context, I wouldn't be surprised if different people have different opinions here, so I was fishing for opinions...

MatzeB added inline comments.Dec 2 2021, 3:10 PM
llvm/lib/CodeGen/RegAllocGreedy.cpp
176

Yes I highly doubt you can actually measure any difference in this particular case... This was more a matter of principle and setting examples for other passes ;-)

MatzeB added inline comments.Dec 2 2021, 3:19 PM
llvm/lib/CodeGen/RegAllocEvictionAdvisor.h
102–107

So I learn: what's the downside of MRI here?

No real downside.

I would just say that reducing dependencies/entanglement with other classes (switching to VirtRegMap is as bad in my view). I just think it's a worthwhile general goal when creating new abstractions. And this seemed to be fixable without any real efforts/or lost convenience.

The goal was to avoid needing to pass the exact same thing (the MRI->getNumVirtRegs()) at the points where we need to resize.

It just seemed to me like we can simply get rid of the need for getNumVirtRegs() in the setStage/setCascade functions by switching to the grow() interface. I hope you can see the code suggestions I made in phabricator that show that (I think phab sometimes does not reproduce them properly in the E-Mails, so just making sure we're not talking past each other because you don't see the suggestions)

Anyway these here are nitpicks/suggestions, no harm done if we cannot implement them after all.

We'll want to use ExtraRegInfo & associated APIs in the ML-based implementation, hence the factoring.

I understand that. I am hinting at possible designs on how much or how little we abstract:

  1. Treat "eviction" as a strategy that is part of RegAllocGreedy and specifically embrace the fact that things only work in combination with RegAllocGreedy:
// RegAllocGreedy.h
class RegAllocGreedy;

// This is interface only works for RAGreedy, hence it is in RegAllocGreedy.h. Benefit: we can directly
// re-use datastructures and call methods on RAGreedy.
class EvictionStrategy {
  RegAllocGreedy *RAGreedy;
  EvictionStrategy(RegAllocGreedy* RAGreedy) : RAGreedy(RAGreedy) {}

  void doStuff() {
    // ...
    RAGreedy->setStage(...);
    // ...
  }
};

class RegAllocGreedy {

  void setStage(...);
  friend class EvictionStrategy;
  // ...
  EvictionStrategy *Eviction;
};

This will require fewer abstraction to be built up, with the downside of having a higher entanglement between the two.

  1. The other end of the spectrum is pushing for more abstraction modeling eviction independently of the rest of the register allocator. This usually comes with the goal of having a cleaner separation of concerns and better re-usability of the algorithm (for other regallocs or compilers?).

Now my point is that the current patches appear to aiming more at option 2) while at the same time the interfaces are clearly heavily inspired/only usable for RegAllocGreedy. So I was posing the question if we should rather acknowledge that reality and aim more for a 1) design instead...

While I personally think 1) is the better choice in this context, I wouldn't be surprised if different people have different opinions here, so I was fishing for opinions...

Option 1 would mean extracting RAGreedy in that header, and that looks like a larger factoring in a .h, in comparison to the ExtraRegInfo stuff.

mtrofin marked an inline comment as done.Dec 2 2021, 3:30 PM
mtrofin added inline comments.
llvm/lib/CodeGen/RegAllocEvictionAdvisor.h
102–107

I like the .grow() idea, my concern was wether we'd see any compile time impact. Let me try it and see.

MatzeB added a comment.Dec 2 2021, 3:39 PM

Option 1 would mean extracting RAGreedy in that header, and that looks like a larger factoring in a .h, in comparison to the ExtraRegInfo stuff.

Yes, but it's just moving the declaration around without changing things otherwise. Which seems like the "smaller" factoring to me. (at the price of higher entanglement as I stated)

Option 1 would mean extracting RAGreedy in that header, and that looks like a larger factoring in a .h, in comparison to the ExtraRegInfo stuff.

Yes, but it's just moving the declaration around without changing things otherwise. Which seems like the "smaller" factoring to me. (at the price of higher entanglement as I stated)

Ack.

I wonder if we can decouple this design problem from this patch. Should there end up being a strong preference for going to a RegAllocGreedy.h, that should be easy to do at any later point, wdyt?

mtrofin added inline comments.Dec 2 2021, 9:36 PM
llvm/lib/CodeGen/RegAllocEvictionAdvisor.h
102–107

Yup, no measurable effect when removing resize and just grow-ing.

mtrofin updated this revision to Diff 392073.Dec 6 2021, 8:12 AM

missed feedback about adding a comment

mtrofin marked an inline comment as done.Dec 6 2021, 8:14 AM

Gentle reminder - could we defer deciding on a RegAllocGreedy.h?

Thanks!

Gentle reminder - @MatzeB, @qcolombet, please let me know how to move this forward - thanks!

wenlei added a subscriber: wenlei.Dec 8 2021, 11:53 PM

Option 1 would mean extracting RAGreedy in that header, and that looks like a larger factoring in a .h, in comparison to the ExtraRegInfo stuff.

Yes, but it's just moving the declaration around without changing things otherwise. Which seems like the "smaller" factoring to me. (at the price of higher entanglement as I stated)

Ack.

I wonder if we can decouple this design problem from this patch. Should there end up being a strong preference for going to a RegAllocGreedy.h, that should be easy to do at any later point, wdyt?

I agree with Matthias that the advisor now is really tied to Greedy and #1 makes sense. Handle this in a later patch is also reasonable, but leaving it in current state for too long probably isn't ideal. If you plan to handle it later, perhaps stick in a TODO comment?

Other than that, the refactoring seems straightforward.

mtrofin updated this revision to Diff 393913.Dec 13 2021, 8:54 AM

added todo to expose RAGreedy in a header instead

Option 1 would mean extracting RAGreedy in that header, and that looks like a larger factoring in a .h, in comparison to the ExtraRegInfo stuff.

Yes, but it's just moving the declaration around without changing things otherwise. Which seems like the "smaller" factoring to me. (at the price of higher entanglement as I stated)

Ack.

I wonder if we can decouple this design problem from this patch. Should there end up being a strong preference for going to a RegAllocGreedy.h, that should be easy to do at any later point, wdyt?

I agree with Matthias that the advisor now is really tied to Greedy and #1 makes sense. Handle this in a later patch is also reasonable, but leaving it in current state for too long probably isn't ideal. If you plan to handle it later, perhaps stick in a TODO comment?

Other than that, the refactoring seems straightforward.

Done - I'll address it once everything is settled (i.e. all the components landed, incl. the ML advisor) - it will probably help with any nuances of the refactoring, too.

wenlei accepted this revision.Dec 13 2021, 9:06 AM

lgtm, thanks. (btw Matthias is on PTO for the holidays and won't be back until Jan)

This revision is now accepted and ready to land.Dec 13 2021, 9:06 AM
This revision was landed with ongoing or failed builds.Dec 13 2021, 10:31 AM
This revision was automatically updated to reflect the committed changes.