This is an archive of the discontinued LLVM Phabricator instance.

[ModuloSchedule] Make PeelingModuloScheduleExpander inheritable.
ClosedPublic

Authored by hgreving on Jun 26 2020, 11:52 AM.

Details

Summary

Basically a NFC, but allows subclasses access to the entire PeelingModuloScheduleExpander
class. We are doing this to allow backends, particularly ones that are not necessarily
upstreamed, to inherit from PeelingModuloScheduleExpander and access its basic structures.

Renames Info into LoopInfo for consistency in PeelingModuloScheduleExpander.

Diff Detail

Event Timeline

hgreving created this revision.Jun 26 2020, 11:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 26 2020, 11:52 AM
hgreving edited the summary of this revision. (Show Details)Jun 26 2020, 12:03 PM
jmolloy accepted this revision.Jun 29 2020, 12:05 AM

LGTM!

This revision is now accepted and ready to land.Jun 29 2020, 12:05 AM

(assuming the LIT failures are fixed of course!)

ThomasRaoux accepted this revision.Jun 30 2020, 3:53 PM
This revision was automatically updated to reflect the committed changes.
jfb added a subscriber: jfb.Jun 30 2020, 9:32 PM
jfb added inline comments.
llvm/include/llvm/CodeGen/ModuloSchedule.h
286

This generates the following diagnostic when building:

llvm/include/llvm/CodeGen/ModuloSchedule.h:279:7: warning: 'llvm::PeelingModuloScheduleExpander' has virtual functions but non-virtual destructor [-Wnon-virtual-dtor]
class PeelingModuloScheduleExpander {
      ^

If you ever destroy a derived class while holding a PeelingModuloScheduleExpander* you'll have a bad time.

Fixed here:
https://github.com/llvm/llvm-project/commit/c7586444ca787c3845ac4ad0bd603709f2abbb0f

Adding an extension point with no testing inside LLVM seems a bit problematic - is there no existing target that could use this? Or a reasonable scale of unit test that could exercise this extension point without a full-blown target?

(also this produced a warning about the fact that this type doesn't have a virtual dtor - was fixed by @jfb in c7586444ca787c3845ac4ad0bd603709f2abbb0f )

Adding an extension point with no testing inside LLVM seems a bit problematic - is there no existing target that could use this? Or a reasonable scale of unit test that could exercise this extension point without a full-blown target?

(also this produced a warning about the fact that this type doesn't have a virtual dtor - was fixed by @jfb in c7586444ca787c3845ac4ad0bd603709f2abbb0f )

The change is basically NFC. It was made in order to allow us using the upstream pass by inheriting from it. I'm not sure what test you would write, are you thinking about a test that tests protected vs. private? Heaxgon is the only upstream target upstream using the modulo scheduler. Full disclosure, we're a bit short staffed and are not in a position writing Hexagon tests. We _would_ like to use the upstream pass and when the time comes, add our improvements to LLVM upstream. Making the peeling modulo scheduler inheritable is a reasonable interface change, because different subtargets have different peeling requirements while sharing common semantics. The change simply allowed for the entire interface to be inheritable. Reality is, if the change is unwanted, we would end up downstreaming the pass entirely and developement on the upstream pass would stop - for now. If you're ok with the change, I think it's beneficial to everybody at this point. LMK, thanks for considering

Adding an extension point with no testing inside LLVM seems a bit problematic - is there no existing target that could use this? Or a reasonable scale of unit test that could exercise this extension point without a full-blown target?

(also this produced a warning about the fact that this type doesn't have a virtual dtor - was fixed by @jfb in c7586444ca787c3845ac4ad0bd603709f2abbb0f )

The change is basically NFC. It was made in order to allow us using the upstream pass by inheriting from it.

Why does "expand" need to be virtual to inherit from it? The current caller in-tree doesn't call this function in a setting that would be applicable to polymorphism, for instance - it creates a concrete PeelingModuloScheduleExpander instance and calls "expand" directly on that.

I'm not sure what test you would write, are you thinking about a test that tests protected vs. private?

Nah - I was assuming the in-tree use was structured in a way that, while there might be only one implementation now, there might be some separation between construction and usage - such that maybe that code (that had usage separate from construction) could be unit tested with, say, a stub derived class to show the overriding behavior being exercised. But since usage is not separate from construction that doesn't seem to be possible/reasonable.

If out-of-tree uses would look much like the in-tree use, it doesn't seem to me like virtuality is required - the derived class would define its own expand function (& it could derive privately from the base class to hide the original implementation) and users would call that one.
If out-of-tree code wants to use dynamic polymorphism here, it seems like it could do so by introducing a small class deriving privately and exposing a virtual function.

But without any use in-tree that looks at least /roughly/ like the sort of thing that would benefit from dynamic polymorphism - I think that's best left out of tree.

Hexagon is the only upstream target upstream using the modulo scheduler. Full disclosure, we're a bit short staffed and are not in a position writing Hexagon tests. We _would_ like to use the upstream pass and when the time comes, add our improvements to LLVM upstream. Making the peeling modulo scheduler inheritable is a reasonable interface change, because different subtargets have different peeling requirements while sharing common semantics.

The change simply allowed for the entire interface to be inheritable. Reality is, if the change is unwanted, we would end up downstreaming the pass entirely and developement on the upstream pass would stop - for now. If you're ok with the change, I think it's beneficial to everybody at this point. LMK, thanks for considering

Who else has a vested interest in having this in-tree? Perhaps they could be CC'd in this review to discuss this.

& would a small virtual shim out-of-tree allow you to work downstream while still having this pass in-use upstream?

In short - the virtuality is not the issue, the inheritability is. The class can be non-virtual, no problem for us. I would like to reuse existing code in the upstream pass that is currently "private". Hence, the "protected" part is important. It also makes sense generally, because a software pipeliner on a specific subtarget may follow different expansion strategies. If you would like to revert the virtuality, no problem at all, if you keep the protected inheritance. I think we should design a better defined interface for this class in the long run. Only one target upstream and us downstream are using it AFAIK, but as we are supporting more targets, we may come up with something better. SG? Can pull in Hexagon people, yes

In short - the virtuality is not the issue, the inheritability is. The class can be non-virtual, no problem for us. I would like to reuse existing code in the upstream pass that is currently "private". Hence, the "protected" part is important. It also makes sense generally, because a software pipeliner on a specific subtarget may follow different expansion strategies. If you would like to revert the virtuality, no problem at all, if you keep the protected inheritance. I think we should design a better defined interface for this class in the long run. Only one target upstream and us downstream are using it AFAIK, but as we are supporting more targets, we may come up with something better. SG? Can pull in Hexagon people, yes

Ah, fair enough. Thanks for explaining!

I've removed the virtual dtor and virtuality from expand in 7a99aab8692c58558b62e9a66120886b8a70fab8

In short - the virtuality is not the issue, the inheritability is. The class can be non-virtual, no problem for us. I would like to reuse existing code in the upstream pass that is currently "private". Hence, the "protected" part is important. It also makes sense generally, because a software pipeliner on a specific subtarget may follow different expansion strategies. If you would like to revert the virtuality, no problem at all, if you keep the protected inheritance. I think we should design a better defined interface for this class in the long run. Only one target upstream and us downstream are using it AFAIK, but as we are supporting more targets, we may come up with something better. SG? Can pull in Hexagon people, yes

Ah, fair enough. Thanks for explaining!

I've removed the virtual dtor and virtuality from expand in 7a99aab8692c58558b62e9a66120886b8a70fab8

Ok. Thanks