[llvm] [InstCombine] Fold select of ordered fcmps of fabs over `isKnownNeverNaN`-selects to a single select (PR #192182)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 22:11:09 PDT 2026


https://github.com/imkiva created https://github.com/llvm/llvm-project/pull/192182

Fold `select (fcmp <ordered> (fabs (select isKnownNeverNaN X, X, Y)), K), ...` into a single compare/select directly on `X`. The outer fcmp is limited to ordered predicates, since only they preserve the original non-NaN behavior.


fixes #143649 
alive2: https://alive2.llvm.org/ce/z/G8UmjY


Generalized proof (needs local alive2 build):
```alive2
declare double @llvm.fabs.f64(double)

define double @src(double %x, double %y, double %k) {
entry:
  %ord = fcmp ord double %x, 0.000000e+00
  %s = select i1 %ord, double %x, double %y
  %a = call double @llvm.fabs.f64(double %s)
  %c = fcmp one double %a, %k
  %r = select i1 %c, double %s, double %y
  ret double %r
}

define double @tgt(double %x, double %y, double %k) {
entry:
  %a2 = call double @llvm.fabs.f64(double %x)
  %c2 = fcmp one double %a2, %k
  %r2 = select i1 %c2, double %x, double %y
  ret double %r2
}
```

>From e009c9eac05ae5a6de4da24a5eaf29912ce40323 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Tue, 14 Apr 2026 17:11:13 +0800
Subject: [PATCH 1/2] [InstCombine] Fold ordered fcmps of fabs over
 NaN-scrubbed selects

---
 .../InstCombine/InstCombineSelect.cpp         | 71 +++++++++++++++++++
 .../Transforms/InstCombine/fcmp-select.ll     | 65 +++++++++++++++++
 2 files changed, 136 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index bffc887d93535..7ecb4ece56015 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3347,6 +3347,74 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
   return ChangedFMF ? &SI : nullptr;
 }
 
+// Fold a select of an ordered fcmp using fabs of a NaN-scrubbed value:
+//   %ord = fcmp ord T %x, 0.0
+//   %s   = select i1 %ord, T %x, T %y
+//   %a   = call T @llvm.fabs.T(T %s)
+//   %c   = fcmp <ordered-pred> T %a, %k
+//   %r   = select i1 %c, T %s, T %y
+//     =>
+//   %a2  = call T @llvm.fabs.T(T %x)
+//   %c2  = fcmp <ordered-pred> T %a2, %k
+//   %r2  = select i1 %c2, T %x, T %y
+static Instruction *
+foldSelectOfOrderedFAbsCmpOfNaNScrubbedValue(SelectInst &SI,
+                                             InstCombinerImpl &IC) {
+  auto *OuterCmp = dyn_cast<FCmpInst>(SI.getCondition());
+  if (!OuterCmp || !OuterCmp->hasOneUse() ||
+      !FCmpInst::isOrdered(OuterCmp->getPredicate()))
+    return nullptr;
+
+  // The NaN path now evaluates fabs(X) instead of fabs(Y), so preserving nnan
+  // on the fcmp could introduce poison when X is NaN.
+  if (OuterCmp->hasNoNaNs())
+    return nullptr;
+
+  Value *Y = SI.getFalseValue();
+  Value *X = nullptr;
+
+  auto *InnerSel = dyn_cast<SelectInst>(SI.getTrueValue());
+  if (!InnerSel)
+    return nullptr;
+
+  // Match: select (fcmp ord X, 0.0), X, Y
+  auto *InnerCmp = dyn_cast<FCmpInst>(InnerSel->getCondition());
+  if (!InnerCmp || !InnerCmp->hasOneUse() ||
+      InnerCmp->getPredicate() != FCmpInst::FCMP_ORD ||
+      InnerSel->getFalseValue() != Y)
+    return nullptr;
+
+  X = InnerSel->getTrueValue();
+  if (InnerCmp->getOperand(0) != X ||
+      !match(InnerCmp->getOperand(1), m_AnyZeroFP()))
+    return nullptr;
+
+  bool Swapped = false;
+  Value *OtherOp = nullptr;
+  auto *FAbs = dyn_cast<IntrinsicInst>(OuterCmp->getOperand(0));
+
+  if (FAbs && FAbs->hasOneUse() && FAbs->getIntrinsicID() == Intrinsic::fabs &&
+      FAbs->getArgOperand(0) == InnerSel) {
+    OtherOp = OuterCmp->getOperand(1);
+  } else if ((FAbs = dyn_cast<IntrinsicInst>(OuterCmp->getOperand(1))) &&
+             FAbs->hasOneUse() && FAbs->getIntrinsicID() == Intrinsic::fabs &&
+             FAbs->getArgOperand(0) == InnerSel) {
+    Swapped = true;
+    OtherOp = OuterCmp->getOperand(0);
+  } else {
+    return nullptr;
+  }
+
+  Value *NewAbs = IC.Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X);
+  Value *NewCmp = Swapped
+                      ? IC.Builder.CreateFCmpFMF(OuterCmp->getPredicate(),
+                                                 OtherOp, NewAbs, OuterCmp)
+                      : IC.Builder.CreateFCmpFMF(OuterCmp->getPredicate(),
+                                                 NewAbs, OtherOp, OuterCmp);
+  Value *NewSel = IC.Builder.CreateSelectFMF(NewCmp, X, Y, &SI);
+  return IC.replaceInstUsesWith(SI, NewSel);
+}
+
 // Match the following IR pattern:
 //   %x.lowbits = and i8 %x, %lowbitmask
 //   %x.lowbits.are.zero = icmp eq i8 %x.lowbits, 0
