This is an archive of the discontinued LLVM Phabricator instance.

[LSR] Address a special case involving NULL.
AbandonedPublic

Authored by stefanp on Sep 7 2022, 7:46 AM.

Details

Reviewers
lei
nemanjai
qcolombet
Group Reviewers
Restricted Project
Summary

While looking at tests with opaque pointers it was noticed that Loop Strength Reduction behaved differently in cases when a pointer is NULL.
This patch adds a special case to deal with NULL.

Diff Detail

Event Timeline

stefanp created this revision.Sep 7 2022, 7:46 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 7 2022, 7:46 AM
stefanp requested review of this revision.Sep 7 2022, 7:46 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 7 2022, 7:46 AM
nikic added a subscriber: nikic.Sep 7 2022, 7:53 AM

Please add some tests for the new conditions.

stefanp added reviewers: qcolombet, Restricted Project.Sep 7 2022, 8:06 AM

Please add some tests for the new conditions.

Yes. Good point. I will try to get a small test for each condition that was changed.

nikic added inline comments.Sep 8 2022, 5:33 AM
llvm/lib/Transforms/Scalar/LICM.cpp
2101 ↗(On Diff #458454)

So, the null special case doesn't make a lot of sense to me, in that promoting a null pointer is pretty pointless -- those accesses are UB anyway, right?

However, I do think that that this bailout can be removed entirely: https://reviews.llvm.org/D133485

stefanp added inline comments.Sep 8 2022, 12:17 PM
llvm/lib/Transforms/Scalar/LICM.cpp
2101 ↗(On Diff #458454)

So, the null special case doesn't make a lot of sense to me, in that promoting a null pointer is pretty pointless -- those accesses are UB anyway, right?

However, I do think that that this bailout can be removed entirely: https://reviews.llvm.org/D133485

I took a look at that patch and I agree that is a better solution than what I have here.
I was trying to be very conservative and make changes only for NULL values but if the bailout can be removed completely that's much better.

I will change this patch to remove the changes in LICM.

stefanp updated this revision to Diff 459824.Sep 13 2022, 11:38 AM

Sorry that this took a few days.
Removed the code from LICM.
Added a test for the loop strength reduction. The test shows simpler code when
the guard for the NULL is added. However, there may be other tests where the
reverse is true.

stefanp retitled this revision from [LICM][LSR] Address a couple of special cases involving NULL. to [LSR] Address a special case involving NULL..Sep 13 2022, 11:41 AM
stefanp edited the summary of this revision. (Show Details)
stefanp edited the summary of this revision. (Show Details)
nikic added inline comments.Sep 13 2022, 12:32 PM
llvm/test/Transforms/LoopStrengthReduce/Power/opaque-null-ptr.ll
2

As this is just testing the IR transform, it would be better to use opt -S -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 -loop-reduce < %s or so (in which case you can also use update_test_checks.py).

efriedma added inline comments.
llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
3478

NULL has a live range.

If you assume all the users of the NULL are GEPs, then I guess in practice the null is going to get eliminated... but GEPs from null should be extremely rare: it implies you're loading from an absolute address. And it's undefined behavior to load from a null pointer unless the function is marked null_pointer_is_valid (or you're in a non-zero address space).

llvm/test/Transforms/LoopStrengthReduce/Power/opaque-null-ptr.ll
27

Does this really reflect actual user code? The first iteration of the loop loads from the constant addresses "4" and "8".

stefanp abandoned this revision.Sep 19 2022, 9:18 AM

Thank you both for looking at this patch.
Looking at the comments I feel like I made an incorrect assumption about NULL pointers in this case and I'm just going to abandon this patch.

However, I have also replied to the comments below.

llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
3478

Fair enough. I agree with you.
This was actually my initial assumption and it seems to me that I was wrong. Therefore, I would like to abandon this patch.

However, I would like to give more background on the motivation of the patch because that is what I was trying to address in the first place. I have been looking at switching some tests from typed pointers to opaque pointers. The issue I have found is that certain passes (including this one) behave differently and sometimes produce different code when we switch from typed to opaque pointers. The reason for this is that we are asking for the "users" of ptr null (here: for (const Use &U : V->uses()) {).
For example:

%i1 = getelementptr inbounds i8, i8* null, i64 %adr1
%f2 = getelementptr inbounds float, float* null, i64 %adr2

vs.

%i1 = getelementptr inbounds i8, ptr null, i64 %adr1
%f2 = getelementptr inbounds float, ptr null, i64 %adr2

In the first example there is one use of i8* null and one use of float* null. However, in the second example we have two uses of ptr null. This then takes a different path through the compiler and we may end up with different code.

Anyway, I agree with you that GEPs from NULL (basically a form of inttoptr) are not common. However, should we be concerned about this behaviour? Would we need to document it? Or it is just rare enough that we don't really care?

llvm/test/Transforms/LoopStrengthReduce/Power/opaque-null-ptr.ll
2

I did try this initially but for some reason I was getting different results for this test.

Anyway, I plan on abandoning this patch so I'm not going to look further into exactly why I am getting different results.

27

This is actually a reduced test from user code.
Unfortunately the resulting test is not realistic user code because the way that it was reduced discarded a lot of the code that would have given the function any real meaning.

efriedma added inline comments.Sep 19 2022, 9:25 AM
llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
3478

If you're iterating over the use-list of "null", you're probably doing something which doesn't make sense, anyway... it should be rare enough that it doesn't really matter.