Implement value #'ing for vector operations, implementing
[oota-llvm.git] / lib / Analysis / BasicAliasAnalysis.cpp
index 0b80e926301a8cce0cc6ddc251b147fae5c4b9f8..2a37ab87fa4ae8c306acbf4043ec8521d822e47f 100644 (file)
@@ -527,6 +527,14 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
   // chain.  For example:
   //        A[i][0] != A[j][1] iff (&A[0][1]-&A[0][0] >= std::max(G1S, G2S))
   //
+  // We have to be careful here about array accesses.  In particular, consider:
+  //        A[1][0] vs A[0][i]
+  // In this case, we don't *know* that the array will be accessed in bounds:
+  // the index could even be negative.  Because of this, we have to
+  // conservatively *give up* and return may alias.  We disregard differing
+  // array subscripts that are followed by a variable index without going
+  // through a struct.
+  //
   unsigned SizeMax = std::max(G1S, G2S);
   if (SizeMax == ~0U) return MayAlias; // Avoid frivolous work.
 
@@ -547,15 +555,36 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
             GEP1Ops[FirstConstantOper] = G1OC;
             GEP2Ops[FirstConstantOper] = G2OC;
           }
-
+          
           if (G1OC != G2OC) {
+            // Handle the "be careful" case above: if this is an array
+            // subscript, scan for a subsequent variable array index.
+            if (isa<ArrayType>(BasePtr1Ty))  {
+              const Type *NextTy =cast<ArrayType>(BasePtr1Ty)->getElementType();
+              bool isBadCase = false;
+              
+              for (unsigned Idx = FirstConstantOper+1;
+                   Idx != MinOperands && isa<ArrayType>(NextTy); ++Idx) {
+                const Value *V1 = GEP1Ops[Idx], *V2 = GEP2Ops[Idx];
+                if (!isa<Constant>(V1) || !isa<Constant>(V2)) {
+                  isBadCase = true;
+                  break;
+                }
+                NextTy = cast<ArrayType>(NextTy)->getElementType();
+              }
+              
+              if (isBadCase) G1OC = 0;
+            }
+
             // Make sure they are comparable (ie, not constant expressions), and
             // make sure the GEP with the smaller leading constant is GEP1.
-            Constant *Compare = ConstantExpr::getSetGT(G1OC, G2OC);
-            if (ConstantBool *CV = dyn_cast<ConstantBool>(Compare)) {
-              if (CV->getValue())   // If they are comparable and G2 > G1
-                std::swap(GEP1Ops, GEP2Ops);  // Make GEP1 < GEP2
-              break;
+            if (G1OC) {
+              Constant *Compare = ConstantExpr::getSetGT(G1OC, G2OC);
+              if (ConstantBool *CV = dyn_cast<ConstantBool>(Compare)) {
+                if (CV->getValue())   // If they are comparable and G2 > G1
+                  std::swap(GEP1Ops, GEP2Ops);  // Make GEP1 < GEP2
+                break;
+              }
             }
           }
         }
@@ -608,17 +637,24 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
   // than the first constant index of GEP2.
 
   // Advance BasePtr[12]Ty over this first differing constant operand.
-  BasePtr2Ty = cast<CompositeType>(BasePtr1Ty)->getTypeAtIndex(GEP2Ops[FirstConstantOper]);
-  BasePtr1Ty = cast<CompositeType>(BasePtr1Ty)->getTypeAtIndex(GEP1Ops[FirstConstantOper]);
+  BasePtr2Ty = cast<CompositeType>(BasePtr1Ty)->
+      getTypeAtIndex(GEP2Ops[FirstConstantOper]);
+  BasePtr1Ty = cast<CompositeType>(BasePtr1Ty)->
+      getTypeAtIndex(GEP1Ops[FirstConstantOper]);
 
   // We are going to be using TargetData::getIndexedOffset to determine the
   // offset that each of the GEP's is reaching.  To do this, we have to convert
   // all variable references to constant references.  To do this, we convert the
-  // initial equal sequence of variables into constant zeros to start with.
-  for (unsigned i = 0; i != FirstConstantOper; ++i)
-    if (!isa<ConstantInt>(GEP1Ops[i]) || !isa<ConstantInt>(GEP2Ops[i]))
+  // initial sequence of array subscripts into constant zeros to start with.
+  const Type *ZeroIdxTy = GEPPointerTy;
+  for (unsigned i = 0; i != FirstConstantOper; ++i) {
+    if (!isa<StructType>(ZeroIdxTy))
       GEP1Ops[i] = GEP2Ops[i] = Constant::getNullValue(Type::UIntTy);
 
+    if (const CompositeType *CT = dyn_cast<CompositeType>(ZeroIdxTy))
+      ZeroIdxTy = CT->getTypeAtIndex(GEP1Ops[i]);
+  }
+
   // We know that GEP1Ops[FirstConstantOper] & GEP2Ops[FirstConstantOper] are ok
 
   // Loop over the rest of the operands...
