Skip to content

Commit 5a4d8cd

Browse files
author
James Molloy
committed
[BasicAA] Non-equal indices in a GEP of a SequentialType don't overlap
If the final indices of two GEPs can be proven to not be equal, and the GEP is of a SequentialType (not a StructType), then the two GEPs do not alias. llvm-svn: 251016
1 parent d8336f3 commit 5a4d8cd

File tree

2 files changed

+81
-8
lines changed

2 files changed

+81
-8
lines changed

llvm/lib/Analysis/BasicAliasAnalysis.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -776,10 +776,9 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
776776
ConstantInt *C2 =
777777
dyn_cast<ConstantInt>(GEP2->getOperand(GEP2->getNumOperands() - 1));
778778

779-
// If the last (struct) indices aren't constants, we can't say anything.
780-
// If they're identical, the other indices might be also be dynamically
781-
// equal, so the GEPs can alias.
782-
if (!C1 || !C2 || C1 == C2)
779+
// If the last (struct) indices are constants and are equal, the other indices
780+
// might be also be dynamically equal, so the GEPs can alias.
781+
if (C1 && C2 && C1 == C2)
783782
return MayAlias;
784783

785784
// Find the last-indexed type of the GEP, i.e., the type you'd get if
@@ -802,12 +801,43 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
802801
IntermediateIndices.push_back(GEP1->getOperand(i + 1));
803802
}
804803

805-
StructType *LastIndexedStruct =
806-
dyn_cast<StructType>(GetElementPtrInst::getIndexedType(
807-
GEP1->getSourceElementType(), IntermediateIndices));
804+
auto *Ty = GetElementPtrInst::getIndexedType(
805+
GEP1->getSourceElementType(), IntermediateIndices);
806+
StructType *LastIndexedStruct = dyn_cast<StructType>(Ty);
808807

809-
if (!LastIndexedStruct)
808+
if (isa<SequentialType>(Ty)) {
809+
// We know that:
810+
// - both GEPs begin indexing from the exact same pointer;
811+
// - the last indices in both GEPs are constants, indexing into a sequential
812+
// type (array or pointer);
813+
// - both GEPs only index through arrays prior to that.
814+
//
815+
// Because array indices greater than the number of elements are valid in
816+
// GEPs, unless we know the intermediate indices are identical between
817+
// GEP1 and GEP2 we cannot guarantee that the last indexed arrays don't
818+
// partially overlap.
819+
for (unsigned i = 0, e = GEP1->getNumIndices() - 1; i != e; ++i)
820+
if (GEP1->getOperand(i + 1) != GEP2->getOperand(i + 1))
821+
return MayAlias;
822+
823+
// Now we know that the array/pointer that GEP1 indexes into and that
824+
// that GEP2 indexes into must either precisely overlap or be disjoint.
825+
// Because they cannot partially overlap and because fields in an array
826+
// cannot overlap, if we can prove the final indices are different between
827+
// GEP1 and GEP2, we can conclude GEP1 and GEP2 don't alias.
828+
829+
// If the last indices are constants, we've already checked they don't
830+
// equal each other so we can exit early.
831+
if (C1 && C2)
832+
return NoAlias;
833+
if (isKnownNonEqual(GEP1->getOperand(GEP1->getNumOperands() - 1),
834+
GEP2->getOperand(GEP2->getNumOperands() - 1),
835+
DL))
836+
return NoAlias;
837+
return MayAlias;
838+
} else if (!LastIndexedStruct || !C1 || !C2) {
810839
return MayAlias;
840+
}
811841

812842
// We know that:
813843
// - both GEPs begin indexing from the exact same pointer;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
2+
3+
; CHECK: Function: t1
4+
; CHECK: NoAlias: i32* %gep1, i32* %gep2
5+
define void @t1([8 x i32]* %p, i32 %addend, i32* %q) {
6+
%knownnonzero = load i32, i32* %q, !range !0
7+
%add = add nsw nuw i32 %addend, %knownnonzero
8+
%gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %addend
9+
%gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %add
10+
ret void
11+
}
12+
13+
; CHECK: Function: t2
14+
; CHECK: PartialAlias: i32* %gep1, i32* %gep2
15+
define void @t2([8 x i32]* %p, i32 %addend, i32* %q) {
16+
%knownnonzero = load i32, i32* %q, !range !0
17+
%add = add nsw nuw i32 %addend, %knownnonzero
18+
%gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend
19+
%gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
20+
ret void
21+
}
22+
23+
; CHECK: Function: t3
24+
; CHECK: MustAlias: i32* %gep1, i32* %gep2
25+
define void @t3([8 x i32]* %p, i32 %addend, i32* %q) {
26+
%knownnonzero = load i32, i32* %q, !range !0
27+
%add = add nsw nuw i32 %addend, %knownnonzero
28+
%gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
29+
%gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
30+
ret void
31+
}
32+
33+
; CHECK: Function: t4
34+
; CHECK: PartialAlias: i32* %gep1, i32* %gep2
35+
define void @t4([8 x i32]* %p, i32 %addend, i32* %q) {
36+
%knownnonzero = load i32, i32* %q, !range !0
37+
%add = add nsw nuw i32 %addend, %knownnonzero
38+
%gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend
39+
%gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 %add, i32 %add
40+
ret void
41+
}
42+
43+
!0 = !{ i32 1, i32 5 }

0 commit comments

Comments
 (0)