Skip to content

Fix an assert in collectUses when handling unknown index offsets. #38492

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

Closed
wants to merge 1 commit into from

Conversation

atrick
Copy link
Contributor

@atrick atrick commented Jul 20, 2021

AccessPathDefUseTraversal accumulates the offsets that it has seen on
the def-use walk while visiting index_addr and casts.

This is quite tricky because either the AccessPath being matched or
the def-use chain could contain unknown offsets. We need to correctly
classify all cases as either an exact, inner, or overlapping match.

For SIL like this

%91 = integer_literal $Builtin.Int64, 0
%113 = builtin "truncOrBitCast_Int64_Word"(%91 : $Builtin.Int64) : $Builtin.Word
%115 = index_addr %114 : $*MyStruct, %113 : $Builtin.Word
%119 = struct_element_addr %115 : $*MyStruct, #MyStruct.klass

We have Path: (@unknown,#0)

There are two issues

(1) When AccessPathDefUseTraversal::checkAndUpdateOffset visits the
struct_element_addr, it fails to pop the unknown offset from the
expected path but continues trying to handle the struct_element_addr
and hits an assert.

That's probably as simple as fixing

< if (pathOffset > 0) {

to be

< if (pathOffset != 0) {

(2) If the builtin "truncOrBitCast_Int64_Word" comes from a literal,
we should not treat it as an unknown offset (given that the literal is
within the size of a word).

We should change the test case above to be a truly unknown offset to
test issue #1. Then add the test case as-is to
accesspath_uses_ossa.sil to test that the constant offset is recognized.

Those can be separate fixes.

AccessPathDefUseTraversal accumulates the offsets that it has seen on
the def-use walk while visiting index_addr and casts.

This is quite tricky because either the AccessPath being matched or
the def-use chain could contain unknown offsets. We need to correctly
classify all cases as either an exact, inner, or overlapping match.

For SIL like this

 %91 = integer_literal $Builtin.Int64, 0
 %113 = builtin "truncOrBitCast_Int64_Word"(%91 : $Builtin.Int64) : $Builtin.Word
 %115 = index_addr %114 : $*MyStruct, %113 : $Builtin.Word
 %119 = struct_element_addr %115 : $*MyStruct, #MyStruct.klass

We have Path: (@unknown,#0)

There are two issues

(1) When AccessPathDefUseTraversal::checkAndUpdateOffset visits the
struct_element_addr, it fails to pop the unknown offset from the
expected path but continues trying to handle the struct_element_addr
and hits an assert.

That's probably as simple as fixing

<    if (pathOffset > 0) {

to be

<    if (pathOffset != 0) {

(2) If the builtin "truncOrBitCast_Int64_Word" comes from a literal,
we should not treat it as an unknown offset (given that the literal is
within the size of a word).

We should change the test case above to be a truly unknown offset to
test issue #1. Then add the test case as-is to
accesspath_uses_ossa.sil to test that the constant offset is recognized.

Those can be separate fixes.
@meg-gupta
Copy link
Contributor

Thanks for the fix! I merged this fix with tests in #38757. PR to get non-unknown access paths in the presence of builtins like truncOrBitCast will be a follow up.

@atrick atrick closed this Aug 8, 2021
@atrick atrick deleted the fix-accesspath-assert branch October 18, 2022 23:43
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