Skip to content

SSAUpdater: don't mistake pre-existing block arguments for inserted phis - #91417

Open
eeckstein wants to merge 1 commit into
swiftlang:mainfrom
eeckstein:fix-ssaupdater
Open

SSAUpdater: don't mistake pre-existing block arguments for inserted phis#91417
eeckstein wants to merge 1 commit into
swiftlang:mainfrom
eeckstein:fix-ssaupdater

Conversation

@eeckstein

Copy link
Copy Markdown
Contributor

isPhi(in:) returned true for any block argument of a block, but both of its uses meant "a phi which this updater inserted into this block". If an available value happened to be a pre-existing block argument (e.g. a switch_enum payload argument), the guards misfired:

  • clearValues refused to invalidate the stale value in that block, so the block and its successors kept forwarding it.
  • propagateValuesThrough then never recomputed the block for the same reason.

Consequently a join block could see the same value arriving from both the defining and the non-defining path, conclude that its predecessors agree, and skip the required phi. The value was then forwarded unconditionally on a path where it was never defined.

This miscompiled nested loops with a conditional assignment in the inner loop: MandatoryRedundantLoadElimination turned the store of the inner loop's induction variable into an unconditional back-edge argument, so the variable was updated in every iteration instead of only when the condition held. Wrong code was generated even at -Onone.

Track the blocks in which the updater inserted a phi in a BasicBlockSet and check that in addition to the value being an argument of the block.

rdar://184416312

`isPhi(in:)` returned true for _any_ block argument of a block, but both of its
uses meant "a phi which this updater inserted into this block". If an available
value happened to be a pre-existing block argument (e.g. a `switch_enum` payload
argument), the guards misfired:

* `clearValues` refused to invalidate the stale value in that block, so the block
  and its successors kept forwarding it.
* `propagateValuesThrough` then never recomputed the block for the same reason.

Consequently a join block could see the same value arriving from both the
defining and the non-defining path, conclude that its predecessors agree, and
skip the required phi. The value was then forwarded unconditionally on a path
where it was never defined.

This miscompiled nested loops with a conditional assignment in the inner loop:
MandatoryRedundantLoadElimination turned the store of the inner loop's induction
variable into an unconditional back-edge argument, so the variable was updated in
every iteration instead of only when the condition held. Wrong code was generated
even at -Onone.

Track the blocks in which the updater inserted a phi in a `BasicBlockSet` and
check that in addition to the value being an argument of the block.

rdar://184416312
@eeckstein

Copy link
Copy Markdown
Contributor Author

@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.

1 participant