[InstSimplify] use ConstantRange to simplify more and-of-icmps
We can simplify (and (icmp X, C1), (icmp X, C2)) to one of the icmps in many cases.
I had to check some of these with Alive to prove to myself it's right, but everything
seems to check out. Eg, the code in instcombine was completely ignoring predicates with
mismatched signedness.
Handling or-of-icmps would be a follow-up step.
Differential Revision: https://reviews.llvm.org/D32143
llvm-svn: 301260
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 0f60f1b..be9beeb 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1575,6 +1575,7 @@
if (Value *X = simplifyAndOfICmpsWithSameOperands(Op0, Op1))
return X;
+ // FIXME: This should be shared with or-of-icmps.
// Look for this pattern: (icmp V, C0) & (icmp V, C1)).
Type *ITy = Op0->getType();
ICmpInst::Predicate Pred0, Pred1;
@@ -1584,10 +1585,16 @@
match(Op1, m_ICmp(Pred1, m_Specific(V), m_APInt(C1)))) {
// Make a constant range that's the intersection of the two icmp ranges.
// If the intersection is empty, we know that the result is false.
- auto Range0 = ConstantRange::makeAllowedICmpRegion(Pred0, *C0);
- auto Range1 = ConstantRange::makeAllowedICmpRegion(Pred1, *C1);
+ auto Range0 = ConstantRange::makeExactICmpRegion(Pred0, *C0);
+ auto Range1 = ConstantRange::makeExactICmpRegion(Pred1, *C1);
if (Range0.intersectWith(Range1).isEmptySet())
return getFalse(ITy);
+
+ // If a range is a superset of the other, the smaller set is all we need.
+ if (Range0.contains(Range1))
+ return Op1;
+ if (Range1.contains(Range0))
+ return Op0;
}
// (icmp (add V, C0), C1) & (icmp V, C0)