Skip to content

Remove unnecessary control flow - #10363

Open
niloc132 wants to merge 46 commits into
gwtproject:mainfrom
niloc132:10248-remove-pointless-returns
Open

Remove unnecessary control flow#10363
niloc132 wants to merge 46 commits into
gwtproject:mainfrom
niloc132:10248-remove-pointless-returns

Conversation

@niloc132

@niloc132 niloc132 commented Jul 9, 2026

Copy link
Copy Markdown
Member

Removes trailing returns in methods and non-loop blocks, breaks in switches, and continues in loops. Returns at the end of loops can be replaced by breaks if the loop is the last statement of the method. By itself, will make no difference in runtime performance, but by removing these can reduce simple byte count and and avoid the appearance of control flow that could prevent pruning or inlining.

Generally speaking, this seems like a silly optimization to make - developers won't end void methods with return or loop blocks with continue, but as other code gets optimized away, these end up being left and can't be removed any other way.

There is a risk here for size regressions through making a method easier to inline, though adding explicit return isn't intended as a way to preventing inlining.

This is a necessary prerequisite for #10240 to avoid risking avoidable size regressions.

Fixes #10248

@niloc132 niloc132 added this to the 2.14 milestone Jul 9, 2026
@niloc132

niloc132 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

Here are some simple changes in the Hello sample that are caused by this patch:

 function dispatchCapturedMouseEvent(evt){
   $clinit_DOM();
-  return;
 }

The first shows the main point of the change, that return should have been optimized out when the rest of the method was removed. Original Java for reference:

private static void dispatchCapturedMouseEvent(Event evt) {
boolean cancelled = !DOM.previewEvent(evt);
if (cancelled || captureElem == null) {
return;
}
if (DOM.dispatchEvent(evt, captureElem)) {
evt.stopPropagation();
}
}

I didn't chase the rest of the optimization, but likely the sCaptureElem field is always null for this project, so the first if is always true, and the rest of the method goes away.

Compiling the Showcase shows that Tree has another such example

case KeyCodes.KEY_RIGHT: {
maybeExpandTreeItem();
break;
}
default: {
return;
}

IntelliJ calls out this pointless return at least, and the optimized output also loses the default and preceding `break.

     case 39:
       {
         topClosedParent = $getTopClosedParent(this$static, this$static.curSelection);
         topClosedParent?$setSelectedItem(this$static, topClosedParent):this$static.curSelection.open?$getChildCount(this$static.curSelection) > 0 && $setSelectedItem(this$static, $getChild(this$static.curSelection, 0)):$setState(this$static.curSelection, true, true);
-        break;
-      }
-
-    default:{
-        return;
       }
 
   }
 }

This is one of a handful of "okay, maybe developers do leave in useless keywords" that we can benefit from (see also PopupPanel, AbstractHasData, SplitPanel, SplitLayoutPanel, CellBrowser, CellTree, CellGridImpl, ...).


With that said, the largest Showcase permutation only loses about 100 bytes from just this patch, about 0.05%, while Hello loses about 7 bytes.

EDIT Updated to reflect comparing compiled output with that of #10270, which should merge first.

@niloc132

niloc132 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

These long running branches got me a little backwards - most of this could/should be moved over to #10270 to make this patch a little simpler, and that PR should land first. I'll make that change so this PR is a little more focused.

vjay82 pushed a commit to vjay82/gwt that referenced this pull request Jul 18, 2026
Adds RemoveUnnecessaryControlFlow optimizer pass and supporting AST/codegen
changes. Merged into the fork's passActive[] pass-gating loop (new index 6,
array size 11).
@vjay82

vjay82 commented Jul 18, 2026

Copy link
Copy Markdown

FYI, this was needed to not crash with a NPE during transpilation of a project of mine:

vjay82@2ebb0ca

@niloc132

Copy link
Copy Markdown
Member Author

Thanks @vjay82 - I made a local commit some time ago in tested but neglected to push it, fixed now.

vjay82 pushed a commit to vjay82/gwt that referenced this pull request Jul 21, 2026
Replace our internal null-guards in RemoveUnnecessaryControlFlow with the call-site finally-block guards from PR gwtproject#10363 (commit a3c31e9), so the fix matches upstream and avoids a future merge conflict.
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.

Remove unnecessary returns in compiled output

2 participants