[llvm] InstSimplify: support floating-point equivalences (PR #115152)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 7 05:49:20 PST 2024


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/115152

>From 55e0a01fd7968ecd516a35977db12c81815b71b5 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Wed, 6 Nov 2024 11:39:26 +0000
Subject: [PATCH 1/2] InstSimplify: cover select folding for fp

In prepraration to extend select folding to include floating-points
using CmpInst::isEquivalence, cover it with tests first.
---
 .../Transforms/InstSimplify/fcmp-select.ll    |  44 +++++
 .../InstSimplify/select-equivalence-fp.ll     | 186 ++++++++++++++++++
 2 files changed, 230 insertions(+)
 create mode 100644 llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll

diff --git a/llvm/test/Transforms/InstSimplify/fcmp-select.ll b/llvm/test/Transforms/InstSimplify/fcmp-select.ll
index 470235a8363118..25fa7efe2d2eb9 100644
--- a/llvm/test/Transforms/InstSimplify/fcmp-select.ll
+++ b/llvm/test/Transforms/InstSimplify/fcmp-select.ll
@@ -111,6 +111,28 @@ define double @oeq_zero_nsz(double %x) {
   ret double %cond
 }
 
+define double @ueq_zero_nsz(double %x) {
+; CHECK-LABEL: @ueq_zero_nsz(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ueq double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[COND:%.*]] = select nsz i1 [[CMP]], double [[X]], double 0.000000e+00
+; CHECK-NEXT:    ret double [[COND]]
+;
+  %cmp = fcmp ueq double %x, 0.0
+  %cond = select nsz i1 %cmp, double %x, double 0.0
+  ret double %cond
+}
+
+define double @ueq_zero_nsz_nnan(double %x) {
+; CHECK-LABEL: @ueq_zero_nsz_nnan(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan ueq double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[COND:%.*]] = select nsz i1 [[CMP]], double [[X]], double 0.000000e+00
+; CHECK-NEXT:    ret double [[COND]]
+;
+  %cmp = fcmp nnan ueq double %x, 0.0
+  %cond = select nsz i1 %cmp, double %x, double 0.0
+  ret double %cond
+}
+
 ; X == 0.0 ? 0.0 : X --> X
 
 define float @oeq_zero_swapped_nsz(float %x) {
@@ -133,6 +155,28 @@ define double @une_zero_nsz(double %x) {
   ret double %cond
 }
 
+define double @one_zero_nsz(double %x) {
+; CHECK-LABEL: @one_zero_nsz(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[COND:%.*]] = select nsz i1 [[CMP]], double [[X]], double 0.000000e+00
+; CHECK-NEXT:    ret double [[COND]]
+;
+  %cmp = fcmp one double %x, 0.0
+  %cond = select nsz i1 %cmp, double %x, double 0.0
+  ret double %cond
+}
+
+define double @one_zero_nsz_nnan(double %x) {
+; CHECK-LABEL: @one_zero_nsz_nnan(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan one double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[COND:%.*]] = select nsz i1 [[CMP]], double [[X]], double 0.000000e+00
+; CHECK-NEXT:    ret double [[COND]]
+;
+  %cmp = fcmp nnan one double %x, 0.0
+  %cond = select nsz i1 %cmp, double %x, double 0.0
+  ret double %cond
+}
+
 ; X != 0.0 ? 0.0 : X --> 0.0
 
 define <2 x double> @une_zero_swapped_nsz(<2 x double> %x) {
diff --git a/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll b/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
new file mode 100644
index 00000000000000..e9e81ad5513713
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
@@ -0,0 +1,186 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+
+define float @select_fcmp_fsub_oeq(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_oeq(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp oeq float %y, 2.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float %fadd, float 0.
+  ret float %sel
+}
+
+define float @select_fcmp_fsub_oeq_zero(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_oeq_zero(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 2.000000e+00
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp oeq float %y, 0.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float %fadd, float 2.
+  ret float %sel
+}
+
+define float @select_fcmp_fsub_ueq(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_ueq(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp ueq float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp ueq float %y, 2.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float %fadd, float 0.
+  ret float %sel
+}
+
+define float @select_fcmp_fsub_ueq_nnan(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_ueq_nnan(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp nnan ueq float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp nnan ueq float %y, 2.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float %fadd, float 0.
+  ret float %sel
+}
+
+define float @select_fcmp_fsub_une(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_une(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp une float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp une float %y, 2.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float 0., float %fadd
+  ret float %sel
+}
+
+define float @select_fcmp_fsub_une_zero(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_une_zero(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp une float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float 2.000000e+00, float [[FADD]]
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp une float %y, 0.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float 2., float %fadd
+  ret float %sel
+}
+
+define float @select_fcmp_fsub_one(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_one(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp one float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp one float %y, 2.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float 0., float %fadd
+  ret float %sel
+}
+
+define float @select_fcmp_fsub_one_nnan(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fsub_one_nnan(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp nnan one float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp nnan one float %y, 2.
+  %fadd = fsub float %y, 2.
+  %sel = select i1 %fcmp, float 0., float %fadd
+  ret float %sel
+}
+
+define float @select_fcmp_fadd(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fadd(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FADD:%.*]] = fadd float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 4.000000e+00
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp oeq float %y, 2.
+  %fadd = fadd float %y, 2.
+  %sel = select i1 %fcmp, float %fadd, float 4.
+  ret float %sel
+}
+
+define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @select_fcmp_fadd_vec(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq <2 x float> [[Y:%.*]], <float 2.000000e+00, float 2.000000e+00>
+; CHECK-NEXT:    [[FADD:%.*]] = fadd <2 x float> [[Y]], <float 2.000000e+00, float 2.000000e+00>
+; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[FADD]], <2 x float> <float 4.000000e+00, float 4.000000e+00>
+; CHECK-NEXT:    ret <2 x float> [[SEL]]
+;
+  %fcmp = fcmp oeq <2 x float> %y, <float 2., float 2.>
+  %fadd = fadd <2 x float> %y, <float 2., float 2.>
+  %sel = select <2 x i1> %fcmp, <2 x float> %fadd, <2 x float> <float 4., float 4.>
+  ret <2 x float> %sel
+}
+
+
+define float @select_fcmp_fdiv(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_fdiv(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 2.000000e+00
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FDIV]], float 1.000000e+00
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp oeq float %y, 2.
+  %fdiv = fdiv float %y, 2.
+  %sel = select i1 %fcmp, float %fdiv, float 1.
+  ret float %sel
+}
+
+define float @select_fcmp_frem(float %x, float %y) {
+; CHECK-LABEL: @select_fcmp_frem(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 3.000000e+00
+; CHECK-NEXT:    [[FREM:%.*]] = frem float [[Y]], 2.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FREM]], float 1.000000e+00
+; CHECK-NEXT:    ret float [[SEL]]
+;
+  %fcmp = fcmp oeq float %y, 3.
+  %frem = frem float %y, 2.
+  %sel = select i1 %fcmp, float %frem, float 1.
+  ret float %sel
+}
+
+define <2 x float> @select_fcmp_insertelement(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @select_fcmp_insertelement(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq <2 x float> [[Y:%.*]], <float 2.000000e+00, float 2.000000e+00>
+; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <2 x float> [[Y]], float 4.000000e+00, i64 0
+; CHECK-NEXT:    [[RETVAL:%.*]] = select <2 x i1> [[CMP]], <2 x float> [[INSERT]], <2 x float> <float 4.000000e+00, float 2.000000e+00>
+; CHECK-NEXT:    ret <2 x float> [[RETVAL]]
+;
+  %fcmp = fcmp oeq <2 x float> %y, <float 2., float 2.>
+  %insert = insertelement <2 x float> %y, float 4., i64 0
+  %sel = select <2 x i1> %fcmp, <2 x float> %insert, <2 x float> <float 4., float 2.>
+  ret <2 x float> %sel
+}
+
+define <4 x float> @select_fcmp_shufflevector_select(<4 x float> %x, <4 x float> %y) {
+; CHECK-LABEL: @select_fcmp_shufflevector_select(
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq <4 x float> [[Y:%.*]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>
+; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x float> [[Y]], <4 x float> poison, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+; CHECK-NEXT:    [[SEL:%.*]] = select <4 x i1> [[FCMP]], <4 x float> [[SHUFFLE]], <4 x float> <float poison, float 2.000000e+00, float poison, float 2.000000e+00>
+; CHECK-NEXT:    ret <4 x float> [[SEL]]
+;
+  %fcmp = fcmp oeq <4 x float> %y, <float 2., float 2., float 2., float 2.>
+  %shuffle = shufflevector <4 x float> %y, <4 x float> poison, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+  %sel = select <4 x i1> %fcmp, <4 x float> %shuffle, <4 x float> <float poison, float 2., float poison, float 2.>
+  ret <4 x float> %sel
+}
+

>From d9bbccbc418db559545aaa9de8617555a9e5f03f Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Tue, 5 Nov 2024 11:52:41 +0000
Subject: [PATCH 2/2] InstSimplify: support floating-point equivalences

Since cd16b07 (IR: introduce CmpInst::isEquivalence), there is now an
isEquivalence routine in CmpInst that we can use to determine
equivalence in simplifySelectWithICmpEq. Implement this, extending
the code from integer-equalities to integer and floating-point
equivalences.
---
 llvm/lib/Analysis/InstructionSimplify.cpp     | 88 ++++++++++++-------
 .../Transforms/InstSimplify/fcmp-select.ll    |  8 +-
 .../InstSimplify/select-equivalence-fp.ll     | 50 +++--------
 3 files changed, 69 insertions(+), 77 deletions(-)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 2cb2612bf611e3..31f577247d3703 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4616,11 +4616,11 @@ static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
 }
 
 /// Try to simplify a select instruction when its condition operand is an
-/// integer equality comparison.
-static Value *simplifySelectWithICmpEq(Value *CmpLHS, Value *CmpRHS,
-                                       Value *TrueVal, Value *FalseVal,
-                                       const SimplifyQuery &Q,
-                                       unsigned MaxRecurse) {
+/// integer equality or floating-point equivalence comparison.
+static Value *simplifySelectWithEquivalence(Value *CmpLHS, Value *CmpRHS,
+                                            Value *TrueVal, Value *FalseVal,
+                                            const SimplifyQuery &Q,
+                                            unsigned MaxRecurse) {
   if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q.getWithoutUndef(),
                              /* AllowRefinement */ false,
                              /* DropFlags */ nullptr, MaxRecurse) == TrueVal)
@@ -4721,11 +4721,11 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
   // the arms of the select. See if substituting this value into the arm and
   // simplifying the result yields the same value as the other arm.
   if (Pred == ICmpInst::ICMP_EQ) {
-    if (Value *V = simplifySelectWithICmpEq(CmpLHS, CmpRHS, TrueVal, FalseVal,
-                                            Q, MaxRecurse))
+    if (Value *V = simplifySelectWithEquivalence(CmpLHS, CmpRHS, TrueVal,
+                                                 FalseVal, Q, MaxRecurse))
       return V;
-    if (Value *V = simplifySelectWithICmpEq(CmpRHS, CmpLHS, TrueVal, FalseVal,
-                                            Q, MaxRecurse))
+    if (Value *V = simplifySelectWithEquivalence(CmpRHS, CmpLHS, TrueVal,
+                                                 FalseVal, Q, MaxRecurse))
       return V;
 
     Value *X;
@@ -4734,11 +4734,11 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
     if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y))) &&
         match(CmpRHS, m_Zero())) {
       // (X | Y) == 0 implies X == 0 and Y == 0.
-      if (Value *V = simplifySelectWithICmpEq(X, CmpRHS, TrueVal, FalseVal, Q,
-                                              MaxRecurse))
+      if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
+                                                   Q, MaxRecurse))
         return V;
-      if (Value *V = simplifySelectWithICmpEq(Y, CmpRHS, TrueVal, FalseVal, Q,
-                                              MaxRecurse))
+      if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
+                                                   Q, MaxRecurse))
         return V;
     }
 
@@ -4746,11 +4746,11 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
     if (match(CmpLHS, m_And(m_Value(X), m_Value(Y))) &&
         match(CmpRHS, m_AllOnes())) {
       // (X & Y) == -1 implies X == -1 and Y == -1.
-      if (Value *V = simplifySelectWithICmpEq(X, CmpRHS, TrueVal, FalseVal, Q,
-                                              MaxRecurse))
+      if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
+                                                   Q, MaxRecurse))
         return V;
-      if (Value *V = simplifySelectWithICmpEq(Y, CmpRHS, TrueVal, FalseVal, Q,
-                                              MaxRecurse))
+      if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
+                                                   Q, MaxRecurse))
         return V;
     }
   }
