mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-05 10:17:36 +00:00
[IR] Add a makeNoWrapRegion
method to ConstantRange
Summary: This will be used in a future change to ScalarEvolution. Reviewers: hfinkel, reames, nlewycky Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D13612 llvm-svn: 250975
This commit is contained in:
parent
b7c31d3a27
commit
e4442f028b
@ -82,6 +82,17 @@ public:
|
||||
static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
|
||||
const ConstantRange &Other);
|
||||
|
||||
/// Return the largest range containing all X such that "X BinOpC C" does not
|
||||
/// wrap (overflow).
|
||||
///
|
||||
/// Example:
|
||||
/// typedef OverflowingBinaryOperator OBO;
|
||||
/// makeNoWrapRegion(Add, i8 1, OBO::NoSignedWrap) == [-128, 127)
|
||||
/// makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap) == [0, -1)
|
||||
/// makeNoWrapRegion(Add, i8 0, OBO::NoUnsignedWrap) == Full Set
|
||||
static ConstantRange makeNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
const APInt &C, unsigned NoWrapKind);
|
||||
|
||||
/// Return the lower value for this range.
|
||||
///
|
||||
const APInt &getLower() const { return Lower; }
|
||||
|
@ -21,7 +21,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/IR/ConstantRange.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@ -125,6 +127,57 @@ ConstantRange ConstantRange::makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
|
||||
.inverse();
|
||||
}
|
||||
|
||||
ConstantRange ConstantRange::makeNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
const APInt &C,
|
||||
unsigned NoWrapKind) {
|
||||
typedef OverflowingBinaryOperator OBO;
|
||||
|
||||
// Computes the intersection of CR0 and CR1. It is different from
|
||||
// intersectWith in that the ConstantRange returned will only contain elements
|
||||
// in both CR0 and CR1 (i.e. SubsetIntersect(X, Y) is a *subset*, proper or
|
||||
// not, of both X and Y).
|
||||
auto SubsetIntersect =
|
||||
[](const ConstantRange &CR0, const ConstantRange &CR1) {
|
||||
return CR0.inverse().unionWith(CR1.inverse()).inverse();
|
||||
};
|
||||
|
||||
assert(BinOp >= Instruction::BinaryOpsBegin &&
|
||||
BinOp < Instruction::BinaryOpsEnd && "Binary operators only!");
|
||||
|
||||
assert((NoWrapKind == OBO::NoSignedWrap ||
|
||||
NoWrapKind == OBO::NoUnsignedWrap ||
|
||||
NoWrapKind == (OBO::NoUnsignedWrap | OBO::NoSignedWrap)) &&
|
||||
"NoWrapKind invalid!");
|
||||
|
||||
unsigned BitWidth = C.getBitWidth();
|
||||
if (BinOp != Instruction::Add)
|
||||
// Conservative answer: empty set
|
||||
return ConstantRange(BitWidth, false);
|
||||
|
||||
if (C.isMinValue())
|
||||
// Full set: nothing signed / unsigned wraps when added to 0.
|
||||
return ConstantRange(BitWidth);
|
||||
|
||||
ConstantRange Result(BitWidth);
|
||||
|
||||
if (NoWrapKind & OBO::NoUnsignedWrap)
|
||||
Result = SubsetIntersect(Result,
|
||||
ConstantRange(APInt::getNullValue(BitWidth), -C));
|
||||
|
||||
if (NoWrapKind & OBO::NoSignedWrap) {
|
||||
if (C.isStrictlyPositive())
|
||||
Result = SubsetIntersect(
|
||||
Result, ConstantRange(APInt::getSignedMinValue(BitWidth),
|
||||
APInt::getSignedMinValue(BitWidth) - C));
|
||||
else
|
||||
Result = SubsetIntersect(
|
||||
Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - C,
|
||||
APInt::getSignedMinValue(BitWidth)));
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// isFullSet - Return true if this set contains all of the elements possible
|
||||
/// for this data-type
|
||||
bool ConstantRange::isFullSet() const {
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "llvm/IR/ConstantRange.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -568,4 +569,55 @@ TEST(ConstantRange, MakeSatisfyingICmpRegion) {
|
||||
ConstantRange(APInt(8, 4), APInt(8, -128)));
|
||||
}
|
||||
|
||||
TEST(ConstantRange, MakeOverflowingRegion) {
|
||||
const int IntMin4Bits = 8;
|
||||
const int IntMax4Bits = 7;
|
||||
typedef OverflowingBinaryOperator OBO;
|
||||
|
||||
for (int Const : {0, -1, -2, 1, 2, IntMin4Bits, IntMax4Bits}) {
|
||||
APInt C(4, Const, true /* = isSigned */);
|
||||
|
||||
auto NUWRegion =
|
||||
ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoUnsignedWrap);
|
||||
|
||||
EXPECT_FALSE(NUWRegion.isEmptySet());
|
||||
|
||||
auto NSWRegion =
|
||||
ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoSignedWrap);
|
||||
|
||||
EXPECT_FALSE(NSWRegion.isEmptySet());
|
||||
|
||||
auto NoWrapRegion = ConstantRange::makeNoWrapRegion(
|
||||
Instruction::Add, C, OBO::NoSignedWrap | OBO::NoUnsignedWrap);
|
||||
|
||||
EXPECT_FALSE(NoWrapRegion.isEmptySet());
|
||||
EXPECT_TRUE(NUWRegion.intersectWith(NSWRegion).contains(NoWrapRegion));
|
||||
|
||||
for (APInt I = NUWRegion.getLower(), E = NUWRegion.getUpper(); I != E;
|
||||
++I) {
|
||||
bool Overflow = false;
|
||||
I.uadd_ov(C, Overflow);
|
||||
EXPECT_FALSE(Overflow);
|
||||
}
|
||||
|
||||
for (APInt I = NSWRegion.getLower(), E = NSWRegion.getUpper(); I != E;
|
||||
++I) {
|
||||
bool Overflow = false;
|
||||
I.sadd_ov(C, Overflow);
|
||||
EXPECT_FALSE(Overflow);
|
||||
}
|
||||
|
||||
for (APInt I = NoWrapRegion.getLower(), E = NoWrapRegion.getUpper(); I != E;
|
||||
++I) {
|
||||
bool Overflow = false;
|
||||
|
||||
I.sadd_ov(C, Overflow);
|
||||
EXPECT_FALSE(Overflow);
|
||||
|
||||
I.uadd_ov(C, Overflow);
|
||||
EXPECT_FALSE(Overflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user