D104806 broke some uses of getMinusSCEV() in DependenceAnalysis: subtraction with different pointer bases returns a SCEVCouldNotCompute. Make sure we avoid cases involving such subtractions.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
LGTM
I think I number of these queries could handle inequal base objects, but given there's no test coverage for it, it doesn't appear to matter.
llvm/lib/Analysis/DependenceAnalysis.cpp | ||
---|---|---|
3556 | We only get here if the two pointers MustAlias. If my understanding of MustAlias is correct (that it means precise and complete overlapping of memory), and if the two references are in the same loop, then comparing indexes seems reasonable. In that case, the effect of the following analysis should be as if src and dst SCEVs have their base pointers replaced with the same value. Not sure what's the best way to deal with such cases. Does it make sense to introduce a mode in getMinusSCEV where different base pointers can be permitted? |
llvm/lib/Analysis/DependenceAnalysis.cpp | ||
---|---|---|
3556 | underlyingObjectsAlias(Src, Dst) == MustAlias is basically a slightly fancier version isIdentifiedObject(getUnderlyingObject(Src)) && isIdentifiedObject(getUnderlyingObject(Dst)) && getUnderlyingObject(Src) == getUnderlyingObject(Dst). The issue here is that getPointerBase() is less powerful than getUnderlyingObject(). It is possible to cast the operands of getMinusSCEV to integers using getPtrToIntExpr(); in that case, you won't get a SCEVCouldNotCompute. But then you end up with a SCEV containing something like ptrtoint(SrcSCEVPointerBase) - ptrtoint(DstSCEVPointerBase), which is basically impossible to analyze. So it seems simpler to just reject early. |
llvm/lib/Analysis/DependenceAnalysis.cpp | ||
---|---|---|
3556 | Oh, also, there's been work to allow SCEV to look through LCSSA PHI nodes; that would allow DependenceAnalysis to analyze more cases. But that patch got reverted; not sure what the current status is. |
llvm/lib/Analysis/DependenceAnalysis.cpp | ||
---|---|---|
3556 | This seems like a subset of cases we should be filtering out. Please also add checks for the access width being unaligned with the store/load size. In this case the base pointers are different but the accesses can still overlap. This case will not be caught by DependenceAnalysis. define void @z0(i32* %A, i64 %n) nounwind uwtable ssp { entry: %arrayidx = getelementptr inbounds i32, i32* %A, i64 %n %arrayidx_cast = bitcast i32* %arrayidx to i64* store i64 0, i64* %arrayidx_cast, align 4 ; CHECK: da analyze - confused! ; CHECK: da analyze - confused! ; CHECK: da analyze - confused! ; CHECK: da analyze - none ; CHECK: da analyze - confused! ; CHECK: da analyze - confused! %add1 = add i64 %n, 1 %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %add1 %0 = load i32, i32* %arrayidx2, align 4 ; Even if the load and store types are the same, if their ; alignments are smaller than the store size and they are ; accesses through something other than a straightforward ; gep, they can still overlap, as this access shows %arrayidx2_cast = bitcast i32* %arrayidx2 to i64* %1 = load i64, i64* %arrayidx2_cast, align 4 ret void } |
llvm/lib/Analysis/DependenceAnalysis.cpp | ||
---|---|---|
3556 | Well, there are a few things we can do in that case:
I'm afraid (1) will hurt performance. And I don't really want to sign up to do (2) or (3). |
llvm/lib/Analysis/DependenceAnalysis.cpp | ||
---|---|---|
3556 | Well currently we do not bail out in the case of (1), so it is worse than loosing performance, we are giving incorrect results. As for (2) and (3) completely agree this is a project and I did not mean to imply that you should undertake it. Apologies, that was not my intention. |
We only get here if the two pointers MustAlias. If my understanding of MustAlias is correct (that it means precise and complete overlapping of memory), and if the two references are in the same loop, then comparing indexes seems reasonable. In that case, the effect of the following analysis should be as if src and dst SCEVs have their base pointers replaced with the same value. Not sure what's the best way to deal with such cases. Does it make sense to introduce a mode in getMinusSCEV where different base pointers can be permitted?