@@ -4761,28 +4761,54 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
 /// Try to simplify a select instruction when its condition operand is a
 /// floating-point comparison.
 static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
-                                     const SimplifyQuery &Q) {
+                                     const SimplifyQuery &Q,
+                                     unsigned MaxRecurse) {
   FCmpInst::Predicate Pred;
-  if (!match(Cond, m_FCmp(Pred, m_Specific(T), m_Specific(F))) &&
-      !match(Cond, m_FCmp(Pred, m_Specific(F), m_Specific(T))))
+  Value *CmpLHS, *CmpRHS;
+  if (!match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
+    return nullptr;
+  FCmpInst *I = cast<FCmpInst>(Cond);
+
+  bool IsEquiv = I->isEquivalence(),
+       IsInverseEquiv = I->isEquivalence(/*Invert=*/true);
+
+  if (IsInverseEquiv)
+    std::swap(T, F);
+
+  // Canonicalize CmpLHS to be T, and CmpRHS to be F, if they're swapped.
+  if (CmpLHS == F && CmpRHS == T)
+    std::swap(CmpLHS, CmpRHS);
+
+  // This transforms is safe if at least one operand is known to not be zero.
+  // Otherwise, the select can change the sign of a zero operand.
+  if (IsEquiv || IsInverseEquiv) {
+    if (Value *V =
+            simplifySelectWithEquivalence(CmpLHS, CmpRHS, T, F, Q, MaxRecurse))
+      return V;
+    if (Value *V =
+            simplifySelectWithEquivalence(CmpRHS, CmpLHS, T, F, Q, MaxRecurse))
+      return V;
+
+    // (T == F) ? T : F --> F
+    // (T != F) ? F : T --> F
+    return CmpLHS == T && CmpRHS == F ? F : nullptr;
+  }
+
+  if (CmpLHS != T || CmpRHS != F)
     return nullptr;
 
-  // This transform is safe if we do not have (do not care about) -0.0 or if
-  // at least one operand is known to not be -0.0. Otherwise, the select can
-  // change the sign of a zero operand.
+  // This transform is also safe if we do not have (do not care about) -0.0.
   bool HasNoSignedZeros =
       Q.CxtI && isa<FPMathOperator>(Q.CxtI) && Q.CxtI->hasNoSignedZeros();
-  const APFloat *C;
-  if (HasNoSignedZeros || (match(T, m_APFloat(C)) && C->isNonZero()) ||
-      (match(F, m_APFloat(C)) && C->isNonZero())) {
+  if (HasNoSignedZeros) {
     // (T == F) ? T : F --> F
-    // (F == T) ? T : F --> F
-    if (Pred == FCmpInst::FCMP_OEQ)
+    if (Pred == FCmpInst::FCMP_OEQ ||
+        (Pred == FCmpInst::FCMP_UEQ && I->hasNoNaNs()))
       return F;
 
     // (T != F) ? T : F --> T
-    // (F != T) ? T : F --> T
-    if (Pred == FCmpInst::FCMP_UNE)
+    if (Pred == FCmpInst::FCMP_UNE ||
+        (Pred == FCmpInst::FCMP_ONE && I->hasNoNaNs()))
       return T;
   }
 
@@ -4955,7 +4981,7 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
           simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
     return V;
 
-  if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal, Q))
+  if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal, Q, MaxRecurse))
     return V;
 
   if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal))
