[llvm] r251016 - [BasicAA] Non-equal indices in a GEP of a SequentialType don't overlap

James Molloy via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 22 06:28:19 PDT 2015


Author: jamesm
Date: Thu Oct 22 08:28:18 2015
New Revision: 251016

URL: http://llvm.org/viewvc/llvm-project?rev=251016&view=rev
Log:
[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.

Added:
    llvm/trunk/test/Analysis/BasicAA/sequential-gep.ll
Modified:
    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp

Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=251016&r1=251015&r2=251016&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Thu Oct 22 08:28:18 2015
@@ -776,10 +776,9 @@ static AliasResult aliasSameBasePointerG
   ConstantInt *C2 =
       dyn_cast<ConstantInt>(GEP2->getOperand(GEP2->getNumOperands() - 1));
 
-  // If the last (struct) indices aren't constants, we can't say anything.
-  // If they're identical, the other indices might be also be dynamically
-  // equal, so the GEPs can alias.
-  if (!C1 || !C2 || C1 == C2)
+  // If the last (struct) indices are constants and are equal, the other indices
+  // might be also be dynamically equal, so the GEPs can alias.
+  if (C1 && C2 && C1 == C2)
     return MayAlias;
 
   // Find the last-indexed type of the GEP, i.e., the type you'd get if
@@ -802,12 +801,43 @@ static AliasResult aliasSameBasePointerG
     IntermediateIndices.push_back(GEP1->getOperand(i + 1));
   }
 
-  StructType *LastIndexedStruct =
-      dyn_cast<StructType>(GetElementPtrInst::getIndexedType(
-          GEP1->getSourceElementType(), IntermediateIndices));
-
-  if (!LastIndexedStruct)
+  auto *Ty = GetElementPtrInst::getIndexedType(
+    GEP1->getSourceElementType(), IntermediateIndices);
+  StructType *LastIndexedStruct = dyn_cast<StructType>(Ty);
+
+  if (isa<SequentialType>(Ty)) {
+    // We know that:
+    // - both GEPs begin indexing from the exact same pointer;
+    // - the last indices in both GEPs are constants, indexing into a sequential
+    //   type (array or pointer);
+    // - both GEPs only index through arrays prior to that.
+    //
+    // Because array indices greater than the number of elements are valid in
+    // GEPs, unless we know the intermediate indices are identical between
+    // GEP1 and GEP2 we cannot guarantee that the last indexed arrays don't
+    // partially overlap.
+    for (unsigned i = 0, e = GEP1->getNumIndices() - 1; i != e; ++i)
+      if (GEP1->getOperand(i + 1) != GEP2->getOperand(i + 1))
+        return MayAlias;
+    
+    // Now we know that the array/pointer that GEP1 indexes into and that
+    // that GEP2 indexes into must either precisely overlap or be disjoint.
+    // Because they cannot partially overlap and because fields in an array
+    // cannot overlap, if we can prove the final indices are different between
+    // GEP1 and GEP2, we can conclude GEP1 and GEP2 don't alias.
+    
+    // If the last indices are constants, we've already checked they don't
+    // equal each other so we can exit early.
+    if (C1 && C2)
+      return NoAlias;
+    if (isKnownNonEqual(GEP1->getOperand(GEP1->getNumOperands() - 1),
+                        GEP2->getOperand(GEP2->getNumOperands() - 1),
+                        DL))
+      return NoAlias;
+    return MayAlias;
+  } else if (!LastIndexedStruct || !C1 || !C2) {
     return MayAlias;
+  }
 
   // We know that:
   // - both GEPs begin indexing from the exact same pointer;

Added: llvm/trunk/test/Analysis/BasicAA/sequential-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/sequential-gep.ll?rev=251016&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/BasicAA/sequential-gep.ll (added)
+++ llvm/trunk/test/Analysis/BasicAA/sequential-gep.ll Thu Oct 22 08:28:18 2015
@@ -0,0 +1,43 @@
+; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; CHECK: Function: t1
+; CHECK: NoAlias: i32* %gep1, i32* %gep2
+define void @t1([8 x i32]* %p, i32 %addend, i32* %q) {
+  %knownnonzero = load i32, i32* %q, !range !0
+  %add = add nsw nuw i32 %addend, %knownnonzero
+  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %addend
+  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %add
+  ret void
+}
+
+; CHECK: Function: t2
+; CHECK: PartialAlias: i32* %gep1, i32* %gep2
+define void @t2([8 x i32]* %p, i32 %addend, i32* %q) {
+  %knownnonzero = load i32, i32* %q, !range !0
+  %add = add nsw nuw i32 %addend, %knownnonzero
+  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend
+  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
+  ret void
+}
+
+; CHECK: Function: t3
+; CHECK: MustAlias: i32* %gep1, i32* %gep2
+define void @t3([8 x i32]* %p, i32 %addend, i32* %q) {
+  %knownnonzero = load i32, i32* %q, !range !0
+  %add = add nsw nuw i32 %addend, %knownnonzero
+  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
+  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
+  ret void
+}
+
+; CHECK: Function: t4
+; CHECK: PartialAlias: i32* %gep1, i32* %gep2
+define void @t4([8 x i32]* %p, i32 %addend, i32* %q) {
+  %knownnonzero = load i32, i32* %q, !range !0
+  %add = add nsw nuw i32 %addend, %knownnonzero
+  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend
+  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 %add, i32 %add
+  ret void
+}
+
+!0 = !{ i32 1, i32 5 }




More information about the llvm-commits mailing list