Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -733,10 +733,9 @@ ConstantInt *C2 = dyn_cast(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 @@ -759,12 +758,43 @@ IntermediateIndices.push_back(GEP1->getOperand(i + 1)); } - StructType *LastIndexedStruct = - dyn_cast(GetElementPtrInst::getIndexedType( - GEP1->getSourceElementType(), IntermediateIndices)); + auto *Ty = GetElementPtrInst::getIndexedType( + GEP1->getSourceElementType(), IntermediateIndices); + StructType *LastIndexedStruct = dyn_cast(Ty); - if (!LastIndexedStruct) + if (isa(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; Index: test/Analysis/BasicAA/sequential-gep.ll =================================================================== --- /dev/null +++ test/Analysis/BasicAA/sequential-gep.ll @@ -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 }