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

Chris Lattner sabre at nondot.org
Wed Nov 25 18:13:03 PST 2009


Author: lattner
Date: Wed Nov 25 20:13:03 2009
New Revision: 89915

URL: http://llvm.org/viewvc/llvm-project?rev=89915&view=rev
Log:
Implement a new DecomposeGEPExpression method, which decomposes a GEP into a list of scaled offsets.  Use this to eliminate some previous ad-hoc code which was subtly broken (it assumed all Constant*'s were non-zero, but strange constant express could be zero).

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=89915&r1=89914&r2=89915&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Wed Nov 25 20:13:03 2009
@@ -405,6 +405,97 @@
   return NoAA::getModRefInfo(CS1, CS2);
 }
 
+/// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose it
+/// into a base pointer with a constant offset and a number of scaled symbolic
+/// offsets.
+static const Value *DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
+               SmallVectorImpl<std::pair<const Value*, uint64_t> > &VarIndices,
+                                           const TargetData *TD) {
+  const Value *OrigPtr = V;
+  BaseOffs = 0;
+  while (1) {
+    // See if this is a bitcast or GEP.
+    const Operator *Op = dyn_cast<Operator>(V);
+    if (Op == 0) return V;
+    
+    if (Op->getOpcode() == Instruction::BitCast) {
+      V = Op->getOperand(0);
+      continue;
+    }
+    
+    if (Op->getOpcode() != Instruction::GetElementPtr)
+      return V;
+    
+    // Don't attempt to analyze GEPs over unsized objects.
+    if (!cast<PointerType>(Op->getOperand(0)->getType())
+          ->getElementType()->isSized())
+      return V;
+    
+    // Walk the indices of the GEP, accumulating them into BaseOff/VarIndices.
+    gep_type_iterator GTI = gep_type_begin(Op);
+    for (User::const_op_iterator I = next(Op->op_begin()), E = Op->op_end();
+         I != E; ++I) {
+      Value *Index = *I;
+      // Compute the (potentially symbolic) offset in bytes for this index.
+      if (const StructType *STy = dyn_cast<StructType>(*GTI++)) {
+        // For a struct, add the member offset.
+        unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
+        if (FieldNo == 0) continue;
+        if (TD == 0) goto FailNoTD;
+        
+        BaseOffs += TD->getStructLayout(STy)->getElementOffset(FieldNo);
+        continue;
+      }
+      
+      // For an array/pointer, add the element offset, explicitly scaled.
+      if (ConstantInt *CIdx = dyn_cast<ConstantInt>(Index)) {
+        if (CIdx->isZero()) continue;
+        if (TD == 0) goto FailNoTD;
+        
+        BaseOffs += TD->getTypeAllocSize(*GTI)*CIdx->getSExtValue();
+        continue;
+      }
+      
+      if (TD == 0) goto FailNoTD;
+      
+      // TODO: Could handle linear expressions here like A[X+1], also A[X*4|1].
+      uint64_t Scale = TD->getTypeAllocSize(*GTI);
+      
+      // If we already had an occurrance of this index variable, merge this
+      // scale into it.  For example, we want to handle:
+      //   A[x][x] -> x*16 + x*4 -> x*20
+      for (unsigned i = 0, e = VarIndices.size(); i != e; ++i) {
+        if (VarIndices[i].first == Index) {
+          Scale += VarIndices[i].second;
+          VarIndices.erase(VarIndices.begin()+i);
+          break;
+        }
+      }
+      
+      // Make sure that we have a scale that makes sense for this target's
+      // pointer size.
+      if (unsigned ShiftBits = 64-TD->getPointerSizeInBits()) {
+        Scale <<= ShiftBits;
+        Scale >>= ShiftBits;
+      }
+      
+      if (Scale)
+        VarIndices.push_back(std::make_pair(Index, Scale));
+    }
+    
+    // Analyze the base pointer next.
+    V = Op->getOperand(0);
+  }
+  
+  // If we don't have TD around, we can't analyze this index, remove all
+  // information we've found.
+FailNoTD:
+  VarIndices.clear();
+  BaseOffs = 0;
+  return OrigPtr;
+}
+
+
 /// aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction
 /// against another pointer.  We know that V1 is a GEP, but we don't know
 /// anything about V2.
@@ -479,10 +570,12 @@
   if (V1Size == ~0U || V2Size == ~0U)
     return MayAlias;
 
