[llvm] r329692 - [DA] Improve alias checking in dependence analysis

David Green via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 10 04:37:21 PDT 2018


Author: dmgreen
Date: Tue Apr 10 04:37:21 2018
New Revision: 329692

URL: http://llvm.org/viewvc/llvm-project?rev=329692&view=rev
Log:
[DA] Improve alias checking in dependence analysis

Improve the alias analysis to account for cases where we
know that src/dst pairs cannot alias due to things like
TBAA. As we know they are noalias, we know no dependency
can occur. Also fixes issues around the size parameter
to AA being incorrect.

Differential Revision: https://reviews.llvm.org/D42381


Added:
    llvm/trunk/test/Analysis/DependenceAnalysis/AA.ll
Modified:
    llvm/trunk/lib/Analysis/DependenceAnalysis.cpp

Modified: llvm/trunk/lib/Analysis/DependenceAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/DependenceAnalysis.cpp?rev=329692&r1=329691&r2=329692&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/DependenceAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/DependenceAnalysis.cpp Tue Apr 10 04:37:21 2018
@@ -621,13 +621,38 @@ void Dependence::dump(raw_ostream &OS) c
   OS << "!\n";
 }
 
+// Returns NoAlias/MayAliass/MustAlias for two memory locations based upon their
+// underlaying objects. If LocA and LocB are known to not alias (for any reason:
+// tbaa, non-overlapping regions etc), then it is known there is no dependecy.
+// Otherwise the underlying objects are checked to see if they point to
+// different identifiable objects.
 static AliasResult underlyingObjectsAlias(AliasAnalysis *AA,
-                                          const DataLayout &DL, const Value *A,
-                                          const Value *B) {
-  const Value *AObj = GetUnderlyingObject(A, DL);
-  const Value *BObj = GetUnderlyingObject(B, DL);
-  return AA->alias(AObj, DL.getTypeStoreSize(AObj->getType()),
-                   BObj, DL.getTypeStoreSize(BObj->getType()));
+                                          const DataLayout &DL,
+                                          const MemoryLocation &LocA,
+                                          const MemoryLocation &LocB) {
+  // Check the original locations (minus size) for noalias, which can happen for
+  // tbaa, incompatible underlying object locations, etc.
+  MemoryLocation LocAS(LocA.Ptr, MemoryLocation::UnknownSize, LocA.AATags);
+  MemoryLocation LocBS(LocB.Ptr, MemoryLocation::UnknownSize, LocB.AATags);
+  if (AA->alias(LocAS, LocBS) == NoAlias)
+    return NoAlias;
+
+  // Check the underlying objects are the same
+  const Value *AObj = GetUnderlyingObject(LocA.Ptr, DL);
+  const Value *BObj = GetUnderlyingObject(LocB.Ptr, DL);
+
+  // If the underlying objects are the same, they must alias
+  if (AObj == BObj)
+    return MustAlias;
+
+  // We may have hit the recursion limit for underlying objects, or have
+  // underlying objects where we don't know they will alias.
+  if (!isIdentifiedObject(AObj) || !isIdentifiedObject(BObj))
+    return MayAlias;
+
+  // Otherwise we know the objects are different and both identified objects so
+  // must not alias.
+  return NoAlias;
 }
 
 
