[llvm-commits] [llvm] r52299 - /llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp

Chris Lattner sabre at nondot.org
Sun Jun 15 23:10:11 PDT 2008


Author: lattner
Date: Mon Jun 16 01:10:11 2008
New Revision: 52299

URL: http://llvm.org/viewvc/llvm-project?rev=52299&view=rev
Log:
Refactor basicaa's main alias function somethin' fierce.  
This fixes several minor bugs (such as returning noalias
for comparisons between external weak functions an null) but
is mostly a cleanup.


Modified:
    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp

Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=52299&r1=52298&r2=52299&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jun 16 01:10:11 2008
@@ -143,7 +143,7 @@
 /// a unique object or an argument, return it.  This returns:
 ///    Arguments, GlobalVariables, Functions, Allocas, Mallocs.
 static const Value *getUnderlyingObject(const Value *V) {
-  if (!isa<PointerType>(V->getType())) return 0;
+  if (!isa<PointerType>(V->getType())) return V;
 
   // If we are at some type of object, return it. GlobalValues and Allocations
   // have unique addresses. 
@@ -159,7 +159,7 @@
         CE->getOpcode() == Instruction::GetElementPtr)
       return getUnderlyingObject(CE->getOperand(0));
   }
-  return 0;
+  return V;
 }
 
 static const User *isGEP(const Value *V) {
@@ -193,9 +193,9 @@
 /// pointsToConstantMemory - Chase pointers until we find a (constant
 /// global) or not.
 bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) {
-  if (const Value *V = getUnderlyingObject(P))
-    if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
-      return GV->isConstant();
+  if (const GlobalVariable *GV = 
+        dyn_cast<GlobalVariable>(getUnderlyingObject(P)))
+    return GV->isConstant();
   return false;
 }
 
@@ -248,9 +248,19 @@
 BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
   if (!isa<Constant>(P)) {
     const Value *Object = getUnderlyingObject(P);
+    
+    // If this is a tail call and P points to a stack location, we know that
+    // the tail call cannot access or modify the local stack.
+    // We cannot exclude byval arguments here; these belong to the caller of
+    // the current function not to the current function, and a tail callee
+    // may reference them.
+    if (isa<AllocaInst>(Object))
+      if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction()))
+        if (CI->isTailCall())
+          return NoModRef;
+    
     // Allocations and byval arguments are "new" objects.
-    if (Object &&
-        (isa<AllocationInst>(Object) || isa<Argument>(Object))) {
+    if (isa<AllocationInst>(Object) || isa<Argument>(Object)) {
       // Okay, the pointer is to a stack allocated (or effectively so, for 
       // for noalias parameters) object.  If the address of this object doesn't
       // escape from this function body to a callee, then we know that no
@@ -263,23 +273,13 @@
           for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
               CI != CE; ++CI)
             if (isa<PointerType>((*CI)->getType()) &&
-                ( getUnderlyingObject(*CI) == P ||
-                  alias(cast<Value>(CI), ~0U, P, ~0U) != NoAlias) )
+                (getUnderlyingObject(*CI) == P ||
+                 alias(cast<Value>(CI), ~0U, P, ~0U) != NoAlias))
               passedAsArg = true;
           
           if (!passedAsArg)
             return NoModRef;
         }
-
-      // If this is a tail call and P points to a stack location, we know that
-      // the tail call cannot access or modify the local stack.
-      // We cannot exclude byval arguments here; these belong to the caller of
-      // the current function not to the current function, and a tail callee
-      // may reference them.
-      if (isa<AllocaInst>(Object))
-        if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction()))
-          if (CI->isTailCall())
-            return NoModRef;
     }
   }
 
@@ -287,6 +287,57 @@
   return AliasAnalysis::getModRefInfo(CS, P, Size);
 }
 
+/// isIdentifiedObject - Return true if this pointer refers to a distinct and
+/// identifiable object.  This returns true for:
+///    Global Variables and Functions
+///    Allocas and Mallocs
+///    ByVal and NoAlias Arguments
+///
+static bool isIdentifiedObject(const Value *V) {
+  if (isa<GlobalValue>(V) || isa<AllocationInst>(V))
+    return true;
+  if (const Argument *A = dyn_cast<Argument>(V))
+    return A->hasNoAliasAttr() || A->hasByValAttr();
+  return false;
+}
+
+/// isKnownNonNull - Return true if we know that the specified value is never
+/// null.
+static bool isKnownNonNull(const Value *V) {
+  // Alloca never returns null, malloc might.
+  if (isa<AllocaInst>(V)) return true;
+  
+  // A byval argument is never null.
+  if (const Argument *A = dyn_cast<Argument>(V))
+    return A->hasByValAttr();
+
+  // Global values are not null unless extern weak.
+  if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
+    return !GV->hasExternalWeakLinkage();
+  return false;
+}
+
+/// isObjectSmallerThan - Return true if we can prove that the object specified
+/// by V is smaller than Size.
+static bool isObjectSmallerThan(const Value *V, unsigned Size,
+                                const TargetData &TD) {
+  const Type *AccessTy = 0;
+  if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
+    AccessTy = GV->getType()->getElementType();
+  
+  if (const AllocationInst *AI = dyn_cast<AllocationInst>(V))
+    if (!AI->isArrayAllocation())
+      AccessTy = AI->getType()->getElementType();
+
+  if (const Argument *A = dyn_cast<Argument>(V))
+    if (A->hasByValAttr())
+      AccessTy = cast<PointerType>(A->getType())->getElementType();
+  
+  if (AccessTy && AccessTy->isSized())
+    return TD.getABITypeSize(AccessTy) < Size;
+  return false;
+}
+
 // alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such
 // as array references.  Note that this function is heavily tail recursive.
 // Hopefully we have a smart C++ compiler.  :)
