Skip to content

Commit 6840c5f

Browse files
committedSep 5, 2017
[ValueTracking, InstCombine] canonicalize fcmp ord/uno with non-NAN ops to null constants
This is a preliminary step towards solving the remaining part of PR27145 - IR for isfinite(): https://bugs.llvm.org/show_bug.cgi?id=27145 In order to solve that one more generally, we need to add matching for and/or of fcmp ord/uno with a constant operand. But while looking at those patterns, I realized we were missing a canonicalization for nonzero constants. Rather than limiting to just folds for constants, we're adding a general value tracking method for this based on an existing DAG helper. By transforming everything to 0.0, we can simplify the existing code in foldLogicOfFCmps() and pick up missing vector folds. Differential Revision: https://reviews.llvm.org/D37427 llvm-svn: 312591
1 parent 8db11a4 commit 6840c5f

File tree

7 files changed

+69
-35
lines changed

7 files changed

+69
-35
lines changed
 

‎llvm/include/llvm/Analysis/ValueTracking.h

+5
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ class Value;
185185
/// x < -0 --> false
186186
bool CannotBeOrderedLessThanZero(const Value *V, const TargetLibraryInfo *TLI);
187187

188+
/// Return true if the floating-point scalar value is not a NaN or if the
189+
/// floating-point vector value has no NaN elements. Return false if a value
190+
/// could ever be NaN.
191+
bool isKnownNeverNaN(const Value *V);
192+
188193
/// Return true if we can prove that the specified FP value's sign bit is 0.
189194
///
190195
/// NaN --> true/false (depending on the NaN's sign bit)

‎llvm/lib/Analysis/ValueTracking.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -2695,6 +2695,41 @@ bool llvm::SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI) {
26952695
return cannotBeOrderedLessThanZeroImpl(V, TLI, true, 0);
26962696
}
26972697

2698+
bool llvm::isKnownNeverNaN(const Value *V) {
2699+
assert(V->getType()->isFPOrFPVectorTy() && "Querying for NaN on non-FP type");
2700+
2701+
// If we're told that NaNs won't happen, assume they won't.
2702+
if (auto *FPMathOp = dyn_cast<FPMathOperator>(V))
2703+
if (FPMathOp->hasNoNaNs())
2704+
return true;
2705+
2706+
// TODO: Handle instructions and potentially recurse like other 'isKnown'
2707+
// functions. For example, the result of sitofp is never NaN.
2708+
2709+
// Handle scalar constants.
2710+
if (auto *CFP = dyn_cast<ConstantFP>(V))
2711+
return !CFP->isNaN();
2712+
2713+
// Bail out for constant expressions, but try to handle vector constants.
2714+
if (!V->getType()->isVectorTy() || !isa<Constant>(V))
2715+
return false;
2716+
2717+
// For vectors, verify that each element is not NaN.
2718+
unsigned NumElts = V->getType()->getVectorNumElements();
2719+
for (unsigned i = 0; i != NumElts; ++i) {
2720+
Constant *Elt = cast<Constant>(V)->getAggregateElement(i);
2721+
if (!Elt)
2722+
return false;
2723+
if (isa<UndefValue>(Elt))
2724+
continue;
2725+
auto *CElt = dyn_cast<ConstantFP>(Elt);
2726+
if (!CElt || CElt->isNaN())
2727+
return false;
2728+
}
2729+
// All elements were confirmed not-NaN or undefined.
2730+
return true;
2731+
}
2732+
26982733
/// If the specified value can be set by repeating the same byte in memory,
26992734
/// return the i8 value that it is represented with. This is
27002735
/// true for all i8 values obviously, but is also true for i32 0, i32 -1,

‎llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

+6-15
Original file line numberDiff line numberDiff line change
@@ -938,21 +938,12 @@ Value *InstCombiner::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd)
938938
if (LHS0->getType() != RHS0->getType())
939939
return nullptr;
940940

941-
auto *LHSC = dyn_cast<ConstantFP>(LHS1);
942-
auto *RHSC = dyn_cast<ConstantFP>(RHS1);
943-
if (LHSC && RHSC) {
944-
assert(!LHSC->getValueAPF().isNaN() && !RHSC->getValueAPF().isNaN() &&
945-
"Failed to simplify fcmp ord/uno with NAN operand");
946-
// Ignore the constants because they can't be NANs:
947-
// (fcmp ord x, c) & (fcmp ord y, c) -> (fcmp ord x, y)
948-
// (fcmp uno x, c) & (fcmp uno y, c) -> (fcmp uno x, y)
949-
return Builder.CreateFCmp(PredL, LHS0, RHS0);
950-
}
951-
952-
// Handle vector zeros. This occurs because the canonical form of
953-
// "fcmp ord/uno x,x" is "fcmp ord/uno x, 0".
954-
if (isa<ConstantAggregateZero>(LHS1) &&
955-
isa<ConstantAggregateZero>(RHS1))
941+
// FCmp canonicalization ensures that (fcmp ord/uno X, X) and
942+
// (fcmp ord/uno X, C) will be transformed to (fcmp X, 0.0).
943+
if (match(LHS1, m_Zero()) && LHS1 == RHS1)
944+
// Ignore the constants because they are obviously not NANs:
945+
// (fcmp ord x, 0.0) & (fcmp ord y, 0.0) -> (fcmp ord x, y)
946+
// (fcmp uno x, 0.0) | (fcmp uno y, 0.0) -> (fcmp uno x, y)
956947
return Builder.CreateFCmp(PredL, LHS0, RHS0);
957948
}
958949

‎llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -4963,6 +4963,19 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
49634963
}
49644964
}
49654965

4966+
// If we're just checking for a NaN (ORD/UNO) and have a non-NaN operand,
4967+
// then canonicalize the operand to 0.0.
4968+
if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) {
4969+
if (!match(Op0, m_Zero()) && isKnownNeverNaN(Op0)) {
4970+
I.setOperand(0, ConstantFP::getNullValue(Op0->getType()));
4971+
return &I;
4972+
}
4973+
if (!match(Op1, m_Zero()) && isKnownNeverNaN(Op1)) {
4974+
I.setOperand(1, ConstantFP::getNullValue(Op0->getType()));
4975+
return &I;
4976+
}
4977+
}
4978+
49664979
// Test if the FCmpInst instruction is used exclusively by a select as
49674980
// part of a minimum or maximum operation. If so, refrain from doing
49684981
// any other folding. This helps out other analyses which understand

‎llvm/test/Transforms/InstCombine/and-fcmp.ll

