namespace llvm {
-template <class SuccessorClass, bool IsReadonly>
+template <class SuccessorClass>
class CRSBuilderBase {
public:
- typedef ConstantRangesSet::RangeT<IsReadonly> RangeTy;
+ typedef ConstantRangesSet::Range RangeTy;
struct RangeEx : public RangeTy {
- typedef ConstantRangesSet::RangeT<IsReadonly> RangeTy;
- typedef typename RangeTy::ConstantIntTy ConstantIntTy;
+ typedef ConstantRangesSet::Range RangeTy;
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) :
+ RangeEx(const IntItem &C) : RangeTy(C), Weight(1) {}
+ RangeEx(const IntItem &L, const IntItem &H) : RangeTy(L, H), Weight(1) {}
+ RangeEx(const IntItem &L, const IntItem &H, unsigned W) :
RangeTy(L, H), Weight(W) {}
unsigned Weight;
};
bool Sorted;
bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
- return LItem->first.High->getValue().uge(RItem->first.Low->getValue());
+ return LItem->first.High->uge(RItem->first.Low);
}
bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) {
"Intersected items with different successors!");
return false;
}
- APInt RLow = RItem->first.Low->getValue();
+ APInt RLow = RItem->first.Low;
if (RLow != APInt::getNullValue(RLow.getBitWidth()))
--RLow;
- return LItem->first.High->getValue().uge(RLow);
+ return LItem->first.High->uge(RLow);
}
void sort() {
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
sort();
CaseItems OldItems = Items;
Items.clear();
- ConstantIntTy *Low = OldItems.begin()->first.Low;
- ConstantIntTy *High = OldItems.begin()->first.High;
+ IntItem *Low = &OldItems.begin()->first.Low;
+ IntItem *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;
+ IntItem *CurHigh = &j->first.High;
++Weight;
- if (CurHigh->getValue().ugt(High->getValue()))
+ if ((*CurHigh)->ugt(*High))
High = CurHigh;
} else {
- RangeEx R(Low, High, Weight);
+ RangeEx R(*Low, *High, Weight);
add(R, Successor);
- Low = j->first.Low;
- High = j->first.High;
+ Low = &j->first.Low;
+ High = &j->first.High;
Weight = 1;
Successor = j->second;
}
}
- RangeEx R(Low, High, Weight);
+ 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) {
+ void add(const IntItem &C, SuccessorClass *S = 0) {
RangeTy R(C);
add(R, S);
}
/// Adds a range.
- void add(ConstantIntTy *Low, ConstantIntTy *High, SuccessorClass *S = 0) {
+ void add(const IntItem &Low, const IntItem &High, SuccessorClass *S = 0) {
RangeTy R(Low, High);
add(R, S);
}
- void add(RangeTy &R, SuccessorClass *S = 0) {
+ void add(const RangeTy &R, SuccessorClass *S = 0) {
RangeEx REx = R;
add(REx, S);
}
- void add(RangeEx &R, SuccessorClass *S = 0) {
+ void add(const 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) {
+ void add(const ConstantRangesSet &CRS, SuccessorClass *S = 0) {
for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) {
RangeTy R = CRS.getItem(i);
add(R, S);
};
template <class SuccessorClass>
-class CRSBuilderT : public CRSBuilderBase<SuccessorClass, false> {
+class CRSBuilderT : public CRSBuilderBase<SuccessorClass> {
public:
- typedef typename CRSBuilderBase<SuccessorClass, false>::RangeTy RangeTy;
- typedef typename CRSBuilderBase<SuccessorClass, false>::RangeIterator
+ typedef typename CRSBuilderBase<SuccessorClass>::RangeTy RangeTy;
+ typedef typename CRSBuilderBase<SuccessorClass>::RangeIterator
RangeIterator;
private:
std::vector<Constant*> Elts;
Elts.reserve(Src.size());
for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) {
- const RangeTy &R = *i;
+ RangeTy &R = *i;
std::vector<Constant*> r;
- if (R.Low != R.High) {
+ if (R.isSingleNumber()) {
r.reserve(2);
- r.push_back(R.Low);
- r.push_back(R.High);
+ // FIXME: Since currently we have ConstantInt based numbers
+ // use hack-conversion of IntItem to ConstantInt
+ r.push_back(R.Low.toConstantInt());
+ r.push_back(R.High.toConstantInt());
} else {
r.reserve(1);
- r.push_back(R.Low);
+ r.push_back(R.Low.toConstantInt());
}
Constant *CV = ConstantVector::get(r);
Elts.push_back(CV);
class BasicBlock;
typedef CRSBuilderT<BasicBlock> CRSBuilder;
-typedef CRSBuilderBase<BasicBlock, true> CRSBuilderConst;
+typedef CRSBuilderBase<BasicBlock> CRSBuilderConst;
}
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/LLVMContext.h"
namespace llvm {
-class ConstantRangesSet;
+template <class ImplTy>
+class IntItemBase {
+protected:
+ ImplTy Implementation;
+ typedef IntItemBase<ImplTy> self;
+public:
+
+ IntItemBase() {}
+
+ IntItemBase(const ImplTy &impl) : Implementation(impl) {}
+
+ // implicit
+ IntItemBase(const APInt& src) : Implementation(src) {}
-template <bool IsReadonly> struct CRSConstantTypes {
- typedef ConstantInt ConstantIntTy;
- typedef ConstantRangesSet ConstantRangesSetTy;
+ operator const APInt&() const {
+ return (const APInt&)Implementation;
+ }
+ bool operator<(const self& RHS) const {
+ return ((const APInt&)*this).ult(RHS);
+ }
+ bool operator==(const self& RHS) const {
+ return (const APInt&)*this == (const APInt&)RHS;
+ }
+ bool operator!=(const self& RHS) const {
+ return (const APInt&)*this != (const APInt&)RHS;
+ }
+ self& operator=(const ImplTy& RHS) {
+ Implementation = RHS;
+ return *this;
+ }
+ const APInt* operator->() const {
+ return &((const APInt&)Implementation);
+ }
+ const APInt& operator*() const {
+ return ((const APInt&)Implementation);
+ }
+ // FIXME: Hack. Will removed.
+ ImplTy& getImplementation() {
+ return Implementation;
+ }
+};
+
+class IntItemConstantIntImpl {
+ const ConstantInt *ConstantIntVal;
+public:
+ IntItemConstantIntImpl() : ConstantIntVal(0) {}
+ IntItemConstantIntImpl(const ConstantInt *Val) : ConstantIntVal(Val) {}
+ IntItemConstantIntImpl(LLVMContext &Ctx, const APInt& src) {
+ ConstantIntVal = cast<ConstantInt>(ConstantInt::get(Ctx, src));
+ }
+ explicit IntItemConstantIntImpl(const APInt& src) {
+ ConstantIntVal =
+ cast<ConstantInt>(ConstantInt::get(llvm::getGlobalContext(), src));
+ }
+ operator const APInt&() const {
+ return ConstantIntVal->getValue();
+ }
+ operator const ConstantInt*() {
+ return ConstantIntVal;
+ }
};
-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;
+class IntItem : public IntItemBase<IntItemConstantIntImpl> {
+ typedef IntItemBase<IntItemConstantIntImpl> ParentTy;
+ IntItem(const IntItemConstantIntImpl& Impl) : ParentTy(Impl) {}
public:
- bool IsWide;
+ IntItem() {}
// implicit
- ConstantRangesSet(Constant *V) : Array(V) {
- ArrayType *ArrTy = cast<ArrayType>(Array->getType());
- VectorType *VecTy = cast<VectorType>(ArrTy->getElementType());
- IntegerType *IntTy = cast<IntegerType>(VecTy->getElementType());
- IsWide = IntTy->getBitWidth() > 64;
- }
+ IntItem(const APInt& src) : ParentTy(src) {}
- 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 {
+ static IntItem fromConstantInt(const ConstantInt *V) {
+ IntItemConstantIntImpl Impl(V);
+ return IntItem(Impl);
+ }
+ static IntItem fromType(Type* Ty, const APInt& V) {
+ ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V));
+ return fromConstantInt(C);
+ }
+ ConstantInt *toConstantInt() {
+ return const_cast<ConstantInt*>((const ConstantInt*)Implementation);
+ }
+};
+
+// TODO: it should be a class in next commit.
+struct IntRange {
+
+ IntItem Low;
+ IntItem High;
+ bool IsEmpty : 1;
+ bool IsSingleNumber : 1;
+// TODO:
+// public:
- typedef typename CRSConstantTypes<IsReadonly>::ConstantIntTy ConstantIntTy;
- typedef std::pair<RangeT, RangeT> SubRes;
+ typedef std::pair<IntRange, IntRange> 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) {}
+ IntRange() : IsEmpty(true) {}
+ IntRange(const IntRange &RHS) :
+ Low(RHS.Low), High(RHS.High), IsEmpty(false), IsSingleNumber(false) {}
+ IntRange(const IntItem &C) :
+ Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {}
+ IntRange(const IntItem &L, const IntItem &H) : Low(L), High(H),
+ IsEmpty(false), IsSingleNumber(false) {}
+
+ bool isEmpty() const { return IsEmpty; }
+ bool isSingleNumber() const { return IsSingleNumber; }
+
+ const IntItem& getLow() {
+ assert(!IsEmpty && "Range is empty.");
+ return Low;
+ }
+ const IntItem& getHigh() {
+ assert(!IsEmpty && "Range is empty.");
+ return High;
+ }
- 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))
+ bool operator<(const IntRange &RHS) const {
+ assert(!IsEmpty && "Left range is empty.");
+ assert(!RHS.IsEmpty && "Right range is empty.");
+ if (Low->getBitWidth() == RHS.Low->getBitWidth()) {
+ if (Low->eq(RHS.Low)) {
+ if (High->ult(RHS.High))
return true;
return false;
}
- if (LowInt.ult(RHSLowInt))
+ if (Low->ult(RHS.Low))
return true;
return false;
} else
- return LowInt.getBitWidth() < RHSLowInt.getBitWidth();
+ return Low->getBitWidth() < RHS.Low->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())
+ bool operator==(const IntRange &RHS) const {
+ assert(!IsEmpty && "Left range is empty.");
+ assert(!RHS.IsEmpty && "Right range is empty.");
+ if (Low->getBitWidth() != RHS.Low->getBitWidth())
return false;
- return Low->getValue() == RHS.Low->getValue() &&
- High->getValue() == RHS.High->getValue();
+ return Low == RHS.Low && High == RHS.High;
}
- bool operator!=(const RangeT &RHS) const {
+ bool operator!=(const IntRange &RHS) const {
return !operator ==(RHS);
}
- static bool LessBySize(const RangeT &LHS, const RangeT &RHS) {
+ static bool LessBySize(const IntRange &LHS, const IntRange &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();;
+ APInt LSize = *LHS.High - *LHS.Low;
+ APInt RSize = *RHS.High - *RHS.Low;
return LSize.ult(RSize);
}
bool isInRange(const APInt &IntVal) const {
- assert(Low && High && "Case range is not initialized.");
- if (IntVal.getBitWidth() != Low->getValue().getBitWidth())
+ assert(!IsEmpty && "Range is empty.");
+ if (IntVal.getBitWidth() != Low->getBitWidth())
return false;
- return IntVal.uge(Low->getValue()) && IntVal.ule(High->getValue());
+ return IntVal.uge(Low) && IntVal.ule(High);
}
- bool isInRange(const ConstantIntTy *CI) const {
- const APInt& IntVal = CI->getValue();
- return isInRange(IntVal);
- }
-
- SubRes sub(const RangeT &RHS) const {
+ SubRes sub(const IntRange &RHS) const {
SubRes Res;
// RHS is either more global and includes this range or
// 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 std::make_pair(IntRange(Low, High), IntRange());
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)) {
+ if (Low->ult(RHS.Low)) {
Res.first.Low = Low;
- Res.first.High = ConstantIntTy::get(RHS.Low->getContext(), --RHSLoInt);
+ APInt NewHigh = RHS.Low;
+ --NewHigh;
+ Res.first.High = NewHigh;
}
- if (HiInt.ugt(RHSHiInt)) {
- Res.second.Low = ConstantIntTy::get(RHS.High->getContext(), ++RHSHiInt);
+ if (High->ugt(RHS.High)) {
+ APInt NewLow = RHS.High;
+ ++NewLow;
+ Res.second.Low = NewLow;
Res.second.High = High;
}
return Res;
}
};
- typedef RangeT<false> Range;
+//===----------------------------------------------------------------------===//
+/// 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:
+
+ bool IsWide;
+
+ // implicit
+ ConstantRangesSet(Constant *V) : Array(V) {
+ ArrayType *ArrTy = cast<ArrayType>(Array->getType());
+ VectorType *VecTy = cast<VectorType>(ArrTy->getElementType());
+ IntegerType *IntTy = cast<IntegerType>(VecTy->getElementType());
+ IsWide = IntTy->getBitWidth() > 64;
+ }
+
+ operator Constant*() { return Array; }
+ operator const Constant*() const { return Array; }
+ Constant *operator->() { return Array; }
+ const Constant *operator->() const { return Array; }
+
+ typedef IntRange 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();
+ bool isSatisfies(const IntItem &CheckingVal) const {
for (unsigned i = 0, e = getNumItems(); i < e; ++i) {
const Constant *CV = Array->getAggregateElement(i);
unsigned VecSize = cast<VectorType>(CV->getType())->getNumElements();
unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements();
switch (NumEls) {
case 1:
- return Range(cast<ConstantInt>(CV->getAggregateElement(0U)),
- cast<ConstantInt>(CV->getAggregateElement(0U)));
+ return Range(IntItem::fromConstantInt(
+ cast<ConstantInt>(CV->getAggregateElement(0U))));
case 2:
- return Range(cast<ConstantInt>(CV->getAggregateElement(0U)),
- cast<ConstantInt>(CV->getAggregateElement(1)));
+ return Range(IntItem::fromConstantInt(
+ cast<ConstantInt>(CV->getAggregateElement(0U))),
+ IntItem::fromConstantInt(
+ cast<ConstantInt>(CV->getAggregateElement(1U))));
default:
assert(0 && "Only pairs and single numbers are allowed here.");
return Range();
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))));
+ return Range(IntItem::fromConstantInt(
+ cast<ConstantInt>(CV->getAggregateElement(0U))),
+ IntItem::fromConstantInt(cast<ConstantInt>(
+ cast<ConstantInt>(CV->getAggregateElement(0U)))));
case 2:
- return Range(cast<ConstantInt>(
- const_cast<Constant*>(CV->getAggregateElement(0U))),
- cast<ConstantInt>(
- const_cast<Constant*>(CV->getAggregateElement(1))));
+ return Range(IntItem::fromConstantInt(
+ cast<ConstantInt>(CV->getAggregateElement(0U))),
+ IntItem::fromConstantInt(
+ cast<ConstantInt>(CV->getAggregateElement(1))));
default:
assert(0 && "Only pairs and single numbers are allowed here.");
return Range();
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();
+ const APInt &Low = getItem(i).Low;
+ const APInt &High = getItem(i).High;
+ const APInt &S = High - Low;
sz += S;
}
return sz.getZExtValue();
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();
+ const APInt &Low = getItem(i).Low;
+ const APInt &High = getItem(i).High;
+ const APInt& S = High - Low;
APInt oldSz = sz;
sz += S;
if (oldSz.uge(i) && sz.ult(i)) {
- APInt Res = getItem(i).Low->getValue();
+ APInt Res = Low;
APInt Offset(oldSz.getBitWidth(), i);
Offset -= oldSz;
Res += Offset;