[llvm-commits] [llvm] r156613 - in /llvm/trunk/include/llvm: CRSBuilder.h ConstantRangesSet.h Support/CRSBuilder.h Support/ConstantRangesSet.h

Stepan Dyatkovskiy stpworld at narod.ru
Fri May 11 03:34:23 PDT 2012


Author: dyatkovskiy
Date: Fri May 11 05:34:23 2012
New Revision: 156613

URL: http://llvm.org/viewvc/llvm-project?rev=156613&view=rev
Log:
PR1255: ConstantRangesSet and CRSBuilder classes moved from include/llvm to include/llvm/Support.


Added:
    llvm/trunk/include/llvm/Support/CRSBuilder.h
    llvm/trunk/include/llvm/Support/ConstantRangesSet.h
Removed:
    llvm/trunk/include/llvm/CRSBuilder.h
    llvm/trunk/include/llvm/ConstantRangesSet.h

Removed: llvm/trunk/include/llvm/CRSBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CRSBuilder.h?rev=156612&view=auto
==============================================================================
--- llvm/trunk/include/llvm/CRSBuilder.h (original)
+++ llvm/trunk/include/llvm/CRSBuilder.h (removed)
@@ -1,252 +0,0 @@
-//===- CRSBuilder.h - ConstantRangesSet Builder -----------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// @file
-/// CRSBuilder allows to build and parse ConstantRangesSet objects.
-/// There is such features like add/remove range, or combine
-/// Two ConstantRangesSet object with neighboring ranges merging.
-/// Set IsReadonly=true if you want to operate with "const ConstantInt" and
-/// "const ConstantRangesSet" objects.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CRSBUILDER_H_
-#define CRSBUILDER_H_
-
-#include "llvm/ConstantRangesSet.h"
-#include <list>
-#include <map>
-#include <vector>
-
-namespace llvm {
-
-template <class SuccessorClass, bool IsReadonly>
-class CRSBuilderBase {
-public:
-  
-  typedef ConstantRangesSet::RangeT<IsReadonly> RangeTy;
-  
-  struct RangeEx : public RangeTy {
-    typedef ConstantRangesSet::RangeT<IsReadonly> RangeTy;
-    typedef typename RangeTy::ConstantIntTy ConstantIntTy;
-    RangeEx() : Weight(1) {}
-    RangeEx(const RangeTy &R) : RangeTy(R.Low, R.High), Weight(1) {}
-    RangeEx(ConstantIntTy *C) : RangeTy(C), Weight(1) {}
-    RangeEx(ConstantIntTy *L, ConstantIntTy *H) : RangeTy(L, H), Weight(1) {}
-    RangeEx(ConstantIntTy *L, ConstantIntTy *H, unsigned W) :
-      RangeTy(L, H), Weight(W) {}
-    unsigned Weight;
-  };
-
-  typedef std::pair<RangeEx, SuccessorClass*> Cluster;
-
-protected:
-
-  typedef std::vector<Cluster> CaseItems;
-  typedef typename CaseItems::iterator CaseItemIt;
-  typedef typename CaseItems::const_iterator CaseItemConstIt;
-
-  struct ClustersCmp {
-    bool operator()(const Cluster &C1, const Cluster &C2) {
-      return C1.first < C2.first;
-    }
-  };
-  
-  CaseItems Items;
-  bool Sorted;
-  
-  bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
-    return LItem->first.High->getValue().uge(RItem->first.Low->getValue());
-  }
-
-  bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) {
-    if (LItem->second != RItem->second) {
-      assert(!isIntersected(LItem, RItem) &&
-             "Intersected items with different successors!");
-      return false;
-    }
-    APInt RLow = RItem->first.Low->getValue();
-    if (RLow != APInt::getNullValue(RLow.getBitWidth()))
-      --RLow;
-    return LItem->first.High->getValue().uge(RLow);
-  }
-  
-  void sort() {
-    if (!Sorted) {
-      std::sort(Items.begin(), Items.end(), ClustersCmp());
-      Sorted = true;
-    }
-  }
-  
-public:
-  
-  typedef typename CRSConstantTypes<IsReadonly>::ConstantIntTy ConstantIntTy;
-  typedef typename CRSConstantTypes<IsReadonly>::ConstantRangesSetTy ConstantRangesSetTy;
-  
-  // Don't public CaseItems itself. Don't allow edit the Items directly. 
-  // Just present the user way to iterate over the internal collection
-  // sharing iterator, begin() and end(). Editing should be controlled by
-  // factory.
-  typedef CaseItemIt RangeIterator;
-  
-  CRSBuilderBase() {
-    Items.reserve(32);
-    Sorted = false;
-  }
-  
-  bool verify() {
-    if (Items.empty())
-      return true;
-    sort();
-    for (CaseItemIt i = Items.begin(), j = i+1, e = Items.end();
-         j != e; i = j++) {
-      if (isIntersected(j, i) && j->second != i->second)
-        return false;
-    }
-    return true;
-  }
-  
-  void optimize() {
-    if (Items.size() < 2)
-      return;
-    sort();
-    CaseItems OldItems = Items;
-    Items.clear();
-    ConstantIntTy *Low = OldItems.begin()->first.Low;
-    ConstantIntTy *High = OldItems.begin()->first.High;
-    unsigned Weight = 1;
-    SuccessorClass *Successor = OldItems.begin()->second;
-    for (CaseItemIt i = OldItems.begin(), j = i+1, e = OldItems.end();
-        j != e; i = j++) {
-      if (isJoinable(i, j)) {
-        ConstantIntTy *CurHigh = j->first.High;
-        ++Weight;
-        if (CurHigh->getValue().ugt(High->getValue()))
-          High = CurHigh;
-      } else {
-        RangeEx R(Low, High, Weight);
-        add(R, Successor);
-        Low = j->first.Low;
-        High = j->first.High; 
-        Weight = 1;
-        Successor = j->second;
-      }
-    }
-    RangeEx R(Low, High, Weight);
-    add(R, Successor);
-    // We recollected the Items, but we kept it sorted.
-    Sorted = true;
-  }
-  
-  /// Adds a constant value.
-  void add(ConstantIntTy *C, SuccessorClass *S = 0) {
-    RangeTy R(C);
-    add(R, S);
-  }
-  
-  /// Adds a range.
-  void add(ConstantIntTy *Low, ConstantIntTy *High, SuccessorClass *S = 0) {
-    RangeTy R(Low, High);
-    add(R, S);
-  }
-  void add(RangeTy &R, SuccessorClass *S = 0) {
-    RangeEx REx = R;
-    add(REx, S);
-  }   
-  void add(RangeEx &R, SuccessorClass *S = 0) {
-    Items.push_back(std::make_pair(R, S));
-    Sorted = false;
-  }  
-  
-  /// Adds all ranges and values from given ranges set to the current
-  /// CRSBuilder object.
-  void add(ConstantRangesSetTy &CRS, SuccessorClass *S = 0) {
-    for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) {
-      RangeTy R = CRS.getItem(i);
-      add(R, S);
-    }
-  }
-  
-  /// Removes items from set.
-  void removeItem(RangeIterator i) { Items.erase(i); }
-  
-  /// Returns true if there is no ranges and values inside.
-  bool empty() const { return Items.empty(); }
-  
-  RangeIterator begin() { return Items.begin(); }
-  RangeIterator end() { return Items.end(); }
-};
-
-template <class SuccessorClass>
-class CRSBuilderT : public CRSBuilderBase<SuccessorClass, false> {
-  
-  typedef typename CRSBuilderBase<SuccessorClass, false>::RangeTy RangeTy;
-  typedef typename CRSBuilderBase<SuccessorClass, false>::RangeIterator
-      RangeIterator;
-  
-  typedef std::list<RangeTy> RangesCollection;
-  typedef typename RangesCollection::iterator RangesCollectionIt;
-  
-  typedef std::map<SuccessorClass*, RangesCollection > CRSMap;
-  typedef typename CRSMap::iterator CRSMapIt;
-  
-  ConstantRangesSet getCase(RangesCollection& Src) {
-    std::vector<Constant*> Elts;
-    Elts.reserve(Src.size());
-    for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) {
-      const RangeTy &R = *i;
-      std::vector<Constant*> r;
-      if (R.Low != R.High) {
-        r.reserve(2);
-        r.push_back(R.Low);
-        r.push_back(R.High);
-      } else {
-        r.reserve(1);
-        r.push_back(R.Low);
-      }
-      Constant *CV = ConstantVector::get(r);
-      Elts.push_back(CV);    
-    }
-    ArrayType *ArrTy =
-        ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size());
-    Constant *Array = ConstantArray::get(ArrTy, Elts);
-    return ConstantRangesSet(Array);     
-  }
-
-public:
-  
-  typedef std::pair<SuccessorClass*, ConstantRangesSet> Case;
-  typedef std::list<Case> Cases;
-  
-  /// Builds the finalized case objects.
-  void getCases(Cases& TheCases) {
-    CRSMap TheCRSMap;
-    for (RangeIterator i = this->begin(); i != this->end(); ++i)
-      TheCRSMap[i->second].push_back(i->first);
-    for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i)
-      TheCases.push_back(std::make_pair(i->first, getCase(i->second)));
-  }
-  
-  /// Builds the finalized case objects ignoring successor values, as though
-  /// all ranges belongs to the same successor.
-  ConstantRangesSet getCase() {
-    RangesCollection Ranges;
-    for (RangeIterator i = this->begin(); i != this->end(); ++i)
-      Ranges.push_back(i->first);
-    return getCase(Ranges);
-  }
-};
-
-class BasicBlock;
-typedef CRSBuilderT<BasicBlock> CRSBuilder;
-typedef CRSBuilderBase<BasicBlock, true> CRSBuilderConst;  
-
-}
-
-#endif /* CRSBUILDER_H_ */

