Support in AAEvaluator to print alias queries of loads/stores with TBAA tags.
authorManman Ren <mren@apple.com>
Fri, 22 Mar 2013 22:34:41 +0000 (22:34 +0000)
committerManman Ren <mren@apple.com>
Fri, 22 Mar 2013 22:34:41 +0000 (22:34 +0000)
Add "evaluate-tbaa" to print alias queries of loads/stores. Alias queries
between pointers do not include TBAA tags.

Add testing case for "placement new". TBAA currently says NoAlias.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177772 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/AliasAnalysisEvaluator.cpp
test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll [new file with mode: 0644]

index e58dde3d93bfa6ebae42cd6bb51cc73775fbcb81..a571463dfe127d47eafa83d0f8f6717c0b3cab65 100644 (file)
@@ -44,6 +44,8 @@ static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden);
 static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
 static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);
 
+static cl::opt<bool> EvalTBAA("evaluate-tbaa", cl::ReallyHidden);
+
 namespace {
   class AAEval : public FunctionPass {
     unsigned NoAlias, MayAlias, PartialAlias, MustAlias;
@@ -123,6 +125,15 @@ PrintModRefResults(const char *Msg, bool P, CallSite CSA, CallSite CSB,
   }
 }
 
+static inline void
+PrintLoadStoreResults(const char *Msg, bool P, const Value *V1,
+                      const Value *V2, const Module *M) {
+  if (P) {
+    errs() << "  " << Msg << ": " << *V1
+           << " <-> " << *V2 << '\n';
+  }
+}
+
 static inline bool isInterestingPointer(Value *V) {
   return V->getType()->isPointerTy()
       && !isa<ConstantPointerNull>(V);
@@ -133,6 +144,8 @@ bool AAEval::runOnFunction(Function &F) {
 
   SetVector<Value *> Pointers;
   SetVector<CallSite> CallSites;
+  SetVector<Value *> Loads;
+  SetVector<Value *> Stores;
 
   for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
     if (I->getType()->isPointerTy())    // Add all pointer arguments.
@@ -141,6 +154,10 @@ bool AAEval::runOnFunction(Function &F) {
   for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
     if (I->getType()->isPointerTy()) // Add all pointer instructions.
       Pointers.insert(&*I);
+    if (EvalTBAA && isa<LoadInst>(&*I))
+      Loads.insert(&*I);
+    if (EvalTBAA && isa<StoreInst>(&*I))
+      Stores.insert(&*I);
     Instruction &Inst = *I;
     if (CallSite CS = cast<Value>(&Inst)) {
       Value *Callee = CS.getCalledValue();
@@ -197,6 +214,61 @@ bool AAEval::runOnFunction(Function &F) {
     }
   }
 
+  if (EvalTBAA) {
+    // iterate over all pairs of load, store
+    for (SetVector<Value *>::iterator I1 = Loads.begin(), E = Loads.end();
+         I1 != E; ++I1) {
+      for (SetVector<Value *>::iterator I2 = Stores.begin(), E2 = Stores.end();
+           I2 != E2; ++I2) {
+        switch (AA.alias(AA.getLocation(cast<LoadInst>(*I1)),
+                         AA.getLocation(cast<StoreInst>(*I2)))) {
+        case AliasAnalysis::NoAlias:
+          PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
+                                F.getParent());
+          ++NoAlias; break;
+        case AliasAnalysis::MayAlias:
+          PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
+                                F.getParent());
+          ++MayAlias; break;
+        case AliasAnalysis::PartialAlias:
+          PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
+                                F.getParent());
+          ++PartialAlias; break;
+        case AliasAnalysis::MustAlias:
+          PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
+                                F.getParent());
+          ++MustAlias; break;
+        }
+      }
+    }
+
+    // iterate over all pairs of store, store
+    for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end();
+         I1 != E; ++I1) {
+      for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) {
+        switch (AA.alias(AA.getLocation(cast<StoreInst>(*I1)),
+                         AA.getLocation(cast<StoreInst>(*I2)))) {
+        case AliasAnalysis::NoAlias:
+          PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
+                                F.getParent());
+          ++NoAlias; break;
+        case AliasAnalysis::MayAlias:
+          PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
+                                F.getParent());
+          ++MayAlias; break;
+        case AliasAnalysis::PartialAlias:
+          PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
+                                F.getParent());
+          ++PartialAlias; break;
+        case AliasAnalysis::MustAlias:
+          PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
+                                F.getParent());
+          ++MustAlias; break;
+        }
+      }
+    }
+  }
+
   // Mod/ref alias analysis: compare all pairs of calls and values
   for (SetVector<CallSite>::iterator C = CallSites.begin(),
          Ce = CallSites.end(); C != Ce; ++C) {
diff --git a/test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll b/test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll
new file mode 100644 (file)
index 0000000..f1edb44
--- /dev/null
@@ -0,0 +1,104 @@
+; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-tbaa -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s
+
+; Generated with "clang -cc1 -disable-llvm-optzns -O1 -emit-llvm"
+; #include <new>
+; struct Foo { long i; };
+; struct Bar { void *p; };
+; long foo(int n) {
+;   Foo *f = new Foo;
+;   f->i = 1;
+;   for (int i=0; i<n; ++i) {
+;     Bar *b = new (f) Bar;
+;     b->p = 0;
+;     f = new (f) Foo;
+;     f->i = i;
+;   }
+;   return f->i;
+; }
+
+; Basic AA says MayAlias, TBAA says NoAlias
+; CHECK: MayAlias: i64* %i5, i8** %p
+; CHECK: NoAlias: store i64 %conv, i64* %i5, align 8, !tbaa !4 <->   store i8* null, i8** %p, align 8, !tbaa !3
+
+%struct.Foo = type { i64 }
+%struct.Bar = type { i8* }
+
+define i64 @_Z3fooi(i32 %n) #0 {
+entry:
+  %n.addr = alloca i32, align 4
+  %f = alloca %struct.Foo*, align 8
+  %i1 = alloca i32, align 4
+  %b = alloca %struct.Bar*, align 8
+  store i32 %n, i32* %n.addr, align 4, !tbaa !0
+  %call = call noalias i8* @_Znwm(i64 8)
+  %0 = bitcast i8* %call to %struct.Foo*
+  store %struct.Foo* %0, %struct.Foo** %f, align 8, !tbaa !3
+  %1 = load %struct.Foo** %f, align 8, !tbaa !3
+  %i = getelementptr inbounds %struct.Foo* %1, i32 0, i32 0
+  store i64 1, i64* %i, align 8, !tbaa !4
+  store i32 0, i32* %i1, align 4, !tbaa !0
+  br label %for.cond
+
+for.cond:
+  %2 = load i32* %i1, align 4, !tbaa !0
+  %3 = load i32* %n.addr, align 4, !tbaa !0
+  %cmp = icmp slt i32 %2, %3
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %4 = load %struct.Foo** %f, align 8, !tbaa !3
+  %5 = bitcast %struct.Foo* %4 to i8*
+  %new.isnull = icmp eq i8* %5, null
+  br i1 %new.isnull, label %new.cont, label %new.notnull
+
+new.notnull:
+  %6 = bitcast i8* %5 to %struct.Bar*
+  br label %new.cont
+
+new.cont:
+  %7 = phi %struct.Bar* [ %6, %new.notnull ], [ null, %for.body ]
+  store %struct.Bar* %7, %struct.Bar** %b, align 8, !tbaa !3
+  %8 = load %struct.Bar** %b, align 8, !tbaa !3
+  %p = getelementptr inbounds %struct.Bar* %8, i32 0, i32 0
+  store i8* null, i8** %p, align 8, !tbaa !3
+  %9 = load %struct.Foo** %f, align 8, !tbaa !3
+  %10 = bitcast %struct.Foo* %9 to i8*
+  %new.isnull2 = icmp eq i8* %10, null
+  br i1 %new.isnull2, label %new.cont4, label %new.notnull3
+
+new.notnull3:
+  %11 = bitcast i8* %10 to %struct.Foo*
+  br label %new.cont4
+
+new.cont4:
+  %12 = phi %struct.Foo* [ %11, %new.notnull3 ], [ null, %new.cont ]
+  store %struct.Foo* %12, %struct.Foo** %f, align 8, !tbaa !3
+  %13 = load i32* %i1, align 4, !tbaa !0
+  %conv = sext i32 %13 to i64
+  %14 = load %struct.Foo** %f, align 8, !tbaa !3
+  %i5 = getelementptr inbounds %struct.Foo* %14, i32 0, i32 0
+  store i64 %conv, i64* %i5, align 8, !tbaa !4
+  br label %for.inc
+
+for.inc:
+  %15 = load i32* %i1, align 4, !tbaa !0
+  %inc = add nsw i32 %15, 1
+  store i32 %inc, i32* %i1, align 4, !tbaa !0
+  br label %for.cond
+
+for.end:
+  %16 = load %struct.Foo** %f, align 8, !tbaa !3
+  %i6 = getelementptr inbounds %struct.Foo* %16, i32 0, i32 0
+  %17 = load i64* %i6, align 8, !tbaa !4
+  ret i64 %17
+}
+
+declare noalias i8* @_Znwm(i64)
+
+attributes #0 = { nounwind }
+
+!0 = metadata !{metadata !"int", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA"}
+!3 = metadata !{metadata !"any pointer", metadata !1}
+!4 = metadata !{metadata !"long", metadata !1}