This is an archive of the discontinued LLVM Phabricator instance.

[DependenceAnalysis] Conservatively exit on type mismatch
Needs ReviewPublic

Authored by artemrad on Aug 13 2021, 11:47 AM.

Details

Summary

DA does not check that types match during analysis. Bitcasts can result in a wide access overlapping a narrower access, but because the pointer values are different, DA considers them independent.

Make sure that alignment matches store size.

Change Summary:

  • Updated description of depends() to be descriptive instead of prescriptive
  • Optimization: exit early if no common loops AND don't care about loop independent dependencies
  • Check that alignment matches store size
  • Renamed PossiblyLoopIndependent to PossiblyIntraIteration to be more clear with intent of code

Diff Detail

Event Timeline

artemrad created this revision.Aug 13 2021, 11:47 AM
artemrad requested review of this revision.Aug 13 2021, 11:47 AM
nikic added a subscriber: nikic.Aug 13 2021, 11:57 AM
nikic added inline comments.
llvm/lib/Analysis/DependenceAnalysis.cpp
3655

Why does this check the type store size of the pointer type, rather than the accessed type?

Meinersbur added inline comments.Aug 13 2021, 12:13 PM
llvm/lib/Analysis/DependenceAnalysis.cpp
3512–3516

Did you intend to replace the non-doxygen comment for depends?

3651

Please consider the LLVM coding style for use of auto.

Meinersbur added inline comments.Aug 13 2021, 1:21 PM
llvm/include/llvm/Analysis/DependenceAnalysis.h
285–286

Maybe we should rename PossiblyLoopIndependent to something else. I don't see how "LoopIndependent" makes a statement about non-loop dependences.

llvm/lib/Analysis/DependenceAnalysis.cpp
3570
3628–3631

underlyingObjectsAlias should return PartialAlias alias in such cases. That is, I think it still may return MustAlias if the address is the same but the size is different. In that case it should be sufficient to a compare just the sizes, but not the alignment

3654–3655

You could consider llvm::MemoryLocation for this. It abstracts over for LoadInst/StoreInst and also determines that access size.

bmahjour added inline comments.Aug 13 2021, 2:13 PM
llvm/include/llvm/Analysis/DependenceAnalysis.h
285–286

Any suggestions on what the rename should be? "Loop-Independent" is well defined in the literature and seems appropriately used here.

llvm/lib/Analysis/DependenceAnalysis.cpp
3572

add a LLVM_DEBUG before returning?

3628–3631

I agree this logic belongs to underlyingObjectsAlias.

3632

DL doesn't change in any invocation of the lambda, so better be captured instead of being passed as arg.

llvm/test/Analysis/DependenceAnalysis/OverlappingAddresses.ll
24

Should we also check if we can prove that the pointer differences will always be larger than the misalignment? For example if this was adding 2 to the base pointer, then the store on line 14 would not overlap with the two loads below.

efriedma added inline comments.Aug 13 2021, 4:27 PM
llvm/lib/Analysis/DependenceAnalysis.cpp
3640

Load/store instructions were fixed so alignment can't be zero.

You can use "LI->getAlign()" to get an llvm::Align instead of an unsigned.

Meinersbur added inline comments.Aug 16 2021, 10:14 AM
llvm/include/llvm/Analysis/DependenceAnalysis.h
285–286

It's just an idea. If it a well-established term we can keep it, I just don't think it is a good one. It gets really confusing if we consider that a dependence can be both, loop-carried and within the same iteration.

for (int i = ...) {
  use(A[0]);
  A[i] = ...;
  use(A[0]);
}

The comment itself would suggest PossiblyIntraIteration.

artemrad updated this revision to Diff 369789.Aug 31 2021, 1:52 PM
artemrad edited the summary of this revision. (Show Details)

Addressed some comments, but not all.

artemrad marked 10 inline comments as done.Aug 31 2021, 1:55 PM
artemrad added inline comments.
llvm/lib/Analysis/DependenceAnalysis.cpp
3512–3516

Nope.

3640

Didn't know this. Neat. Fixed.

3655

Good catch. I missed this. Fixed

artemrad marked 3 inline comments as done.Sep 1 2021, 11:34 AM
Meinersbur added inline comments.Sep 1 2021, 9:34 PM
llvm/lib/Analysis/DependenceAnalysis.cpp
3595–3598

Seems to make sense that DependenceAnalysis does not handle accesses that fall between two array elements. Am I correct that his makes sure that each load/store will access at most one alignment "slot"? And therefore conservatively bails out for any type that is larger than its alignment (such as _Complex, struct, classes, etc.)?

In that case, I propose a reformulation:

DependenceAnalysis assumes that accesses never partially overlap. Here we ensure that every access size is smaller than the alignment. This guarantees that two aligned accesses either have the same pointer value, or do not alias, not even partially.
FIXME: This excludes many common cases from analysis, such as array of structs, _Complex and bitcasts to i8* (eg. memset, memcpy, fallback type for many optimization passes).

3599

An "unaligned access" would be an access that is ... not aligned. However, this lambda tests whether partial overlap is possible despite alignment. Proposed name: "IsAccSizeExceeedingAlignment" (or some of the like).

3606

[nit] redundant outer parens

Is Width <= Alignment sufficient?

3609–3610

What makes partial overlap impossible if both pointer's last operation is a GEP?

3611–3616

llvm::Type::getPointerElementType() is a shortcut for cast<PointerType>(...)->getElementType()

nikic added inline comments.Sep 2 2021, 12:50 AM
llvm/lib/Analysis/DependenceAnalysis.cpp
3602

getLoadStoreType() + getLoadStoreAlignment()

3611–3616

This should use getLoadStoreType() for opaque pointer compatibility as well.