summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2017-11-19 15:34:27 +0000
committerSanjay Patel <spatel@rotateright.com>2017-11-19 15:34:27 +0000
commiteb731b09f3cbea16487d1abc63029d5fa2d899b2 (patch)
tree726b0ff4495a502662e7ec77d2c27db93cee5ed5 /llvm/lib
parentd7ff94f0357b6c16e39ac39d0e336a2280d0d05b (diff)
downloadbcm5719-llvm-eb731b09f3cbea16487d1abc63029d5fa2d899b2.tar.gz
bcm5719-llvm-eb731b09f3cbea16487d1abc63029d5fa2d899b2.zip
[InstSimplify] fold and/or of fcmp ord/uno when operand is known nnan
The 'ord' and 'uno' predicates have a logic operation for NAN built into their definitions: FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) So we can simplify patterns like this: (fcmp ord (known NNAN), X) && (fcmp ord X, Y) --> fcmp ord X, Y (fcmp uno (known NNAN), X) || (fcmp uno X, Y) --> fcmp uno X, Y It might be better to split this into (X uno 0) | (Y uno 0) as a canonicalization, but that would be another patch. Differential Revision: https://reviews.llvm.org/D40130 llvm-svn: 318627
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp60
1 files changed, 51 insertions, 9 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 78ae0abf2a1..76af3dcd90e 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1550,7 +1550,44 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
return nullptr;
}
-static Value *simplifyAndOrOfICmps(Value *Op0, Value *Op1, bool IsAnd) {
+static Value *simplifyAndOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd) {
+ Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
+ Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
+ if (LHS0->getType() != RHS0->getType())
+ return nullptr;
+
+ FCmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
+ if ((PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD && IsAnd) ||
+ (PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO && !IsAnd)) {
+ // (fcmp ord NNAN, X) & (fcmp ord X, Y) --> fcmp ord X, Y
+ // (fcmp ord NNAN, X) & (fcmp ord Y, X) --> fcmp ord Y, X
+ // (fcmp ord X, NNAN) & (fcmp ord X, Y) --> fcmp ord X, Y
+ // (fcmp ord X, NNAN) & (fcmp ord Y, X) --> fcmp ord Y, X
+ // (fcmp uno NNAN, X) | (fcmp uno X, Y) --> fcmp uno X, Y
+ // (fcmp uno NNAN, X) | (fcmp uno Y, X) --> fcmp uno Y, X
+ // (fcmp uno X, NNAN) | (fcmp uno X, Y) --> fcmp uno X, Y
+ // (fcmp uno X, NNAN) | (fcmp uno Y, X) --> fcmp uno Y, X
+ if ((isKnownNeverNaN(LHS0) && (LHS1 == RHS0 || LHS1 == RHS1)) ||
+ (isKnownNeverNaN(LHS1) && (LHS0 == RHS0 || LHS0 == RHS1)))
+ return RHS;
+
+ // (fcmp ord X, Y) & (fcmp ord NNAN, X) --> fcmp ord X, Y
+ // (fcmp ord Y, X) & (fcmp ord NNAN, X) --> fcmp ord Y, X
+ // (fcmp ord X, Y) & (fcmp ord X, NNAN) --> fcmp ord X, Y
+ // (fcmp ord Y, X) & (fcmp ord X, NNAN) --> fcmp ord Y, X
+ // (fcmp uno X, Y) | (fcmp uno NNAN, X) --> fcmp uno X, Y
+ // (fcmp uno Y, X) | (fcmp uno NNAN, X) --> fcmp uno Y, X
+ // (fcmp uno X, Y) | (fcmp uno X, NNAN) --> fcmp uno X, Y
+ // (fcmp uno Y, X) | (fcmp uno X, NNAN) --> fcmp uno Y, X
+ if ((isKnownNeverNaN(RHS0) && (RHS1 == LHS0 || RHS1 == LHS1)) ||
+ (isKnownNeverNaN(RHS1) && (RHS0 == LHS0 || RHS0 == LHS1)))
+ return LHS;
+ }
+
+ return nullptr;
+}
+
+static Value *simplifyAndOrOfCmps(Value *Op0, Value *Op1, bool IsAnd) {
// Look through casts of the 'and' operands to find compares.
auto *Cast0 = dyn_cast<CastInst>(Op0);
auto *Cast1 = dyn_cast<CastInst>(Op1);
@@ -1560,13 +1597,18 @@ static Value *simplifyAndOrOfICmps(Value *Op0, Value *Op1, bool IsAnd) {
Op1 = Cast1->getOperand(0);
}
- auto *Cmp0 = dyn_cast<ICmpInst>(Op0);
- auto *Cmp1 = dyn_cast<ICmpInst>(Op1);
- if (!Cmp0 || !Cmp1)
- return nullptr;
+ Value *V = nullptr;
+ auto *ICmp0 = dyn_cast<ICmpInst>(Op0);
+ auto *ICmp1 = dyn_cast<ICmpInst>(Op1);
+ if (ICmp0 && ICmp1)
+ V = IsAnd ? simplifyAndOfICmps(ICmp0, ICmp1) :
+ simplifyOrOfICmps(ICmp0, ICmp1);
+
+ auto *FCmp0 = dyn_cast<FCmpInst>(Op0);
+ auto *FCmp1 = dyn_cast<FCmpInst>(Op1);
+ if (FCmp0 && FCmp1)
+ V = simplifyAndOrOfFCmps(FCmp0, FCmp1, IsAnd);
- Value *V =
- IsAnd ? simplifyAndOfICmps(Cmp0, Cmp1) : simplifyOrOfICmps(Cmp0, Cmp1);
if (!V)
return nullptr;
if (!Cast0)
@@ -1645,7 +1687,7 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return Op1;
}
- if (Value *V = simplifyAndOrOfICmps(Op0, Op1, true))
+ if (Value *V = simplifyAndOrOfCmps(Op0, Op1, true))
return V;
// Try some generic simplifications for associative operations.
@@ -1766,7 +1808,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B)))))
return Op0;
- if (Value *V = simplifyAndOrOfICmps(Op0, Op1, false))
+ if (Value *V = simplifyAndOrOfCmps(Op0, Op1, false))
return V;
// Try some generic simplifications for associative operations.
OpenPOWER on IntegriCloud