Skip to content

Commit c31eb82

Browse files
committed
[BasicAA] Fix nsw handling for negated scales (PR63266)
We currently preserve the nsw flag when negating scales, which is incorrect for INT_MIN. However, just dropping the NSW flag in this case makes BasicAA behavior unreliable and asymmetric, because we may or may not drop the NSW flag depending on which side gets subtracted. Instead, leave the Scale alone and add an additional IsNegated flag, which indicates that the whole VarIndex should be interpreted as a subtraction. This allows us to retain the NSW flag. When accumulating the offset range, we need to use subtraction instead of adding for IsNegated indices. Everything else works on the absolute value of the scale, so the negation does not matter there. Fixes #63266. Differential Revision: https://reviews.llvm.org/D153270
1 parent 51b0398 commit c31eb82

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

llvm/lib/Analysis/BasicAliasAnalysis.cpp

+34-7
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,17 @@ struct VariableGEPIndex {
461461
/// True if all operations in this expression are NSW.
462462
bool IsNSW;
463463

464+
/// True if the index should be subtracted rather than added. We don't simply
465+
/// negate the Scale, to avoid losing the NSW flag: X - INT_MIN*1 may be
466+
/// non-wrapping, while X + INT_MIN*(-1) wraps.
467+
bool IsNegated;
468+
469+
bool hasNegatedScaleOf(const VariableGEPIndex &Other) const {
470+
if (IsNegated == Other.IsNegated)
471+
return Scale == -Other.Scale;
472+
return Scale == Other.Scale;
473+
}
474+
464475
void dump() const {
465476
print(dbgs());
466477
dbgs() << "\n";
@@ -470,7 +481,9 @@ struct VariableGEPIndex {
470481
<< ", zextbits=" << Val.ZExtBits
471482
<< ", sextbits=" << Val.SExtBits
472483
<< ", truncbits=" << Val.TruncBits
473-
<< ", scale=" << Scale << ")";
484+
<< ", scale=" << Scale
485+
<< ", nsw=" << IsNSW
486+
<< ", negated=" << IsNegated << ")";
474487
}
475488
};
476489
}
@@ -659,7 +672,8 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL,
659672
Scale = adjustToIndexSize(Scale, IndexSize);
660673

661674
if (!!Scale) {
662-
VariableGEPIndex Entry = {LE.Val, Scale, CxtI, LE.IsNSW};
675+
VariableGEPIndex Entry = {LE.Val, Scale, CxtI, LE.IsNSW,
676+
/* IsNegated */ false};
663677
Decomposed.VarIndices.push_back(Entry);
664678
}
665679
}
@@ -1151,9 +1165,14 @@ AliasResult BasicAAResult::aliasGEP(
11511165
assert(OffsetRange.getBitWidth() == Scale.getBitWidth() &&
11521166
"Bit widths are normalized to MaxIndexSize");
11531167
if (Index.IsNSW)
1154-
OffsetRange = OffsetRange.add(CR.smul_sat(ConstantRange(Scale)));
1168+
CR = CR.smul_sat(ConstantRange(Scale));
1169+
else
1170+
CR = CR.smul_fast(ConstantRange(Scale));
1171+
1172+
if (Index.IsNegated)
1173+
OffsetRange = OffsetRange.sub(CR);
11551174
else
1156-
OffsetRange = OffsetRange.add(CR.smul_fast(ConstantRange(Scale)));
1175+
OffsetRange = OffsetRange.add(CR);
11571176
}
11581177

11591178
// We now have accesses at two offsets from the same base:
@@ -1220,7 +1239,7 @@ AliasResult BasicAAResult::aliasGEP(
12201239
// inequality of values across loop iterations.
12211240
const VariableGEPIndex &Var0 = DecompGEP1.VarIndices[0];
12221241
const VariableGEPIndex &Var1 = DecompGEP1.VarIndices[1];
1223-
if (Var0.Scale == -Var1.Scale && Var0.Val.TruncBits == 0 &&
1242+
if (Var0.hasNegatedScaleOf(Var1) && Var0.Val.TruncBits == 0 &&
12241243
Var0.Val.hasSameCastsAs(Var1.Val) && !AAQI.MayBeCrossIteration &&
12251244
isKnownNonEqual(Var0.Val.V, Var1.Val.V, DL, &AC, /* CxtI */ nullptr,
12261245
DT))
@@ -1701,6 +1720,13 @@ void BasicAAResult::subtractDecomposedGEPs(DecomposedGEP &DestGEP,
17011720
!Dest.Val.hasSameCastsAs(Src.Val))
17021721
continue;
17031722

1723+
// Normalize IsNegated if we're going to lose the NSW flag anyway.
1724+
if (Dest.IsNegated) {
1725+
Dest.Scale = -Dest.Scale;
1726+
Dest.IsNegated = false;
1727+
Dest.IsNSW = false;
1728+
}
1729+
17041730
// If we found it, subtract off Scale V's from the entry in Dest. If it
17051731
// goes to zero, remove the entry.
17061732
if (Dest.Scale != Src.Scale) {
@@ -1715,7 +1741,8 @@ void BasicAAResult::subtractDecomposedGEPs(DecomposedGEP &DestGEP,
17151741

17161742
// If we didn't consume this entry, add it to the end of the Dest list.
17171743
if (!Found) {
1718-
VariableGEPIndex Entry = {Src.Val, -Src.Scale, Src.CxtI, Src.IsNSW};
1744+
VariableGEPIndex Entry = {Src.Val, Src.Scale, Src.CxtI, Src.IsNSW,
1745+
/* IsNegated */ true};
17191746
DestGEP.VarIndices.push_back(Entry);
17201747
}
17211748
}
@@ -1737,7 +1764,7 @@ bool BasicAAResult::constantOffsetHeuristic(const DecomposedGEP &GEP,
17371764
const VariableGEPIndex &Var0 = GEP.VarIndices[0], &Var1 = GEP.VarIndices[1];
17381765

17391766
if (Var0.Val.TruncBits != 0 || !Var0.Val.hasSameCastsAs(Var1.Val) ||
1740-
Var0.Scale != -Var1.Scale ||
1767+
!Var0.hasNegatedScaleOf(Var1) ||
17411768
Var0.Val.V->getType() != Var1.Val.V->getType())
17421769
return false;
17431770

llvm/test/Analysis/BasicAA/range.ll

+1-2
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,8 @@ define void @benign_overflow(ptr %p, i64 %o) {
239239
ret void
240240
}
241241

242-
; FIXME: This is a miscompile
243242
; CHECK-LABEL: pr63266
244-
; CHECK: NoAlias: i8* %gep2, i8* %offset16
243+
; CHECK: MayAlias: i8* %gep2, i8* %offset16
245244
define void @pr63266(i1 %c, ptr %base) {
246245
entry:
247246
%offset16 = getelementptr inbounds i8, ptr %base, i64 16

0 commit comments

Comments
 (0)