summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-03-21 17:17:13 +0000
committerSanjay Patel <spatel@rotateright.com>2018-03-21 17:17:13 +0000
commit778032f39d8aa5105f92a6ed70040e029d63397f (patch)
treedf5208f0c73cfc66f2652f5483a75373259d9827 /llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
parent87aec1b194bd1ae1a3aff49cb3d49cb82edcd7bc (diff)
downloadbcm5719-llvm-778032f39d8aa5105f92a6ed70040e029d63397f.tar.gz
bcm5719-llvm-778032f39d8aa5105f92a6ed70040e029d63397f.zip
[InstCombine] add folds for xor-of-icmp signbit tests (PR36682)
This is part of solving: https://bugs.llvm.org/show_bug.cgi?id=36682 There's also a leftover improvement from the long-ago-closed: https://bugs.llvm.org/show_bug.cgi?id=5438 https://rise4fun.com/Alive/dC1 llvm-svn: 328119
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 4a5a6d1ccbc..7c720d80092 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2363,6 +2363,36 @@ Value *InstCombiner::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
}
}
+ // TODO: This can be generalized to compares of non-signbits using
+ // decomposeBitTestICmp(). It could be enhanced more by using (something like)
+ // foldLogOpOfMaskedICmps().
+ ICmpInst::Predicate PredL = LHS->getPredicate();
+ ICmpInst::Predicate PredR = RHS->getPredicate();
+ Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
+ Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
+ if ((LHS->hasOneUse() || RHS->hasOneUse()) && PredL == PredR) {
+ // (X > -1) ^ (Y > -1) --> (X ^ Y) < 0
+ // (X < 0) ^ (Y < 0) --> (X ^ Y) < 0
+ if ((match(LHS1, m_AllOnes()) && match(RHS1, m_AllOnes()) &&
+ PredL == CmpInst::ICMP_SGT) ||
+ (match(LHS1, m_Zero()) && match(RHS1, m_Zero()) &&
+ PredL == CmpInst::ICMP_SLT)) {
+ Value *Zero = ConstantInt::getNullValue(LHS0->getType());
+ return Builder.CreateICmpSLT(Builder.CreateXor(LHS0, RHS0), Zero);
+ }
+ }
+ if ((LHS->hasOneUse() || RHS->hasOneUse())) {
+ // (X > -1) ^ (Y < 0) --> (X ^ Y) > -1
+ // (X < 0) ^ (Y > -1) --> (X ^ Y) > -1
+ if ((match(LHS1, m_AllOnes()) && match(RHS1, m_Zero()) &&
+ PredL == CmpInst::ICMP_SGT && PredR == CmpInst::ICMP_SLT) ||
+ (match(LHS1, m_Zero()) && match(RHS1, m_AllOnes()) &&
+ PredL == CmpInst::ICMP_SLT && PredR == CmpInst::ICMP_SGT)) {
+ Value *MinusOne = ConstantInt::getAllOnesValue(LHS0->getType());
+ return Builder.CreateICmpSGT(Builder.CreateXor(LHS0, RHS0), MinusOne);
+ }
+ }
+
// Instead of trying to imitate the folds for and/or, decompose this 'xor'
// into those logic ops. That is, try to turn this into an and-of-icmps
// because we have many folds for that pattern.
OpenPOWER on IntegriCloud