-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[InstCombine] Generalise optimisation of redundant floating point comparisons with ConstantFPRange
#159315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[InstCombine] Generalise optimisation of redundant floating point comparisons with ConstantFPRange
#159315
Conversation
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: Rajveer Singh Bharadwaj (Rajveer100) ChangesFollow up of #158097 Similar to Full diff: https://github.com/llvm/llvm-project/pull/159315.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 100fa428cb842..ffe0b2dd6f6ff 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -35,6 +35,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
+#include "llvm/IR/ConstantFPRange.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
@@ -1812,6 +1813,49 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1,
return nullptr;
}
+/// Test if a pair of compares with a shared operand and 2 constants has an
+/// empty set intersection, full set union, or if one compare is a superset of
+/// the other.
+static Value *simplifyAndOrOfFCmpsWithConstants(FCmpInst *Cmp0, FCmpInst *Cmp1,
+ bool IsAnd) {
+ // Look for this pattern: {and/or} (fcmp X, C0), (fcmp X, C1)).
+ if (Cmp0->getOperand(0) != Cmp1->getOperand(0))
+ return nullptr;
+
+ const APFloat *C0, *C1;
+ if (!match(Cmp0->getOperand(1), m_APFloat(C0)) ||
+ !match(Cmp1->getOperand(1), m_APFloat(C1)))
+ return nullptr;
+
+ auto Range0 = ConstantFPRange::makeExactFCmpRegion(Cmp0->getPredicate(), *C0);
+ auto Range1 = ConstantFPRange::makeExactFCmpRegion(Cmp1->getPredicate(), *C1);
+
+ if (!Range0 || !Range1)
+ return nullptr;
+
+ // For and-of-compares, check if the intersection is empty:
+ // (fcmp X, C0) && (fcmp X, C1) --> empty set --> false
+ if (IsAnd && (*Range0).intersectWith(*Range1).isEmptySet())
+ return getFalse(Cmp0->getType());
+
+ // For or-of-compares, check if the union is full:
+ // (fcmp X, C0) || (fcmp X, C1) --> full set --> true
+ if (!IsAnd && (*Range0).unionWith(*Range1).isFullSet())
+ return getTrue(Cmp0->getType());
+
+ // Is one range a superset of the other?
+ // If this is and-of-compares, take the smaller set:
+ // (fcmp sgt X, 4) && (fcmp sgt X, 42) --> fcmp sgt X, 42
+ // If this is or-of-compares, take the larger set:
+ // (fcmp sgt X, 4) || (fcmp sgt X, 42) --> fcmp sgt X, 4
+ if ((*Range0).contains(*Range1))
+ return IsAnd ? Cmp1 : Cmp0;
+ if ((*Range1).contains(*Range0))
+ return IsAnd ? Cmp0 : Cmp1;
+
+ return nullptr;
+}
+
static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
FCmpInst *RHS, bool IsAnd) {
Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
@@ -1850,34 +1894,8 @@ static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
: ConstantInt::getBool(LHS->getType(), !IsAnd);
}
- Value *V0;
- const APFloat *V0Op1, *V1Op1;
- // (fcmp olt V0, V0Op1) || (fcmp olt V0, V1Op1)
- // --> fcmp olt V0, max(V0Op1, V1Op1)
- // (fcmp ogt V0, V0Op1) || (fcmp ogt V0, V1Op1)
- // --> fcmp ogt V0, max(V0Op1, V1Op1)
- //
- // (fcmp olt V0, V0Op1) && (fcmp olt V0, V1Op1)
- // --> fcmp olt V0, min(V0Op1, V1Op1)
- // (fcmp ogt V0, V0Op1) && (fcmp ogt V0, V1Op1)
- // --> fcmp ogt V0, min(V0Op1, V1Op1)
- if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Value(V0),
- m_APFloat(V0Op1))) &&
- match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Specific(V0),
- m_APFloat(V1Op1)))) {
- if (*V0Op1 > *V1Op1)
- return IsAnd ? RHS : LHS;
- if (*V1Op1 > *V0Op1)
- return IsAnd ? LHS : RHS;
- } else if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Value(V0),
- m_APFloat(V0Op1))) &&
- match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Specific(V0),
- m_APFloat(V1Op1)))) {
- if (*V0Op1 < *V1Op1)
- return IsAnd ? RHS : LHS;
- if (*V1Op1 < *V0Op1)
- return IsAnd ? LHS : RHS;
- }
+ if (auto *V = simplifyAndOrOfFCmpsWithConstants(LHS, RHS, IsAnd))
+ return V;
return nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/redundant-fcmp.ll b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll
index 0f5fe9fb9a1b2..5d1529ef0b214 100644
--- a/llvm/test/Transforms/InstCombine/redundant-fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll
@@ -45,8 +45,8 @@ define i1 @or_fcmp_redundant_or4(double %v0) {
ret i1 %v3
}
-define i1 @or_fcmp_redundant_or_neg1(double %v0) {
-; CHECK-LABEL: @or_fcmp_redundant_or_neg1(
+define i1 @or_fcmp_redundant_or_5(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or_5(
; CHECK-NEXT: [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02
; CHECK-NEXT: [[V2:%.*]] = fcmp ogt double [[V0]], 1.990000e+00
; CHECK-NEXT: [[V3:%.*]] = or i1 [[V1]], [[V2]]
@@ -58,8 +58,8 @@ define i1 @or_fcmp_redundant_or_neg1(double %v0) {
ret i1 %v3
}
-define i1 @or_fcmp_redundant_or_neg2(double %v0) {
-; CHECK-LABEL: @or_fcmp_redundant_or_neg2(
+define i1 @or_fcmp_redundant_or_6(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or_6(
; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02
; CHECK-NEXT: [[V2:%.*]] = fcmp olt double [[V0]], 1.990000e+00
; CHECK-NEXT: [[V3:%.*]] = or i1 [[V1]], [[V2]]
@@ -115,12 +115,9 @@ define i1 @or_fcmp_redundant_and4(double %v0) {
ret i1 %v3
}
-define i1 @or_fcmp_redundant_and_neg1(double %v0) {
-; CHECK-LABEL: @or_fcmp_redundant_and_neg1(
-; CHECK-NEXT: [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02
-; CHECK-NEXT: [[V2:%.*]] = fcmp ogt double [[V0]], 1.990000e+00
-; CHECK-NEXT: [[V3:%.*]] = and i1 [[V1]], [[V2]]
-; CHECK-NEXT: ret i1 [[V3]]
+define i1 @or_fcmp_redundant_and_5(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and_5(
+; CHECK-NEXT: ret i1 false
;
%v1 = fcmp olt double %v0, 1.000000e-02
%v2 = fcmp ogt double %v0, 1.990000e+00
@@ -128,8 +125,8 @@ define i1 @or_fcmp_redundant_and_neg1(double %v0) {
ret i1 %v3
}
-define i1 @or_fcmp_redundant_and_neg2(double %v0) {
-; CHECK-LABEL: @or_fcmp_redundant_and_neg2(
+define i1 @or_fcmp_redundant_and_6(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and_6(
; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02
; CHECK-NEXT: [[V2:%.*]] = fcmp olt double [[V0]], 1.990000e+00
; CHECK-NEXT: [[V3:%.*]] = and i1 [[V1]], [[V2]]
|
66ced86
to
5b032ab
Compare
5b032ab
to
a9d6669
Compare
llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll
Outdated
Show resolved
Hide resolved
…parisons with `ConstantFPRange` Follow up of llvm#158097 Similar to `simplifyAndOrOfICmpsWithConstants`, we can do so for floating point comparisons.
a9d6669
to
c06a312
Compare
4a99eb5
to
d58da88
Compare
@zyw-bot mfuzz |
d58da88
to
34646df
Compare
34646df
to
dd232fc
Compare
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG w/ tests fixed. Thank you!
Co-authored-by: Yingwei Zheng <[email protected]>
dd232fc
to
f95bdfc
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/65/builds/22918 Here is the relevant piece of the build log for the reference
|
Follow up of #158097
Similar to
simplifyAndOrOfICmpsWithConstants
, we can do so for floating point comparisons.