Removed: llvm/trunk/include/llvm/ConstantRangesSet.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ConstantRangesSet.h?rev=156612&view=auto
==============================================================================
--- llvm/trunk/include/llvm/ConstantRangesSet.h (original)
+++ llvm/trunk/include/llvm/ConstantRangesSet.h (removed)
@@ -1,272 +0,0 @@
-//===-- llvm/ConstantRangesSet.h - The constant set of ranges ---*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// @file
-/// This file contains class that implements constant set of ranges:
-/// [<Low0,High0>,...,<LowN,HighN>]. Mainly, this set is used by SwitchInst and
-/// represents case value that may contain multiple ranges for a single
-/// successor.
-///
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CONSTANTRANGESSET_H_
-#define CONSTANTRANGESSET_H_
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-
-namespace llvm {
-  
-class ConstantRangesSet;  
-  
-template <bool IsReadonly> struct CRSConstantTypes {
-  typedef ConstantInt ConstantIntTy;
-  typedef ConstantRangesSet ConstantRangesSetTy;  
-};
-
-template <>
-struct CRSConstantTypes<true> {
-  typedef const ConstantInt ConstantIntTy;
-  typedef const ConstantRangesSet ConstantRangesSetTy;
-};  
-  
-//===----------------------------------------------------------------------===//
-/// ConstantRangesSet - class that implements constant set of ranges.
-/// It is a wrapper for some real "holder" class (currently ConstantArray).
-/// It contains functions, that allows to parse "holder" like a set of ranges.
-/// Note: It is assumed that "holder" is inherited from Constant object.
-///       ConstantRangesSet may be converted to and from Constant* pointer.
-///
-class ConstantRangesSet {
-  Constant *Array;
-public:
-  
-  // implicit
-  ConstantRangesSet(Constant *V) : Array(V) {}
-  
-  operator Constant*() { return Array; }
-  operator const Constant*() const { return Array; }
-  Constant *operator->() { return Array; }
-  const Constant *operator->() const { return Array; }
-   
-  template <bool IsReadonly>
-  struct RangeT {
-    
-    typedef typename CRSConstantTypes<IsReadonly>::ConstantIntTy ConstantIntTy;
-    typedef std::pair<RangeT, RangeT> SubRes;
-    
-    ConstantIntTy *Low;
-    ConstantIntTy *High;
-   
-    RangeT() : Low(0), High(0) {}
-    RangeT(const RangeT<false> &RHS) : Low(RHS.Low), High(RHS.High) {}
-    RangeT(ConstantIntTy *C) : Low(C), High(C) {}
-    RangeT(ConstantIntTy *L, ConstantIntTy *H) : Low(L), High(H) {}
-   
-    bool operator<(const RangeT &RHS) const {
-      assert(Low && High && "Case range is not initialized.");
-      assert(RHS.Low && RHS.High && "Right case range is not initialized.");
-      const APInt &LowInt = Low->getValue();
-      const APInt &HighInt = High->getValue();
-      const APInt &RHSLowInt = RHS.Low->getValue();
-      const APInt &RHSHighInt = RHS.High->getValue();
-      if (LowInt.getBitWidth() == RHSLowInt.getBitWidth()) {
-        if (LowInt.eq(RHSLowInt)) {
-          if (HighInt.ult(RHSHighInt))
-            return true;
-          return false;
-        }
-        if (LowInt.ult(RHSLowInt))
-          return true;
-        return false;
-      } else
-        return LowInt.getBitWidth() < RHSLowInt.getBitWidth();      
-    }
-
-    bool operator==(const RangeT &RHS) const {
-      assert(Low && High && "Case range is not initialized.");
-      assert(RHS.Low && RHS.High && "Right case range is not initialized.");
-      if (Low->getValue().getBitWidth() != RHS.Low->getValue().getBitWidth())
-        return false;
-      return Low->getValue() == RHS.Low->getValue() &&
-             High->getValue() == RHS.High->getValue();      
-    }
- 
-    bool operator!=(const RangeT &RHS) const {
-      return !operator ==(RHS);      
-    }
- 
-    static bool LessBySize(const RangeT &LHS, const RangeT &RHS) {
-      assert(LHS.Low->getBitWidth() == RHS.Low->getBitWidth() && 
-          "This type of comparison requires equal bit width for LHS and RHS");
-      APInt LSize = LHS.High->getValue() - LHS.Low->getValue();
-      APInt RSize = RHS.High->getValue() - RHS.Low->getValue();;
-      return LSize.ult(RSize);      
-    }
- 
-    bool isInRange(const APInt &IntVal) const {
-      assert(Low && High && "Case range is not initialized.");
-      if (IntVal.getBitWidth() != Low->getValue().getBitWidth())
-        return false;
-      return IntVal.uge(Low->getValue()) && IntVal.ule(High->getValue());      
-    }    
-  
-    bool isInRange(const ConstantIntTy *CI) const {
-      const APInt& IntVal = CI->getValue();
-      return isInRange(IntVal);
-    }
-  
-    SubRes sub(const RangeT &RHS) const {
-      SubRes Res;
-      
-      // RHS is either more global and includes this range or
-      // if it doesn't intersected with this range.
-      if (!isInRange(RHS.Low) && !isInRange(RHS.High)) {
-        
-        // If RHS more global (it is enough to check
-        // only one border in this case.
-        if (RHS.isInRange(Low))
-          return std::make_pair(RangeT(Low, High), RangeT()); 
-        
-        return Res;
-      }
-      
-      const APInt& LoInt = Low->getValue();
-      const APInt& HiInt = High->getValue();
-      APInt RHSLoInt = RHS.Low->getValue();
-      APInt RHSHiInt = RHS.High->getValue();
-      if (LoInt.ult(RHSLoInt)) {
-        Res.first.Low = Low;
-        Res.first.High = ConstantIntTy::get(RHS.Low->getContext(), --RHSLoInt);
-      }
-      if (HiInt.ugt(RHSHiInt)) {
-        Res.second.Low = ConstantIntTy::get(RHS.High->getContext(), ++RHSHiInt);
-        Res.second.High = High;
-      }
-      return Res;      
-    }
-  };      
-
-  typedef RangeT<false> Range;
- 
-  /// Checks is the given constant satisfies this case. Returns
-  /// true if it equals to one of contained values or belongs to the one of
-  /// contained ranges.
-  bool isSatisfies(const ConstantInt *C) const {
-    const APInt &CheckingVal = C->getValue();
-    for (unsigned i = 0, e = getNumItems(); i < e; ++i) {
-      const Constant *CV = Array->getAggregateElement(i);
-      unsigned VecSize = cast<VectorType>(CV->getType())->getNumElements();
-      switch (VecSize) {
-      case 1:
-        if (cast<const ConstantInt>(CV->getAggregateElement(0U))->getValue() ==
-            CheckingVal)
-          return true;
-        break;
-      case 2: {
-        const APInt &Lo =
-            cast<const ConstantInt>(CV->getAggregateElement(0U))->getValue();
-        const APInt &Hi =
-            cast<const ConstantInt>(CV->getAggregateElement(1))->getValue();
-        if (Lo.uge(CheckingVal) && Hi.ule(CheckingVal))
-          return true;
-      }
-        break;
-      default:
-        assert(0 && "Only pairs and single numbers are allowed here.");
-        break;
-      }
-    }
-    return false;    
-  }
-  
-  /// Returns set's item with given index.
-  Range getItem(unsigned idx) {
-    Constant *CV = Array->getAggregateElement(idx);
-    unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements();
-    switch (NumEls) {
-    case 1:
-      return Range(cast<ConstantInt>(CV->getAggregateElement(0U)),
-                   cast<ConstantInt>(CV->getAggregateElement(0U)));
-    case 2:
-      return Range(cast<ConstantInt>(CV->getAggregateElement(0U)),
-                   cast<ConstantInt>(CV->getAggregateElement(1)));
-    default:
-      assert(0 && "Only pairs and single numbers are allowed here.");
-      return Range();
-    }    
-  }
-  
-  const Range getItem(unsigned idx) const {
-    const Constant *CV = Array->getAggregateElement(idx);
-    
-    unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements();
-    switch (NumEls) {
-    case 1:
-      return Range(cast<ConstantInt>(
-                     const_cast<Constant*>(CV->getAggregateElement(0U))),
-                   cast<ConstantInt>(
-                     const_cast<Constant*>(CV->getAggregateElement(0U))));
-    case 2:
-      return Range(cast<ConstantInt>(
-                     const_cast<Constant*>(CV->getAggregateElement(0U))),
-                   cast<ConstantInt>(
-                     const_cast<Constant*>(CV->getAggregateElement(1))));
-    default:
-      assert(0 && "Only pairs and single numbers are allowed here.");
-      return Range();
-    }    
-  }
-  
-  /// Return number of items (ranges) stored in set.
-  unsigned getNumItems() const {
-    return cast<ArrayType>(Array->getType())->getNumElements();
-  }
-  
-  /// Returns set the size, that equals number of all values + sizes of all
-  /// ranges.
-  /// Ranges set is considered as flat numbers collection.
-  /// E.g.: for range [<0>, <1>, <4,8>] the size will 7;
-  ///       for range [<0>, <1>, <5>] the size will 3
-  unsigned getSize() const {
-    APInt sz(getItem(0).Low->getBitWidth(), 0);
-    for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
-      const APInt &S = getItem(i).High->getValue() - getItem(i).Low->getValue();
-      sz += S;
-    }
-    return sz.getZExtValue();    
-  }
-  
-  /// Allows to access single value even if it belongs to some range.
-  /// Ranges set is considered as flat numbers collection.
-  /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] 
-  /// For range [<1>, <4,8>] getSingleValue(3) returns 6.
-  APInt getSingleValue(unsigned idx) const {
-    APInt sz(getItem(0).Low->getBitWidth(), 0);
-    for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
-      const APInt& S = getItem(i).High->getValue() - getItem(i).Low->getValue();
-      APInt oldSz = sz;
-      sz += S;
-      if (oldSz.uge(i) && sz.ult(i)) {
-        APInt Res = getItem(i).Low->getValue();
-        APInt Offset(oldSz.getBitWidth(), i);
-        Offset -= oldSz;
-        Res += Offset;
-        return Res;
-      }
-    }
-    assert(0 && "Index exceeds high border.");
-    return sz;    
-  }
-};  
-
-}
-
-#endif /* CONSTANTRANGESSET_H_ */

