-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DA] Aliasing checks in DA are incorrect #41488
Comments
assigned to @DMG862 |
To repeat what I said on the mailing list: We shouldn't need both the AA check here and the underlying-object check also, as the AA check includes an underlying-object check (and not much else, aside from checks on metadata, when both sizes are unknown). However, as this example shows, the fact that the two SSA values in question refer to different, identified underlying objects, doesn't prevent them from having a cross-iteration dependence as the identify of those underlying objects can change across different iterations (and, thus, the underlying object of one variable in one iteration might be the underlying object used by another variable in another iteration). I'm open to suggestions on how to best resolve this situation. I'm leaning toward suggesting that we have a metadata-only AA query, and use that here, instead of calling something that will invoke BasicAA's logic. My metadata-only AA query, I specifically mean a fundamental dependency-analysis query, likely implemented by the AA subsystem for code-reuse reasons, which answers the question: is there some reason to believe that any instances of these two values never take the same value along any dynamic path through the CFG (or something similar). |
There may be other instances where AliasAnalysis::alias() is used like this (for sure in my private code), so would it be safer to have chnage this function to return the "per-function/across iterations" result? The current AliasAnalysis::alias() behavior could then be moved to a new AliasAnalysis::alias_ssa() function and used where that is intended/safe. |
I went looking through LAA for some inspiration, but it appears to fall into this trap too. This slightly modified code: for.body: ; preds = %for.body, %entry for.cond.cleanup: ; preds = %for.body Seems to produces two alias sets:
LAA: Accesses(2):
Which I believe means it did not find any sorts of dependencies. I guess isn't a problem for the clients of LAA like the vectoriser as they will always be blocked by the cross-loop phis anyway. |
Exactly, it does the same thing. |
I think DI should query AA only on the underylying object. That is:
Since we are looking whether the base array itself is overlapping (any of its element might be accessed), rather the individual element in one iteration. |
Use the Memory SSA representation to check whether the base address of two memory accesses are defined by a same memory SSA node. This fixes llvm#41488 "Aliasing checks in DA are incorrect", and fixes the first testcase in llvm#53942 "[DependenceAnalysis] assumes base pointer invariance". This patch depends on a series of patches to preserve MemorySSA in the passes that require array dependence analysis. For instance, loop-fuse fails 2 tests in test/Transforms/LoopFusion because the transform invalidates the MemorySSA.
Memory SSA is way too heavy to maintain in loop passes. |
Extended Description
The Aliasing checks in DA currently do this:
// Check the original locations (minus size) for noalias, which can happen for
// tbaa, incompatible underlying object locations, etc.
MemoryLocation LocAS(LocA.Ptr, LocationSize::unknown(), LocA.AATags);
MemoryLocation LocBS(LocB.Ptr, LocationSize::unknown(), LocB.AATags);
if (AA->alias(LocAS, LocBS) == NoAlias)
return NoAlias;
// Check the underlying objects are the same
const Value *AObj = GetUnderlyingObject(LocA.Ptr, DL);
const Value *BObj = GetUnderlyingObject(LocB.Ptr, DL);
// If the underlying objects are the same, they must alias
if (AObj == BObj)
return MustAlias;
// We may have hit the recursion limit for underlying objects, or have
// underlying objects where we don't know they will alias.
if (!isIdentifiedObject(AObj) || !isIdentifiedObject(BObj))
return MayAlias;
// Otherwise we know the objects are different and both identified objects so
// must not alias.
return NoAlias;
The alias check is invalid for cases like this, which will return noalias for individual loop iterations, but we care about cross-loop dependencies:
define float @f() {
entry:
%g = alloca float, align 4
%h = alloca float, align 4
br label %for.body
for.body: ; preds = %for.body, %entry
%p = phi float* [ %g, %entry ], [ %q, %for.body ]
%q = phi float* [ %h, %entry ], [ %p, %for.body ]
%0 = load float, float* %p, align 4
store float undef, float* %q, align 4
%branch_cond = fcmp ugt float %0, 0.0
br i1 %branch_cond, label %for.cond.cleanup, label %for.body
for.cond.cleanup: ; preds = %for.body
ret float undef
}
The text was updated successfully, but these errors were encountered: