-
Notifications
You must be signed in to change notification settings - Fork 448
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
Support for op= assignments in the frontend/midend #5108
base: main
Are you sure you want to change the base?
Conversation
ChrisDodd
commented
Jan 22, 2025
- these are parsed as IR::OpAssignmentStatements
- they are (optionally) converted to normal assignments in the frontend
- they may be kept as special nodes by backends that desire to treat them specially (making it easier to generate 2-operands instructions)
- frontend and midend passes are all made aware of the new IR node kinds and deal with them appropriately (either disabling transforms or fixing them to be correct in the presence of OpAssignmentStatements
There was a similar PR once but it was never resolved #3669. I guess this one supersedes it. Related P4-specification issue: p4lang/p4-spec#1139 |
It seems like a good idea to have a test case that has side effects in the l-value, e.g. something like |
7346913
to
c0058f6
Compare
- these are parsed as IR::OpAssignmentStatements - they are (optionally) converted to normal assignments in the frontend - they may be kept as special nodes by backends that desire to treat them specially (making it easier to generate 2-operands instructions) - frontend and midend passes are all made aware of the new IR node kinds and deal with them appropriately (either disabling transforms or fixing them to be correct in the presence of OpAssignmentStatements Signed-off-by: Chris Dodd <[email protected]>
c0058f6
to
6f82eaf
Compare
I added this in a second testcase, as well as pulling in @rst0git's testcase |
This patch adds support for compound assignment expressions of the form `E1 op= E2`. Signed-off-by: Radostin Stoyanov <[email protected]> Signed-off-by: Chris Dodd <[email protected]>
The P4Testgen failures are because of crashes in BMv2. It is possible that the generated JSON is invalid. |
The .stf test I wrote by hand works fine, so BMv2 is at least reading the JSON and running that packet correctly. The testgen script seems to be creating tests with packets that are too short (the p4 program expects a packet with 48 bytes of headers), so it is getting PacketTooShort in the parser and then apparently crashing? |
5e82b7a
to
bbfafb0
Compare
Signed-off-by: Chris Dodd <[email protected]>
Looking more closely, the problem is due to indexing a header stack with a value from the packet that might be out of range, which causes BMv2 to crash with an exception. I fixed the P4 to mask the value so it will always be in range; that seems to have fixed the problem. |
apply { | ||
hdr.rest[postincr(hdr.data.b1) & 7].x |= hdr.data.f1; | ||
hdr.rest[postincr(hdr.data.b1) & 7].x |= hdr.data.f2; | ||
} |
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.
It seems like a good idea to surround these assignment statements with a condition like if (hdr.rest[7].isValid())
. If that one is valid, then according to the way this program is written, all of the other elements will be valid, too. Or you can go all out and check for all 8 of them being valid.
That would help in ensuring that p4testgen produces tests that match BMv2's behavior.
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 am only reviewing the contents of the test programs, and their expected output files. not the C++ implementation code. Those parts of this PR look correct to me.
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 think this should go through at least preliminary spec discussion first.
While this might seem innocent, there are corner cases involving compound operations that are weird in some languages, and we should make sure that they either don't apply to P4, or that we are OK with them.
- The LHS can contain side effects. I.e.
foo[reg.read(4) +: 8] += 5
. If side effect ordering is enabled, than this is probably OK, but if it is disabled (which is possible in frontend) then suddenly we duplicate the side effect, which is very wrong. There can be more cases probably, this is just first I can think of. - The rewrite can duplicate large expressions. Maybe this is not a problem, but still, it should be considered.
I'll take closer look at the code later, but there is an approving review and I think this is not ready to be merged.
Sorry to be stepping in with a reject, but I think we should consider how do we want to treat partial reviews. I would propose the following:
This way, an approval only appears when the PR is sufficiently reviewed. I think this makes sense in general. While I expect most P4C devs do a similar calculation in their heads before they click on merge button, I think it makes more sense to have this done on the side of reviewers :-). That is how we do it in our backend too. |
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.
Attempting to change my earlier approval to just a comment, based on vlstill's meta-suggestion of not approving until a complete review has come in.
My review was only for part of the PR's changes, not all of them.
@vlstill Thanks for the comments. It makes sense to me, and I have cancelled my Approval for this PR, and in future it makes sense for my partial reviews (which I often do) to only add a comment, not an Approval. |
@vlstill wrote in an earlier comment: "The LHS can contain side effects. I.e. foo[reg.read(4) +: 8] += 5. If side effect ordering is enabled, than this is probably OK, but if it is disabled (which is possible in frontend) then suddenly we duplicate the side effect, which is very wrong." Every pass can be disabled in the frontend or midend by consumers of this code, yes? We cannot be held responsible for someone else shooting themselves in the foot. Or is there some sense in which you believe that we recommend that people skip arbitrary passes without warning them that this is dangerous? |
Yes, every frontend pass can be skipped, but not every has easy to use hooks for that. (Also, Tofino is one of the targets that skips side effects ordering, and that is now in P4C.) Sadly, many passes require guarantees about IR that other passes establish while we have no way of checking these guarantees hold. To make matters worse, this is not just about requiring other passes to run before, but also requiring intermediate passes to not break the guarantees. That said, this goes beyond just side effect ordering (although I am not sure if there are other existing cases that do that too) as it can cause re-evaluation. Sadly the transformation needed to fix this locally (in the compound-op rewriting pass) would basically just replicate side effect ordering (I don't see a way to do it simply, as we would need to go into the LHS and replace subexpressions there). At the very least, it should be clearly documented that this pass is only correct if side effects ordering is enabled. I would probably go as far as checking that if the rewrite is enabled, then SEO must be enabled using a |
I did put comments to that effect in the FrontEndPolicy jeader file, so anyone who overrides that to disable side effect ordering should see it. Perhaps |
Thank you.
I agree, someone could be disabling SEO now and then they will not read the documentation. Still I would say |