[llvm] [InstCombine] Fold copysign of selects from sign comparison to sign operand (PR #85627)
Krishna Narayanan via llvm-commits
llvm-commits at lists.llvm.org
Sat May 11 05:35:31 PDT 2024
https://github.com/Krishna-13-cyber updated https://github.com/llvm/llvm-project/pull/85627
>From 96403f5361e5331a35fe8d158859e01bf208a22f Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Mon, 18 Mar 2024 14:12:15 +0530
Subject: [PATCH 1/5] Add support for folding sign comparison to sign operand
---
.../InstCombine/InstCombineSelect.cpp | 45 +++++++++++++++++++
llvm/test/Transforms/InstCombine/fcmp.ll | 16 +++++++
2 files changed, 61 insertions(+)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index ee76a6294428b..49e10646eb5d1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2790,6 +2790,47 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
return ChangedFMF ? &SI : nullptr;
}
+// Canonicalize select with fcmp -> select
+static Instruction *foldSelectWithFCmp(SelectInst &SI, InstCombinerImpl &IC) {
+ /* From
+ %4 = fcmp olt float %1, 0.000000e+00
+ %5 = and i1 %4, %0
+ %6 = select i1 %5, float -1.000000e+00, float 1.000000e+00
+ */
+ /* To
+ %4 = select i1 %0, float %1, float 1.000000e+00
+ */
+ Value *CondVal = SI.getCondition();
+ Value *TrueVal = SI.getTrueValue();
+ Value *FalseVal = SI.getFalseValue();
+ Value *One = Constant::getAllOnesValue(FalseVal->getType());
+ Value *X, *C, *Op;
+ const APFloat *A, *E;
+ CmpInst::Predicate Pred;
+ for (bool Swap : {false, true}) {
+ if (Swap)
+ std::swap(TrueVal, FalseVal);
+ if (match(&SI, (m_Value(CondVal), m_APFloat(A), m_APFloat(E)))) {
+ if (!match(TrueVal, m_APFloatAllowUndef(A)) &&
+ !match(FalseVal, m_APFloatAllowUndef(E)))
+ return nullptr;
+ if (!match(CondVal, m_And(m_FCmp(Pred, m_Specific(X), m_PosZeroFP()),
+ m_Value(C))) &&
+ (X->hasOneUse() && C->hasOneUse()))
+ return nullptr;
+ if (!A->isNegative() && E->isNegative())
+ return nullptr;
+ if (!Swap && (Pred == FCmpInst::FCMP_OLT)) {
+ return SelectInst::Create(C, X, One);
+ }
+ if (Swap && (Pred == FCmpInst::FCMP_OGT)) {
+ return SelectInst::Create(C, X, One);
+ }
+ }
+ }
+ return nullptr;
+}
+
// Match the following IR pattern:
// %x.lowbits = and i8 %x, %lowbitmask
// %x.lowbits.are.zero = icmp eq i8 %x.lowbits, 0
@@ -3508,6 +3549,10 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
if (Instruction *Fabs = foldSelectWithFCmpToFabs(SI, *this))
return Fabs;
+ // Fold selecting to ffold.
+ if (Instruction *Ffold = foldSelectWithFCmp(SI, *this))
+ return Ffold;
+
// See if we are selecting two values based on a comparison of the two values.
if (ICmpInst *ICI = dyn_cast<ICmpInst>(CondVal))
if (Instruction *Result = foldSelectInstWithICmp(SI, ICI))
diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index 159c84d0dd8aa..574fb1f941774 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -1284,3 +1284,19 @@ define <1 x i1> @bitcast_1vec_eq0(i32 %x) {
%cmp = fcmp oeq <1 x float> %f, zeroinitializer
ret <1 x i1> %cmp
}
+
+define float @copysign_conditional(i1 noundef zeroext %0, float %1, float %2) {
+; CHECK-LABEL: define float @copysign_conditional(
+; CHECK-SAME: i1 noundef zeroext [[TMP0:%.*]], float [[TMP1:%.*]], float [[TMP2:%.*]]) {
+; CHECK-NEXT: [[TMP4:%.*]] = fcmp olt float [[TMP1]], 0.000000e+00
+; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP0]]
+; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT: [[TMP7:%.*]] = tail call float @llvm.copysign.f32(float [[TMP2]], float [[TMP6]])
+; CHECK-NEXT: ret float [[TMP7]]
+;
+ %4 = fcmp olt float %1, 0.000000e+00
+ %5 = and i1 %4, %0
+ %6 = select i1 %5, float -1.000000e+00, float 1.000000e+00
+ %7 = tail call float @llvm.copysign.f32(float %2, float %6)
+ ret float %7
+}
\ No newline at end of file
>From 4626d38314ea4883aaa3564e1ce167dd3a06c0d6 Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Mon, 25 Mar 2024 21:38:56 +0530
Subject: [PATCH 2/5] Update with copysign as root inst
---
.../InstCombine/InstCombineCalls.cpp | 41 +++++++++++++++++
.../InstCombine/InstCombineSelect.cpp | 45 -------------------
llvm/test/Transforms/InstCombine/copysign.ll | 15 +++++++
llvm/test/Transforms/InstCombine/fcmp.ll | 16 -------
4 files changed, 56 insertions(+), 61 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 8537dbc6fe531..6a372ca5a34ce 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2479,6 +2479,47 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (match(Mag, m_FAbs(m_Value(X))) || match(Mag, m_FNeg(m_Value(X))))
return replaceOperand(*II, 0, X);
+ Value *A, *B;
+ CmpInst::Predicate Pred;
+ const APFloat *TC, *FC;
+ if (!match(Sign, m_Select((m_And(m_Value(B),
+ m_FCmp(Pred, m_Value(A), m_PosZeroFP()))),
+ m_APFloat(TC), m_APFloat(FC))))
+ return nullptr;
+ // Match select ?, TC, FC where the constants are equal but negated.
+ // Check for these 8 conditions
+ /*
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->true, A<0.
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->true, A>0.
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->false, A>0.
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->false, A<0.
+ */
+ /*
+ copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A<0.
+ copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A>0.
+ copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, A) B->false, A>0.
+ copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, -A) B->false, A<0.
+ */
+ assert(TC != FC);
+
+ if (Pred == CmpInst::FCMP_OLT)
+ if (match(A, m_Negative())) {
+ if (!match(B, m_ZeroInt()) && TC->isNegative())
+ return replaceOperand(*II, 1, A);
+ if (match(B, m_ZeroInt()) && TC->isNegative())
+ A = Builder.CreateFNeg(A);
+ return replaceOperand(*II, 1, A);
+ } else
+ return replaceOperand(*II, 1, A);
+ if (Pred == CmpInst::FCMP_OGT)
+ if (match(A, m_Negative())) {
+ A = Builder.CreateFNeg(A);
+ return replaceOperand(*II, 1, A);
+ } else if (!match(B, m_ZeroInt()) && TC->isNegative())
+ A = Builder.CreateFNeg(A);
+ return replaceOperand(*II, 1, A);
+ if (match(B, m_ZeroInt()) && TC->isNegative())
+ return replaceOperand(*II, 1, A);
break;
}
case Intrinsic::fabs: {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 49e10646eb5d1..ee76a6294428b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2790,47 +2790,6 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
return ChangedFMF ? &SI : nullptr;
}
-// Canonicalize select with fcmp -> select
-static Instruction *foldSelectWithFCmp(SelectInst &SI, InstCombinerImpl &IC) {
- /* From
- %4 = fcmp olt float %1, 0.000000e+00
- %5 = and i1 %4, %0
- %6 = select i1 %5, float -1.000000e+00, float 1.000000e+00
- */
- /* To
- %4 = select i1 %0, float %1, float 1.000000e+00
- */
- Value *CondVal = SI.getCondition();
- Value *TrueVal = SI.getTrueValue();
- Value *FalseVal = SI.getFalseValue();
- Value *One = Constant::getAllOnesValue(FalseVal->getType());
- Value *X, *C, *Op;
- const APFloat *A, *E;
- CmpInst::Predicate Pred;
- for (bool Swap : {false, true}) {
- if (Swap)
- std::swap(TrueVal, FalseVal);
- if (match(&SI, (m_Value(CondVal), m_APFloat(A), m_APFloat(E)))) {
- if (!match(TrueVal, m_APFloatAllowUndef(A)) &&
- !match(FalseVal, m_APFloatAllowUndef(E)))
- return nullptr;
- if (!match(CondVal, m_And(m_FCmp(Pred, m_Specific(X), m_PosZeroFP()),
- m_Value(C))) &&
- (X->hasOneUse() && C->hasOneUse()))
- return nullptr;
- if (!A->isNegative() && E->isNegative())
- return nullptr;
- if (!Swap && (Pred == FCmpInst::FCMP_OLT)) {
- return SelectInst::Create(C, X, One);
- }
- if (Swap && (Pred == FCmpInst::FCMP_OGT)) {
- return SelectInst::Create(C, X, One);
- }
- }
- }
- return nullptr;
-}
-
// Match the following IR pattern:
// %x.lowbits = and i8 %x, %lowbitmask
// %x.lowbits.are.zero = icmp eq i8 %x.lowbits, 0
@@ -3549,10 +3508,6 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
if (Instruction *Fabs = foldSelectWithFCmpToFabs(SI, *this))
return Fabs;
- // Fold selecting to ffold.
- if (Instruction *Ffold = foldSelectWithFCmp(SI, *this))
- return Ffold;
-
// See if we are selecting two values based on a comparison of the two values.
if (ICmpInst *ICI = dyn_cast<ICmpInst>(CondVal))
if (Instruction *Result = foldSelectInstWithICmp(SI, ICI))
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index abc707acf0cd3..c6f3eb1168301 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -109,3 +109,18 @@ define float @fabs_mag(float %x, float %y) {
%r = call float @llvm.copysign.f32(float %a, float %y)
ret float %r
}
+
+define float @copysign_conditional(i1 noundef zeroext %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp olt float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+ ret float %res
+}
diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index 574fb1f941774..159c84d0dd8aa 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -1284,19 +1284,3 @@ define <1 x i1> @bitcast_1vec_eq0(i32 %x) {
%cmp = fcmp oeq <1 x float> %f, zeroinitializer
ret <1 x i1> %cmp
}
-
-define float @copysign_conditional(i1 noundef zeroext %0, float %1, float %2) {
-; CHECK-LABEL: define float @copysign_conditional(
-; CHECK-SAME: i1 noundef zeroext [[TMP0:%.*]], float [[TMP1:%.*]], float [[TMP2:%.*]]) {
-; CHECK-NEXT: [[TMP4:%.*]] = fcmp olt float [[TMP1]], 0.000000e+00
-; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP0]]
-; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float -1.000000e+00, float 1.000000e+00
-; CHECK-NEXT: [[TMP7:%.*]] = tail call float @llvm.copysign.f32(float [[TMP2]], float [[TMP6]])
-; CHECK-NEXT: ret float [[TMP7]]
-;
- %4 = fcmp olt float %1, 0.000000e+00
- %5 = and i1 %4, %0
- %6 = select i1 %5, float -1.000000e+00, float 1.000000e+00
- %7 = tail call float @llvm.copysign.f32(float %2, float %6)
- ret float %7
-}
\ No newline at end of file
>From 7caf6f4078750fbffe05c6f5a46ba39e8628a147 Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Fri, 29 Mar 2024 23:27:20 +0530
Subject: [PATCH 3/5] Update with adding predicates and tests
---
.../InstCombine/InstCombineCalls.cpp | 47 +++++++++----------
llvm/test/Transforms/InstCombine/copysign.ll | 46 ++++++++++++++++--
2 files changed, 64 insertions(+), 29 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 6a372ca5a34ce..ec3d13ececa1f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2482,45 +2482,44 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *A, *B;
CmpInst::Predicate Pred;
const APFloat *TC, *FC;
- if (!match(Sign, m_Select((m_And(m_Value(B),
- m_FCmp(Pred, m_Value(A), m_PosZeroFP()))),
+ if (!match(Sign, m_Select((m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
+ m_Value(B))),
m_APFloat(TC), m_APFloat(FC))))
return nullptr;
- // Match select ?, TC, FC where the constants are equal but negated.
- // Check for these 8 conditions
/*
+ Match select ?, TC, FC where the constants are equal but negated.
+ Check for these conditions:
+ olt/ule
copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->true, A<0.
copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->true, A>0.
copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->false, A>0.
copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->false, A<0.
+ ogt/uge
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A<0.
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A>0.
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->false, A>0.
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->false,
+ A<0.
*/
- /*
- copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A<0.
- copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A>0.
- copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, A) B->false, A>0.
- copysign(Mag, B & (A > 0.0) ? -TC : TC) --> copysign(Mag, -A) B->false, A<0.
- */
- assert(TC != FC);
-
- if (Pred == CmpInst::FCMP_OLT)
- if (match(A, m_Negative())) {
+ if (Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_ULE)
+ if (match(A, m_Negative()))
if (!match(B, m_ZeroInt()) && TC->isNegative())
return replaceOperand(*II, 1, A);
if (match(B, m_ZeroInt()) && TC->isNegative())
A = Builder.CreateFNeg(A);
return replaceOperand(*II, 1, A);
- } else
return replaceOperand(*II, 1, A);
- if (Pred == CmpInst::FCMP_OGT)
- if (match(A, m_Negative())) {
- A = Builder.CreateFNeg(A);
+ if (Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_UGE)
+ if (match(A, m_Negative())) {
+ A = Builder.CreateFNeg(A);
+ return replaceOperand(*II, 1, A);
+ }
+ if (!match(B, m_ZeroInt()) && TC->isNegative())
+ A = Builder.CreateFNeg(A);
return replaceOperand(*II, 1, A);
- } else if (!match(B, m_ZeroInt()) && TC->isNegative())
- A = Builder.CreateFNeg(A);
- return replaceOperand(*II, 1, A);
- if (match(B, m_ZeroInt()) && TC->isNegative())
- return replaceOperand(*II, 1, A);
- break;
+ if (match(B, m_ZeroInt()) && TC->isNegative())
+ return replaceOperand(*II, 1, A);
+ break;
}
case Intrinsic::fabs: {
Value *Cond, *TVal, *FVal;
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index c6f3eb1168301..3f9e92b9dc03a 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -110,12 +110,9 @@ define float @fabs_mag(float %x, float %y) {
ret float %r
}
-define float @copysign_conditional(i1 noundef zeroext %x, float %y, float %z) {
+define float @copysign_conditional(i1 %x, float %y, float %z) {
; CHECK-LABEL: @copysign_conditional(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
-; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
; CHECK-NEXT: ret float [[RES]]
;
%cmp = fcmp olt float %y, 0.000000e+00
@@ -124,3 +121,42 @@ define float @copysign_conditional(i1 noundef zeroext %x, float %y, float %z) {
%res = tail call float @llvm.copysign.f32(float %z, float %sel)
ret float %res
}
+
+define float @copysign_conditional2(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional2(
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp ogt float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+ ret float %res
+}
+
+define float @copysign_conditional3(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional3(
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp uge float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+ ret float %res
+}
+
+define float @copysign_conditional4(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional4(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[X:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[Z:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp fast olt float %y, 0.000000e+00
+ %sel = select i1 %x, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %z, float %cond1)
+ ret float %res
+}
>From 200e78705bd4250f2a95d1ccbf57cbd808f3ab2c Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Fri, 19 Apr 2024 00:45:13 +0530
Subject: [PATCH 4/5] Update with handling conditional branches and tests
---
.../InstCombine/InstCombineCalls.cpp | 50 +++++++++----------
llvm/test/Transforms/InstCombine/copysign.ll | 35 +++++++------
2 files changed, 40 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index ec3d13ececa1f..42b4464357ec7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2486,40 +2486,36 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
m_Value(B))),
m_APFloat(TC), m_APFloat(FC))))
return nullptr;
+
/*
Match select ?, TC, FC where the constants are equal but negated.
Check for these conditions:
olt/ule
- copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->true, A<0.
- copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->true, A>0.
- copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->false, A>0.
- copysign(Mag, B & (A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->false, A<0.
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->true, A<0.
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->true, A>0.
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->false, A>0.
+ copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, -A) B->false, A<0.
ogt/uge
- copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A<0.
- copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->true, A>0.
- copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, A) B->false, A>0.
- copysign(Mag, B & !(A < 0.0) ? -TC : TC) --> copysign(Mag, -A) B->false,
- A<0.
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) -> copysign(Mag, -A) B->true, A<0.
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) -> copysign(Mag, -A) B->true, A>0.
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->false, A>0.
+ copysign(Mag, B & !(A < 0.0) ? -TC : TC) -> copysign(Mag, -A) B->false,A<0.
*/
- if (Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_ULE)
- if (match(A, m_Negative()))
- if (!match(B, m_ZeroInt()) && TC->isNegative())
- return replaceOperand(*II, 1, A);
- if (match(B, m_ZeroInt()) && TC->isNegative())
- A = Builder.CreateFNeg(A);
- return replaceOperand(*II, 1, A);
- return replaceOperand(*II, 1, A);
- if (Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_UGE)
- if (match(A, m_Negative())) {
- A = Builder.CreateFNeg(A);
- return replaceOperand(*II, 1, A);
- }
- if (!match(B, m_ZeroInt()) && TC->isNegative())
+
+ if (Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_ULE) {
+ if (match(A, m_Negative()) && TC->isNegative())
+ if (match(B, m_ZeroInt()))
A = Builder.CreateFNeg(A);
- return replaceOperand(*II, 1, A);
- if (match(B, m_ZeroInt()) && TC->isNegative())
- return replaceOperand(*II, 1, A);
- break;
+ return replaceOperand(*II, 1, A);
+ }
+ if (Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_UGE) {
+ if (match(A, m_Negative()))
+ A = Builder.CreateFNeg(A);
+ else if (TC->isNegative() && !match(B, m_ZeroInt()))
+ A = Builder.CreateFNeg(A);
+ return replaceOperand(*II, 1, A);
+ }
+ break;
}
case Intrinsic::fabs: {
Value *Cond, *TVal, *FVal;
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index 3f9e92b9dc03a..f4522a6e614e5 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -110,8 +110,8 @@ define float @fabs_mag(float %x, float %y) {
ret float %r
}
-define float @copysign_conditional(i1 %x, float %y, float %z) {
-; CHECK-LABEL: @copysign_conditional(
+define float @copysign_conditional_olt(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_olt(
; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
; CHECK-NEXT: ret float [[RES]]
;
@@ -122,9 +122,10 @@ define float @copysign_conditional(i1 %x, float %y, float %z) {
ret float %res
}
-define float @copysign_conditional2(i1 %x, float %y, float %z) {
-; CHECK-LABEL: @copysign_conditional2(
-; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+define float @copysign_conditional_ogt(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ogt(
+; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[Y:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
; CHECK-NEXT: ret float [[RES]]
;
%cmp = fcmp ogt float %y, 0.000000e+00
@@ -134,9 +135,10 @@ define float @copysign_conditional2(i1 %x, float %y, float %z) {
ret float %res
}
-define float @copysign_conditional3(i1 %x, float %y, float %z) {
-; CHECK-LABEL: @copysign_conditional3(
-; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+define float @copysign_conditional_uge(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_uge(
+; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[Y:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
; CHECK-NEXT: ret float [[RES]]
;
%cmp = fcmp uge float %y, 0.000000e+00
@@ -146,17 +148,14 @@ define float @copysign_conditional3(i1 %x, float %y, float %z) {
ret float %res
}
-define float @copysign_conditional4(i1 %x, float %y, float %z) {
-; CHECK-LABEL: @copysign_conditional4(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[X:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
-; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[Z:%.*]], float [[COND1]])
+define float @copysign_conditional_ule(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ule(
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
; CHECK-NEXT: ret float [[RES]]
;
- %cmp = fcmp fast olt float %y, 0.000000e+00
- %sel = select i1 %x, i1 %cmp, i1 false
- %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
- %res = tail call fast float @llvm.copysign.f32(float %z, float %cond1)
+ %cmp = fcmp ule float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
ret float %res
}
>From f698c9f1fbd420678f340fb0e0e0be49ffa5025b Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Sat, 11 May 2024 18:03:39 +0530
Subject: [PATCH 5/5] Update tests with swapped constants, fast math handling
---
.../InstCombine/InstCombineCalls.cpp | 4 +-
llvm/test/Transforms/InstCombine/copysign.ll | 184 ++++++++++++++++++
2 files changed, 186 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 42b4464357ec7..9c44e85db6396 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2482,8 +2482,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *A, *B;
CmpInst::Predicate Pred;
const APFloat *TC, *FC;
- if (!match(Sign, m_Select((m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
- m_Value(B))),
+ if (!match(Sign, m_Select(m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
+ m_Value(B)),
m_APFloat(TC), m_APFloat(FC))))
return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index f4522a6e614e5..3f292978b9116 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -159,3 +159,187 @@ define float @copysign_conditional_ule(i1 %x, float %y, float %z) {
%res = tail call float @llvm.copysign.f32(float %z, float %sel)
ret float %res
}
+
+define float @copysign_conditional_olt_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_olt_inverse(
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp olt float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+ ret float %res
+}
+
+define float @copysign_conditional_ogt_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ogt_inverse(
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp ogt float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+ ret float %res
+}
+
+define float @copysign_conditional_ule_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ule_inverse(
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp ule float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+ ret float %res
+}
+
+define float @copysign_conditional_uge_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_uge_inverse(
+; CHECK-NEXT: [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp = fcmp uge float %y, 0.000000e+00
+ %and = and i1 %cmp, %x
+ %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+ %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_ogt(i1 noundef zeroext %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ogt(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast ogt float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_olt(i1 noundef zeroext %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_olt(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast olt float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_ugt(i1 %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ugt(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast ugt float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_ule(i1 %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ule(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ule float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast ule float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_olt_inverse(i1 %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_olt_inverse(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast olt float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_ugt_inverse(i1 %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ugt_inverse(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast ugt float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_ule_inverse(i1 %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ule_inverse(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ule float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast ule float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1 = select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
+
+define float @copysign_conditional_fast_ogt_inverse(i1 %cond, float %x, float %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ogt_inverse(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT: [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT: ret float [[RES]]
+;
+entry:
+ %cmp = fcmp fast ogt float %x, 0.000000e+00
+ %sel = select i1 %cond, i1 %cmp, i1 false
+ %cond1= select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+ %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+ ret float %res
+}
More information about the llvm-commits
mailing list