[llvm-commits] [llvm] r152490 - in /llvm/trunk: include/llvm/Value.h lib/Analysis/InstructionSimplify.cpp lib/VMCore/Value.cpp

Chandler Carruth chandlerc at gmail.com
Sat Mar 10 00:39:09 PST 2012


Author: chandlerc
Date: Sat Mar 10 02:39:09 2012
New Revision: 152490

URL: http://llvm.org/viewvc/llvm-project?rev=152490&view=rev
Log:
Refactor some methods to look through bitcasts and GEPs on pointers into
a common collection of methods on Value, and share their implementation.
We had two variations in two different places already, and I need the
third variation for inline cost estimation.

Reviewed by Duncan Sands on IRC, but further comments here welcome.

Modified:
    llvm/trunk/include/llvm/Value.h
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/lib/VMCore/Value.cpp

Modified: llvm/trunk/include/llvm/Value.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Value.h?rev=152490&r1=152489&r2=152490&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Value.h (original)
+++ llvm/trunk/include/llvm/Value.h Sat Mar 10 02:39:09 2012
@@ -263,14 +263,32 @@
     return true; // Values are always values.
   }
 
-  /// stripPointerCasts - This method strips off any unneeded pointer
-  /// casts from the specified value, returning the original uncasted value.
-  /// Note that the returned value has pointer type if the specified value does.
+  /// stripPointerCasts - This method strips off any unneeded pointer casts and
+  /// all-zero GEPs from the specified value, returning the original uncasted
+  /// value. If this is called on a non-pointer value, it returns 'this'.
   Value *stripPointerCasts();
   const Value *stripPointerCasts() const {
     return const_cast<Value*>(this)->stripPointerCasts();
   }
 
+  /// stripConstantOffsets - This method strips off unneeded pointer casts and
+  /// all-constant GEPs from the specified value, returning the original
+  /// pointer value. If this is called on a non-pointer value, it returns
+  /// 'this'.
+  Value *stripConstantOffsets();
+  const Value *stripConstantOffsets() const {
+    return const_cast<Value*>(this)->stripConstantOffsets();
+  }
+
+  /// stripInBoundsOffsets - This method strips off unneeded pointer casts and
+  /// any in-bounds Offsets from the specified value, returning the original
+  /// pointer value. If this is called on a non-pointer value, it returns
+  /// 'this'.
+  Value *stripInBoundsOffsets();
+  const Value *stripInBoundsOffsets() const {
+    return const_cast<Value*>(this)->stripInBoundsOffsets();
+  }
+
   /// isDereferenceablePointer - Test if this value is always a pointer to
   /// allocated and suitably aligned memory for a simple load or store.
   bool isDereferenceablePointer() const;

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=152490&r1=152489&r2=152490&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Sat Mar 10 02:39:09 2012
@@ -1522,28 +1522,6 @@
   return 0;
 }
 
-/// stripPointerAdjustments - This is like Value::stripPointerCasts, but also
-/// removes inbounds gep operations, regardless of their indices.
-static Value *stripPointerAdjustmentsImpl(Value *V,
-                                    SmallPtrSet<GEPOperator*, 8> &VisitedGEPs) {
-  GEPOperator *GEP = dyn_cast<GEPOperator>(V);
-  if (GEP == 0 || !GEP->isInBounds())
-    return V;
-
-  // If we've already seen this GEP, we will end up infinitely looping.  This
-  // can happen in unreachable code.
-  if (!VisitedGEPs.insert(GEP))
-    return V;
-  
-  return stripPointerAdjustmentsImpl(GEP->getOperand(0)->stripPointerCasts(),
-                                     VisitedGEPs);
-}
-
-static Value *stripPointerAdjustments(Value *V) {
-  SmallPtrSet<GEPOperator*, 8> VisitedGEPs;
-  return stripPointerAdjustmentsImpl(V, VisitedGEPs);
-}
-
 
 /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
 /// fold the result.  If not, this returns null.
@@ -1625,9 +1603,9 @@
   // Be more aggressive about stripping pointer adjustments when checking a
   // comparison of an alloca address to another object.  We can rip off all
   // inbounds GEP operations, even if they are variable.
-  LHSPtr = stripPointerAdjustments(LHSPtr);
+  LHSPtr = LHSPtr->stripInBoundsOffsets();
   if (llvm::isIdentifiedObject(LHSPtr)) {
-    RHSPtr = stripPointerAdjustments(RHSPtr);
+    RHSPtr = RHSPtr->stripInBoundsOffsets();
     if (llvm::isKnownNonNull(LHSPtr) || llvm::isKnownNonNull(RHSPtr)) {
       // If both sides are different identified objects, they aren't equal
       // unless they're null.
@@ -1644,7 +1622,7 @@
     if (llvm::isKnownNonNull(LHSPtr) && isa<ConstantPointerNull>(RHSPtr))
       return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
   } else if (isa<Argument>(LHSPtr)) {
-    RHSPtr = stripPointerAdjustments(RHSPtr);
+    RHSPtr = RHSPtr->stripInBoundsOffsets();
     // An alloca can't be equal to an argument.
     if (isa<AllocaInst>(RHSPtr))
       return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));

Modified: llvm/trunk/lib/VMCore/Value.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Value.cpp?rev=152490&r1=152489&r2=152490&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Value.cpp (original)
+++ llvm/trunk/lib/VMCore/Value.cpp Sat Mar 10 02:39:09 2012
@@ -317,20 +317,43 @@
     BB->replaceSuccessorsPhiUsesWith(cast<BasicBlock>(New));
 }
 
-Value *Value::stripPointerCasts() {
-  if (!getType()->isPointerTy())
-    return this;
+namespace {
+// Various metrics for how much to strip off of pointers.
+enum PointerStripKind {
+  PSK_ZeroIndices,
+  PSK_ConstantIndices,
+  PSK_InBounds,
+  PSK_All
+};
+
+template <PointerStripKind StripKind>
+static Value *stripPointerCastsAndOffsets(Value *V) {
+  if (!V->getType()->isPointerTy())
+    return V;
 
   // Even though we don't look through PHI nodes, we could be called on an
   // instruction in an unreachable block, which may be on a cycle.
   SmallPtrSet<Value *, 4> Visited;
 
-  Value *V = this;
   Visited.insert(V);
   do {
     if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
-      if (!GEP->hasAllZeroIndices())
-        return V;
+      switch (StripKind) {
+      case PSK_ZeroIndices:
+        if (!GEP->hasAllZeroIndices())
+          return V;
+        break;
+      case PSK_ConstantIndices:
+        if (!GEP->hasAllConstantIndices())
+          return V;
+        break;
+      case PSK_InBounds:
+        if (!GEP->isInBounds())
+          return V;
+        break;
+      case PSK_All:
+        break;
+      }
       V = GEP->getPointerOperand();
     } else if (Operator::getOpcode(V) == Instruction::BitCast) {
       V = cast<Operator>(V)->getOperand(0);
@@ -346,6 +369,19 @@
 
   return V;
 }
+} // namespace
+
+Value *Value::stripPointerCasts() {
+  return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this);
+}
+
+Value *Value::stripConstantOffsets() {
+  return stripPointerCastsAndOffsets<PSK_ConstantIndices>(this);
+}
+
+Value *Value::stripInBoundsOffsets() {
+  return stripPointerCastsAndOffsets<PSK_InBounds>(this);
+}
 
 /// isDereferenceablePointer - Test if this value is always a pointer to
 /// allocated and suitably aligned memory for a simple load or store.





More information about the llvm-commits mailing list