Skip to content

[move-only] Fix SIL representation and SILOptimizer to preserve value deinits #66314

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 14 commits into from
Jun 6, 2023

Conversation

atrick
Copy link
Contributor

@atrick atrick commented Jun 3, 2023

Fix SIL representation and SILOptimizer to preserve value deinits.

Fixes:

  • rdar://110079028 ([move-only] Finish SIL support for drop_deinit)
  • rdar://109849028 ([move-only] LowerAggregateInstrs eliminates struct deinitialization)

Many basic SIL passes were silently deleting the struct and enum deinits:

  • SROA
  • Mem2Reg
  • RLE
  • DSE
  • FunctionSignatureOpts
  • LowerAggregates
  • SILCombine
  • EarlyCodeMotion
  • ReleaseHoisting
  • many passes that rely on ARC analysis (RCIndentity)

Major Changes:

  • add SIL verification for drop_deinit
  • fix ownership lowering to handle drop_deinit
  • disable deinit devirtualization (until the optimizer is tested)
  • fix 'shouldExpand' to recognize value deinits; impacts many passes
  • fix dead function elimination to collect and preserve value deinits
  • fix RCIdentity to recognize value deinits; impacts many passes
  • fix SILCombine special cases to preserve value deinits
  • fix TypeLowering to preserve value deinits; mainly fixes LowerAggregates

Copy link
Contributor

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

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

A simplification and a question

@atrick atrick force-pushed the fix-dropdeinit branch 2 times, most recently from 3ad3764 to 47eaff5 Compare June 4, 2023 06:14
SILValue addr = B.createStructElementAddr(
cleanupLoc, selfValue, vd, ti.getLoweredType().getAddressType());
addr = B.createBeginAccess(
cleanupLoc, addr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
Copy link
Contributor

Choose a reason for hiding this comment

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

Question. Shouldn't we perhaps do the same thing here for destroy_addr like we do for objects. Then we would be really consistent across the code base.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

drop_deinit on an address doesn't have the same OSSA semantics as it does on a value. The address and value forms definitely should be separate opcodes to avoid this confusion (in some later PR).

It is analogous to destroy_addr vs. destroy_value. destroy_addr has nothing to do with OSSA, and drop_deinit on an address does not change the meaning of any subsequent destroy_addr. drop_deinit on an address does not actually do anything except block optimization on the address, preventing us from promoting it to OSSA!

So drop_deinit on an address doesn't have any SIL requirements and has no structural verification. As such, SILGen cannot emit a destroy_addr for a discarded value. That would be outright wrong. And OSSA lowering is not affected at all by a drop_deinit on an address.

@atrick atrick force-pushed the fix-dropdeinit branch 4 times, most recently from eff1206 to f62e5f6 Compare June 6, 2023 08:04
@atrick
Copy link
Contributor Author

atrick commented Jun 6, 2023

@swift-ci test

@atrick atrick changed the title [move-only] Fix drop_deinit: SILOptimizer support for struct-deinit [move-only] Fix SIL representation and SILOptimizer to preserve value deinits Jun 6, 2023
@atrick
Copy link
Contributor Author

atrick commented Jun 6, 2023

@swift-ci smoke test windows

atrick added 14 commits June 6, 2023 09:17
drop_deinit ultimately only affects the semantics of its
destroy_value. Avoid generating releases for destroys in which the
deinit has been dropped. Instead, individually release the members.
drop_deinit only exists in ownership SIL. Remove IRGen support.

A drop_deinit can only ever be destroyed or destructured.

A destructure of a struct-with-deinit requires a drop_deinit operand.
to MoveOnlyDeinitDevirtualization
It is not needed for correctness and hides most of the deinit related
optimizer bugs.
Many basic SIL passes were silently deleting the struct deinit:
- SROA
- Mem2Reg
- RLE
- DSE
- FunctionSignatureOpts
- LowerAggregates

Fixes rdar://109849028 ([move-only] LowerAggregateInstrs eliminates struct deinitialization)
Multiple code motion and ARC related passes were removing struct/enum
deinits.

Passes fixed include:
- SILCombine
- EarlyCodeMotion
- ReleaseHoisting
- *many* passes that rely on ARC analysis (RCIndentity)
Fix a special case in visitReleaseValueInst for enum-with-deinit.
MoveOnlyLoadableStruct should only lower to memberwise destroys if it
has no deinit.
The -Onone passes fail to remove struct_extract, so the CHECK
lines will fail.
@atrick
Copy link
Contributor Author

atrick commented Jun 6, 2023

@swift-ci smoke test

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