1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00

[BasicAA] Fix a bug with relational reasoning across iterations

Due to the recursion through phis basicaa does, the code needs to be extremely careful not to reason about equality between values which might represent distinct iterations. I'm generally skeptical of the correctness of the whole scheme, but this particular patch fixes one particular instance which is demonstrateable incorrect.

Interestingly, this appears to be the second attempted fix for the same issue. The former fix is incomplete and doesn't address the actual issue.

Differential Revision: https://reviews.llvm.org/D92694
This commit is contained in:
Philip Reames 2020-12-05 14:05:48 -08:00
parent e24be6085b
commit e27a387f8e
3 changed files with 39 additions and 21 deletions

View File

@ -202,6 +202,12 @@ private:
const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject,
LocationSize ObjectAccessSize);
AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
LocationSize MaybeV1Size,
const GEPOperator *GEP2,
LocationSize MaybeV2Size,
const DataLayout &DL);
/// A Heuristic for aliasGEP that searches for a constant offset
/// between the variables.
///

View File

@ -1032,11 +1032,11 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call1,
/// Provide ad-hoc rules to disambiguate accesses through two GEP operators,
/// both having the exact same pointer operand.
static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
LocationSize MaybeV1Size,
const GEPOperator *GEP2,
LocationSize MaybeV2Size,
const DataLayout &DL) {
AliasResult BasicAAResult::aliasSameBasePointerGEPs(const GEPOperator *GEP1,
LocationSize MaybeV1Size,
const GEPOperator *GEP2,
LocationSize MaybeV2Size,
const DataLayout &DL) {
assert(GEP1->getPointerOperand()->stripPointerCastsAndInvariantGroups() ==
GEP2->getPointerOperand()->stripPointerCastsAndInvariantGroups() &&
GEP1->getPointerOperandType() == GEP2->getPointerOperandType() &&
@ -1126,24 +1126,12 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
if (C1 && C2)
return NoAlias;
{
// If we're not potentially reasoning about values from different
// iterations, see if we can prove them inequal.
Value *GEP1LastIdx = GEP1->getOperand(GEP1->getNumOperands() - 1);
Value *GEP2LastIdx = GEP2->getOperand(GEP2->getNumOperands() - 1);
if (isa<PHINode>(GEP1LastIdx) || isa<PHINode>(GEP2LastIdx)) {
// If one of the indices is a PHI node, be safe and only use
// computeKnownBits so we don't make any assumptions about the
// relationships between the two indices. This is important if we're
// asking about values from different loop iterations. See PR32314.
// TODO: We may be able to change the check so we only do this when
// we definitely looked through a PHINode.
if (GEP1LastIdx != GEP2LastIdx &&
GEP1LastIdx->getType() == GEP2LastIdx->getType()) {
KnownBits Known1 = computeKnownBits(GEP1LastIdx, DL);
KnownBits Known2 = computeKnownBits(GEP2LastIdx, DL);
if (Known1.Zero.intersects(Known2.One) ||
Known1.One.intersects(Known2.Zero))
return NoAlias;
}
} else if (isKnownNonEqual(GEP1LastIdx, GEP2LastIdx, DL))
if (VisitedPhiBBs.empty() &&
isKnownNonEqual(GEP1LastIdx, GEP2LastIdx, DL))
return NoAlias;
}
}

View File

@ -173,3 +173,27 @@ exit:
}
declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i1)
; CHECK-LABEL: unsound_inequality
; CHECK: MayAlias: i32* %arrayidx13, i32* %phi
; CHECK: MayAlias: i32* %arrayidx5, i32* %phi
; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5
; When recursively reasoning about phis, we can't use predicates between
; two values as we might be comparing the two from different iterations.
define i32 @unsound_inequality(i32* %jj7, i32* %j) {
entry:
%oa5 = alloca [100 x i32], align 16
br label %for.body
for.body: ; preds = %for.body, %entry
%phi = phi i32* [ %arrayidx13, %for.body ], [ %j, %entry ]
%idx = load i32, i32* %jj7, align 4
%arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* %oa5, i64 0, i32 %idx
store i32 0, i32* %arrayidx5, align 4
store i32 0, i32* %phi, align 4
%notequal = add i32 %idx, 1
%arrayidx13 = getelementptr inbounds [100 x i32], [100 x i32]* %oa5, i64 0, i32 %notequal
store i32 0, i32* %arrayidx13, align 4
br label %for.body
}