+2-4
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,8 @@ define i1 @fcmp_ord_nonzero(float %x, float %y) {
4141

4242
define <3 x i1> @fcmp_ord_nonzero_vec(<3 x float> %x, <3 x float> %y) {
4343
; CHECK-LABEL: @fcmp_ord_nonzero_vec(
44-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <3 x float> %x, <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>
45-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <3 x float> %y, <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00>
46-
; CHECK-NEXT: [[AND:%.*]] = and <3 x i1> [[CMP1]], [[CMP2]]
47-
; CHECK-NEXT: ret <3 x i1> [[AND]]
44+
; CHECK-NEXT: [[TMP1:%.*]] = fcmp ord <3 x float> %x, %y
45+
; CHECK-NEXT: ret <3 x i1> [[TMP1]]
4846
;
4947
%cmp1 = fcmp ord <3 x float> %x, <float 1.0, float 2.0, float 3.0>
5048
%cmp2 = fcmp ord <3 x float> %y, <float 3.0, float 2.0, float 1.0>

‎llvm/test/Transforms/InstCombine/fcmp-special.ll

+6-12
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ define i1 @ord_zero(float %x) {
3535

3636
define i1 @ord_nonzero(double %x) {
3737
; CHECK-LABEL: @ord_nonzero(
38-
; CHECK-NEXT: [[F:%.*]] = fcmp ord double %x, 3.000000e+00
38+
; CHECK-NEXT: [[F:%.*]] = fcmp ord double %x, 0.000000e+00
3939
; CHECK-NEXT: ret i1 [[F]]
4040
;
4141
%f = fcmp ord double %x, 3.0
@@ -62,7 +62,7 @@ define i1 @uno_zero(double %x) {
6262

6363
define i1 @uno_nonzero(float %x) {
6464
; CHECK-LABEL: @uno_nonzero(
65-
; CHECK-NEXT: [[F:%.*]] = fcmp uno float %x, 3.000000e+00
65+
; CHECK-NEXT: [[F:%.*]] = fcmp uno float %x, 0.000000e+00
6666
; CHECK-NEXT: ret i1 [[F]]
6767
;
6868
%f = fcmp uno float %x, 3.0
@@ -89,7 +89,7 @@ define <2 x i1> @ord_zero_vec(<2 x double> %x) {
8989

9090
define <2 x i1> @ord_nonzero_vec(<2 x float> %x) {
9191
; CHECK-LABEL: @ord_nonzero_vec(
92-
; CHECK-NEXT: [[F:%.*]] = fcmp ord <2 x float> %x, <float 3.000000e+00, float 5.000000e+00>
92+
; CHECK-NEXT: [[F:%.*]] = fcmp ord <2 x float> %x, zeroinitializer
9393
; CHECK-NEXT: ret <2 x i1> [[F]]
9494
;
9595
%f = fcmp ord <2 x float> %x, <float 3.0, float 5.0>
@@ -116,7 +116,7 @@ define <2 x i1> @uno_zero_vec(<2 x float> %x) {
116116

117117
define <2 x i1> @uno_nonzero_vec(<2 x double> %x) {
118118
; CHECK-LABEL: @uno_nonzero_vec(
119-
; CHECK-NEXT: [[F:%.*]] = fcmp uno <2 x double> %x, <double 3.000000e+00, double 5.000000e+00>
119+
; CHECK-NEXT: [[F:%.*]] = fcmp uno <2 x double> %x, zeroinitializer
120120
; CHECK-NEXT: ret <2 x i1> [[F]]
121121
;
122122
%f = fcmp uno <2 x double> %x, <double 3.0, double 5.0>
@@ -148,10 +148,7 @@ define <2 x i1> @uno_vec_with_nan(<2 x double> %x) {
148148

149149
define i1 @nnan_ops_to_fcmp_ord(float %x, float %y) {
150150
; CHECK-LABEL: @nnan_ops_to_fcmp_ord(
151-
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float %x, %y
152-
; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float %x, %y
153-
; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[MUL]], [[DIV]]
154-
; CHECK-NEXT: ret i1 [[CMP]]
151+
; CHECK-NEXT: ret i1 true
155152
;
156153
%mul = fmul nnan float %x, %y
157154
%div = fdiv nnan float %x, %y
@@ -163,10 +160,7 @@ define i1 @nnan_ops_to_fcmp_ord(float %x, float %y) {
163160

164161
define i1 @nnan_ops_to_fcmp_uno(float %x, float %y) {
165162
; CHECK-LABEL: @nnan_ops_to_fcmp_uno(
166-
; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float %x, %y
167-
; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float %x, %y
168-
; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[MUL]], [[DIV]]
169-
; CHECK-NEXT: ret i1 [[CMP]]
163+
; CHECK-NEXT: ret i1 false
170164
;
171165
%mul = fmul nnan float %x, %y
172166
%div = fdiv nnan float %x, %y

‎llvm/test/Transforms/InstCombine/or-fcmp.ll

+2-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ define i1 @fcmp_uno_nonzero(float %x, float %y) {
1414

1515
define <3 x i1> @fcmp_uno_nonzero_vec(<3 x float> %x, <3 x float> %y) {
1616
; CHECK-LABEL: @fcmp_uno_nonzero_vec(
17-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <3 x float> %x, <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>
18-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <3 x float> %y, <float 3.000000e+00, float 2.000000e+00, float 1.000000e+00>
19-
; CHECK-NEXT: [[OR:%.*]] = or <3 x i1> [[CMP1]], [[CMP2]]
20-
; CHECK-NEXT: ret <3 x i1> [[OR]]
17+
; CHECK-NEXT: [[TMP1:%.*]] = fcmp uno <3 x float> %x, %y
18+
; CHECK-NEXT: ret <3 x i1> [[TMP1]]
2119
;
2220
%cmp1 = fcmp uno <3 x float> %x, <float 1.0, float 2.0, float 3.0>
2321
%cmp2 = fcmp uno <3 x float> %y, <float 3.0, float 2.0, float 1.0>

0 commit comments

Comments
 (0)
Please sign in to comment.