-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SandboxIR] IR Tracker #99238
[SandboxIR] IR Tracker #99238
Conversation
a9d3476
to
5e8c1c4
Compare
class IRChangeBase { | ||
protected: | ||
#ifndef NDEBUG | ||
unsigned Idx = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment about Idx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, if it's only used for debugging, why can't we print the index when iterating over the change vector?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we could do that. In an early implementation there was no Parent pointer, so Idx had to be a member of the change class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant if we're dumping the entire vector of changes, can't we do something like
for (auto [C, Idx]: enumerate(changes)) {
errs() << Idx << ": " << C << "\n";
}
so no need for IRChangeBase
to know anything about its index
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could do that, but wouldn't it be nice to also get the index when we dump a specific change object? This could be useful for example when a revert()
crashes and we need to figure out which of the changes is this one (there may be many of them of the same class).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you've found that useful in the past, then sure
UseSet(const Use &U, SandboxIRTracker &Tracker) | ||
: IRChangeBase(TrackID::UseSet, Tracker), U(U), OrigV(U.get()) {} | ||
// For isa<> etc. | ||
static bool classof(const IRChangeBase *Other) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this used for? it doesn't really make sense to have both virtual inheritance and isa<>
on a class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I think this is dead code. I think it was meant to be used for fast upcasting, but I think it's not used anywhere. I will remove it. Thanks for noticing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm now that classof()
is not needed, the only use of the TrackID
should be for dumping the class name when debugging. This could be done by simply passing the class name to the parent constructor like:
UseSet(const Use &U, Tracker &Tracker) : IRChangeBase("UseSet", &Parent: Tracker), ...
But ideally we should only use the name in the debug build.
What is a good way of #ifdefing it? Should I use two separate constructors? or one constructor with an #ifdefed argument like:
UseSet(const Use &U, Tracker &Tracker) : IRChangeBase(
#ifndef NDEBUG
"UseSet",
#endif // NDEBUG
&Parent: Tracker), ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you expect that this is actually going to get used? can we just drop it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i.e. how often is this actually going to help with debugging an issue? and how often are issues around this going to appear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in general having too many differences between a NDEBUG and non-NDEBUG build makes it more annoying to develop and harder to catch issues that only arise in one configuration. I'd lean toward simplifying when possible and only adding debugging aids when the types of issues it helps debug come up often enough and the debugging aid actually makes it easier to debug
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When there is a bug in checkpointing it is useful to get a dump and see which changes are in the Changes vector and look if any of them looks suspicious. Without it you will just have to guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another option is to keep it in the prod build for now and remove it later once the whole infrastructure is stable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you manually print the string in the dump()
override? instead of keeping something as a member variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that works too.
llvm/docs/SandboxIR.md
Outdated
Internally this will go through the changes and run any finalization required. | ||
|
||
Please note that after a call to `revert()` or `accept()` tracking will stop. | ||
So the user would need to start it again if needed with a call to `save()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the user would need to start it again if needed with a call to `save()`. | |
To start tracking again, the user needs to call `save()`. |
class IRChangeBase { | ||
protected: | ||
#ifndef NDEBUG | ||
unsigned Idx = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, if it's only used for debugging, why can't we print the index when iterating over the change vector?
|
||
#ifndef NDEBUG | ||
/// \Returns the \p Idx'th change. This is used for testing. | ||
IRChangeBase *getChange(unsigned Idx) const { return Changes[Idx].get(); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems like testing implementation details rather than testing behavior. can we just test observable IR accept/revert behavior rather than the test verifying individual IRChangeBase
s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we can drop this.
Revert, ///> Undoing changes | ||
Accept, ///> Accepting changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these states ever used for anything? is there anything to gain from setting the state to Revert
/Accept
when reverting/accepting (like InMiddleOfCreatingChange
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are, but let's remove them for now and we can add them when they are actually needed. There may be a way to do without them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using the same IR API functions from within the body of the revert()
functions so we need a way to tell whether we are reverting or not, but perhaps the Disabled
state is good enough.
|
||
// Check RUWIf when the lambda returns true. | ||
Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return true; }); | ||
EXPECT_EQ(Tracker.size(), 2u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems like testing implementation details, I'm not sure it's necessary to test this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK we can do without this.
LLVMContext C; | ||
std::unique_ptr<Module> M; | ||
|
||
void parseIR(LLVMContext &C, const char *IR) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these helper methods are in almost every unittest, we really need these common utilities for all unittests somewhere shared (if they don't already exist), but that's a problem for another day
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah there is a lot of replication.
sandboxir::Instruction *St1 = &*It++; | ||
Ctx.save(); | ||
// Check RUWIf when the lambda returns false. | ||
Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return false; }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nothing is getting checked after this RUWI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
EXPECT_EQ(St0->getOperand(0), Ld1); | ||
EXPECT_EQ(St1->getOperand(0), Ld1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are sorta redundant with the other unittests, I'd argue we only need to check after the accept/revert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, in the other tests the tracker is not recording, so there is a chance that they are not executing the same code.
This is the first patch in a series of patches for the IR change tracking component of SandboxIR. The tracker collects changes in a vector of `IRChangeBase` objects and provides a `save()`/`accept()`/`revert()` API. Each type of IR changing event is captured by a dedicated subclass of `IRChangeBase`. This patch implements only one of them, that for updating a `sandboxir::Use` source value, named `UseSet`.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/287 Here is the relevant piece of the build log for the reference:
|
This is the first patch in a series of patches for the IR change tracking component of SandboxIR. The tracker collects changes in a vector of `IRChangeBase` objects and provides a `save()`/`accept()`/`revert()` API. Each type of IR changing event is captured by a dedicated subclass of `IRChangeBase`. This patch implements only one of them, that for updating a `sandboxir::Use` source value, named `UseSet`.
This is the first patch in a series of patches for the IR change tracking component of SandboxIR. The tracker collects changes in a vector of `IRChangeBase` objects and provides a `save()`/`accept()`/`revert()` API. Each type of IR changing event is captured by a dedicated subclass of `IRChangeBase`. This patch implements only one of them, that for updating a `sandboxir::Use` source value, named `UseSet`.
Summary: This is the first patch in a series of patches for the IR change tracking component of SandboxIR. The tracker collects changes in a vector of `IRChangeBase` objects and provides a `save()`/`accept()`/`revert()` API. Each type of IR changing event is captured by a dedicated subclass of `IRChangeBase`. This patch implements only one of them, that for updating a `sandboxir::Use` source value, named `UseSet`. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251568
This is the first patch in a series of patches for the IR change tracking component of SandboxIR.
The tracker collects changes in a vector of
IRChangeBase
objects and provides asave()
/accept()
/revert()
API.Each type of IR changing event is captured by a dedicated subclass of
IRChangeBase
. This patch implements only one of them, that for updating asandboxir::Use
source value, namedUseSet
.