Added: llvm/trunk/include/llvm/Support/CRSBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CRSBuilder.h?rev=156613&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Support/CRSBuilder.h (added)
+++ llvm/trunk/include/llvm/Support/CRSBuilder.h Fri May 11 05:34:23 2012
@@ -0,0 +1,252 @@
+//===- CRSBuilder.h - ConstantRangesSet Builder -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file
+/// CRSBuilder allows to build and parse ConstantRangesSet objects.
+/// There is such features like add/remove range, or combine
+/// Two ConstantRangesSet object with neighboring ranges merging.
+/// Set IsReadonly=true if you want to operate with "const ConstantInt" and
+/// "const ConstantRangesSet" objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CRSBUILDER_H_
+#define CRSBUILDER_H_
+
+#include "llvm/Support/ConstantRangesSet.h"
+#include <list>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+template <class SuccessorClass, bool IsReadonly>
+class CRSBuilderBase {
+public:
+  
+  typedef ConstantRangesSet::RangeT<IsReadonly> RangeTy;
+  
+  struct RangeEx : public RangeTy {
+    typedef ConstantRangesSet::RangeT<IsReadonly> RangeTy;
+    typedef typename RangeTy::ConstantIntTy ConstantIntTy;
+    RangeEx() : Weight(1) {}
+    RangeEx(const RangeTy &R) : RangeTy(R.Low, R.High), Weight(1) {}
+    RangeEx(ConstantIntTy *C) : RangeTy(C), Weight(1) {}
+    RangeEx(ConstantIntTy *L, ConstantIntTy *H) : RangeTy(L, H), Weight(1) {}
+    RangeEx(ConstantIntTy *L, ConstantIntTy *H, unsigned W) :
+      RangeTy(L, H), Weight(W) {}
+    unsigned Weight;
+  };
+
+  typedef std::pair<RangeEx, SuccessorClass*> Cluster;
+
+protected:
+
+  typedef std::vector<Cluster> CaseItems;
+  typedef typename CaseItems::iterator CaseItemIt;
+  typedef typename CaseItems::const_iterator CaseItemConstIt;
+
+  struct ClustersCmp {
+    bool operator()(const Cluster &C1, const Cluster &C2) {
+      return C1.first < C2.first;
+    }
+  };
+  
+  CaseItems Items;
+  bool Sorted;
+  
+  bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
+    return LItem->first.High->getValue().uge(RItem->first.Low->getValue());
+  }
+
+  bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) {
+    if (LItem->second != RItem->second) {
+      assert(!isIntersected(LItem, RItem) &&
+             "Intersected items with different successors!");
+      return false;
+    }
+    APInt RLow = RItem->first.Low->getValue();
+    if (RLow != APInt::getNullValue(RLow.getBitWidth()))
+      --RLow;
+    return LItem->first.High->getValue().uge(RLow);
+  }
+  
+  void sort() {
+    if (!Sorted) {
+      std::sort(Items.begin(), Items.end(), ClustersCmp());
+      Sorted = true;
+    }
+  }
+  
+public:
+  
+  typedef typename CRSConstantTypes<IsReadonly>::ConstantIntTy ConstantIntTy;
+  typedef typename CRSConstantTypes<IsReadonly>::ConstantRangesSetTy ConstantRangesSetTy;
+  
+  // Don't public CaseItems itself. Don't allow edit the Items directly. 
+  // Just present the user way to iterate over the internal collection
+  // sharing iterator, begin() and end(). Editing should be controlled by
+  // factory.
+  typedef CaseItemIt RangeIterator;
+  
+  CRSBuilderBase() {
+    Items.reserve(32);
+    Sorted = false;
+  }
+  
+  bool verify() {
+    if (Items.empty())
+      return true;
+    sort();
+    for (CaseItemIt i = Items.begin(), j = i+1, e = Items.end();
+         j != e; i = j++) {
+      if (isIntersected(j, i) && j->second != i->second)
+        return false;
+    }
+    return true;
+  }
+  
+  void optimize() {
+    if (Items.size() < 2)
+      return;
+    sort();
+    CaseItems OldItems = Items;
+    Items.clear();
+    ConstantIntTy *Low = OldItems.begin()->first.Low;
+    ConstantIntTy *High = OldItems.begin()->first.High;
+    unsigned Weight = 1;
+    SuccessorClass *Successor = OldItems.begin()->second;
+    for (CaseItemIt i = OldItems.begin(), j = i+1, e = OldItems.end();
+        j != e; i = j++) {
+      if (isJoinable(i, j)) {
+        ConstantIntTy *CurHigh = j->first.High;
+        ++Weight;
+        if (CurHigh->getValue().ugt(High->getValue()))
+          High = CurHigh;
+      } else {
+        RangeEx R(Low, High, Weight);
+        add(R, Successor);
+        Low = j->first.Low;
+        High = j->first.High; 
+        Weight = 1;
+        Successor = j->second;
+      }
+    }
+    RangeEx R(Low, High, Weight);
+    add(R, Successor);
+    // We recollected the Items, but we kept it sorted.
+    Sorted = true;
+  }
+  
+  /// Adds a constant value.
+  void add(ConstantIntTy *C, SuccessorClass *S = 0) {
+    RangeTy R(C);
+    add(R, S);
+  }
+  
+  /// Adds a range.
+  void add(ConstantIntTy *Low, ConstantIntTy *High, SuccessorClass *S = 0) {
+    RangeTy R(Low, High);
+    add(R, S);
+  }
+  void add(RangeTy &R, SuccessorClass *S = 0) {
+    RangeEx REx = R;
+    add(REx, S);
+  }   
+  void add(RangeEx &R, SuccessorClass *S = 0) {
+    Items.push_back(std::make_pair(R, S));
+    Sorted = false;
+  }  
+  
+  /// Adds all ranges and values from given ranges set to the current
+  /// CRSBuilder object.
+  void add(ConstantRangesSetTy &CRS, SuccessorClass *S = 0) {
+    for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) {
+      RangeTy R = CRS.getItem(i);
+      add(R, S);
+    }
+  }
+  
+  /// Removes items from set.
+  void removeItem(RangeIterator i) { Items.erase(i); }
+  
+  /// Returns true if there is no ranges and values inside.
+  bool empty() const { return Items.empty(); }
+  
+  RangeIterator begin() { return Items.begin(); }
+  RangeIterator end() { return Items.end(); }
+};
+
+template <class SuccessorClass>
+class CRSBuilderT : public CRSBuilderBase<SuccessorClass, false> {
+  
+  typedef typename CRSBuilderBase<SuccessorClass, false>::RangeTy RangeTy;
+  typedef typename CRSBuilderBase<SuccessorClass, false>::RangeIterator
+      RangeIterator;
+  
+  typedef std::list<RangeTy> RangesCollection;
+  typedef typename RangesCollection::iterator RangesCollectionIt;
+  
+  typedef std::map<SuccessorClass*, RangesCollection > CRSMap;
+  typedef typename CRSMap::iterator CRSMapIt;
+  
+  ConstantRangesSet getCase(RangesCollection& Src) {
+    std::vector<Constant*> Elts;
+    Elts.reserve(Src.size());
+    for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) {
+      const RangeTy &R = *i;
+      std::vector<Constant*> r;
+      if (R.Low != R.High) {
+        r.reserve(2);
+        r.push_back(R.Low);
+        r.push_back(R.High);
+      } else {
+        r.reserve(1);
+        r.push_back(R.Low);
+      }
+      Constant *CV = ConstantVector::get(r);
+      Elts.push_back(CV);    
+    }
+    ArrayType *ArrTy =
+        ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size());
+    Constant *Array = ConstantArray::get(ArrTy, Elts);
+    return ConstantRangesSet(Array);     
+  }
+
+public:
+  
+  typedef std::pair<SuccessorClass*, ConstantRangesSet> Case;
+  typedef std::list<Case> Cases;
+  
+  /// Builds the finalized case objects.
+  void getCases(Cases& TheCases) {
+    CRSMap TheCRSMap;
+    for (RangeIterator i = this->begin(); i != this->end(); ++i)
+      TheCRSMap[i->second].push_back(i->first);
+    for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i)
+      TheCases.push_back(std::make_pair(i->first, getCase(i->second)));
+  }
+  
+  /// Builds the finalized case objects ignoring successor values, as though
+  /// all ranges belongs to the same successor.
+  ConstantRangesSet getCase() {
+    RangesCollection Ranges;
+    for (RangeIterator i = this->begin(); i != this->end(); ++i)
+      Ranges.push_back(i->first);
+    return getCase(Ranges);
+  }
+};
+
+class BasicBlock;
+typedef CRSBuilderT<BasicBlock> CRSBuilder;
+typedef CRSBuilderBase<BasicBlock, true> CRSBuilderConst;  
+
+}
+
+#endif /* CRSBUILDER_H_ */

