-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
[mypyc] Remove unused labels and gotos #15244
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
| CallC, | ||
| Cast, | ||
| ComparisonOp, | ||
| ControlOp, | ||
| DecRef, | ||
| Extend, | ||
| Float, | ||
|
|
@@ -123,6 +124,28 @@ def generate_native_function( | |
| for i, block in enumerate(blocks): | ||
| block.label = i | ||
|
|
||
| # Find blocks that are never jumped to or are only jumped to from the | ||
| # block directly above it. This allows for more labels and gotos to be | ||
| # eliminated during code generation. | ||
|
Comment on lines
+127
to
+129
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only labels are eliminated here, no?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code only marks the basic blocks as "referenced" if they meet the conditions above, nothing actually gets eliminated here. And yes, during codegen, labels won't be emitted for these "unreferenced" blocks, same for |
||
| for block in fn.blocks: | ||
| terminator = block.terminator | ||
| assert isinstance(terminator, ControlOp) | ||
|
|
||
| for target in terminator.targets(): | ||
| is_next_block = target.label == block.label + 1 | ||
|
|
||
| # Always emit labels for GetAttr error checks since the emit code that | ||
| # generates them will add instructions between the branch and the | ||
| # next label, causing the label to be wrongly removed. A better | ||
| # solution would be to change the IR so that it adds a basic block | ||
| # inbetween the calls. | ||
| is_problematic_op = isinstance(terminator, Branch) and any( | ||
| isinstance(s, GetAttr) for s in terminator.sources() | ||
| ) | ||
|
|
||
| if not is_next_block or is_problematic_op: | ||
| fn.blocks[target.label].referenced = True | ||
|
|
||
| common = frequently_executed_blocks(fn.blocks[0]) | ||
|
|
||
| for i in range(len(blocks)): | ||
|
|
@@ -216,17 +239,20 @@ def visit_branch(self, op: Branch) -> None: | |
|
|
||
| if false is self.next_block: | ||
| if op.traceback_entry is None: | ||
| self.emit_line(f"if ({cond}) goto {self.label(true)};") | ||
| if true is not self.next_block: | ||
| self.emit_line(f"if ({cond}) goto {self.label(true)};") | ||
dosisod marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| else: | ||
| self.emit_line(f"if ({cond}) {{") | ||
| self.emit_traceback(op) | ||
| self.emit_lines("goto %s;" % self.label(true), "}") | ||
| else: | ||
| self.emit_line(f"if ({cond}) {{") | ||
| self.emit_traceback(op) | ||
| self.emit_lines( | ||
| "goto %s;" % self.label(true), "} else", " goto %s;" % self.label(false) | ||
| ) | ||
|
|
||
| if true is not self.next_block: | ||
| self.emit_line("goto %s;" % self.label(true)) | ||
|
|
||
| self.emit_lines("} else", " goto %s;" % self.label(false)) | ||
|
|
||
| def visit_return(self, op: Return) -> None: | ||
| value_str = self.reg(op.value) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.