This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Remove attributes after hoisting free above null check
ClosedPublic

Authored by smeenai on Oct 10 2021, 2:11 PM.

Details

Summary

If the parameter had been annotated as nonnull because of the null
check, we want to remove the attribute, since it may no longer apply and
could result in miscompiles if left. Similarly, we also want to remove
undef-implying attributes, since they may not apply anymore either.

Fixes PR52110.

Diff Detail

Event Timeline

smeenai created this revision.Oct 10 2021, 2:11 PM
smeenai requested review of this revision.Oct 10 2021, 2:11 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 10 2021, 2:11 PM
nikic accepted this revision.Oct 10 2021, 2:45 PM

LGTM

This is not the most precise way to do it (I think it would be sufficient to drop nonnull and convert dereferenceable into dereferenceable_or_null), but I don't think there's particular value in being precise either.

This revision is now accepted and ready to land.Oct 10 2021, 2:45 PM
smeenai updated this revision to Diff 378842.Oct 11 2021, 5:38 PM

Adjust attributes more precisely

smeenai requested review of this revision.Oct 11 2021, 5:43 PM

Thanks for the review!

I decided to take the more precise approach, because it seemed cleaner and was a good excuse for me to learn more of the attribute APIs :) I agree about the preciseness being unnecessary, but it shouldn't hurt either.

I'm requesting review again because I've never worked with attributes before, so I wanted to double check that (a) this is what you had in mind, and (b) there's not a simpler way to do the attribute replacement (it's a bit annoying that CallBase supports addDereferenceableParamAttr directly but adding dereferenceable_or_null requires going through AttributeList, but it also seemed overkill to add that method for this single use case). Thanks!

I thought about the validity of this transformation.
To be pedantic, the validity is unclear when ptr is
(1) an out-of-bounds pointer such that (intptr_t)ptr is 0.
But, I remember people wanted to regard free(ptr) as equivalent to free(null) in that case, so it would be fine.
(2) a partially undefined pointer s.t. ptr = undef | 1
But... I couldn't see any such expression appear in practice, and I don't think LLVM is strictly correct with respect to partially undef pointers

Therefore, if the transformation is considered beneficial, I think the optimization is fine.

I thought about the validity of this transformation.
To be pedantic, the validity is unclear when ptr is
(1) an out-of-bounds pointer such that (intptr_t)ptr is 0.
But, I remember people wanted to regard free(ptr) as equivalent to free(null) in that case, so it would be fine.
(2) a partially undefined pointer s.t. ptr = undef | 1
But... I couldn't see any such expression appear in practice, and I don't think LLVM is strictly correct with respect to partially undef pointers

Therefore, if the transformation is considered beneficial, I think the optimization is fine.

Thank you! Does the logic and implementation of this particular change (remove any non-null implying attributes when hoisting the call above the null check) make sense to you?

nikic accepted this revision.Oct 13 2021, 12:13 PM

LGTM

This revision is now accepted and ready to land.Oct 13 2021, 12:13 PM
smeenai updated this revision to Diff 379534.Oct 13 2021, 3:31 PM

Add test for combination of nonnull and dereferenceable

LGTM

Thanks for the quick reviews!

This revision was landed with ongoing or failed builds.Oct 13 2021, 3:35 PM
This revision was automatically updated to reflect the committed changes.