Skip to content

Optimize enum comparisons #81780

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

Merged
merged 4 commits into from
May 28, 2025
Merged

Conversation

eeckstein
Copy link
Contributor

This PR contains two optimizations which dramatically improve performance of certain enum comparisons:

Peephole optimization for raw-value enum comparisons

Optimize (the very inefficient) RawRepresentable comparison function call to a simple compare of enum tags.
For example,

  enum E: String {
    case  a, b, c
  }

is compared by getting the raw values of both operands and doing a string compare.
This peephole optimizations replaces the call to such a comparison function with a direct compare of the enum tags, which boils down to a single integer comparison instruction.

rdar://151788987

Always inline synthesized enum comparisons if one of the operands is a constant enum

If there is a "constant" enum argument to a synthesized enum comparison, we can always inline it, because most of it will be constant folded anyway.
This ensures the compiler is not creating terrible code for very simple enum comparisons, like

   if someEnum == .someCase {
      ...
   }

rdar://85677499

@eeckstein eeckstein requested review from jckarter, a team, slavapestov, hborla and xedin as code owners May 27, 2025 05:14
@eeckstein eeckstein requested review from atrick, meg-gupta and nate-chandler and removed request for hborla May 27, 2025 05:14
@eeckstein
Copy link
Contributor Author

@swift-ci test

@eeckstein
Copy link
Contributor Author

@swift-ci apple silicon benchmark

1 similar comment
@eeckstein
Copy link
Contributor Author

@swift-ci apple silicon benchmark

@eeckstein
Copy link
Contributor Author

@swift-ci clean apple silicon benchmark

@eeckstein
Copy link
Contributor Author

@swift-ci benchmark

eeckstein added 4 commits May 27, 2025 12:11
Optimize (the very inefficient) RawRepresentable comparison function call to a simple compare of enum tags.
For example,
```
  enum E: String {
    case  a, b, c
  }
```
is compared by getting the raw values of both operands and doing a string compare.
This peephole optimizations replaces the call to such a comparison function with a direct compare of the enum tags, which boils down to a single integer comparison instruction.

rdar://151788987
…nctions

So that optimizations can identify and deal with them.
… of the operands is a constant enum

If there is a "constant" enum argument to a synthesized enum comparison, we can always inline it, because most of it will be constant folded anyway.
This ensures the compiler is not creating terrible code for very simple enum comparisons, like
```
   if someEnum == .someCase {
      ...
   }
```

rdar://85677499
@eeckstein eeckstein force-pushed the optimize-enum-comparison branch from ed521c7 to ed8922b Compare May 27, 2025 10:11
@eeckstein
Copy link
Contributor Author

@swift-ci test

Func ==(_:_:) has generic signature change from to <T where T : Swift.RawRepresentable, T.RawValue : Swift.Equatable>
Func ==(_:_:) has mangled name changing from 'Swift.== infix(Swift.Optional<Any.Type>, Swift.Optional<Any.Type>) -> Swift.Bool' to 'Swift.== infix<A where A: Swift.RawRepresentable, A.RawValue: Swift.Equatable>(A, A) -> Swift.Bool'
Func ==(_:_:) has parameter 0 type change from (any Any.Type)? to τ_0_0
Func ==(_:_:) has parameter 1 type change from (any Any.Type)? to τ_0_0
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these ABI changes caused just by the addition of @_semantics("rawrepresentable.is_equal")?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think what's happening here is that the api-digester is mixing up different overloads of the func ==

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, that's unfortunate.

Copy link
Contributor

Choose a reason for hiding this comment

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

(probably worth a bug report against the api-digester, if you can file one)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nkcsgexi do you know, is my assumption correct?

@eeckstein
Copy link
Contributor Author

@swift-ci smoke test windows

@eeckstein
Copy link
Contributor Author

@swift-ci smoke test macos

@eeckstein eeckstein merged commit 89bdb31 into swiftlang:main May 28, 2025
4 of 5 checks passed
@eeckstein eeckstein deleted the optimize-enum-comparison branch May 28, 2025 05:01
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