[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
Thu Apr 18 12:16:00 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/4] 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 ee76a6294428b3..49e10646eb5d15 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 159c84d0dd8aa9..574fb1f9417742 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/4] 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 8537dbc6fe531b..6a372ca5a34cea 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 49e10646eb5d15..ee76a6294428b3 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 abc707acf0cd3f..c6f3eb11683013 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 574fb1f9417742..159c84d0dd8aa9 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/4] 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 6a372ca5a34cea..ec3d13ececa1f1 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 c6f3eb11683013..3f9e92b9dc03ab 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/4] 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 ec3d13ececa1f1..42b4464357ec71 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 3f9e92b9dc03ab..f4522a6e614e50 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
 }



More information about the llvm-commits mailing list