[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