[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

Nick Lewycky nicholas at mxc.ca
Mon Jun 28 22:22:31 PDT 2010


Dan Gohman wrote:
> 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.

Dan,

Why is this an additional pass? Why not infer Interprocedural from 
SameParent()? The idempotents that basicaa was testing for should still 
hold true whenever SameParent() is true. It looks like the 
'Interprocedural BasicAA' is basically a bugfix on BasicAA.

> 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 ("

> +
> +  if(const Argument *arg = dyn_cast<Argument>(V))
> +    return arg->getParent();

"if ("

Nick

> +
> +  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
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>




More information about the llvm-commits mailing list