-  SmallVector<Value*, 16> GEPOperands;
-  const Value *BasePtr = GetGEPOperands(GEP1, GEPOperands);
-
-  AliasResult R = aliasCheck(BasePtr, ~0U, V2, V2Size);
+  int64_t GEP1BaseOffset;
+  SmallVector<std::pair<const Value*, uint64_t>, 4> VariableIndices;
+  const Value *GEP1BasePtr =
+    DecomposeGEPExpression(GEP1, GEP1BaseOffset, VariableIndices, TD);
+    
+  AliasResult R = aliasCheck(GEP1BasePtr, ~0U, V2, V2Size);
   if (R != MustAlias)
     // If V2 may alias GEP base pointer, conservatively returns MayAlias.
     // If V2 is known not to alias GEP base pointer, then the two values
@@ -491,48 +584,34 @@
     // with the first operand of the getelementptr".
     return R;
 
-  // If there is at least one non-zero constant index, we know they cannot
-  // alias.
-  bool ConstantFound = false;
-  bool AllZerosFound = true;
-  for (unsigned i = 0, e = GEPOperands.size(); i != e; ++i)
-    if (const Constant *C = dyn_cast<Constant>(GEPOperands[i])) {
-      if (!C->isNullValue()) {
-        ConstantFound = true;
-        AllZerosFound = false;
-        break;
-      }
-    } else {
-      AllZerosFound = false;
-    }
-
   // If we have getelementptr <ptr>, 0, 0, 0, 0, ... and V2 must aliases
   // the ptr, the end result is a must alias also.
-  if (AllZerosFound)
+  if (GEP1BaseOffset == 0 && VariableIndices.empty())
     return MustAlias;
 
-  if (ConstantFound) {
-    if (V2Size <= 1 && V1Size <= 1)  // Just pointer check?
+  // If we have a known constant offset, see if this offset is larger than the
+  // access size being queried.  If so, and if no variable indices can remove
+  // pieces of this constant, then we know we have a no-alias.  For example,
+  //   &A[100] != &A.
+  
+  // In order to handle cases like &A[100][i] where i is an out of range
+  // subscript, we have to ignore all constant offset pieces that are a multiple
+  // of a scaled index.  Do this by removing constant offsets that are a
+  // multiple of any of our variable indices.  This allows us to transform
+  // things like &A[i][1] because i has a stride of (e.g.) 8 bytes but the 1
+  // provides an offset of 4 bytes (assuming a <= 4 byte access).
+  for (unsigned i = 0, e = VariableIndices.size(); i != e && GEP1BaseOffset;++i)
+    if (int64_t RemovedOffset = GEP1BaseOffset/VariableIndices[i].second)
+      GEP1BaseOffset -= RemovedOffset*VariableIndices[i].second;
+  
+  // If our known offset is bigger than the access size, we know we don't have
+  // an alias.
+  if (GEP1BaseOffset) {
+    if (GEP1BaseOffset >= (int64_t)V2Size ||
+        GEP1BaseOffset <= -(int64_t)V1Size)
       return NoAlias;
-
-    // Otherwise we have to check to see that the distance is more than
-    // the size of the argument... build an index vector that is equal to
-    // the arguments provided, except substitute 0's for any variable
-    // indexes we find...
-    if (TD &&
-        cast<PointerType>(BasePtr->getType())->getElementType()->isSized()) {
-      for (unsigned i = 0; i != GEPOperands.size(); ++i)
-        if (!isa<ConstantInt>(GEPOperands[i]))
-          GEPOperands[i] = Constant::getNullValue(GEPOperands[i]->getType());
-      int64_t Offset = TD->getIndexedOffset(BasePtr->getType(),
-                                            &GEPOperands[0],
-                                            GEPOperands.size());
-
-      if (Offset >= (int64_t)V2Size || Offset <= -(int64_t)V1Size)
-        return NoAlias;
-    }
   }
-
+  
   return MayAlias;
 }
 
@@ -713,6 +792,8 @@
       return NoAlias;
   }
 
+  // FIXME: This isn't aggressively handling alias(GEP, PHI) for example: if the
+  // GEP can't simplify, we don't even look at the PHI cases.
   if (!isa<GEPOperator>(V1) && isa<GEPOperator>(V2)) {
     std::swap(V1, V2);
     std::swap(V1Size, V2Size);





More information about the llvm-commits mailing list