@@ -319,92 +370,31 @@
   const Value *O1 = getUnderlyingObject(V1);
   const Value *O2 = getUnderlyingObject(V2);
 
-  // Pointing at a discernible object?
-  if (O1) {
-    if (O2) {
-      if (const Argument *O1Arg = dyn_cast<Argument>(O1)) {
-        // Incoming argument cannot alias locally allocated object!
-        if (isa<AllocationInst>(O2)) return NoAlias;
-        
-        // If they are two different objects, and one is a noalias argument
-        // then they do not alias.
-        if (O1 != O2 && O1Arg->hasNoAliasAttr())
-          return NoAlias;
-
-        // Byval arguments can't alias globals or other arguments.
-        if (O1 != O2 && O1Arg->hasByValAttr()) return NoAlias;
-        
-        // Otherwise, nothing is known...
-      } 
-      
-      if (const Argument *O2Arg = dyn_cast<Argument>(O2)) {
-        // Incoming argument cannot alias locally allocated object!
-        if (isa<AllocationInst>(O1)) return NoAlias;
-        
-        // If they are two different objects, and one is a noalias argument
-        // then they do not alias.
-        if (O1 != O2 && O2Arg->hasNoAliasAttr())
-          return NoAlias;
-          
-        // Byval arguments can't alias globals or other arguments.
-        if (O1 != O2 && O2Arg->hasByValAttr()) return NoAlias;
-        
-        // Otherwise, nothing is known...
-      
-      } else if (O1 != O2 && !isa<Argument>(O1)) {
-        // If they are two different objects, and neither is an argument,
-        // we know that we have no alias.
-        return NoAlias;
-      }
-
-      // If they are the same object, they we can look at the indexes.  If they
-      // index off of the object is the same for both pointers, they must alias.
-      // If they are provably different, they must not alias.  Otherwise, we
-      // can't tell anything.
-    }
-
-    // Unique values don't alias null, except non-byval arguments.
-    if (isa<ConstantPointerNull>(V2)) {
-      if (const Argument *O1Arg = dyn_cast<Argument>(O1)) {
-        if (O1Arg->hasByValAttr()) 
-          return NoAlias;
-      } else {
-        return NoAlias;                    
-      }
-    }
-
-    if (isa<GlobalVariable>(O1) ||
-        (isa<AllocationInst>(O1) &&
-         !cast<AllocationInst>(O1)->isArrayAllocation()))
-      if (cast<PointerType>(O1->getType())->getElementType()->isSized()) {
-        // If the size of the other access is larger than the total size of the
-        // global/alloca/malloc, it cannot be accessing the global (it's
-        // undefined to load or store bytes before or after an object).
-        const Type *ElTy = cast<PointerType>(O1->getType())->getElementType();
-        unsigned GlobalSize = getTargetData().getABITypeSize(ElTy);
-        if (GlobalSize < V2Size && V2Size != ~0U)
-          return NoAlias;
-      }
-  }
-
-  if (O2) {
-    if (!isa<Argument>(O2) && isa<ConstantPointerNull>(V1))
-      return NoAlias;                    // Unique values don't alias null
-
-    if (isa<GlobalVariable>(O2) ||
-        (isa<AllocationInst>(O2) &&
-         !cast<AllocationInst>(O2)->isArrayAllocation()))
-      if (cast<PointerType>(O2->getType())->getElementType()->isSized()) {
-        // If the size of the other access is larger than the total size of the
-        // global/alloca/malloc, it cannot be accessing the object (it's
-        // undefined to load or store bytes before or after an object).
-        const Type *ElTy = cast<PointerType>(O2->getType())->getElementType();
-        unsigned GlobalSize = getTargetData().getABITypeSize(ElTy);
-        if (GlobalSize < V1Size && V1Size != ~0U)
-          return NoAlias;
-      }
+  if (O1 != O2) {
+    // If V1/V2 point to two different objects we know that we have no alias.
+    if (isIdentifiedObject(O1) && isIdentifiedObject(O2))
+      return NoAlias;
+  
+    // Incoming argument cannot alias locally allocated object!
+    if ((isa<Argument>(O1) && isa<AllocationInst>(O2)) ||
+        (isa<Argument>(O2) && isa<AllocationInst>(O1)))
+      return NoAlias;
+    
+    // Most objects can't alias null.
+    if ((isa<ConstantPointerNull>(V2) && isKnownNonNull(O1)) ||
+        (isa<ConstantPointerNull>(V1) && isKnownNonNull(O2)))
+      return NoAlias;
   }
-
+  
+  // If the size of one access is larger than the entire object on the other
+  // side, then we know such behavior is undefined and can assume no alias.
+  const TargetData &TD = getTargetData();
+  if ((V1Size != ~0U && isObjectSmallerThan(O2, V1Size, TD)) ||
+      (V2Size != ~0U && isObjectSmallerThan(O1, V2Size, TD)))
+    return NoAlias;
+  
+  
+  
   // If we have two gep instructions with must-alias'ing base pointers, figure
   // out if the indexes to the GEP tell us anything about the derived pointer.
   // Note that we also handle chains of getelementptr instructions as well as





More information about the llvm-commits mailing list