Skip to content

Commit 3c87f66

Browse files
authored
[BasicAA] Make use of nusw+nuw -> nneg implication (#102141)
If the GEP is both nuw and inbounds/nusw, the offset is non-negative. Pass this information to CastedValue and make use of it when determining the value range. Proof for nusw+nuw->nneg: https://alive2.llvm.org/ce/z/a_CKAw Proof for the test case: https://alive2.llvm.org/ce/z/yJ3ymP
1 parent 7753429 commit 3c87f66

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

llvm/lib/Analysis/BasicAliasAnalysis.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,10 @@ struct CastedValue {
337337
assert(N.getBitWidth() == V->getType()->getPrimitiveSizeInBits() &&
338338
"Incompatible bit width");
339339
if (TruncBits) N = N.truncate(N.getBitWidth() - TruncBits);
340+
if (IsNonNegative && !N.isAllNonNegative())
341+
N = N.intersectWith(
342+
ConstantRange(APInt::getZero(N.getBitWidth()),
343+
APInt::getSignedMinValue(N.getBitWidth())));
340344
if (SExtBits) N = N.signExtend(N.getBitWidth() + SExtBits);
341345
if (ZExtBits) N = N.zeroExtend(N.getBitWidth() + ZExtBits);
342346
return N;
@@ -693,15 +697,17 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL,
693697

694698
// If the integer type is smaller than the index size, it is implicitly
695699
// sign extended or truncated to index size.
700+
bool NUSW = GEPOp->hasNoUnsignedSignedWrap();
701+
bool NonNeg = NUSW && GEPOp->hasNoUnsignedWrap();
696702
unsigned Width = Index->getType()->getIntegerBitWidth();
697703
unsigned SExtBits = IndexSize > Width ? IndexSize - Width : 0;
698704
unsigned TruncBits = IndexSize < Width ? Width - IndexSize : 0;
699705
LinearExpression LE = GetLinearExpression(
700-
CastedValue(Index, 0, SExtBits, TruncBits, false), DL, 0, AC, DT);
706+
CastedValue(Index, 0, SExtBits, TruncBits, NonNeg), DL, 0, AC, DT);
701707

702708
// Scale by the type size.
703709
unsigned TypeSize = AllocTypeSize.getFixedValue();
704-
LE = LE.mul(APInt(IndexSize, TypeSize), GEPOp->hasNoUnsignedSignedWrap());
710+
LE = LE.mul(APInt(IndexSize, TypeSize), NUSW);
705711
Decomposed.Offset += LE.Offset.sext(MaxIndexSize);
706712
APInt Scale = LE.Scale.sext(MaxIndexSize);
707713

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: opt < %s -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
2+
3+
; CHECK-LABEL: test
4+
; CHECK: NoAlias: i8* %p.minus.2, i8* %p.plus.2
5+
; CHECK: MayAlias: i8* %p.idx.maybeneg, i8* %p.minus.2
6+
; CHECK: MayAlias: i8* %p.idx.maybeneg, i8* %p.plus.2
7+
; CHECK: NoAlias: i8* %p.idx.nneg, i8* %p.minus.2
8+
; CHECK: MayAlias: i8* %p.idx.nneg, i8* %p.plus.2
9+
; CHECK: MustAlias: i8* %p.idx.maybeneg, i8* %p.idx.nneg
10+
define void @test(ptr %p, i64 %idx) {
11+
%p.minus.2 = getelementptr i8, ptr %p, i64 -2
12+
%p.plus.2 = getelementptr i8, ptr %p, i64 2
13+
%p.idx.maybeneg = getelementptr inbounds i8, ptr %p, i64 %idx
14+
%p.idx.nneg = getelementptr nuw nusw i8, ptr %p, i64 %idx
15+
load i8, ptr %p.minus.2
16+
load i8, ptr %p.plus.2
17+
load i8, ptr %p.idx.maybeneg
18+
load i8, ptr %p.idx.nneg
19+
ret void
20+
}

0 commit comments

Comments
 (0)