[ConstantRange] Make getEquivalentICmp smarter
authorSanjoy Das <sanjoy@playingwithpointers.com>
Sun, 2 Oct 2016 00:09:49 +0000 (00:09 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Sun, 2 Oct 2016 00:09:49 +0000 (00:09 +0000)
This change teaches getEquivalentICmp to be smarter about generating
ICMP_NE and ICMP_EQ predicates.

llvm-svn: 283057

llvm/lib/IR/ConstantRange.cpp
llvm/unittests/IR/ConstantRangeTest.cpp

index 0f5c712..0dbefc7 100644 (file)
@@ -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 = inverse().getSingleElement()) {
+    Pred = CmpInst::ICMP_NE;
+    RHS = *OnlyMissingElt;
+    Success = true;
   } else if (getLower().isMinSignedValue() || getLower().isMinValue()) {
     Pred =
         getLower().isMinSignedValue() ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT;
index f7a8a82..423f062 100644 (file)
@@ -760,6 +760,37 @@ 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));
+
+  // 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