[llvm-commits] [llvm] r107109 - in /llvm/trunk: include/llvm/Analysis/AliasAnalysis.h include/llvm/Analysis/Passes.h lib/Analysis/AliasAnalysis.cpp lib/Analysis/BasicAliasAnalysis.cpp test/Analysis/BasicAA/interprocedural.ll

Dan Gohman gohman at apple.com
Mon Jun 28 17:50:39 PDT 2010


Author: djg
Date: Mon Jun 28 19:50:39 2010
New Revision: 107109

URL: http://llvm.org/viewvc/llvm-project?rev=107109&view=rev
Log:
Add an Intraprocedural form of BasicAliasAnalysis, which aims to
properly handles instructions and arguments defined in different
functions, or across recursive function iterations.

Added:
    llvm/trunk/test/Analysis/BasicAA/interprocedural.ll
Modified:
    llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
    llvm/trunk/include/llvm/Analysis/Passes.h
    llvm/trunk/lib/Analysis/AliasAnalysis.cpp
    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp

Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=107109&r1=107108&r2=107109&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Mon Jun 28 19:50:39 2010
@@ -344,10 +344,10 @@
 /// identifiable object.  This returns true for:
 ///    Global Variables and Functions (but not Global Aliases)
 ///    Allocas and Mallocs
-///    ByVal and NoAlias Arguments
-///    NoAlias returns
+///    ByVal and NoAlias Arguments, if Interprocedural is false
+///    NoAlias returns, if Interprocedural is false
 ///
-bool isIdentifiedObject(const Value *V);
+bool isIdentifiedObject(const Value *V, bool Interprocedural = false);
 
 } // End llvm namespace
 

Modified: llvm/trunk/include/llvm/Analysis/Passes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Passes.h?rev=107109&r1=107108&r2=107109&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/Passes.h (original)
+++ llvm/trunk/include/llvm/Analysis/Passes.h Mon Jun 28 19:50:39 2010
@@ -73,6 +73,14 @@
 
   //===--------------------------------------------------------------------===//
   //
+  // createInterproceduralBasicAliasAnalysisPass - This pass is similar to
+  // baiscaa, except that it properly supports queries to values which live
+  // in different functions.
+  //
+  ImmutablePass *createInterproceduralBasicAliasAnalysisPass();
+
+  //===--------------------------------------------------------------------===//
+  //
   /// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows
   /// about the semantics of a set of libcalls specified by LCI.  The newly
   /// constructed pass takes ownership of the pointer that is provided.

Modified: llvm/trunk/lib/Analysis/AliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=107109&r1=107108&r2=107109&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/AliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/AliasAnalysis.cpp Mon Jun 28 19:50:39 2010
@@ -229,16 +229,20 @@
 /// identifiable object.  This returns true for:
 ///    Global Variables and Functions (but not Global Aliases)
 ///    Allocas and Mallocs
-///    ByVal and NoAlias Arguments
-///    NoAlias returns
+///    ByVal and NoAlias Arguments, if Interprocedural is false
+///    NoAlias returns, if Interprocedural is false
 ///