diff --git a/llvm/test/Transforms/InstSimplify/fcmp-select.ll b/llvm/test/Transforms/InstSimplify/fcmp-select.ll
index 25fa7efe2d2eb9..dc09ee2707f138 100644
--- a/llvm/test/Transforms/InstSimplify/fcmp-select.ll
+++ b/llvm/test/Transforms/InstSimplify/fcmp-select.ll
@@ -124,9 +124,7 @@ define double @ueq_zero_nsz(double %x) {
 
 define double @ueq_zero_nsz_nnan(double %x) {
 ; CHECK-LABEL: @ueq_zero_nsz_nnan(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan ueq double [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[COND:%.*]] = select nsz i1 [[CMP]], double [[X]], double 0.000000e+00
-; CHECK-NEXT:    ret double [[COND]]
+; CHECK-NEXT:    ret double 0.000000e+00
 ;
   %cmp = fcmp nnan ueq double %x, 0.0
   %cond = select nsz i1 %cmp, double %x, double 0.0
@@ -168,9 +166,7 @@ define double @one_zero_nsz(double %x) {
 
 define double @one_zero_nsz_nnan(double %x) {
 ; CHECK-LABEL: @one_zero_nsz_nnan(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan one double [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[COND:%.*]] = select nsz i1 [[CMP]], double [[X]], double 0.000000e+00
-; CHECK-NEXT:    ret double [[COND]]
+; CHECK-NEXT:    ret double [[COND:%.*]]
 ;
   %cmp = fcmp nnan one double %x, 0.0
   %cond = select nsz i1 %cmp, double %x, double 0.0
diff --git a/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll b/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
index e9e81ad5513713..d5973aabcfae94 100644
--- a/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
+++ b/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
@@ -3,10 +3,7 @@
 
 define float @select_fcmp_fsub_oeq(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fsub_oeq(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 2.000000e+00
-; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
-; CHECK-NEXT:    ret float [[SEL]]
+; CHECK-NEXT:    ret float 0.000000e+00
 ;
   %fcmp = fcmp oeq float %y, 2.
   %fadd = fsub float %y, 2.
@@ -42,10 +39,7 @@ define float @select_fcmp_fsub_ueq(float %x, float %y) {
 
 define float @select_fcmp_fsub_ueq_nnan(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fsub_ueq_nnan(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp nnan ueq float [[Y:%.*]], 2.000000e+00
-; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
-; CHECK-NEXT:    ret float [[SEL]]
+; CHECK-NEXT:    ret float 0.000000e+00
 ;
   %fcmp = fcmp nnan ueq float %y, 2.
   %fadd = fsub float %y, 2.
@@ -55,10 +49,7 @@ define float @select_fcmp_fsub_ueq_nnan(float %x, float %y) {
 
 define float @select_fcmp_fsub_une(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fsub_une(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp une float [[Y:%.*]], 2.000000e+00
-; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
-; CHECK-NEXT:    ret float [[SEL]]
+; CHECK-NEXT:    ret float 0.000000e+00
 ;
   %fcmp = fcmp une float %y, 2.
   %fadd = fsub float %y, 2.
@@ -94,10 +85,7 @@ define float @select_fcmp_fsub_one(float %x, float %y) {
 
 define float @select_fcmp_fsub_one_nnan(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fsub_one_nnan(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp nnan one float [[Y:%.*]], 2.000000e+00
-; CHECK-NEXT:    [[FADD:%.*]] = fsub float [[Y]], 2.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
-; CHECK-NEXT:    ret float [[SEL]]
+; CHECK-NEXT:    ret float 0.000000e+00
 ;
   %fcmp = fcmp nnan one float %y, 2.
   %fadd = fsub float %y, 2.
@@ -107,10 +95,7 @@ define float @select_fcmp_fsub_one_nnan(float %x, float %y) {
 
 define float @select_fcmp_fadd(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fadd(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 2.000000e+00
-; CHECK-NEXT:    [[FADD:%.*]] = fadd float [[Y]], 2.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 4.000000e+00
-; CHECK-NEXT:    ret float [[SEL]]
+; CHECK-NEXT:    ret float 4.000000e+00
 ;
   %fcmp = fcmp oeq float %y, 2.
   %fadd = fadd float %y, 2.
@@ -120,10 +105,7 @@ define float @select_fcmp_fadd(float %x, float %y) {
 
 define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x, <2 x float> %y) {
 ; CHECK-LABEL: @select_fcmp_fadd_vec(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq <2 x float> [[Y:%.*]], <float 2.000000e+00, float 2.000000e+00>
-; CHECK-NEXT:    [[FADD:%.*]] = fadd <2 x float> [[Y]], <float 2.000000e+00, float 2.000000e+00>
-; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[FADD]], <2 x float> <float 4.000000e+00, float 4.000000e+00>
-; CHECK-NEXT:    ret <2 x float> [[SEL]]
+; CHECK-NEXT:    ret <2 x float> splat (float 4.000000e+00)
 ;
   %fcmp = fcmp oeq <2 x float> %y, <float 2., float 2.>
   %fadd = fadd <2 x float> %y, <float 2., float 2.>
@@ -134,10 +116,7 @@ define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x, <2 x float> %y) {
 
 define float @select_fcmp_fdiv(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fdiv(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 2.000000e+00
-; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[Y]], 2.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FDIV]], float 1.000000e+00
-; CHECK-NEXT:    ret float [[SEL]]
+; CHECK-NEXT:    ret float 1.000000e+00
 ;
   %fcmp = fcmp oeq float %y, 2.
   %fdiv = fdiv float %y, 2.
@@ -147,10 +126,7 @@ define float @select_fcmp_fdiv(float %x, float %y) {
 
 define float @select_fcmp_frem(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_frem(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[Y:%.*]], 3.000000e+00
-; CHECK-NEXT:    [[FREM:%.*]] = frem float [[Y]], 2.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[FREM]], float 1.000000e+00
-; CHECK-NEXT:    ret float [[SEL]]
+; CHECK-NEXT:    ret float 1.000000e+00
 ;
   %fcmp = fcmp oeq float %y, 3.
   %frem = frem float %y, 2.
@@ -160,10 +136,7 @@ define float @select_fcmp_frem(float %x, float %y) {
 
 define <2 x float> @select_fcmp_insertelement(<2 x float> %x, <2 x float> %y) {
 ; CHECK-LABEL: @select_fcmp_insertelement(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq <2 x float> [[Y:%.*]], <float 2.000000e+00, float 2.000000e+00>
-; CHECK-NEXT:    [[INSERT:%.*]] = insertelement <2 x float> [[Y]], float 4.000000e+00, i64 0
-; CHECK-NEXT:    [[RETVAL:%.*]] = select <2 x i1> [[CMP]], <2 x float> [[INSERT]], <2 x float> <float 4.000000e+00, float 2.000000e+00>
-; CHECK-NEXT:    ret <2 x float> [[RETVAL]]
+; CHECK-NEXT:    ret <2 x float> <float 4.000000e+00, float 2.000000e+00>
 ;
   %fcmp = fcmp oeq <2 x float> %y, <float 2., float 2.>
   %insert = insertelement <2 x float> %y, float 4., i64 0
@@ -173,10 +146,7 @@ define <2 x float> @select_fcmp_insertelement(<2 x float> %x, <2 x float> %y) {
 
 define <4 x float> @select_fcmp_shufflevector_select(<4 x float> %x, <4 x float> %y) {
 ; CHECK-LABEL: @select_fcmp_shufflevector_select(
-; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq <4 x float> [[Y:%.*]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>
-; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x float> [[Y]], <4 x float> poison, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
-; CHECK-NEXT:    [[SEL:%.*]] = select <4 x i1> [[FCMP]], <4 x float> [[SHUFFLE]], <4 x float> <float poison, float 2.000000e+00, float poison, float 2.000000e+00>
-; CHECK-NEXT:    ret <4 x float> [[SEL]]
+; CHECK-NEXT:    ret <4 x float> <float poison, float 2.000000e+00, float poison, float 2.000000e+00>
 ;
   %fcmp = fcmp oeq <4 x float> %y, <float 2., float 2., float 2., float 2.>
   %shuffle = shufflevector <4 x float> %y, <4 x float> poison, <4 x i32> <i32 4, i32 1, i32 6, i32 3>



More information about the llvm-commits mailing list