@@ -4599,6 +4667,9 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
   if (Instruction *Fabs = foldSelectWithFCmpToFabs(SI, *this))
     return Fabs;
 
+  if (Instruction *I = foldSelectOfOrderedFAbsCmpOfNaNScrubbedValue(SI, *this))
+    return I;
+
   // See if we are selecting two values based on a comparison of the two values.
   if (CmpInst *CI = dyn_cast<CmpInst>(CondVal))
     if (Instruction *NewSel = foldSelectValueEquivalence(SI, *CI))
diff --git a/llvm/test/Transforms/InstCombine/fcmp-select.ll b/llvm/test/Transforms/InstCombine/fcmp-select.ll
index 268cd4675c6cc..0b4e9ebff1c92 100644
--- a/llvm/test/Transforms/InstCombine/fcmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp-select.ll
@@ -3,6 +3,7 @@
 
 declare void @use(i1)
 declare void @usef64(double)
+declare double @llvm.fabs.f64(double)
 
 ; X == 42.0 ? X : 42.0 --> 42.0
 
@@ -280,6 +281,70 @@ define i1 @test_fcmp_ord_select_fcmp_oeq_var_const(double %x) {
   ret i1 %cmp2
 }
 
+define double @test_fcmp_ord_select_fabs_fcmp_one_select_var_const(double %x) {
+; CHECK-LABEL: @test_fcmp_ord_select_fabs_fcmp_one_select_var_const(
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double 0.000000e+00
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %cmp1 = fcmp ord double %x, 0.000000e+00
+  %sel1 = select i1 %cmp1, double %x, double 0.000000e+00
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double 0.000000e+00
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_select_fabs_fcmp_une_select_var_const(double %x) {
+; CHECK-LABEL: @test_fcmp_ord_select_fabs_fcmp_une_select_var_const(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[CMP1]], double [[X]], double 0.000000e+00
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SEL1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp une double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[CMP2]], double [[SEL1]], double 0.000000e+00
+; CHECK-NEXT:    ret double [[SEL2]]
+;
+  %cmp1 = fcmp ord double %x, 0.000000e+00
+  %sel1 = select i1 %cmp1, double %x, double 0.000000e+00
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp une double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double 0.000000e+00
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_select_fabs_fcmp_nnan_one_select_var_var(double %x, double %y) {
+; CHECK-LABEL: @test_fcmp_ord_select_fabs_fcmp_nnan_one_select_var_var(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[CMP1]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SEL1]])
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp nnan one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[CMP2]], double [[SEL1]], double [[Y]]
+; CHECK-NEXT:    ret double [[SEL2]]
+;
+  %cmp1 = fcmp ord double %x, 0.000000e+00
+  %sel1 = select i1 %cmp1, double %x, double %y
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp nnan one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_select_fabs_rhs_fcmp_ogt_select_var_var(double %x, double %y, double %k) {
+; CHECK-LABEL: @test_fcmp_ord_select_fabs_rhs_fcmp_ogt_select_var_var(
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ninf ogt double [[K:%.*]], [[ABS]]
+; CHECK-NEXT:    [[SEL:%.*]] = select nnan i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %cmp1 = fcmp ord double %x, 0.000000e+00
+  %sel1 = select i1 %cmp1, double %x, double %y
+  %abs = call ninf double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp ninf ogt double %k, %abs
+  %sel2 = select nnan i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
 ; Make sure that we recognize the SPF correctly.
 
 define float @test_select_nnan_nsz_fcmp_olt(float %x) {

>From 9dc2eb2f2e76fdbd6bc7bddb528852d4f9c04b63 Mon Sep 17 00:00:00 2001
From: imkiva <zengtao at iscas.ac.cn>
Date: Wed, 15 Apr 2026 13:08:11 +0800
Subject: [PATCH 2/2] [InstCombine] Use `isKnownNeverNaN`

---
 .../InstCombine/InstCombineSelect.cpp         |  57 ++++++--
 .../Transforms/InstCombine/fcmp-select.ll     | 124 ++++++++++++++++++
 2 files changed, 169 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 7ecb4ece56015..21556d8aabee1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3347,9 +3347,50 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
   return ChangedFMF ? &SI : nullptr;
 }
 
+static bool matchIsNaNTest(FCmpInst *Cmp, Value *X, bool MatchIsNaN,
+                           InstCombinerImpl &IC) {
+  FCmpInst::Predicate ExpectedPred =
+      MatchIsNaN ? FCmpInst::FCMP_UNO : FCmpInst::FCMP_ORD;
+  if (Cmp->getPredicate() != ExpectedPred)
+    return false;
+
+  Value *Cmp0 = Cmp->getOperand(0), *Cmp1 = Cmp->getOperand(1);
+  if (Cmp0 == X && Cmp1 == X)
+    return true;
+
+  auto IsKnownNeverNaN = [&](Value *V) {
+    return match(V, m_NonNaN()) ||
+           isKnownNeverNaN(V, IC.getSimplifyQuery().getWithInstruction(Cmp));
+  };
+
+  return (Cmp0 == X && IsKnownNeverNaN(Cmp1)) ||
+         (Cmp1 == X && IsKnownNeverNaN(Cmp0));
+}
+
+// Match a select that returns X when X is not NaN, and Y otherwise.
+static Value *matchNaNScrubbedValue(SelectInst *SI, Value *Y,
+                                    InstCombinerImpl &IC) {
+  auto *Cmp = dyn_cast<FCmpInst>(SI->getCondition());
+  if (!Cmp || !Cmp->hasOneUse())
+    return nullptr;
+
+  Value *X;
+  bool MatchIsNaN;
+  if (SI->getFalseValue() == Y) {
+    X = SI->getTrueValue();
+    MatchIsNaN = false;
+  } else if (SI->getTrueValue() == Y) {
+    X = SI->getFalseValue();
+    MatchIsNaN = true;
+  } else {
+    return nullptr;
+  }
+
+  return matchIsNaNTest(Cmp, X, MatchIsNaN, IC) ? X : nullptr;
+}
+
 // Fold a select of an ordered fcmp using fabs of a NaN-scrubbed value:
-//   %ord = fcmp ord T %x, 0.0
-//   %s   = select i1 %ord, T %x, T %y
+//   %s   = select i1 (isnotnan T %x), T %x, T %y
 //   %a   = call T @llvm.fabs.T(T %s)
 //   %c   = fcmp <ordered-pred> T %a, %k
 //   %r   = select i1 %c, T %s, T %y
@@ -3377,16 +3418,8 @@ foldSelectOfOrderedFAbsCmpOfNaNScrubbedValue(SelectInst &SI,
   if (!InnerSel)
     return nullptr;
 
-  // Match: select (fcmp ord X, 0.0), X, Y
-  auto *InnerCmp = dyn_cast<FCmpInst>(InnerSel->getCondition());
-  if (!InnerCmp || !InnerCmp->hasOneUse() ||
-      InnerCmp->getPredicate() != FCmpInst::FCMP_ORD ||
-      InnerSel->getFalseValue() != Y)
-    return nullptr;
-
-  X = InnerSel->getTrueValue();
-  if (InnerCmp->getOperand(0) != X ||
-      !match(InnerCmp->getOperand(1), m_AnyZeroFP()))
+  X = matchNaNScrubbedValue(InnerSel, Y, IC);
+  if (!X)
     return nullptr;
 
   bool Swapped = false;
diff --git a/llvm/test/Transforms/InstCombine/fcmp-select.ll b/llvm/test/Transforms/InstCombine/fcmp-select.ll
index 0b4e9ebff1c92..4cc009c066865 100644
--- a/llvm/test/Transforms/InstCombine/fcmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp-select.ll
@@ -296,6 +296,130 @@ define double @test_fcmp_ord_select_fabs_fcmp_one_select_var_const(double %x) {
   ret double %sel2
 }
 
+define double @test_fcmp_ord_commuted_select_fabs_fcmp_one_select_var_const(double %x) {
+; CHECK-LABEL: @test_fcmp_ord_commuted_select_fabs_fcmp_one_select_var_const(
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double 0.000000e+00
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %cmp1 = fcmp ord double 0.000000e+00, %x
+  %sel1 = select i1 %cmp1, double %x, double 0.000000e+00
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double 0.000000e+00
+  ret double %sel2
+}
+
+define double @test_fcmp_uno_select_fabs_fcmp_one_select_var_var(double %x, double %y) {
+; CHECK-LABEL: @test_fcmp_uno_select_fabs_fcmp_one_select_var_var(
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %cmp1 = fcmp uno double %x, 0.000000e+00
+  %sel1 = select i1 %cmp1, double %y, double %x
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_select_fabs_fcmp_one_select_nonnan_const(double %x, double %y) {
+; CHECK-LABEL: @test_fcmp_ord_select_fabs_fcmp_one_select_nonnan_const(
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %cmp1 = fcmp ord double %x, 1.000000e+00
+  %sel1 = select i1 %cmp1, double %x, double %y
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_self_select_fabs_fcmp_one_select_var_var(double %x, double %y) {
+; CHECK-LABEL: @test_fcmp_ord_self_select_fabs_fcmp_one_select_var_var(
+; CHECK-NEXT:    [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %cmp1 = fcmp ord double %x, %x
+  %sel1 = select i1 %cmp1, double %x, double %y
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_select_fabs_fcmp_one_select_uitofp_nonnan(double %x, double %y, i32 %i) {
+; CHECK-LABEL: @test_fcmp_ord_select_fabs_fcmp_one_select_uitofp_nonnan(
+; CHECK:         [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %nonnan = uitofp i32 %i to double
+  %cmp1 = fcmp ord double %x, %nonnan
+  %sel1 = select i1 %cmp1, double %x, double %y
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_commuted_select_fabs_fcmp_one_select_sitofp_nonnan(double %x, double %y, i32 %i) {
+; CHECK-LABEL: @test_fcmp_ord_commuted_select_fabs_fcmp_one_select_sitofp_nonnan(
+; CHECK:         [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %nonnan = sitofp i32 %i to double
+  %cmp1 = fcmp ord double %nonnan, %x
+  %sel1 = select i1 %cmp1, double %x, double %y
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
+define double @test_fcmp_uno_select_fabs_fcmp_one_select_uitofp_nonnan(double %x, double %y, i32 %i) {
+; CHECK-LABEL: @test_fcmp_uno_select_fabs_fcmp_one_select_uitofp_nonnan(
+; CHECK:         [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[ABS]], 0x7FF0000000000000
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %nonnan = uitofp i32 %i to double
+  %cmp1 = fcmp uno double %x, %nonnan
+  %sel1 = select i1 %cmp1, double %y, double %x
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp one double %abs, 0x7FF0000000000000
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
+define double @test_fcmp_ord_select_fabs_rhs_fcmp_ogt_select_uitofp_nonnan(double %x, double %y, double %k, i32 %i) {
+; CHECK-LABEL: @test_fcmp_ord_select_fabs_rhs_fcmp_ogt_select_uitofp_nonnan(
+; CHECK:         [[ABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt double [[K:%.*]], [[ABS]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], double [[X]], double [[Y:%.*]]
+; CHECK-NEXT:    ret double [[SEL]]
+;
+  %nonnan = uitofp i32 %i to double
+  %cmp1 = fcmp ord double %x, %nonnan
+  %sel1 = select i1 %cmp1, double %x, double %y
+  %abs = call double @llvm.fabs.f64(double %sel1)
+  %cmp2 = fcmp ogt double %k, %abs
+  %sel2 = select i1 %cmp2, double %sel1, double %y
+  ret double %sel2
+}
+
 define double @test_fcmp_ord_select_fabs_fcmp_une_select_var_const(double %x) {
 ; CHECK-LABEL: @test_fcmp_ord_select_fabs_fcmp_une_select_var_const(
 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord double [[X:%.*]], 0.000000e+00



More information about the llvm-commits mailing list