mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-12 15:51:35 +00:00
[ConstantRange] Make getEquivalentICmp smarter
This change teaches getEquivalentICmp to be smarter about generating ICMP_NE and ICMP_EQ predicates. An earlier version of this change was landed as rL283057 which had a use-after-free bug. This new version has a fix for that bug, and a (C++ unittests/) test case that would have triggered it rL283057. llvm-svn: 283078
This commit is contained in:
parent
cc2b5dd90f
commit
26178861cc
@ -166,6 +166,14 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If this set contains all but a single element, return it, otherwise return
|
||||
/// null.
|
||||
const APInt *getSingleMissingElement() const {
|
||||
if (Lower == Upper + 1)
|
||||
return &Upper;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Return true if this set contains exactly one member.
|
||||
///
|
||||
bool isSingleElement() const { return getSingleElement() != nullptr; }
|
||||
|
@ -147,6 +147,14 @@ bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred,
|
||||
Pred = isEmptySet() ? CmpInst::ICMP_ULT : CmpInst::ICMP_UGE;
|
||||
RHS = APInt(getBitWidth(), 0);
|
||||
Success = true;
|
||||
} else if (auto *OnlyElt = getSingleElement()) {
|
||||
Pred = CmpInst::ICMP_EQ;
|
||||
RHS = *OnlyElt;
|
||||
Success = true;
|
||||
} else if (auto *OnlyMissingElt = getSingleMissingElement()) {
|
||||
Pred = CmpInst::ICMP_NE;
|
||||
RHS = *OnlyMissingElt;
|
||||
Success = true;
|
||||
} else if (getLower().isMinSignedValue() || getLower().isMinValue()) {
|
||||
Pred =
|
||||
getLower().isMinSignedValue() ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT;
|
||||
|
@ -102,10 +102,19 @@ TEST_F(ConstantRangeTest, Equality) {
|
||||
TEST_F(ConstantRangeTest, SingleElement) {
|
||||
EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(nullptr));
|
||||
EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(nullptr));
|
||||
EXPECT_EQ(Full.getSingleMissingElement(), static_cast<APInt *>(nullptr));
|
||||
EXPECT_EQ(Empty.getSingleMissingElement(), static_cast<APInt *>(nullptr));
|
||||
|
||||
EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa));
|
||||
EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(nullptr));
|
||||
EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(nullptr));
|
||||
|
||||
EXPECT_EQ(One.getSingleMissingElement(), static_cast<APInt *>(nullptr));
|
||||
EXPECT_EQ(Some.getSingleMissingElement(), static_cast<APInt *>(nullptr));
|
||||
|
||||
ConstantRange OneInverse = One.inverse();
|
||||
EXPECT_EQ(*OneInverse.getSingleMissingElement(), *One.getSingleElement());
|
||||
|
||||
EXPECT_FALSE(Full.isSingleElement());
|
||||
EXPECT_FALSE(Empty.isSingleElement());
|
||||
EXPECT_TRUE(One.isSingleElement());
|
||||
@ -760,6 +769,42 @@ TEST(ConstantRange, GetEquivalentICmp) {
|
||||
EXPECT_FALSE(ConstantRange(APInt::getMinValue(32) - APInt(32, 100),
|
||||
APInt::getMinValue(32) + APInt(32, 100))
|
||||
.getEquivalentICmp(Pred, RHS));
|
||||
|
||||
EXPECT_TRUE(ConstantRange(APInt(32, 100)).getEquivalentICmp(Pred, RHS));
|
||||
EXPECT_EQ(Pred, CmpInst::ICMP_EQ);
|
||||
EXPECT_EQ(RHS, APInt(32, 100));
|
||||
|
||||
EXPECT_TRUE(
|
||||
ConstantRange(APInt(32, 100)).inverse().getEquivalentICmp(Pred, RHS));
|
||||
EXPECT_EQ(Pred, CmpInst::ICMP_NE);
|
||||
EXPECT_EQ(RHS, APInt(32, 100));
|
||||
|
||||
EXPECT_TRUE(
|
||||
ConstantRange(APInt(512, 100)).inverse().getEquivalentICmp(Pred, RHS));
|
||||
EXPECT_EQ(Pred, CmpInst::ICMP_NE);
|
||||
EXPECT_EQ(RHS, APInt(512, 100));
|
||||
|
||||
// NB! It would be correct for the following four calls to getEquivalentICmp
|
||||
// to return ordered predicates like CmpInst::ICMP_ULT or CmpInst::ICMP_UGT.
|
||||
// However, that's not the case today.
|
||||
|
||||
EXPECT_TRUE(ConstantRange(APInt(32, 0)).getEquivalentICmp(Pred, RHS));
|
||||
EXPECT_EQ(Pred, CmpInst::ICMP_EQ);
|
||||
EXPECT_EQ(RHS, APInt(32, 0));
|
||||
|
||||
EXPECT_TRUE(
|
||||
ConstantRange(APInt(32, 0)).inverse().getEquivalentICmp(Pred, RHS));
|
||||
EXPECT_EQ(Pred, CmpInst::ICMP_NE);
|
||||
EXPECT_EQ(RHS, APInt(32, 0));
|
||||
|
||||
EXPECT_TRUE(ConstantRange(APInt(32, -1)).getEquivalentICmp(Pred, RHS));
|
||||
EXPECT_EQ(Pred, CmpInst::ICMP_EQ);
|
||||
EXPECT_EQ(RHS, APInt(32, -1));
|
||||
|
||||
EXPECT_TRUE(
|
||||
ConstantRange(APInt(32, -1)).inverse().getEquivalentICmp(Pred, RHS));
|
||||
EXPECT_EQ(Pred, CmpInst::ICMP_NE);
|
||||
EXPECT_EQ(RHS, APInt(32, -1));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user