This is an archive of the discontinued LLVM Phabricator instance.

[GlobalDCE] Don't add dependency via icmp against inbouds pointer
Needs ReviewPublic

Authored by aykevl on Mar 11 2023, 10:31 AM.

Details

Summary

This patch optimizes the following case:

static int x;
bool foo(int *n) {
    return &x == n;
}

To remove the static global that isn't otherwise used:

bool foo(int *n) {
    return false;
}

This is not a valid optimization in C. However, there are cases where
this can be valid in other language if the pointer parameter n is known
to point into a valid object (either via the dereferenceable_or_null
attribute or an inbouds gep). The logic here is the same as for
https://reviews.llvm.org/D60047.

The motivator for this is runtime type information in TinyGo. There are
two ways type information globals are referenced: either by storing it
in an interface value, or by comparing the interface type against the
type information global. It is this second use (the comparison) that
leads to a significant code size increase of double digit percents in
some cases.

We currently work around this using a hack, but I'd like this to be
supported natively in LLVM so we can simplify the compiler and make use
of a normal LTO pipeline instead of our homegrown LTO variant.

Diff Detail

Event Timeline

aykevl created this revision.Mar 11 2023, 10:31 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 11 2023, 10:31 AM
aykevl requested review of this revision.Mar 11 2023, 10:31 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 11 2023, 10:31 AM
aykevl added inline comments.Mar 11 2023, 11:18 AM
llvm/lib/Transforms/IPO/GlobalDCE.cpp
70

Note this function is basically a copy of https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/CaptureTracking.cpp#L60. I guess this could be generalized, perhaps making it a method on Value?

StephenFan added inline comments.
llvm/lib/Transforms/IPO/GlobalDCE.cpp
102

Your isDereferenceableOrNull function can handle the GetElementPtr instruction, but isLocalGlobal can not handle GetElementPtr. Maybe we need to call stripInBoundsOffsets on Op0 and Op1?

khei4 added a subscriber: khei4.EditedMar 15 2023, 5:34 PM

Drive-by comments: Although I'm not sure about dereferenceable and noalias semantics, in this case, is it appropriate to use noalias instead of dereferenceable, if you want to know the pointers (in)equality? And use getUnderlyingObject for GEPs? I think dereferenceable GV aliases seem normal.
langref for parameter attributes

Edit: also these changes seem better to be placed on InstSimplify rather than GlobalDCE, because they are not dead code.

llvm/test/Transforms/GlobalDCE/icmp.ll
1–3

It might be better to use update_test_checks.py for maintainability. And if this is target independent test, you shouldn't hard code target info.

https://github.com/khei4/llvm-project/blob/main/llvm/lib/Analysis/InstructionSimplify.cpp#L2700~L2727
seems like noalias only itself is not sufficient to judge pointer inequality.

This patch is all over the place. We have different other places where we simplify globals or comparisons, this should go there instead.

llvm/lib/Analysis/TypeMetadataUtils.cpp
272

Why is this code in this file?

llvm/lib/Transforms/IPO/GlobalDCE.cpp
64–67
84

We should not copy code.

107

This code doesn't belong here. No other such logic is used in this traversal.