Added: llvm/trunk/include/llvm/Support/ConstantRangesSet.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ConstantRangesSet.h?rev=156613&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Support/ConstantRangesSet.h (added)
+++ llvm/trunk/include/llvm/Support/ConstantRangesSet.h Fri May 11 05:34:23 2012
@@ -0,0 +1,272 @@
+//===-- llvm/ConstantRangesSet.h - The constant set of ranges ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file
+/// This file contains class that implements constant set of ranges:
+/// [<Low0,High0>,...,<LowN,HighN>]. Mainly, this set is used by SwitchInst and
+/// represents case value that may contain multiple ranges for a single
+/// successor.
+///
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CONSTANTRANGESSET_H_
+#define CONSTANTRANGESSET_H_
+
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+
+namespace llvm {
+  
+class ConstantRangesSet;  
+  
+template <bool IsReadonly> struct CRSConstantTypes {
+  typedef ConstantInt ConstantIntTy;
+  typedef ConstantRangesSet ConstantRangesSetTy;  
+};
+
+template <>
+struct CRSConstantTypes<true> {
+  typedef const ConstantInt ConstantIntTy;
+  typedef const ConstantRangesSet ConstantRangesSetTy;
+};  
+  
+//===----------------------------------------------------------------------===//
+/// ConstantRangesSet - class that implements constant set of ranges.
+/// It is a wrapper for some real "holder" class (currently ConstantArray).
+/// It contains functions, that allows to parse "holder" like a set of ranges.
+/// Note: It is assumed that "holder" is inherited from Constant object.
+///       ConstantRangesSet may be converted to and from Constant* pointer.
+///
+class ConstantRangesSet {
+  Constant *Array;
+public:
+  
+  // implicit
+  ConstantRangesSet(Constant *V) : Array(V) {}
+  
+  operator Constant*() { return Array; }
+  operator const Constant*() const { return Array; }
+  Constant *operator->() { return Array; }
+  const Constant *operator->() const { return Array; }
+   
+  template <bool IsReadonly>
+  struct RangeT {
+    
+    typedef typename CRSConstantTypes<IsReadonly>::ConstantIntTy ConstantIntTy;
+    typedef std::pair<RangeT, RangeT> SubRes;
+    
+    ConstantIntTy *Low;
+    ConstantIntTy *High;
+   
+    RangeT() : Low(0), High(0) {}
+    RangeT(const RangeT<false> &RHS) : Low(RHS.Low), High(RHS.High) {}
+    RangeT(ConstantIntTy *C) : Low(C), High(C) {}
+    RangeT(ConstantIntTy *L, ConstantIntTy *H) : Low(L), High(H) {}
+   
+    bool operator<(const RangeT &RHS) const {
+      assert(Low && High && "Case range is not initialized.");
+      assert(RHS.Low && RHS.High && "Right case range is not initialized.");
+      const APInt &LowInt = Low->getValue();
+      const APInt &HighInt = High->getValue();
+      const APInt &RHSLowInt = RHS.Low->getValue();
+      const APInt &RHSHighInt = RHS.High->getValue();
+      if (LowInt.getBitWidth() == RHSLowInt.getBitWidth()) {
+        if (LowInt.eq(RHSLowInt)) {
+          if (HighInt.ult(RHSHighInt))
+            return true;
+          return false;
+        }
+        if (LowInt.ult(RHSLowInt))
+          return true;
+        return false;
+      } else
+        return LowInt.getBitWidth() < RHSLowInt.getBitWidth();      
+    }
+
+    bool operator==(const RangeT &RHS) const {
+      assert(Low && High && "Case range is not initialized.");
+      assert(RHS.Low && RHS.High && "Right case range is not initialized.");
+      if (Low->getValue().getBitWidth() != RHS.Low->getValue().getBitWidth())
+        return false;
+      return Low->getValue() == RHS.Low->getValue() &&
+             High->getValue() == RHS.High->getValue();      
+    }
+ 
+    bool operator!=(const RangeT &RHS) const {
+      return !operator ==(RHS);      
+    }
+ 
+    static bool LessBySize(const RangeT &LHS, const RangeT &RHS) {
+      assert(LHS.Low->getBitWidth() == RHS.Low->getBitWidth() && 
+          "This type of comparison requires equal bit width for LHS and RHS");
+      APInt LSize = LHS.High->getValue() - LHS.Low->getValue();
+      APInt RSize = RHS.High->getValue() - RHS.Low->getValue();;
+      return LSize.ult(RSize);      
+    }
+ 
+    bool isInRange(const APInt &IntVal) const {
+      assert(Low && High && "Case range is not initialized.");
+      if (IntVal.getBitWidth() != Low->getValue().getBitWidth())
+        return false;
+      return IntVal.uge(Low->getValue()) && IntVal.ule(High->getValue());      
+    }    
+  
+    bool isInRange(const ConstantIntTy *CI) const {
+      const APInt& IntVal = CI->getValue();
+      return isInRange(IntVal);
+    }
+  
+    SubRes sub(const RangeT &RHS) const {
+      SubRes Res;
+      
+      // RHS is either more global and includes this range or
+      // if it doesn't intersected with this range.
+      if (!isInRange(RHS.Low) && !isInRange(RHS.High)) {
+        
+        // If RHS more global (it is enough to check
+        // only one border in this case.
+        if (RHS.isInRange(Low))
+          return std::make_pair(RangeT(Low, High), RangeT()); 
+        
+        return Res;
+      }
+      
+      const APInt& LoInt = Low->getValue();
+      const APInt& HiInt = High->getValue();
+      APInt RHSLoInt = RHS.Low->getValue();
+      APInt RHSHiInt = RHS.High->getValue();
+      if (LoInt.ult(RHSLoInt)) {
+        Res.first.Low = Low;
+        Res.first.High = ConstantIntTy::get(RHS.Low->getContext(), --RHSLoInt);
+      }
+      if (HiInt.ugt(RHSHiInt)) {
+        Res.second.Low = ConstantIntTy::get(RHS.High->getContext(), ++RHSHiInt);
+        Res.second.High = High;
+      }
+      return Res;      
+    }
+  };      
+
+  typedef RangeT<false> Range;
+ 
+  /// Checks is the given constant satisfies this case. Returns
+  /// true if it equals to one of contained values or belongs to the one of
+  /// contained ranges.
+  bool isSatisfies(const ConstantInt *C) const {
+    const APInt &CheckingVal = C->getValue();
+    for (unsigned i = 0, e = getNumItems(); i < e; ++i) {
+      const Constant *CV = Array->getAggregateElement(i);
+      unsigned VecSize = cast<VectorType>(CV->getType())->getNumElements();
+      switch (VecSize) {
+      case 1:
+        if (cast<const ConstantInt>(CV->getAggregateElement(0U))->getValue() ==
+            CheckingVal)
+          return true;
+        break;
+      case 2: {
+        const APInt &Lo =
+            cast<const ConstantInt>(CV->getAggregateElement(0U))->getValue();
+        const APInt &Hi =
+            cast<const ConstantInt>(CV->getAggregateElement(1))->getValue();
+        if (Lo.uge(CheckingVal) && Hi.ule(CheckingVal))
+          return true;
+      }
+        break;
+      default:
+        assert(0 && "Only pairs and single numbers are allowed here.");
+        break;
+      }
+    }
+    return false;    
+  }
+  
+  /// Returns set's item with given index.
+  Range getItem(unsigned idx) {
+    Constant *CV = Array->getAggregateElement(idx);
+    unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements();
+    switch (NumEls) {
+    case 1:
+      return Range(cast<ConstantInt>(CV->getAggregateElement(0U)),
+                   cast<ConstantInt>(CV->getAggregateElement(0U)));
+    case 2:
+      return Range(cast<ConstantInt>(CV->getAggregateElement(0U)),
+                   cast<ConstantInt>(CV->getAggregateElement(1)));
+    default:
+      assert(0 && "Only pairs and single numbers are allowed here.");
+      return Range();
+    }    
+  }
+  
+  const Range getItem(unsigned idx) const {
+    const Constant *CV = Array->getAggregateElement(idx);
+    
+    unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements();
+    switch (NumEls) {
+    case 1:
+      return Range(cast<ConstantInt>(
+                     const_cast<Constant*>(CV->getAggregateElement(0U))),
+                   cast<ConstantInt>(
+                     const_cast<Constant*>(CV->getAggregateElement(0U))));
+    case 2:
+      return Range(cast<ConstantInt>(
+                     const_cast<Constant*>(CV->getAggregateElement(0U))),
+                   cast<ConstantInt>(
+                     const_cast<Constant*>(CV->getAggregateElement(1))));
+    default:
+      assert(0 && "Only pairs and single numbers are allowed here.");
+      return Range();
+    }    
+  }
+  
+  /// Return number of items (ranges) stored in set.
+  unsigned getNumItems() const {
+    return cast<ArrayType>(Array->getType())->getNumElements();
+  }
+  
+  /// Returns set the size, that equals number of all values + sizes of all
+  /// ranges.
+  /// Ranges set is considered as flat numbers collection.
+  /// E.g.: for range [<0>, <1>, <4,8>] the size will 7;
+  ///       for range [<0>, <1>, <5>] the size will 3
+  unsigned getSize() const {
+    APInt sz(getItem(0).Low->getBitWidth(), 0);
+    for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
+      const APInt &S = getItem(i).High->getValue() - getItem(i).Low->getValue();
+      sz += S;
+    }
+    return sz.getZExtValue();    
+  }
+  
+  /// Allows to access single value even if it belongs to some range.
+  /// Ranges set is considered as flat numbers collection.
+  /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] 
+  /// For range [<1>, <4,8>] getSingleValue(3) returns 6.
+  APInt getSingleValue(unsigned idx) const {
+    APInt sz(getItem(0).Low->getBitWidth(), 0);
+    for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
+      const APInt& S = getItem(i).High->getValue() - getItem(i).Low->getValue();
+      APInt oldSz = sz;
+      sz += S;
+      if (oldSz.uge(i) && sz.ult(i)) {
+        APInt Res = getItem(i).Low->getValue();
+        APInt Offset(oldSz.getBitWidth(), i);
+        Offset -= oldSz;
+        Res += Offset;
+        return Res;
+      }
+    }
+    assert(0 && "Index exceeds high border.");
+    return sz;    
+  }
+};  
+
+}
+
+#endif /* CONSTANTRANGESSET_H_ */





More information about the llvm-commits mailing list