-bool llvm::isIdentifiedObject(const Value *V) {
-  if (isa<AllocaInst>(V) || isNoAliasCall(V))
+bool llvm::isIdentifiedObject(const Value *V, bool Interprocedural) {
+  if (isa<AllocaInst>(V))
     return true;
   if (isa<GlobalValue>(V) && !isa<GlobalAlias>(V))
     return true;
-  if (const Argument *A = dyn_cast<Argument>(V))
-    return A->hasNoAliasAttr() || A->hasByValAttr();
+  if (!Interprocedural) {
+    if (isNoAliasCall(V))
+      return true;
+    if (const Argument *A = dyn_cast<Argument>(V))
+      return A->hasNoAliasAttr() || A->hasByValAttr();
+  }
   return false;
 }
 

Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=107109&r1=107108&r2=107109&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jun 28 19:50:39 2010
@@ -55,9 +55,10 @@
 
 /// isNonEscapingLocalObject - Return true if the pointer is to a function-local
 /// object that never escapes from the function.
-static bool isNonEscapingLocalObject(const Value *V) {
+static bool isNonEscapingLocalObject(const Value *V, bool Interprocedural) {
   // If this is a local allocation, check to see if it escapes.
-  if (isa<AllocaInst>(V) || isNoAliasCall(V))
+  if (isa<AllocaInst>(V) ||
+      (!Interprocedural && isNoAliasCall(V)))
     // Set StoreCaptures to True so that we can assume in our callers that the
     // pointer is not the result of a load instruction. Currently
     // PointerMayBeCaptured doesn't have any special analysis for the
@@ -68,16 +69,32 @@
   // If this is an argument that corresponds to a byval or noalias argument,
   // then it has not escaped before entering the function.  Check if it escapes
   // inside the function.
-  if (const Argument *A = dyn_cast<Argument>(V))
-    if (A->hasByValAttr() || A->hasNoAliasAttr()) {
-      // Don't bother analyzing arguments already known not to escape.
-      if (A->hasNoCaptureAttr())
-        return true;
-      return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
-    }
+  if (!Interprocedural)
+    if (const Argument *A = dyn_cast<Argument>(V))
+      if (A->hasByValAttr() || A->hasNoAliasAttr()) {
+        // Don't bother analyzing arguments already known not to escape.
+        if (A->hasNoCaptureAttr())
+          return true;
+        return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
+      }
   return false;
 }
 
+/// isEscapeSource - Return true if the pointer is one which would have
+/// been considered an escape by isNonEscapingLocalObject.
+static bool isEscapeSource(const Value *V, bool Interprocedural) {
+  if (!Interprocedural)
+    if (isa<CallInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V))
+      return true;
+
+  // The load case works because isNonEscapingLocalObject considers all
+  // stores to be escapes (it passes true for the StoreCaptures argument
+  // to PointerMayBeCaptured).
+  if (isa<LoadInst>(V))
+    return true;
+
+  return false;
+}
 
 /// isObjectSmallerThan - Return true if we can prove that the object specified
 /// by V is smaller than Size.
@@ -177,19 +194,51 @@
 ImmutablePass *llvm::createNoAAPass() { return new NoAA(); }
 
 //===----------------------------------------------------------------------===//
-// BasicAA Pass
+// BasicAliasAnalysis Pass
 //===----------------------------------------------------------------------===//
 
+static const Function *getParent(const Value *V) {
+  if(const Instruction *inst = dyn_cast<Instruction>(V))
+    return inst->getParent()->getParent();
+
+  if(const Argument *arg = dyn_cast<Argument>(V))
+    return arg->getParent();
+
+  return NULL;
+}
+
+static bool sameParent(const Value *O1, const Value *O2) {
+
+  const Function *F1 = getParent(O1);
+  const Function *F2 = getParent(O2);
+
+  return !F1 || !F2 || F1 == F2;
+}
+
 namespace {
   /// BasicAliasAnalysis - This is the default alias analysis implementation.
   /// Because it doesn't chain to a previous alias analysis (like -no-aa), it
   /// derives from the NoAA class.
   struct BasicAliasAnalysis : public NoAA {
+    /// Interprocedural - Flag for "interprocedural" mode, where we must
+    /// support queries of values which live in different functions.
+    bool Interprocedural;
+
     static char ID; // Class identification, replacement for typeinfo
-    BasicAliasAnalysis() : NoAA(&ID) {}
+    BasicAliasAnalysis()
+      : NoAA(&ID), Interprocedural(false) {}
+    BasicAliasAnalysis(void *PID, bool interprocedural)
+      : NoAA(PID), Interprocedural(interprocedural) {}
+
     AliasResult alias(const Value *V1, unsigned V1Size,
                       const Value *V2, unsigned V2Size) {
       assert(Visited.empty() && "Visited must be cleared after use!");
+#ifdef XDEBUG
+      assert((Interprocedural || sameParent(V1, V2)) &&
+             "BasicAliasAnalysis (-basicaa) doesn't support interprocedural "
+             "queries; use InterproceduralAliasAnalysis "
+             "(-interprocedural-basic-aa) instead.");
+#endif
       AliasResult Alias = aliasCheck(V1, V1Size, V2, V2Size);
       Visited.clear();
       return Alias;
@@ -284,7 +333,7 @@
   // then the call can not mod/ref the pointer unless the call takes the pointer
   // as an argument, and itself doesn't capture it.
   if (!isa<Constant>(Object) && CS.getInstruction() != Object &&
-      isNonEscapingLocalObject(Object)) {
+      isNonEscapingLocalObject(Object, Interprocedural)) {
     bool PassedAsArg = false;
     unsigned ArgNo = 0;
     for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
@@ -705,18 +754,25 @@
 
   if (O1 != O2) {
     // If V1/V2 point to two different objects we know that we have no alias.
-    if (isIdentifiedObject(O1) && isIdentifiedObject(O2))
+    if (isIdentifiedObject(O1, Interprocedural) &&
+        isIdentifiedObject(O2, Interprocedural))
       return NoAlias;
 
     // Constant pointers can't alias with non-const isIdentifiedObject objects.
-    if ((isa<Constant>(O1) && isIdentifiedObject(O2) && !isa<Constant>(O2)) ||
-        (isa<Constant>(O2) && isIdentifiedObject(O1) && !isa<Constant>(O1)))
+    if ((isa<Constant>(O1) &&
+         isIdentifiedObject(O2, Interprocedural) &&
+         !isa<Constant>(O2)) ||
+        (isa<Constant>(O2) &&
+         isIdentifiedObject(O1, Interprocedural) &&
+         !isa<Constant>(O1)))
       return NoAlias;
 
-    // Arguments can't alias with local allocations or noalias calls.
-    if ((isa<Argument>(O1) && (isa<AllocaInst>(O2) || isNoAliasCall(O2))) ||
-        (isa<Argument>(O2) && (isa<AllocaInst>(O1) || isNoAliasCall(O1))))
-      return NoAlias;
+    // Arguments can't alias with local allocations or noalias calls, unless
+    // we have to consider interprocedural aliasing.
+    if (!Interprocedural)
+      if ((isa<Argument>(O1) && (isa<AllocaInst>(O2) || isNoAliasCall(O2))) ||
+          (isa<Argument>(O2) && (isa<AllocaInst>(O1) || isNoAliasCall(O1))))
+        return NoAlias;
 
     // Most objects can't alias null.
     if ((isa<ConstantPointerNull>(V2) && isKnownNonNull(O1)) ||
@@ -733,17 +789,13 @@
   
   // If one pointer is the result of a call/invoke or load and the other is a
   // non-escaping local object, then we know the object couldn't escape to a
-  // point where the call could return it. The load case works because
-  // isNonEscapingLocalObject considers all stores to be escapes (it
-  // passes true for the StoreCaptures argument to PointerMayBeCaptured).
+  // point where the call could return it.
   if (O1 != O2) {
-    if ((isa<CallInst>(O1) || isa<InvokeInst>(O1) || isa<LoadInst>(O1) ||
-         isa<Argument>(O1)) &&
-        isNonEscapingLocalObject(O2))
+    if (isEscapeSource(O1, Interprocedural) &&
+        isNonEscapingLocalObject(O2, Interprocedural))
       return NoAlias;
-    if ((isa<CallInst>(O2) || isa<InvokeInst>(O2) || isa<LoadInst>(O2) ||
-         isa<Argument>(O2)) &&
-        isNonEscapingLocalObject(O1))
+    if (isEscapeSource(O2, Interprocedural) &&
+        isNonEscapingLocalObject(O1, Interprocedural))
       return NoAlias;
   }
 
@@ -776,3 +828,33 @@
 
 // Make sure that anything that uses AliasAnalysis pulls in this file.
 DEFINING_FILE_FOR(BasicAliasAnalysis)
+
+//===----------------------------------------------------------------------===//
+// InterproceduralBasicAliasAnalysis Pass
+//===----------------------------------------------------------------------===//
+
+namespace {
+  /// InterproceduralBasicAliasAnalysis - This is similar to basicaa, except
+  /// that it properly supports queries to values which live in different
+  /// functions.
+  ///
+  /// Note that we don't currently take this to the extreme, analyzing all
+  /// call sites of a function to answer a query about an Argument.
+  ///
+  struct InterproceduralBasicAliasAnalysis : public BasicAliasAnalysis {
+    static char ID; // Class identification, replacement for typeinfo
+    InterproceduralBasicAliasAnalysis() : BasicAliasAnalysis(&ID, true) {}
+  };
+}
+
+// Register this pass...
+char InterproceduralBasicAliasAnalysis::ID = 0;
+static RegisterPass<InterproceduralBasicAliasAnalysis>
+W("interprocedural-basic-aa", "Interprocedural Basic Alias Analysis", false, true);
+
+// Declare that we implement the AliasAnalysis interface
+static RegisterAnalysisGroup<AliasAnalysis> Z(W);
+
+ImmutablePass *llvm::createInterproceduralBasicAliasAnalysisPass() {
+  return new InterproceduralBasicAliasAnalysis();
+}

Added: llvm/trunk/test/Analysis/BasicAA/interprocedural.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/interprocedural.ll?rev=107109&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/BasicAA/interprocedural.ll (added)
+++ llvm/trunk/test/Analysis/BasicAA/interprocedural.ll Mon Jun 28 19:50:39 2010
@@ -0,0 +1,42 @@
+; RUN: opt -interprocedural-basic-aa  -interprocedural-aa-eval -print-all-alias-modref-info -disable-output < %s |& FileCheck %s
+
+; The noalias attribute is not safe in an interprocedural context.
+; CHECK: MayAlias: i8* %p, i8* %q
+
+define void @t0(i8* noalias %p) {
+  store i8 0, i8* %p
+  ret void
+}
+define void @t1(i8* noalias %q) {
+  store i8 0, i8* %q
+  ret void
+}
+
+; An alloca can alias an argument in a different function.
+; CHECK: MayAlias: i32* %r, i32* %s
+
+define void @s0(i32* %r) {
+  store i32 0, i32* %r
+  ret void
+}
+
+define void @s1() {
+  %s = alloca i32, i32 10
+  store i32 0, i32* %s
+  call void @s0(i32* %s)
+  ret void
+}
+
+; An alloca can alias an argument in a recursive function.
+; CHECK: MayAlias: i64* %t, i64* %u
+; CHECK: MayAlias: i64* %u, i64* %v
+; CHECK: MayAlias: i64* %t, i64* %v
+
+define i64* @r0(i64* %u) {
+  %t = alloca i64, i32 10
+  %v = call i64* @r0(i64* %t)
+  store i64 0, i64* %t
+  store i64 0, i64* %u
+  store i64 0, i64* %v
+  ret i64* %t
+}





More information about the llvm-commits mailing list