Skip to content

Fix #2032: avoid propagating mutated SROA fields - #3929

Open
siegfriedpammer wants to merge 1 commit into
masterfrom
fix-2032-tdcu-copy-propagation
Open

Fix #2032: avoid propagating mutated SROA fields#3929
siegfriedpammer wants to merge 1 commit into
masterfrom
fix-2032-tdcu-copy-propagation

Conversation

@siegfriedpammer

Copy link
Copy Markdown
Member

Summary

  • Keep aggressive SROA from propagating a display-class field to its source variable when the field is assigned again after initialization.
  • Re-enable the existing AggressiveScalarReplacementOfAggregates Test9 regression case.

Fixes #2032

Testing

  • OPENSSL_ENABLE_SHA1_SIGNATURES=1 dotnet test --project ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj --filter 'FullyQualifiedName~UglyTestRunner.AggressiveScalarReplacementOfAggregates' --report-trx

Aggressive scalar replacement propagated a display-class field to its
source variable even when the field is mutated after initialization,
aliasing two distinct source-level variables (Test9: thisField and
this). Propagation is now cancelled when the field sees a second store
or its address escapes, but only for propagation targets that cannot
absorb the store: 'this' and variables that are themselves
scalar-replaced display classes. Parameters continue to propagate,
because their remaining uses are already restricted by
ResolveVariableToPropagate and a captured parameter mutated inside a
lambda (DelegateConstruction's Bug951) must keep mapping to the
parameter. Checking CanPropagate first also keeps the guard away from
Mono state-machine fields, whose VariableToDeclare is pre-bound to a
state-machine variable that Propagate(null) would discard.

Re-enables Test9 and adds Test10 covering the escaping-address variant
(Interlocked.Exchange(ref displayClass.thisField, ...)).

Assisted-by: OpenCode:openai/gpt-5.5:OpenCode
Assisted-by: Claude:claude-fable-5:Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens the correctness conditions for aggressive SROA in TransformDisplayClassUsage by preventing propagation of display-class fields back to certain source variables when the field is mutated again (additional stores or escaping address), and updates the Ugly SROA regression tests to cover the fixed behavior.

Changes:

  • Detect post-initialization mutations/escapes of captured fields and disable propagation when it cannot be safely redirected (notably for this and scalar-replaced display-class variables).
  • Add a small helper (IsReadOnlyOrInitializerUse) to distinguish plain reads / recorded initializer stores from later mutations.
  • Re-enable the prior Test9 regression case and add Test10 covering an address-escape mutation via Interlocked.Exchange.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs Adds a guard that disables unsafe propagation when a captured field is mutated after initialization, plus a helper to classify field uses.
ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.Expected.cs Updates expected decompiler output: re-enables Test9 and adds Test10 (Interlocked-based mutation case).
ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.cs Updates input test case source: re-enables Test9 and adds Test10 with Interlocked.Exchange.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

Follow up on #1981 - TDCU copy propagation correctness

2 participants