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

Fix how an instruction's used/blocked frames are calculated #73

Merged
merged 21 commits into from
Jun 1, 2022

Conversation

kalzoo
Copy link
Contributor

@kalzoo kalzoo commented Jun 1, 2022

Closes #72

See issue for context.

Reworks the way that frame-blocking is computed for an instruction within the scope of a program. The previous way was to perform that work directly in Program::get_used_frames and then just pull those frames out of the program's FrameSet. This was brittle and harder to understand in the light of the Quil spec.

This new approach is simpler in that it takes place in two steps:

  • First, a FrameMatchCondition is computed for an instruction, which is independent of the program in which that instruction lives.
  • Then, that condition is evaluated against the program's FrameSet, which converts the "abstract" frame requirements of the instruction to the concrete frames available in the program.

It also adds a new private method, Instruction::parse, for the convenience of the tests, so that single instructions can easily be used as fixtures.

I considered using rstest for the table-driven test, but I'm not sure if we need that yet, and it will be easy to change over if we do.

Notes for reviewers:

  • Please carefully compare the tests added in this MR to the quil spec and note/question where they disagree. Note that DELAY's behavior is not fully specified in the spec, and so I kept its behavior consistent with how it was already enforced here. Thoughts welcome on that.
  • Please consider if there is a reason that include_blocking is not enough information to distinguish all use cases to know the frames for an instruction. Currently, this allows for returning either used frames (those which the instruction will actively use, and for which it will take a dependency on instructions which earlier block it) or blocked frames (instruction may or may not use it, but it prevents other instructions from using it until it's done). Is there any other category of frames that we'd want to query for, or is this boolean argument enough?
  • There are some inelegant fixes here (such as querying the used frames and then the blocking frames separately). I don't want inelegance to block this PR (which itself is blocking other work), but if you see a quick, neat fix - please suggest it.

@kalzoo kalzoo changed the base branch from main to feat/improve-dot-graphs June 1, 2022 01:57
Copy link
Contributor

@notmgsk notmgsk left a comment

Choose a reason for hiding this comment

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

Reasoning is sound, and the solution is clear. Small nitpicks and maybe some additional tests, but not blocking (heh).

src/program/mod.rs Show resolved Hide resolved
src/program/graph.rs Outdated Show resolved Hide resolved
src/program/graph.rs Outdated Show resolved Hide resolved
src/program/mod.rs Outdated Show resolved Hide resolved
src/program/mod.rs Outdated Show resolved Hide resolved
src/program/mod.rs Outdated Show resolved Hide resolved
src/program/frame.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@genos genos left a comment

Choose a reason for hiding this comment

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

Nicely done! A few questions, but barring the failing tests, LGTM

All,

/// Match all frames which shares any one of these names
AnyOfNames(&'a [String]),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why slices here? You're using vectors below (because of needing to put recursive ones on the heap), and if these get large enough, I imagine a set-based solution would be faster.

Copy link
Contributor

Choose a reason for hiding this comment

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

Removing the lifetime stuff would probably simplify downstream code as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes it a little simpler/cheaper to build the filter in the first place, without cloning. I originally had vecs everywhere, then slices, and then came to this and it came out cleanest. It is inconsistent though

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose it makes sense if you see them all as slices but the Vec as just a Box<&[_]> due to the type recursion

src/program/frame.rs Outdated Show resolved Hide resolved
src/program/frame.rs Show resolved Hide resolved
src/program/graph.rs Outdated Show resolved Hide resolved
@kalzoo
Copy link
Contributor Author

kalzoo commented Jun 1, 2022

Thanks @notmgsk and @genos for the review - fixed the things that were sure to fix - let me know what you think.

@genos
Copy link
Contributor

genos commented Jun 1, 2022

LGTM 🎉

@kalzoo
Copy link
Contributor Author

kalzoo commented Jun 2, 2022

Note: this fails the example cited in this issue; if the spec remains unchanged, the approach here will need to be modified.

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.

Bug in FENCE / NONBLOCKING behavior
3 participants