[llvm] 3491f2f - [InstCombine] replace negated operand in fcmp with 0.0
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 10 09:53:41 PST 2022
Author: Sanjay Patel
Date: 2022-03-10T12:53:32-05:00
New Revision: 3491f2f4b0336cdb788fed3ff03a4b31c58db14e
URL: https://github.com/llvm/llvm-project/commit/3491f2f4b0336cdb788fed3ff03a4b31c58db14e
DIFF: https://github.com/llvm/llvm-project/commit/3491f2f4b0336cdb788fed3ff03a4b31c58db14e.diff
LOG: [InstCombine] replace negated operand in fcmp with 0.0
X (any pred) -X --> X (any pred) 0.0
This works with all FP values and preserves FMF.
Alive2 examples:
https://alive2.llvm.org/ce/z/dj6jhp
This can also create one of the patterns that we match as "fabs"
as shown in one of the test diffs.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/fabs.ll
llvm/test/Transforms/InstCombine/fcmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index d3f6693b16db2..651d564763074 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6527,6 +6527,25 @@ static Instruction *foldFabsWithFcmpZero(FCmpInst &I, InstCombinerImpl &IC) {
}
}
+static Instruction *foldFCmpFNegCommonOp(FCmpInst &I) {
+ CmpInst::Predicate Pred = I.getPredicate();
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ // Canonicalize fneg as Op1.
+ if (match(Op0, m_FNeg(m_Value())) && !match(Op1, m_FNeg(m_Value()))) {
+ std::swap(Op0, Op1);
+ Pred = I.getSwappedPredicate();
+ }
+
+ if (!match(Op1, m_FNeg(m_Specific(Op0))))
+ return nullptr;
+
+ // Replace the negated operand with 0.0:
+ // fcmp Pred Op0, -Op0 --> fcmp Pred Op0, 0.0
+ Constant *Zero = ConstantFP::getNullValue(Op0->getType());
+ return new FCmpInst(Pred, Op0, Zero, "", &I);
+}
+
Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
bool Changed = false;
@@ -6585,6 +6604,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_FNeg(m_Value(Y))))
return new FCmpInst(I.getSwappedPredicate(), X, Y, "", &I);
+ if (Instruction *R = foldFCmpFNegCommonOp(I))
+ return R;
+
// Test if the FCmpInst instruction is used exclusively by a select as
// part of a minimum or maximum operation. If so, refrain from doing
// any other folding. This helps out other analyses which understand
diff --git a/llvm/test/Transforms/InstCombine/fabs.ll b/llvm/test/Transforms/InstCombine/fabs.ll
index 6d42ca9989199..725b906f92bb9 100644
--- a/llvm/test/Transforms/InstCombine/fabs.ll
+++ b/llvm/test/Transforms/InstCombine/fabs.ll
@@ -351,10 +351,8 @@ define fp128 @select_fcmp_ogt_zero(fp128 %x) {
define float @select_fcmp_ogt_fneg(float %a) {
; CHECK-LABEL: @select_fcmp_ogt_fneg(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[FNEG]], [[A]]
-; CHECK-NEXT: [[R:%.*]] = select nsz i1 [[CMP]], float [[A]], float [[FNEG]]
-; CHECK-NEXT: ret float [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call nsz float @llvm.fabs.f32(float [[A:%.*]])
+; CHECK-NEXT: ret float [[TMP1]]
;
%fneg = fneg float %a
%cmp = fcmp ogt float %a, %fneg
diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index 5db6bd3c028e4..b0211d52f197f 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -832,8 +832,7 @@ define i1 @lossy_uno(half %x) {
define i1 @fneg_oeq(float %a) {
; CHECK-LABEL: @fneg_oeq(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -843,8 +842,7 @@ define i1 @fneg_oeq(float %a) {
define i1 @fneg_ogt(half %a) {
; CHECK-LABEL: @fneg_ogt(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg half [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt half [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt half [[A:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg half %a
@@ -854,8 +852,7 @@ define i1 @fneg_ogt(half %a) {
define <2 x i1> @fneg_oge(<2 x float> %a) {
; CHECK-LABEL: @fneg_oge(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg fast <2 x float> [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge <2 x float> [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ole <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%fneg = fneg fast <2 x float> %a
@@ -867,7 +864,7 @@ define i1 @fneg_olt(float %a, float* %q) {
; CHECK-LABEL: @fneg_olt(
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4
-; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -878,8 +875,7 @@ define i1 @fneg_olt(float %a, float* %q) {
define i1 @fneg_ole(float %a) {
; CHECK-LABEL: @fneg_ole(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ole float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz oge float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -889,8 +885,7 @@ define i1 @fneg_ole(float %a) {
define i1 @fneg_one(float %a) {
; CHECK-LABEL: @fneg_one(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -900,8 +895,7 @@ define i1 @fneg_one(float %a) {
define i1 @fneg_ord(float %a) {
; CHECK-LABEL: @fneg_ord(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -911,8 +905,7 @@ define i1 @fneg_ord(float %a) {
define i1 @fneg_uno(float %a) {
; CHECK-LABEL: @fneg_uno(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -922,8 +915,7 @@ define i1 @fneg_uno(float %a) {
define i1 @fneg_ueq(half %a) {
; CHECK-LABEL: @fneg_ueq(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg half [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[A:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg half %a
@@ -933,8 +925,7 @@ define i1 @fneg_ueq(half %a) {
define <2 x i1> @fneg_ugt(<2 x float> %a) {
; CHECK-LABEL: @fneg_ugt(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg fast <2 x float> [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt <2 x float> [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ult <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%fneg = fneg fast <2 x float> %a
@@ -946,7 +937,7 @@ define i1 @fneg_uge(float %a, float* %q) {
; CHECK-LABEL: @fneg_uge(
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4
-; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ule float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -957,8 +948,7 @@ define i1 @fneg_uge(float %a, float* %q) {
define i1 @fneg_ult(float %a) {
; CHECK-LABEL: @fneg_ult(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ult float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ugt float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -968,8 +958,7 @@ define i1 @fneg_ult(float %a) {
define i1 @fneg_ule(float %a) {
; CHECK-LABEL: @fneg_ule(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ule float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan uge float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -979,8 +968,7 @@ define i1 @fneg_ule(float %a) {
define i1 @fneg_une(float %a) {
; CHECK-LABEL: @fneg_une(
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[FNEG]], [[A]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
@@ -991,8 +979,7 @@ define i1 @fneg_une(float %a) {
define i1 @fneg_oeq_swap(float %p) {
; CHECK-LABEL: @fneg_oeq_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1004,8 +991,7 @@ define i1 @fneg_oeq_swap(float %p) {
define i1 @fneg_ogt_swap(half %p) {
; CHECK-LABEL: @fneg_ogt_swap(
; CHECK-NEXT: [[A:%.*]] = fadd half [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg half [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt half [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt half [[A]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd half %p, %p ; thwart complexity-based canonicalization
@@ -1017,8 +1003,7 @@ define i1 @fneg_ogt_swap(half %p) {
define <2 x i1> @fneg_oge_swap(<2 x float> %p) {
; CHECK-LABEL: @fneg_oge_swap(
; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg fast <2 x float> [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge <2 x float> [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge <2 x float> [[A]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization
@@ -1032,7 +1017,7 @@ define i1 @fneg_olt_swap(float %p, float* %q) {
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4
-; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1045,8 +1030,7 @@ define i1 @fneg_olt_swap(float %p, float* %q) {
define i1 @fneg_ole_swap(float %p) {
; CHECK-LABEL: @fneg_ole_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ole float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ole float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1058,8 +1042,7 @@ define i1 @fneg_ole_swap(float %p) {
define i1 @fneg_one_swap(float %p) {
; CHECK-LABEL: @fneg_one_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1071,8 +1054,7 @@ define i1 @fneg_one_swap(float %p) {
define i1 @fneg_ord_swap(float %p) {
; CHECK-LABEL: @fneg_ord_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1084,8 +1066,7 @@ define i1 @fneg_ord_swap(float %p) {
define i1 @fneg_uno_swap(float %p) {
; CHECK-LABEL: @fneg_uno_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1097,8 +1078,7 @@ define i1 @fneg_uno_swap(float %p) {
define i1 @fneg_ueq_swap(half %p) {
; CHECK-LABEL: @fneg_ueq_swap(
; CHECK-NEXT: [[A:%.*]] = fadd half [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg half [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[A]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd half %p, %p ; thwart complexity-based canonicalization
@@ -1110,8 +1090,7 @@ define i1 @fneg_ueq_swap(half %p) {
define <2 x i1> @fneg_ugt_swap(<2 x float> %p) {
; CHECK-LABEL: @fneg_ugt_swap(
; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg fast <2 x float> [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt <2 x float> [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt <2 x float> [[A]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization
@@ -1125,7 +1104,7 @@ define i1 @fneg_uge_swap(float %p, float* %q) {
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4
-; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1138,8 +1117,7 @@ define i1 @fneg_uge_swap(float %p, float* %q) {
define i1 @fneg_ult_swap(float %p) {
; CHECK-LABEL: @fneg_ult_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ult float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ult float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1151,8 +1129,7 @@ define i1 @fneg_ult_swap(float %p) {
define i1 @fneg_ule_swap(float %p) {
; CHECK-LABEL: @fneg_ule_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ule float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ule float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
@@ -1164,8 +1141,7 @@ define i1 @fneg_ule_swap(float %p) {
define i1 @fneg_une_swap(float %p) {
; CHECK-LABEL: @fneg_une_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
-; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[A]], [[FNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
More information about the llvm-commits
mailing list