Skip to content

gh-154910: Constant-fold f-strings with constant fields in the compiler - #154911

Open
overlorde wants to merge 1 commit into
python:mainfrom
overlorde:fix-issue-154910
Open

gh-154910: Constant-fold f-strings with constant fields in the compiler#154911
overlorde wants to merge 1 commit into
python:mainfrom
overlorde:fix-issue-154910

Conversation

@overlorde

Copy link
Copy Markdown
Contributor

The flowgraph optimizer folds constant expressions in most positions, but f-strings with constant fields were left unfolded. This adds two folds:

  • fold_format_simple: LOAD_CONST c, FORMAT_SIMPLE becomes LOAD_CONST format(c) when c is a constant of exact type str, int, float or bool. This mirrors the fast path of the FORMAT_SIMPLE instruction itself: formatting an exact str is the identity (the instruction is simply removed), and formatting the other three types cannot call user code, so the result is known at compile time.
  • fold_build_string_of_constants: BUILD_STRING over constant strings becomes a single string constant, the same shape as fold_tuple_of_constants.

Together they compile an f-string built entirely from constant fields down to one LOAD_CONST:

>>> dis.dis(lambda: f'{1}{2}')
   RESUME                   0
   LOAD_CONST               1 ('12')
   RETURN_VALUE

Partly-constant f-strings also benefit: the constant fields drop their FORMAT_SIMPLE, so e.g. f'{"prefix"}{x}' performs one runtime format instead of two.

Fields with a conversion or a format spec are not touched: CONVERT_VALUE is not a constant load, so the fold doesn't match f'{1!r}', and FORMAT_WITH_SPEC is left as a possible follow-up (it is pure for the same types when the spec is constant).

On a debug free-threaded build, f'{1}{2}' went from ~1770 ns/call to ~34 ns/call, the same as the literal '12'.

…compiler

Fold FORMAT_SIMPLE on constants of exact type str, int, float or bool
in the flowgraph optimizer, mirroring the instruction's own fast path:
formatting an exact str is the identity, and formatting the other three
types cannot call user code. BUILD_STRING over constant strings is then
folded to a single string constant, so f-strings built entirely from
constant fields compile to one LOAD_CONST.

Fields with a conversion or a format spec are unaffected: CONVERT_VALUE
is not a constant load, so the fold does not match, and FORMAT_WITH_SPEC
is left for a possible follow-up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant