This is an archive of the discontinued LLVM Phabricator instance.

[Loads] Add canReplacePointersIfEqual helper.
ClosedPublic

Authored by fhahn on Aug 7 2020, 7:02 AM.

Details

Summary

This patch adds an initial, incomeplete and unsound implementation of
canReplacePointersIfEqual to check if a pointer value A can be replaced
by another pointer value B, that are deemed to be equivalent through
some means (e.g. information from conditions).

Note that is in general not sound to blindly replace pointers based on
equality, for example if they are based on different underlying objects.

LLVM's memory model is not completely settled as of now; see
https://bugs.llvm.org/show_bug.cgi?id=34548 for a more detailed
discussion.

The initial version of canReplacePointersIfEqual only rejects a very
specific case: replacing a pointer with a constant expression that is
not dereferenceable. Such a replacement is problematic and can be
restricted relatively easily without impacting most code. Using it to
limit replacements in GVN/SCCP/CVP only results in small differences in
7 programs out of MultiSource/SPEC2000/SPEC2006 on X86 with -O3 -flto.

This patch is supposed to be an initial step to improve the current
situation and the helper should be made stricter in the future. But this
will require careful analysis of the impact on performance.

Diff Detail

Event Timeline

fhahn created this revision.Aug 7 2020, 7:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 7 2020, 7:02 AM
fhahn requested review of this revision.Aug 7 2020, 7:02 AM
fhahn updated this revision to Diff 283903.Aug 7 2020, 7:22 AM

Directly take DataLayout as argument, as CtxI can be null.

efriedma added inline comments.Aug 7 2020, 12:12 PM
llvm/include/llvm/Analysis/Loads.h
161

Maybe make this note a little louder: put NOTE in all caps, at the beginning of a new paragraph.

llvm/lib/Analysis/Loads.cpp
515

This check is full of holes... but I guess it's a good thing if we can start marking the places in transforms where this matters without worrying too much about the initial performance impact.

nikic added a subscriber: nikic.Aug 7 2020, 12:18 PM
nikic added inline comments.
llvm/lib/Analysis/Loads.cpp
515

This check looks fundamentally incompatible with opaque pointers.

nikic added inline comments.Aug 7 2020, 12:28 PM
llvm/lib/Analysis/Loads.cpp
515

Maybe just check derefability of a single byte, instead of the pointer element type?

fhahn updated this revision to Diff 283997.Aug 7 2020, 12:46 PM

Made the language a bit louder, also add note to canReplacePointersIfEqual definition.

fhahn added inline comments.Aug 7 2020, 12:51 PM
llvm/lib/Analysis/Loads.cpp
515

This check is full of holes... but I guess it's a good thing if we can start marking the places in transforms where this matters without worrying too much about the initial performance impact.

Yes, I added a note. The holes are intentional, to avoid causing too many issues at once and allowing us to gradually tighten the restrictions. FWIW if you require both pointers to be dereferenceable, there are binary changes in ~50 programs out of MultiSource/SPEC2000/SPEC2006, so not too terrible either. But it's probably better to take things in steps.

This check looks fundamentally incompatible with opaque pointers.
Maybe just check derefability of a single byte, instead of the pointer element type?

That might work, but we probably should do this for all uses of isDereferenceablePointer, potentially as follow-up?

nikic added inline comments.Aug 7 2020, 1:33 PM
llvm/lib/Analysis/Loads.cpp
515

That might work, but we probably should do this for all uses of isDereferenceablePointer, potentially as follow-up?

To be clear, the problem is not in the isDereferenceablePointer() API, but in the way it is used in this specific case. Other uses of this API correctly pass in a load type, not a pointer element type. As you do not have access to a load type here, checking for a single byte seems like the best you can do.

fhahn updated this revision to Diff 285350.Aug 13 2020, 6:09 AM

Use isDereferenceableAndAlignedPointer directly and pass size of 1.

fhahn added inline comments.Aug 13 2020, 6:12 AM
llvm/lib/Analysis/Loads.cpp
515

Oh right, I missed that the type is actually only used to get the size. Changed to use isDereferenceableAndAlignedPointer directly.

Hi, I agree this is is a desirable direction.
Should we have a unit test for this function?

fhahn updated this revision to Diff 287882.Aug 26 2020, 2:25 AM

Hi, I agree this is is a desirable direction.
Should we have a unit test for this function?

That seems like a good idea, I added a unit test, which also contains a note that the current implementation is incomplete. I also extended the note in the header to state that returning true currently means unknown if they can be replaced.

aqjune accepted this revision.Aug 26 2020, 10:30 AM

LGTM

llvm/include/llvm/Analysis/Loads.h
166

Would it be better if it starts with CanReplace...?

This revision is now accepted and ready to land.Aug 26 2020, 10:30 AM
fhahn added a comment.Sep 1 2020, 12:56 PM

Thanks!

llvm/include/llvm/Analysis/Loads.h
166

I think https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly suggests starting function names with lowercases. The functions in this file seem to mix both upper and lower case first characters. Given that I think it is slightly better to go with the suggestion in the docs. But I am happy to change post-commit if I am missing something and upper case would be better!

This revision was landed with ongoing or failed builds.Sep 1 2020, 12:58 PM
This revision was automatically updated to reflect the committed changes.