Skip to content

Conversation

@kripken
Copy link
Member

@kripken kripken commented Jan 30, 2024

This pass finds all string.const and creates globals for them. After this transform, no
string.const appears anywhere but in a global, and each string appears in one global
which is then global.get-ed everywhere.

This avoids overhead in VMs where executing a string.const is an allocation, and is
also a good step towards imported strings. For that, this pass will be extended from
gathering to a full lowering pass, which will first gather into globals as this pass does,
and then turn each of those globals with a string.const into an imported externref.
(For that reason this pass is in a file called StringLowering, as the two passes will
share much of their code, and the larger pass should decide the name I think.)

This pass runs in -O2 and above. Repeated executions have no downside (see
details in code).

cc @gkdn

@kripken
Copy link
Member Author

kripken commented Jan 30, 2024

NFC one-line change to type-updating.h is a drive-by I noticed while writing this.

Removed test is the one added by #6234 that checks we do not inline strings from globals. But this pass does that very operation, which interferes with the test, so remove it, and anyhow the test is being removed in #6258 (perhaps this should land after that?)

Comment on lines 134 to 135
auto stringIndex = stringIndexes[stringConst->string];
auto& globalName = globalNames[stringIndex];
Copy link
Member

Choose a reason for hiding this comment

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

It looks like the only use of stringIndexes is to look up an index into globalNames. Can we skip a step here and have globalNames map directly from string to name?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea! Done.

Comment on lines 164 to 165
// Sort our new globals to the start, as others may use them.
std::stable_sort(
Copy link
Member

Choose a reason for hiding this comment

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

Existing globals may also have many uses as well. Is there a principled reason to expect the new globals to be used more frequently?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is for correctness, not compactness. This sort just makes sure, in the simplest way I can think of, that our new globals are in a valid position. We leave frequency sorting for reorder-globals (which we run after this).

Copy link
Member Author

Choose a reason for hiding this comment

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

(And to answer the question, in case I've misunderstood your intent: no, there's no reason to expect the new globals to be more or less used than the old. It's just that the old are already in a proper position.)

Copy link
Member

Choose a reason for hiding this comment

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

Oh, I see. Can you expand the comment to make this more explicit? Perhaps "Sort our new globals to the start to ensure validity, as existing globals initializers may reference them."

continue;
}
auto* stringConst = (*stringPtr)->cast<StringConst>();
auto importName = globalNames[stringIndexes[stringConst->string]];
Copy link
Member

Choose a reason for hiding this comment

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

The globals aren't imported, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Heh, thanks, fixed. This was a leftover name from the larger pass that also adds the imports, which I simplified into this as a first step...

Copy link
Member

@tlively tlively left a comment

Choose a reason for hiding this comment

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

LGTM % those final comment.

@kripken kripken merged commit dfcae55 into WebAssembly:main Jan 31, 2024
@kripken kripken deleted the string.gathering branch January 31, 2024 22:29
kripken added a commit that referenced this pull request Jan 31, 2024
This reverts commit 9090ce5.

This has the effect of once more propagating string constants from
globals to other places (and from non-globals too), which is useful
for various optimizations even if it isn't useful in the final output.
To fix the final output problem, #6257 added a pass that is run at the
end to collect string.const to globals, which allows us to once more
propagate strings in the optimizer, now without a downside.
radekdoulik pushed a commit to dotnet/binaryen that referenced this pull request Jul 12, 2024
This pass finds all string.const and creates globals for them. After this transform, no
string.const appears anywhere but in a global, and each string appears in one global
which is then global.get-ed everywhere.

This avoids overhead in VMs where executing a string.const is an allocation, and is
also a good step towards imported strings. For that, this pass will be extended from
gathering to a full lowering pass, which will first gather into globals as this pass does,
and then turn each of those globals with a string.const into an imported externref.
(For that reason this pass is in a file called StringLowering, as the two passes will
share much of their code, and the larger pass should decide the name I think.)

This pass runs in -O2 and above. Repeated executions have no downside (see
details in code).
radekdoulik pushed a commit to dotnet/binaryen that referenced this pull request Jul 12, 2024
WebAssembly#6258)

This reverts commit 9090ce5.

This has the effect of once more propagating string constants from
globals to other places (and from non-globals too), which is useful
for various optimizations even if it isn't useful in the final output.
To fix the final output problem, WebAssembly#6257 added a pass that is run at the
end to collect string.const to globals, which allows us to once more
propagate strings in the optimizer, now without a downside.
@gkdn gkdn mentioned this pull request Aug 31, 2024
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.

2 participants