@@ -3298,8 +3323,9 @@ DependenceInfo::depends(Instruction *Src
   Value *SrcPtr = getLoadStorePointerOperand(Src);
   Value *DstPtr = getLoadStorePointerOperand(Dst);
 
-  switch (underlyingObjectsAlias(AA, F->getParent()->getDataLayout(), DstPtr,
-                                 SrcPtr)) {
+  switch (underlyingObjectsAlias(AA, F->getParent()->getDataLayout(),
+                                 MemoryLocation::get(Dst),
+                                 MemoryLocation::get(Src))) {
   case MayAlias:
   case PartialAlias:
     // cannot analyse objects if we don't understand their aliasing.
@@ -3715,8 +3741,9 @@ const SCEV *DependenceInfo::getSplitIter
   assert(isLoadOrStore(Dst));
   Value *SrcPtr = getLoadStorePointerOperand(Src);
   Value *DstPtr = getLoadStorePointerOperand(Dst);
-  assert(underlyingObjectsAlias(AA, F->getParent()->getDataLayout(), DstPtr,
-                                SrcPtr) == MustAlias);
+  assert(underlyingObjectsAlias(AA, F->getParent()->getDataLayout(),
+                                MemoryLocation::get(Dst),
+                                MemoryLocation::get(Src)) == MustAlias);
 
   // establish loop nesting levels
   establishNestingLevels(Src, Dst);

Added: llvm/trunk/test/Analysis/DependenceAnalysis/AA.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/DependenceAnalysis/AA.ll?rev=329692&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/DependenceAnalysis/AA.ll (added)
+++ llvm/trunk/test/Analysis/DependenceAnalysis/AA.ll Tue Apr 10 04:37:21 2018
@@ -0,0 +1,140 @@
+; RUN: opt < %s -analyze -basicaa -tbaa -da | FileCheck %s
+
+; CHECK-LABEL: 'Dependence Analysis' for function 'test_no_noalias'
+; CHECK: da analyze - none!
+; CHECK: da analyze - confused!
+; CHECK: da analyze - none!
+define void @test_no_noalias(i32* %A, i32* %B) {
+  store i32 1, i32* %A
+  store i32 2, i32* %B
+  ret void
+}
+
+; CHECK-LABEL: test_one_noalias
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+define void @test_one_noalias(i32* noalias %A, i32* %B) {
+  store i32 1, i32* %A
+  store i32 2, i32* %B
+  ret void
+}
+
+; CHECK-LABEL: test_two_noalias
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+define void @test_two_noalias(i32* noalias %A, i32* noalias %B) {
+  store i32 1, i32* %A
+  store i32 2, i32* %B
+  ret void
+}
+
+; CHECK-LABEL: test_global_alias
+; CHECK: da analyze - none!
+; CHECK: da analyze - confused!
+; CHECK: da analyze - none!
+ at g = global i32 5
+define void @test_global_alias(i32* %A) {
+  store i32 1, i32* %A
+  store i32 2, i32* @g
+  ret void
+}
+
+; CHECK-LABEL: test_global_noalias
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+define void @test_global_noalias(i32* noalias %A) {
+  store i32 1, i32* %A
+  store i32 2, i32* @g
+  ret void
+}
+
+; CHECK-LABEL: test_global_size
+; CHECK: da analyze - none!
+; CHECK: da analyze - confused!
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+; CHECK: da analyze - confused!
+; CHECK: da analyze - none!
+
+ at a = global i16 5, align 2
+ at b = global i16* @a, align 4
+define void @test_global_size() {
+  %l0 = load i16*, i16** @b, align 4
+  %l1 = load i16, i16* %l0, align 2
+  store i16 1, i16* @a, align 2
+  ret void
+}
+
+; CHECK-LABEL: test_tbaa_same
+; CHECK: da analyze - none!
+; CHECK: da analyze - confused!
+; CHECK: da analyze - none!
+define void @test_tbaa_same(i32* %A, i32* %B) {
+  store i32 1, i32* %A, !tbaa !5
+  store i32 2, i32* %B, !tbaa !5
+  ret void
+}
+
+; CHECK-LABEL: test_tbaa_diff
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+; CHECK: da analyze - none!
+define void @test_tbaa_diff(i32* %A, i16* %B) {
+  store i32 1, i32* %A, !tbaa !5
+  store i16 2, i16* %B, !tbaa !9
+  ret void
+}
+
+; CHECK-LABEL: tbaa_loop
+; CHECK: da analyze - input
+; CHECK: da analyze - none
+; CHECK: da analyze - output
+define void @tbaa_loop(i32 %I, i32 %J, i32* nocapture %A, i16* nocapture readonly %B) {
+entry:
+  %cmp = icmp ne i32 %J, 0
+  %cmp122 = icmp ne i32 %I, 0
+  %or.cond = and i1 %cmp, %cmp122
+  br i1 %or.cond, label %for.outer.preheader, label %for.end
+
+for.outer.preheader:
+  br label %for.outer
+
+for.outer:
+  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0, %for.outer.preheader ]
+  br label %for.inner
+
+for.inner:
+  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
+  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
+  %arrayidx.us = getelementptr inbounds i16, i16* %B, i32 %j.us
+  %0 = load i16, i16* %arrayidx.us, align 4, !tbaa !9
+  %sext = sext i16 %0 to i32
+  %add.us = add i32 %sext, %sum1.us
+  %inc.us = add nuw i32 %j.us, 1
+  %exitcond = icmp eq i32 %inc.us, %J
+  br i1 %exitcond, label %for.latch, label %for.inner
+
+for.latch:
+  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
+  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
+  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4, !tbaa !5
+  %add8.us = add nuw i32 %i.us, 1
+  %exitcond25 = icmp eq i32 %add8.us, %I
+  br i1 %exitcond25, label %for.end.loopexit, label %for.outer
+
+for.end.loopexit:
+  br label %for.end
+
+for.end:
+  ret void
+}
+
+!5 = !{!6, !6, i64 0}
+!6 = !{!"int", !7, i64 0}
+!7 = !{!"omnipotent char", !8, i64 0}
+!8 = !{!"Simple C/C++ TBAA"}
+!9 = !{!10, !10, i64 0}
+!10 = !{!"short", !7, i64 0}




More information about the llvm-commits mailing list