[llvm] 8529470 - [InstCombine] fold fcmp-of-copysign idiom
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 17 07:32:45 PST 2021
Author: Sanjay Patel
Date: 2021-02-17T10:32:33-05:00
New Revision: 85294703a74a532448b3d3801d4e9a5c6024547a
URL: https://github.com/llvm/llvm-project/commit/85294703a74a532448b3d3801d4e9a5c6024547a
DIFF: https://github.com/llvm/llvm-project/commit/85294703a74a532448b3d3801d4e9a5c6024547a.diff
LOG: [InstCombine] fold fcmp-of-copysign idiom
As discussed in:
https://llvm.org/PR49179
...this pattern shows up in library code.
There are several potential generalizations as noted,
but we need to be careful that we get FP special-values
right, and it's not clear how much variation we should
expect to see from this exact idiom.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/fcmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index cd9a036179b6..30048d1232cb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6267,6 +6267,26 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
}
}
+ // Convert a sign-bit test of an FP value into a cast and integer compare.
+ // TODO: Simplify if the copysign constant is 0.0 or NaN.
+ // TODO: Handle non-zero compare constants.
+ // TODO: Handle other predicates.
+ const APFloat *C;
+ if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::copysign>(m_APFloat(C),
+ m_Value(X)))) &&
+ match(Op1, m_AnyZeroFP()) && !C->isZero() && !C->isNaN()) {
+ Type *IntType = Builder.getIntNTy(X->getType()->getScalarSizeInBits());
+ if (auto *VecTy = dyn_cast<VectorType>(OpType))
+ IntType = VectorType::get(IntType, VecTy->getElementCount());
+
+ // copysign(non-zero constant, X) < 0.0 --> (bitcast X) < 0
+ if (Pred == FCmpInst::FCMP_OLT) {
+ Value *IntX = Builder.CreateBitCast(X, IntType);
+ return new ICmpInst(ICmpInst::ICMP_SLT, IntX,
+ ConstantInt::getNullValue(IntType));
+ }
+ }
+
if (I.getType()->isVectorTy())
if (Instruction *Res = foldVectorCmp(I, Builder))
return Res;
diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index 62e747701152..c9941ec46c99 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -583,8 +583,8 @@ define <2 x i1> @test27_recipX_gt_vecsplat(<2 x float> %X) {
define i1 @is_signbit_set(double %x) {
; CHECK-LABEL: @is_signbit_set(
-; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fcmp olt double [[S]], 0.000000e+00
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
+; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double 1.0, double %x)
@@ -592,10 +592,12 @@ define i1 @is_signbit_set(double %x) {
ret i1 %r
}
+; Vectors are ok; the sign of zero in the compare doesn't matter; the copysign constant can be any non-zero number.
+
define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) {
; CHECK-LABEL: @is_signbit_set_anyzero(
-; CHECK-NEXT: [[S:%.*]] = call <2 x double> @llvm.copysign.v2f64(<2 x double> <double 4.200000e+01, double 4.200000e+01>, <2 x double> [[X:%.*]])
-; CHECK-NEXT: [[R:%.*]] = fcmp olt <2 x double> [[S]], zeroinitializer
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x double> [[X:%.*]] to <2 x i64>
+; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i64> [[TMP1]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%s = call <2 x double> @llvm.copysign.v2f64(<2 x double> <double 42.0, double 42.0>, <2 x double> %x)
@@ -603,6 +605,8 @@ define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) {
ret <2 x i1> %r
}
+; TODO: Handle
diff erent predicates.
+
define i1 @is_signbit_clear(double %x) {
; CHECK-LABEL: @is_signbit_clear(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]])
@@ -614,6 +618,8 @@ define i1 @is_signbit_clear(double %x) {
ret i1 %r
}
+; Negative test - uses
+
define i1 @is_signbit_set_extra_use(double %x, double* %p) {
; CHECK-LABEL: @is_signbit_set_extra_use(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
@@ -627,6 +633,8 @@ define i1 @is_signbit_set_extra_use(double %x, double* %p) {
ret i1 %r
}
+; TODO: Handle non-zero compare constant.
+
define i1 @is_signbit_clear_nonzero(double %x) {
; CHECK-LABEL: @is_signbit_clear_nonzero(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]])
@@ -638,6 +646,8 @@ define i1 @is_signbit_clear_nonzero(double %x) {
ret i1 %r
}
+; TODO: Handle zero copysign constant.
+
define i1 @is_signbit_set_simplify_zero(double %x) {
; CHECK-LABEL: @is_signbit_set_simplify_zero(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[X:%.*]])
@@ -649,6 +659,8 @@ define i1 @is_signbit_set_simplify_zero(double %x) {
ret i1 %r
}
+; TODO: Handle NaN copysign constant.
+
define i1 @is_signbit_set_simplify_nan(double %x) {
; CHECK-LABEL: @is_signbit_set_simplify_nan(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0xFFFFFFFFFFFFFFFF, double [[X:%.*]])
More information about the llvm-commits
mailing list