-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Description
Hi! We recently hit a miscompile issue that slp-vectorizer turned two 8 byte(memory overlap) load/store into one 16 byte load/store and we further pinpointed to an incorrect alias analysis.
Here is the reduced LLVM IR to repro: reduced.ll.txt
Cmd:
opt -S -passes=slp-vectorizer < reduced.ll
Incorrect codegen result: (notice the load <2 x i64>/ store <2 x i64> )
15: ; preds = %15, %14
%16 = phi ptr [ %0, %15 ], [ %13, %14 ]
%17 = phi ptr [ null, %15 ], [ %8, %14 ]
%18 = load <2 x i64>, ptr %16, align 1
%19 = shufflevector <2 x i64> %18, <2 x i64> poison, <2 x i32> <i32 1, i32 0>
store <2 x i64> %19, ptr %17, align 1
br i1 false, label %15, label %.loopexit42.2
It's a very tricky case, here are some explanations and pictures to help demo the issue:
-
To be simple, let's start using the node
%3as root, the node value is a alias check for the same value alias(<%3, %3>) (this is because it's under theMaybeCrossIteration(BasicAliasAnalysis.cpp) to check if it's no-alias across different iterations ) -
Before recursively checking the dependencies on def-use chain, it initializes the cache with NoAlias(IIUC, this is an assumption based NoAlias BasicAliasAnalysis.cpp#L1691-L1693)

-
Keep checking the alias recursively, i,e. check
<%23, %23>, --><%7, %7>--><%3, 3>until it finds a circle. Then it runs the code in BasicAliasAnalysis.cpp#L1693-L1702, which fetches the initial assumption based value in the cache for %3. -
Then the recursion return back to %7. IIUC, Now %7 is done all the dependencies check, it runs the code to update status to
definitive. Since it depends on an assumption based value(%3), it's pushed into theAssumptionBasedResults(code) which IIUC later if the assumption is disproven, we will remove all the results based on this assumption. -
(Bug occurs!) when processing %8's child %7, as previously %7 is marked as
definitive, %8 is not considered as a assumption based(code) and never pushed intoAssumptionBasedResult, this is incorrect because actually %7 is assumption based(its dependence %3 is assumption based and have't been proven yet), and <%8, %8> is missing to be pushed intoAssumptionBasedResult.
- Return and process %3's right child %99, say <%99> is not a NoAlias, now the previous %3's NoAlias assumption is disproven, all the
AssumptionBaseResultbased on %3 are disproven, i,e.<%23, %23>,<%7,%7>are removed from cache and needed to recompute, but as %8 is missing inAssumptionBasedResult, <%8, %8> is still in the cache. Later any query uses the <%8, %8> is incorrect, in this case, it causes the incorrect <%16, %17> alias that leads to the miscomplile.
In summary:
There seems to be a bug in this assumption-disproven mechanism: An assumption-based result is marked as a definitive result once all dependencies are processed. However, this approach can be problematic if the node is in a cycle, a definitive result may still be assumption-based, as its dependencies' aliases may not all be definitive. Computing a result
based on an incorrect definitive result can lead to escaping invalidation in the cache, i.e. when assumptions got invalidated correctly due to other alias on dependencies, part of the chain may fail to invalidate because an assumption-based result was prematurely marked as definitive.
Therefore, I'm posting here to ask for help how to properly fix this, thanks in advance!
Metadata
Metadata
Assignees
Labels
Type
Projects
Status