@@ -705,11 +741,7 @@ namespace {
 
 // Note that this list cannot contain libm functions (such as acos and sqrt)
 // that set errno on a domain or other error.
-static const char *DoesntAccessMemoryTable[] = {
-  // LLVM intrinsics:
-  "llvm.frameaddress", "llvm.returnaddress", "llvm.readport",
-  "llvm.isunordered", "llvm.sqrt", "llvm.ctpop", "llvm.ctlz", "llvm.cttz",
-
+static const char *DoesntAccessMemoryFns[] = {
   "abs", "labs", "llabs", "imaxabs", "fabs", "fabsf", "fabsl",
   "trunc", "truncf", "truncl", "ldexp",
 
@@ -720,6 +752,8 @@ static const char *DoesntAccessMemoryTable[] = {
   "hypot",
   "sin", "sinf", "sinl",
   "tan", "tanf", "tanl",      "tanh", "tanhf", "tanhl",
+  
+  "floor", "floorf", "floorl", "ceil", "ceilf", "ceill",
 
   // ctype.h
   "isalnum", "isalpha", "iscntrl", "isdigit", "isgraph", "islower", "isprint"
@@ -744,10 +778,8 @@ static const char *DoesntAccessMemoryTable[] = {
   "__signbit", "__signbitf", "__signbitl",
 };
 
-static const unsigned DAMTableSize =
-    sizeof(DoesntAccessMemoryTable)/sizeof(DoesntAccessMemoryTable[0]);
 
-static const char *OnlyReadsMemoryTable[] = {
+static const char *OnlyReadsMemoryFns[] = {
   "atoi", "atol", "atof", "atoll", "atoq", "a64l",
   "bcmp", "memcmp", "memchr", "memrchr", "wmemcmp", "wmemchr",
 
@@ -771,34 +803,45 @@ static const char *OnlyReadsMemoryTable[] = {
   "feof_unlocked", "ferror_unlocked", "fileno_unlocked"
 };
 
-static const unsigned ORMTableSize =
-    sizeof(OnlyReadsMemoryTable)/sizeof(OnlyReadsMemoryTable[0]);
-
 AliasAnalysis::ModRefBehavior
 BasicAliasAnalysis::getModRefBehavior(Function *F, CallSite CS,
                                       std::vector<PointerAccessInfo> *Info) {
   if (!F->isExternal()) return UnknownModRefBehavior;
 
+  static std::vector<const char*> NoMemoryTable, OnlyReadsMemoryTable;
+
   static bool Initialized = false;
   if (!Initialized) {
+    NoMemoryTable.insert(NoMemoryTable.end(),
+                         DoesntAccessMemoryFns, 
+                         DoesntAccessMemoryFns+
+                sizeof(DoesntAccessMemoryFns)/sizeof(DoesntAccessMemoryFns[0]));
+
+    OnlyReadsMemoryTable.insert(OnlyReadsMemoryTable.end(),
+                                OnlyReadsMemoryFns, 
+                                OnlyReadsMemoryFns+
+                      sizeof(OnlyReadsMemoryFns)/sizeof(OnlyReadsMemoryFns[0]));
+#define GET_MODREF_BEHAVIOR
+#include "llvm/Intrinsics.gen"
+#undef GET_MODREF_BEHAVIOR
+    
     // Sort the table the first time through.
-    std::sort(DoesntAccessMemoryTable, DoesntAccessMemoryTable+DAMTableSize,
-              StringCompare());
-    std::sort(OnlyReadsMemoryTable, OnlyReadsMemoryTable+ORMTableSize,
+    std::sort(NoMemoryTable.begin(), NoMemoryTable.end(), StringCompare());
+    std::sort(OnlyReadsMemoryTable.begin(), OnlyReadsMemoryTable.end(),
               StringCompare());
     Initialized = true;
   }
 
-  const char **Ptr = std::lower_bound(DoesntAccessMemoryTable,
-                                      DoesntAccessMemoryTable+DAMTableSize,
-                                      F->getName().c_str(), StringCompare());
-  if (Ptr != DoesntAccessMemoryTable+DAMTableSize && *Ptr == F->getName())
+  std::vector<const char*>::iterator Ptr =
+    std::lower_bound(NoMemoryTable.begin(), NoMemoryTable.end(),
+                     F->getName().c_str(), StringCompare());
+  if (Ptr != NoMemoryTable.end() && *Ptr == F->getName())
     return DoesNotAccessMemory;
 
-  Ptr = std::lower_bound(OnlyReadsMemoryTable,
-                         OnlyReadsMemoryTable+ORMTableSize,
+  Ptr = std::lower_bound(OnlyReadsMemoryTable.begin(),
+                         OnlyReadsMemoryTable.end(),
                          F->getName().c_str(), StringCompare());
-  if (Ptr != OnlyReadsMemoryTable+ORMTableSize && *Ptr == F->getName())
+  if (Ptr != OnlyReadsMemoryTable.end() && *Ptr == F->getName())
     return OnlyReadsMemory;
 
   return UnknownModRefBehavior;