diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1560,6 +1560,45 @@ if (isEscapeSource(O2) && AAQI.CI->isNotCapturedBeforeOrAt(O1, cast(O2))) return AliasResult::NoAlias; + } else { + // In case the underlying object is a pointer to a structure and the GEP + // operators refer two different fields of it. + // Let's return NoAlias only when there is no doubt about it. + if (const PointerType *PtrTy = dyn_cast(O1->getType())) { + if (!(PtrTy->isOpaque())) { + if (PtrTy->getElementType()->isStructTy()) { + const GEPOperator *GEP1 = dyn_cast(V1); + const GEPOperator *GEP2 = dyn_cast(V2); + if (GEP1 && GEP2) { + if ((GEP1->hasIndices() && GEP2->hasIndices()) && + ((GEP1->getNumIndices() <= 3U) && + (GEP2->getNumIndices() <= 3U))) { + const auto &Ids1 = GEP1->idx_begin(); + const auto &Ids2 = GEP2->idx_begin(); + for (int i = 0; i < 2; i++) { + const ConstantInt *Idx1 = dyn_cast(Ids1[i]); + const ConstantInt *Idx2 = dyn_cast(Ids2[i]); + if (Idx1 && Idx2) { + int64_t id1 = Idx1->getSExtValue(); + int64_t id2 = Idx2->getSExtValue(); + switch (i) { + case 0: // Make sure it is 'the same' struct + if (id1 == id2) + continue; + break; + case 1: // Make sure it is different field of the same struct + if (id1 != id2) // It is not: no alias possible! + return AliasResult::NoAlias; + break; + } + } + break; // We can't continue analyzing that... + } + } + } + } + } + } } // If the size of one access is larger than the entire object on the other diff --git a/llvm/test/Transforms/LoopVectorize/global_alias.ll b/llvm/test/Transforms/LoopVectorize/global_alias.ll --- a/llvm/test/Transforms/LoopVectorize/global_alias.ll +++ b/llvm/test/Transforms/LoopVectorize/global_alias.ll @@ -769,7 +769,7 @@ ;; === Now, the tests that we could vectorize with induction changes or run-time checks === -; /// Different objects, swapped induction, alias at the end +; /// Different objects, swapped induction, assuming no alias ; int mayAlias01 (int a) { ; int i; ; for (i=0; i +; CHECK: add nsw <4 x i32> ; CHECK: ret define i32 @mayAlias01(i32 %a) nounwind { @@ -819,7 +819,7 @@ ret i32 %7 } -; /// Different objects, swapped induction, alias at the beginning +; /// Different objects, swapped induction, assuming no alias ; int mayAlias02 (int a) { ; int i; ; for (i=0; i +; CHECK: add nsw <4 x i32> ; CHECK: ret define i32 @mayAlias02(i32 %a) nounwind { @@ -934,7 +934,7 @@ ; return Foo.A[a]; ; } ; CHECK-LABEL: define i32 @mustAlias01( -; CHECK-NOT: add nsw <4 x i32> +; CHECK: add nsw <4 x i32> ; CHECK: ret define i32 @mustAlias01(i32 %a) nounwind { @@ -984,7 +984,7 @@ ; return Foo.A[a]; ; } ; CHECK-LABEL: define i32 @mustAlias02( -; CHECK-NOT: add nsw <4 x i32> +; CHECK: add nsw <4 x i32> ; CHECK: ret define i32 @mustAlias02(i32 %a) nounwind { @@ -1033,7 +1033,7 @@ ; return Foo.A[a]; ; } ; CHECK-LABEL: define i32 @mustAlias03( -; CHECK-NOT: add nsw <4 x i32> +; CHECK: add nsw <4 x i32> ; CHECK: ret define i32 @mustAlias03(i32 %a) nounwind {