summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Instructions.h4
-rw-r--r--include/llvm/Support/IntegersSubset.h222
-rw-r--r--include/llvm/Support/IntegersSubsetMapping.h6
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp4
-rw-r--r--lib/VMCore/Verifier.cpp4
5 files changed, 142 insertions, 98 deletions
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index 89a5a307f2..99186f5f50 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -2552,13 +2552,13 @@ public:
/// that it is handled by the default handler.
CaseIt findCaseValue(const ConstantInt *C) {
for (CaseIt i = case_begin(), e = case_end(); i != e; ++i)
- if (i.getCaseValueEx().isSatisfies(C->getValue()))
+ if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C)))
return i;
return case_default();
}
ConstCaseIt findCaseValue(const ConstantInt *C) const {
for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i)
- if (i.getCaseValueEx().isSatisfies(C->getValue()))
+ if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C)))
return i;
return case_default();
}
diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h
index 894b104da9..b0cfd85a9b 100644
--- a/include/llvm/Support/IntegersSubset.h
+++ b/include/llvm/Support/IntegersSubset.h
@@ -25,88 +25,143 @@
namespace llvm {
-template <class ImplTy>
-class IntItemBase {
-protected:
- ImplTy Implementation;
- typedef IntItemBase<ImplTy> self;
-public:
-
- IntItemBase() {}
-
- IntItemBase(const ImplTy &impl) : Implementation(impl) {}
+ // The IntItem is a wrapper for APInt.
+ // 1. It determines sign of integer, it allows to use
+ // comparison operators >,<,>=,<=, and as result we got shorter and cleaner
+ // constructions.
+ // 2. It helps to implement PR1255 (case ranges) as a series of small patches.
+ // 3. Currently we can interpret IntItem both as ConstantInt and as APInt.
+ // It allows to provide SwitchInst methods that works with ConstantInt for
+ // non-updated passes. And it allows to use APInt interface for new methods.
+ // 4. IntItem can be easily replaced with APInt.
- // implicit
- IntItemBase(const APInt& src) : Implementation(src) {}
-
- operator const APInt&() const {
- return (const APInt&)Implementation;
+ // The set of macros that allows to propagate APInt operators to the IntItem.
+
+#define INT_ITEM_DEFINE_COMPARISON(op,func) \
+ bool operator op (const APInt& RHS) const { \
+ return ConstantIntVal->getValue().func(RHS); \
}
- bool operator<(const self& RHS) const {
- return ((const APInt&)*this).ult(RHS);
+
+#define INT_ITEM_DEFINE_UNARY_OP(op) \
+ IntItem operator op () const { \
+ APInt res = op(ConstantIntVal->getValue()); \
+ Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
+ return IntItem(cast<ConstantInt>(NewVal)); \
}
- bool operator==(const self& RHS) const {
- return (const APInt&)*this == (const APInt&)RHS;
+
+#define INT_ITEM_DEFINE_BINARY_OP(op) \
+ IntItem operator op (const APInt& RHS) const { \
+ APInt res = ConstantIntVal->getValue() op RHS; \
+ Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
+ return IntItem(cast<ConstantInt>(NewVal)); \
}
- bool operator!=(const self& RHS) const {
- return (const APInt&)*this != (const APInt&)RHS;
+
+#define INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(op) \
+ IntItem& operator op (const APInt& RHS) {\
+ APInt res = ConstantIntVal->getValue();\
+ res op RHS; \
+ Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
+ ConstantIntVal = cast<ConstantInt>(NewVal); \
+ return *this; \
}
- 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();
+
+#define INT_ITEM_DEFINE_PREINCDEC(op) \
+ IntItem& operator op () { \
+ APInt res = ConstantIntVal->getValue(); \
+ op(res); \
+ Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
+ ConstantIntVal = cast<ConstantInt>(NewVal); \
+ return *this; \
+ }
+
+#define INT_ITEM_DEFINE_POSTINCDEC(op) \
+ IntItem& operator op (int) { \
+ APInt res = ConstantIntVal->getValue();\
+ op(res); \
+ Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
+ OldConstantIntVal = ConstantIntVal; \
+ ConstantIntVal = cast<ConstantInt>(NewVal); \
+ return IntItem(OldConstantIntVal); \
+ }
+
+#define INT_ITEM_DEFINE_OP_STANDARD_INT(RetTy, op, IntTy) \
+ RetTy operator op (IntTy RHS) const { \
+ return (*this) op APInt(ConstantIntVal->getValue().getBitWidth(), RHS); \
}
- operator const ConstantInt*() {
- return ConstantIntVal;
- }
-};
-class IntItem : public IntItemBase<IntItemConstantIntImpl> {
- typedef IntItemBase<IntItemConstantIntImpl> ParentTy;
- IntItem(const IntItemConstantIntImpl& Impl) : ParentTy(Impl) {}
+class IntItem {
+ ConstantInt *ConstantIntVal;
+ IntItem(const ConstantInt *V) : ConstantIntVal(const_cast<ConstantInt*>(V)) {}
public:
IntItem() {}
- // implicit
- IntItem(const APInt& src) : ParentTy(src) {}
+ operator const APInt&() const {
+ return (const APInt&)ConstantIntVal->getValue();
+ }
+
+ // Propogate APInt operators.
+ // Note, that
+ // /,/=,>>,>>= are not implemented in APInt.
+ // <<= is implemented for unsigned RHS, but not implemented for APInt RHS.
+
+ INT_ITEM_DEFINE_COMPARISON(<, ult);
+ INT_ITEM_DEFINE_COMPARISON(>, ugt);
+ INT_ITEM_DEFINE_COMPARISON(<=, ule);
+ INT_ITEM_DEFINE_COMPARISON(>=, uge);
+ INT_ITEM_DEFINE_COMPARISON(==, eq);
+ INT_ITEM_DEFINE_COMPARISON(!=, ne);
+
+ INT_ITEM_DEFINE_BINARY_OP(*);
+ INT_ITEM_DEFINE_BINARY_OP(+);
+ INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,+,uint64_t);
+ INT_ITEM_DEFINE_BINARY_OP(-);
+ INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,-,uint64_t);
+ INT_ITEM_DEFINE_BINARY_OP(<<);
+ INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,<<,unsigned);
+ INT_ITEM_DEFINE_BINARY_OP(&);
+ INT_ITEM_DEFINE_BINARY_OP(^);
+ INT_ITEM_DEFINE_BINARY_OP(|);
+
+ INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(*=);
+ INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(+=);
+ INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(-=);
+ INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(&=);
+ INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(^=);
+ INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(|=);
+
+ // Special case for <<=
+ IntItem& operator <<= (unsigned RHS) {
+ APInt res = ConstantIntVal->getValue();
+ res <<= RHS;
+ Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res);
+ ConstantIntVal = cast<ConstantInt>(NewVal);
+ return *this;
+ }
+
+ INT_ITEM_DEFINE_UNARY_OP(-);
+ INT_ITEM_DEFINE_UNARY_OP(~);
+
+ INT_ITEM_DEFINE_PREINCDEC(++);
+ INT_ITEM_DEFINE_PREINCDEC(--);
+
+ // The set of workarounds, since currently we use ConstantInt implemented
+ // integer.
static IntItem fromConstantInt(const ConstantInt *V) {
- IntItemConstantIntImpl Impl(V);
- return IntItem(Impl);
+ return IntItem(V);
}
static IntItem fromType(Type* Ty, const APInt& V) {
ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V));
return fromConstantInt(C);
}
+ static IntItem withImplLikeThis(const IntItem& LikeThis, const APInt& V) {
+ ConstantInt *C = cast<ConstantInt>(ConstantInt::get(
+ LikeThis.ConstantIntVal->getContext(), V));
+ return fromConstantInt(C);
+ }
ConstantInt *toConstantInt() {
- return const_cast<ConstantInt*>((const ConstantInt*)Implementation);
+ return ConstantIntVal;
}
};
@@ -145,24 +200,19 @@ struct IntRange {
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 (Low->ult(RHS.Low))
+ if (Low == RHS.Low) {
+ if (High > RHS.High)
return true;
return false;
- } else
- return Low->getBitWidth() < RHS.Low->getBitWidth();
+ }
+ if (Low < RHS.Low)
+ return true;
+ return false;
}
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 == RHS.Low && High == RHS.High;
}
@@ -171,18 +221,12 @@ struct IntRange {
}
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 - *LHS.Low;
- APInt RSize = *RHS.High - *RHS.Low;
- return LSize.ult(RSize);
+ return (LHS.High - LHS.Low) < (RHS.High - RHS.Low);
}
- bool isInRange(const APInt &IntVal) const {
+ bool isInRange(const IntItem &IntVal) const {
assert(!IsEmpty && "Range is empty.");
- if (IntVal.getBitWidth() != Low->getBitWidth())
- return false;
- return IntVal.uge(Low) && IntVal.ule(High);
+ return IntVal >= Low && IntVal <= High;
}
SubRes sub(const IntRange &RHS) const {
@@ -200,14 +244,14 @@ struct IntRange {
return Res;
}
- if (Low->ult(RHS.Low)) {
+ if (Low < RHS.Low) {
Res.first.Low = Low;
- APInt NewHigh = RHS.Low;
+ IntItem NewHigh = RHS.Low;
--NewHigh;
Res.first.High = NewHigh;
}
- if (High->ugt(RHS.High)) {
- APInt NewLow = RHS.High;
+ if (High > RHS.High) {
+ IntItem NewLow = RHS.High;
++NewLow;
Res.second.Low = NewLow;
Res.second.High = High;
@@ -332,7 +376,7 @@ public:
/// 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);
+ APInt sz(((const APInt&)getItem(0).Low).getBitWidth(), 0);
for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
const APInt &Low = getItem(i).Low;
const APInt &High = getItem(i).High;
@@ -347,7 +391,7 @@ public:
/// [<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);
+ APInt sz(((const APInt&)getItem(0).Low).getBitWidth(), 0);
for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
const APInt &Low = getItem(i).Low;
const APInt &High = getItem(i).High;
diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h
index eaa2f5be2f..374a68772e 100644
--- a/include/llvm/Support/IntegersSubsetMapping.h
+++ b/include/llvm/Support/IntegersSubsetMapping.h
@@ -67,7 +67,7 @@ protected:
bool Sorted;
bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
- return LItem->first.High->uge(RItem->first.Low);
+ return LItem->first.High >= RItem->first.Low;
}
bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) {
@@ -79,7 +79,7 @@ protected:
APInt RLow = RItem->first.Low;
if (RLow != APInt::getNullValue(RLow.getBitWidth()))
--RLow;
- return LItem->first.High->uge(RLow);
+ return LItem->first.High >= RLow;
}
void sort() {
@@ -159,7 +159,7 @@ public:
if (isJoinable(i, j)) {
IntItem *CurHigh = &j->first.High;
++Weight;
- if ((*CurHigh)->ugt(*High))
+ if (*CurHigh > *High)
High = CurHigh;
} else {
RangeEx R(*Low, *High, Weight);
diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp
index d54010195d..d4b6ed0003 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -655,8 +655,8 @@ void Interpreter::visitSwitchInst(SwitchInst &I) {
for (unsigned n = 0, en = Case.getNumItems(); n != en; ++n) {
IntegersSubset::Range r = Case.getItem(n);
// FIXME: Currently work with ConstantInt based numbers.
- const ConstantInt *LowCI = r.Low.getImplementation();
- const ConstantInt *HighCI = r.High.getImplementation();
+ const ConstantInt *LowCI = r.Low.toConstantInt();
+ const ConstantInt *HighCI = r.High.toConstantInt();
GenericValue Low = getOperandValue(const_cast<ConstantInt*>(LowCI), SF);
GenericValue High = getOperandValue(const_cast<ConstantInt*>(HighCI), SF);
if (executeICMP_ULE(Low, CondVal, ElTy).IntVal != 0 &&
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index e093c52f99..7afe342899 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -813,9 +813,9 @@ void Verifier::visitSwitchInst(SwitchInst &SI) {
IntegersSubset CaseRanges = i.getCaseValueEx();
for (unsigned ri = 0, rie = CaseRanges.getNumItems(); ri < rie; ++ri) {
IntegersSubset::Range r = CaseRanges.getItem(ri);
- Assert1(r.Low->getBitWidth() == IntTy->getBitWidth(),
+ Assert1(((const APInt&)r.Low).getBitWidth() == IntTy->getBitWidth(),
"Switch constants must all be same type as switch value!", &SI);
- Assert1(r.High->getBitWidth() == IntTy->getBitWidth(),
+ Assert1(((const APInt&)r.High).getBitWidth() == IntTy->getBitWidth(),
"Switch constants must all be same type as switch value!", &SI);
Mapping.add(r);
RangeSetMap[r] = i.getCaseIndex();