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

Disable the expansion of header unions in the copy structures pass. #5093

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

fruffy
Copy link
Collaborator

@fruffy fruffy commented Jan 7, 2025

This expansion currently seems broken:
The pass expands something like

hdr.addr_dst = addr_0;

to

hdr.addr_dst.ipv4.setValid();
hdr.addr_dst.ipv4.addr = addr_0.ipv4.addr;
hdr.addr_dst.ipv6.setValid();
hdr.addr_dst.ipv6.addr = addr_0.ipv6.addr;

This assignment always invalidates ipv4, even though it may be valid. Some context: #4853 (comment)

@fruffy fruffy added run-validation Use this tag to trigger a Validation CI run. breaking-change This change may break assumptions of compiler back ends. core Topics concerning the core segments of the compiler (frontend, midend, parser) labels Jan 7, 2025
@fruffy fruffy force-pushed the fruffy/copystructures_fix branch 2 times, most recently from 056d312 to 9a164e9 Compare January 7, 2025 15:48
@@ -73,13 +73,14 @@ const IR::Node *DoCopyStructures::postorder(IR::AssignmentStatement *statement)
FIXME: this is not correct for header unions and should be fixed.
The fix bellow, commented-out, causes problems elsewhere.
https://github.com/p4lang/p4c/issues/3842
if (ltype->is<IR::Type_HeaderUnion>())
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure, but it appears that these changes are attempting to fix the issue #3842 mentioned in comments just before this line, and thus those comments can be removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well, the current fix just disables union expansion by default to avoid running into #3842. Ideally, we fix the problem in the copyStructures pass somehow by tracking validity.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, this PR is not fixing that issue, if I understand the changes correctly. You are just disabling incorrect transformations.

fruffy added 2 commits January 7, 2025 17:44
Signed-off-by: fruffy <[email protected]>
Signed-off-by: fruffy <[email protected]>
@fruffy fruffy force-pushed the fruffy/copystructures_fix branch from 9a164e9 to 1a3989f Compare January 7, 2025 16:44
Copy link
Contributor

@vlstill vlstill left a comment

Choose a reason for hiding this comment

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

This seems to me like a reasonable interim solution. But the fix for the header union assignments should not be that hard (and it would not be less efficient than the current incorrect code).

builder.append("error");
builder.append("error ");
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems unrelated. Also, it would be better to print the space only after the if (!isDeclaration).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is intentional. Fixes a bug introduced by #5036. If you do not change this line you will produce incorrect reference files. I am actually a little concerned why this is not picked up in checks.

if (u_1[1w0].h1.isValid()) {
u_1[1].h1.setValid();
u_1[1].h1 = u_1[1w0].h1;
u_1[1].h2.setInvalid();
u_1[1].h3.setInvalid();
} else {
u_1[1].h1.setInvalid();
}
if (u_1[1w0].h2.isValid()) {
u_1[1].h2.setValid();
u_1[1].h2 = u_1[1w0].h2;
u_1[1].h1.setInvalid();
u_1[1].h3.setInvalid();
} else {
u_1[1].h2.setInvalid();
}
if (u_1[1w0].h3.isValid()) {
u_1[1].h3.setValid();
u_1[1].h3 = u_1[1w0].h3;
u_1[1].h1.setInvalid();
u_1[1].h2.setInvalid();
} else {
u_1[1].h3.setInvalid();
}
u_1[1] = u_1[1w0];
Copy link
Contributor

Choose a reason for hiding this comment

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

@fruffy, the old code is quite different from what you have written in the PR topic, do you have an example which produces such a code?

Also, this code is surprisingly close to what I would say is the correct (but inefficient on many targets) code.

        // or invalidate them one-by-one here to avoid need for target to be able to invalidate whole HU
        u_1[1].setInvalid();
        if (u_1[1w0].h1.isValid()) {
            u_1[1].h1.setValid();
            u_1[1].h1 = u_1[1w0].h1;
        }
        if (u_1[1w0].h2.isValid()) {
            u_1[1].h2.setValid();
            u_1[1].h2 = u_1[1w0].h2;
        }
        if (u_1[1w0].h3.isValid()) {
            u_1[1].h3.setValid();
            u_1[1].h3 = u_1[1w0].h3;
        }

The ifs can be else-if too, which would make it more explicit these are truly alternatives (in which case the setInvalid might be in a final else branch). The way I wrote it here it might be easier for some targets that for some reason don't invalidate other alternatives, but that is really a bug in the target as the u.hi.setValid() could be also written explicitly by the user.

The biggest problem in the original rewriting is the else branch which invalidates the HU if u_1[0].h3 is not valid. Given how close it is, it is probably worth it just fixing it.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, based on a quick look in the code it might not be that simple, because we would need to change this if generation based on whether or not we are inside union as the current rewriting is the same for all headers, whether in structs or in unions -- which is why it is wrong. That said, it seems to me like CopyStructures in this case just expands the union (through it being StructLike) and then something else inserts the headers' if. If this was expanded by CopyStructures, it would be expanded to the level of fields of the header.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change This change may break assumptions of compiler back ends. core Topics concerning the core segments of the compiler (frontend, midend, parser) run-validation Use this tag to trigger a Validation CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants