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

Defuse analysis fails with "Overwriting definitions" #3650

Closed
vhavel opened this issue Nov 1, 2022 · 4 comments · Fixed by #3653
Closed

Defuse analysis fails with "Overwriting definitions" #3650

vhavel opened this issue Nov 1, 2022 · 4 comments · Fixed by #3653
Assignees
Labels
bug This behavior is unintended and should be fixed. fixed This topic is considered to be fixed.

Comments

@vhavel
Copy link

vhavel commented Nov 1, 2022

The attached file: defuse_fail.p4.txt triggers a failed BUG_CHECK during def-use analysis:

Compiler Bug: Overwriting definitions at <BlockStatement>(1396)

I checked the IR before def-use is invoked - the problematic BlockStatement is reachable on two control-flow program paths, but def-use seems to assume the IR doesn't share nodes. The node sharing is created by the inlining pass (running before defuse since #3591). Inlining substitutes both C1.apply method calls with C1 body, but the body isn't deep-copied, hence the two places where C1 is inlined share part of the IR subtree.

@mihaibudiu
Copy link
Contributor

Indeed, def-use cannot work when IR DAGs are shared, because it keeps a map from statement to definitions, so statements cannot be reused. It was supposed to clone everything needed before running, though. Will have to figure out why.

@mihaibudiu mihaibudiu added the bug This behavior is unintended and should be fixed. label Nov 1, 2022
@mihaibudiu mihaibudiu self-assigned this Nov 1, 2022
@vhavel
Copy link
Author

vhavel commented Nov 2, 2022

Indeed, def-use cannot work when IR DAGs are shared, because it keeps a map from statement to definitions, so statements cannot be reused. It was supposed to clone everything needed before running, though. Will have to figure out why.

Shouldn't inlining be responsible for cloning the inlined IR subtree? Adding Substitutions::preorder(IR::Statement* stmt) method which returns stmt->clone() seems to help in this particular case, but maybe GeneralInliner should just duplicate whole inlined body? Simple clone() isn't enough though, because it shallow-copies.

@mihaibudiu
Copy link
Contributor

The rule is that if a pass needs some preconditions it should establish them by itself.
The order of passes changes, and new passes get inserted.
(But we do expect some changes never to be undone by subsequent passes - the treeness of the IR DAG is not one of them.)

@mihaibudiu
Copy link
Contributor

Also, some statements are simply impossible to clone due to the design of the visitor structure, for example even if you clone the EmptyStatement you still get in the resulting tree the original one - there's a check in the visitor which returns the original node if it is equivalent with the replacement node, and any two EmptyStatements are always equivalent. So the DefUse pass needs to replace them with empty blocks, which fortunately are not considered equivalent.

@mihaibudiu mihaibudiu added the fixed This topic is considered to be fixed. label Nov 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This behavior is unintended and should be fixed. fixed This topic is considered to be fixed.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants