Skip to content
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

Merged
merged 1 commit into from
Jul 18, 2024
Merged

[SandboxIR] IR Tracker #99238

merged 1 commit into from
Jul 18, 2024

Conversation

vporpo
Copy link
Contributor

@vporpo vporpo commented Jul 16, 2024

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/include/llvm/SandboxIR/SandboxIR.h Show resolved Hide resolved
llvm/docs/SandboxIR.md Show resolved Hide resolved
llvm/include/llvm/SandboxIR/SandboxIRTracker.h Outdated Show resolved Hide resolved
llvm/include/llvm/SandboxIR/SandboxIRTracker.h Outdated Show resolved Hide resolved
llvm/include/llvm/SandboxIR/SandboxIRTracker.h Outdated Show resolved Hide resolved
llvm/include/llvm/SandboxIR/SandboxIRTracker.h Outdated Show resolved Hide resolved
llvm/include/llvm/SandboxIR/SandboxIRTracker.h Outdated Show resolved Hide resolved
llvm/include/llvm/SandboxIR/SandboxIRTracker.h Outdated Show resolved Hide resolved
llvm/lib/SandboxIR/SandboxIRTracker.cpp Outdated Show resolved Hide resolved
llvm/lib/SandboxIR/SandboxIRTracker.cpp Outdated Show resolved Hide resolved
llvm/docs/SandboxIR.md Show resolved Hide resolved
class IRChangeBase {
protected:
#ifndef NDEBUG
unsigned Idx = 0;
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

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).

Copy link
Contributor

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) {
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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), ...

Copy link
Contributor

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?

Copy link
Contributor

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?

Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that works too.

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()`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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;
Copy link
Contributor

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(); }
Copy link
Contributor

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 IRChangeBases

Copy link
Contributor Author

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.

Comment on lines 109 to 110
Revert, ///> Undoing changes
Accept, ///> Accepting changes
Copy link
Contributor

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)?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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);
Copy link
Contributor

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

Copy link
Contributor Author

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) {
Copy link
Contributor

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

Copy link
Contributor Author

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; });
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines +98 to +101
EXPECT_EQ(St0->getOperand(0), Ld1);
EXPECT_EQ(St1->getOperand(0), Ld1);
Copy link
Contributor

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

Copy link
Contributor Author

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`.
@vporpo vporpo merged commit 5338bd3 into llvm:main Jul 18, 2024
5 of 7 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 18, 2024

LLVM Buildbot has detected a new failure on builder lld-x86_64-win running on as-worker-93 while building llvm at step 7 "test-build-unified-tree-check-all".

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:

Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM-Unit :: Support/./SupportTests.exe/39/86' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe-LLVM-Unit-18504-39-86.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=86 GTEST_SHARD_INDEX=39 C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe
--

Script:
--
C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe --gtest_filter=ProgramEnvTest.CreateProcessLongPath
--
C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(160): error: Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(163): error: fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied



C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:160
Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:163
fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied




********************


Harini0924 pushed a commit to Harini0924/llvm-project that referenced this pull request Jul 22, 2024
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`.
sgundapa pushed a commit to sgundapa/upstream_effort that referenced this pull request Jul 23, 2024
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`.
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants