When forming SSE min and max nodes for UGE and ULE comparisons, it's
authorDan Gohman <gohman@apple.com>
Wed, 24 Feb 2010 06:52:40 +0000 (06:52 +0000)
committerDan Gohman <gohman@apple.com>
Wed, 24 Feb 2010 06:52:40 +0000 (06:52 +0000)
necessary to swap the operands to handle NaN and negative zero properly.

Also, reintroduce logic for checking for NaN conditions when forming
SSE min and max instructions, fixed to take into consideration NaNs and
negative zeros. This allows forming min and max instructions in more
cases.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97025 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/SelectionDAG.h
include/llvm/CodeGen/SelectionDAGNodes.h
include/llvm/Constants.h
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/sse-minmax.ll

index e62860314cdd37e6cc68ecad51f20eff749abfa3..09651e6c605cc073ef6c2fd31f06828002425f1b 100644 (file)
@@ -898,6 +898,15 @@ public:
   /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN.
   bool isKnownNeverNaN(SDValue Op) const;
 
+  /// isKnownNeverZero - Test whether the given SDValue is known to never be
+  /// positive or negative Zero.
+  bool isKnownNeverZero(SDValue Op) const;
+
+  /// isEqualTo - Test whether two SDValues are known to compare equal. This
+  /// is true if they are the same value, or if one is negative zero and the
+  /// other positive zero.
+  bool isEqualTo(SDValue A, SDValue B) const;
+
   /// isVerifiedDebugInfoDesc - Returns true if the specified SDValue has
   /// been verified as a debug information descriptor.
   bool isVerifiedDebugInfoDesc(SDValue Op) const;
index 90669136204c198efeefdf83d91de6a09846bd37..950963ea1879052d912c1fc91e75e1e51a6b5efd 100644 (file)
@@ -1815,6 +1815,12 @@ public:
   const APFloat& getValueAPF() const { return Value->getValueAPF(); }
   const ConstantFP *getConstantFPValue() const { return Value; }
 
+  /// isZero - Return true if the value is positive or negative zero.
+  bool isZero() const { return Value->isZero(); }
+
+  /// isNaN - Return true if the value is a NaN.
+  bool isNaN() const { return Value->isNaN(); }
+
   /// isExactlyValue - We don't rely on operator== working on double values, as
   /// it returns true for things that are clearly not equal, like -0.0 and 0.0.
   /// As such, this method can be used to do an exact bit-for-bit comparison of
index bd14303d6701344be866b3faa0f41abda0362456..c706329fb28bb734b2f60bdb30dbdfaebc25fbaf 100644 (file)
@@ -276,6 +276,12 @@ public:
     return Val.isZero() && Val.isNegative();
   }
 
+  /// isZero - Return true if the value is positive or negative zero.
+  bool isZero() const { return Val.isZero(); }
+
+  /// isNaN - Return true if the value is a NaN.
+  bool isNaN() const { return Val.isNaN(); }
+
   /// isExactlyValue - We don't rely on operator== working on double values, as
   /// it returns true for things that are clearly not equal, like -0.0 and 0.0.
   /// As such, this method can be used to do an exact bit-for-bit comparison of
index f8930b8ff0c3590562fd635379aba2c5f062f26d..41050211b2e687cdbff88e42327286de2d613d14 100644 (file)
@@ -2235,6 +2235,29 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op) const {
   return false;
 }
 
+bool SelectionDAG::isKnownNeverZero(SDValue Op) const {
+  // If the value is a constant, we can obviously see if it is a zero or not.
+  if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Op))
+    return !C->isZero();
+
+  // TODO: Recognize more cases here.
+
+  return false;
+}
+
+bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const {
+  // Check the obvious case.
+  if (A == B) return true;
+
+  // For for negative and positive zero.
+  if (const ConstantFPSDNode *CA = dyn_cast<ConstantFPSDNode>(A))
+    if (const ConstantFPSDNode *CB = dyn_cast<ConstantFPSDNode>(B))
+      if (CA->isZero() && CB->isZero()) return true;
+
+  // Otherwise they may not be equal.
+  return false;
+}
+
 bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const {
   GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
   if (!GA) return false;
index 3bbe5fb70f6d4fccb93d0fe61079711e2a0e3d33..d2d76da838cc75186236df2a77725c7f401dfecb 100644 (file)
@@ -8833,18 +8833,35 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
 
     unsigned Opcode = 0;
     // Check for x CC y ? x : y.
-    if (LHS == Cond.getOperand(0) && RHS == Cond.getOperand(1)) {
+    if (DAG.isEqualTo(LHS, Cond.getOperand(0)) &&
+        DAG.isEqualTo(RHS, Cond.getOperand(1))) {
       switch (CC) {
       default: break;
       case ISD::SETULT:
-        if (!UnsafeFPMath) break;
+        // Converting this to a min would handle NaNs incorrectly, and swapping
+        // the operands would cause it to handle comparisons between positive
+        // and negative zero incorrectly.
+        if (!FiniteOnlyFPMath() &&
+            (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) {
+          if (!UnsafeFPMath &&
+              !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS)))
+            break;
+          std::swap(LHS, RHS);
+        }
         Opcode = X86ISD::FMIN;
         break;
       case ISD::SETOLE:
-        if (!UnsafeFPMath) break;
+        // Converting this to a min would handle comparisons between positive
+        // and negative zero incorrectly.
+        if (!UnsafeFPMath &&
+            !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(RHS))
+          break;
         Opcode = X86ISD::FMIN;
         break;
       case ISD::SETULE:
+        // Converting this to a min would handle both negative zeros and NaNs
+        // incorrectly, but we can swap the operands to fix both.
+        std::swap(LHS, RHS);
       case ISD::SETOLT:
       case ISD::SETLT:
       case ISD::SETLE:
@@ -8852,14 +8869,30 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
         break;
 
       case ISD::SETOGE:
-        if (!UnsafeFPMath) break;
+        // Converting this to a max would handle comparisons between positive
+        // and negative zero incorrectly.
+        if (!UnsafeFPMath &&
+            !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(LHS))
+          break;
         Opcode = X86ISD::FMAX;
         break;
       case ISD::SETUGT:
-        if (!UnsafeFPMath) break;
+        // Converting this to a max would handle NaNs incorrectly, and swapping
+        // the operands would cause it to handle comparisons between positive
+        // and negative zero incorrectly.
+        if (!FiniteOnlyFPMath() &&
+            (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) {
+          if (!UnsafeFPMath &&
+              !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS)))
+            break;
+          std::swap(LHS, RHS);
+        }
         Opcode = X86ISD::FMAX;
         break;
       case ISD::SETUGE:
+        // Converting this to a max would handle both negative zeros and NaNs
+        // incorrectly, but we can swap the operands to fix both.
+        std::swap(LHS, RHS);
       case ISD::SETOGT:
       case ISD::SETGT:
       case ISD::SETGE:
@@ -8867,18 +8900,34 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
         break;
       }
     // Check for x CC y ? y : x -- a min/max with reversed arms.
-    } else if (LHS == Cond.getOperand(1) && RHS == Cond.getOperand(0)) {
+    } else if (DAG.isEqualTo(LHS, Cond.getOperand(1)) &&
+               DAG.isEqualTo(RHS, Cond.getOperand(0))) {
       switch (CC) {
       default: break;
       case ISD::SETOGE:
-        if (!UnsafeFPMath) break;
+        // Converting this to a min would handle comparisons between positive
+        // and negative zero incorrectly, and swapping the operands would
+        // cause it to handle NaNs incorrectly.
+        if (!UnsafeFPMath &&
+            !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) {
+          if (!FiniteOnlyFPMath() &&
+              (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS)))
+            break;
+          std::swap(LHS, RHS);
+        }
         Opcode = X86ISD::FMIN;
         break;
       case ISD::SETUGT:
-        if (!UnsafeFPMath) break;
+        // Converting this to a min would handle NaNs incorrectly.
+        if (!UnsafeFPMath &&
+            (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS)))
+          break;
         Opcode = X86ISD::FMIN;
         break;
       case ISD::SETUGE:
+        // Converting this to a min would handle both negative zeros and NaNs
+        // incorrectly, but we can swap the operands to fix both.
+        std::swap(LHS, RHS);
       case ISD::SETOGT:
       case ISD::SETGT:
       case ISD::SETGE:
@@ -8886,14 +8935,29 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
         break;
 
       case ISD::SETULT:
-        if (!UnsafeFPMath) break;
+        // Converting this to a max would handle NaNs incorrectly.
+        if (!FiniteOnlyFPMath() &&
+            (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS)))
+          break;
         Opcode = X86ISD::FMAX;
         break;
       case ISD::SETOLE:
-        if (!UnsafeFPMath) break;
+        // Converting this to a max would handle comparisons between positive
+        // and negative zero incorrectly, and swapping the operands would
+        // cause it to handle NaNs incorrectly.
+        if (!UnsafeFPMath &&
+            !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(RHS)) {
+          if (!FiniteOnlyFPMath() &&
+              (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS)))
+            break;
+          std::swap(LHS, RHS);
+        }
         Opcode = X86ISD::FMAX;
         break;
       case ISD::SETULE:
+        // Converting this to a max would handle both negative zeros and NaNs
+        // incorrectly, but we can swap the operands to fix both.
+        std::swap(LHS, RHS);
       case ISD::SETOLT:
       case ISD::SETLT:
       case ISD::SETLE:
index f8590fdb28850cb31ab0397c8cbfb7b41e7739fa..19fbed015b2fdb188e7aef6e7d225456e56f5c8b 100644 (file)
@@ -1,13 +1,15 @@
 ; RUN: llc < %s -march=x86-64 -asm-verbose=false | FileCheck %s
 ; RUN: llc < %s -march=x86-64 -asm-verbose=false -enable-unsafe-fp-math | FileCheck -check-prefix=UNSAFE %s
+; RUN: llc < %s -march=x86-64 -asm-verbose=false -enable-finite-only-fp-math | FileCheck -check-prefix=FINITE %s
 
 ; Some of these patterns can be matched as SSE min or max. Some of
 ; then can be matched provided that the operands are swapped.
 ; Some of them can't be matched at all and require a comparison
 ; and a conditional branch.
 
-; The naming convention is {,x_}{o,u}{gt,lt,ge,le}{,_inverse}
+; The naming convention is {,x_,y_}{o,u}{gt,lt,ge,le}{,_inverse}
 ; x_ : use 0.0 instead of %y
+; y_ : use -0.0 instead of %y
 ; _inverse : swap the arms of the select.
 
 ; CHECK:      ogt:
@@ -16,6 +18,9 @@
 ; UNSAFE:      ogt:
 ; UNSAFE-NEXT: maxsd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ogt:
+; FINITE-NEXT: maxsd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ogt(double %x, double %y) nounwind {
   %c = fcmp ogt double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -28,6 +33,9 @@ define double @ogt(double %x, double %y) nounwind {
 ; UNSAFE:      olt:
 ; UNSAFE-NEXT: minsd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      olt:
+; FINITE-NEXT: minsd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @olt(double %x, double %y) nounwind {
   %c = fcmp olt double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -42,6 +50,10 @@ define double @olt(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: minsd  %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ogt_inverse:
+; FINITE-NEXT: minsd  %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ogt_inverse(double %x, double %y) nounwind {
   %c = fcmp ogt double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -56,6 +68,10 @@ define double @ogt_inverse(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: maxsd  %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      olt_inverse:
+; FINITE-NEXT: maxsd  %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @olt_inverse(double %x, double %y) nounwind {
   %c = fcmp olt double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -67,6 +83,9 @@ define double @olt_inverse(double %x, double %y) nounwind {
 ; UNSAFE:      oge:
 ; UNSAFE-NEXT: maxsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      oge:
+; FINITE-NEXT: maxsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @oge(double %x, double %y) nounwind {
   %c = fcmp oge double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -77,6 +96,8 @@ define double @oge(double %x, double %y) nounwind {
 ; CHECK-NEXT: ucomisd %xmm0, %xmm1
 ; UNSAFE:      ole:
 ; UNSAFE-NEXT: minsd %xmm1, %xmm0
+; FINITE:      ole:
+; FINITE-NEXT: minsd %xmm1, %xmm0
 define double @ole(double %x, double %y) nounwind {
   %c = fcmp ole double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -89,6 +110,10 @@ define double @ole(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: minsd %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      oge_inverse:
+; FINITE-NEXT: minsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @oge_inverse(double %x, double %y) nounwind {
   %c = fcmp oge double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -101,6 +126,10 @@ define double @oge_inverse(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: maxsd %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ole_inverse:
+; FINITE-NEXT: maxsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ole_inverse(double %x, double %y) nounwind {
   %c = fcmp ole double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -115,6 +144,10 @@ define double @ole_inverse(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: pxor  %xmm1, %xmm1
 ; UNSAFE-NEXT: maxsd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ogt:
+; FINITE-NEXT: pxor  %xmm1, %xmm1
+; FINITE-NEXT: maxsd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ogt(double %x) nounwind {
   %c = fcmp ogt double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -129,6 +162,10 @@ define double @x_ogt(double %x) nounwind {
 ; UNSAFE-NEXT: pxor  %xmm1, %xmm1
 ; UNSAFE-NEXT: minsd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_olt:
+; FINITE-NEXT: pxor  %xmm1, %xmm1
+; FINITE-NEXT: minsd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_olt(double %x) nounwind {
   %c = fcmp olt double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -145,6 +182,11 @@ define double @x_olt(double %x) nounwind {
 ; UNSAFE-NEXT: minsd  %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ogt_inverse:
+; FINITE-NEXT: pxor   %xmm1, %xmm1
+; FINITE-NEXT: minsd  %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ogt_inverse(double %x) nounwind {
   %c = fcmp ogt double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
@@ -161,6 +203,11 @@ define double @x_ogt_inverse(double %x) nounwind {
 ; UNSAFE-NEXT: maxsd  %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_olt_inverse:
+; FINITE-NEXT: pxor   %xmm1, %xmm1
+; FINITE-NEXT: maxsd  %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_olt_inverse(double %x) nounwind {
   %c = fcmp olt double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
@@ -173,6 +220,10 @@ define double @x_olt_inverse(double %x) nounwind {
 ; UNSAFE-NEXT: pxor    %xmm1, %xmm1
 ; UNSAFE-NEXT: maxsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_oge:
+; FINITE-NEXT: pxor    %xmm1, %xmm1
+; FINITE-NEXT: maxsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_oge(double %x) nounwind {
   %c = fcmp oge double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -185,6 +236,10 @@ define double @x_oge(double %x) nounwind {
 ; UNSAFE-NEXT: pxor %xmm1, %xmm1
 ; UNSAFE-NEXT: minsd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ole:
+; FINITE-NEXT: pxor %xmm1, %xmm1
+; FINITE-NEXT: minsd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ole(double %x) nounwind {
   %c = fcmp ole double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -198,6 +253,11 @@ define double @x_ole(double %x) nounwind {
 ; UNSAFE-NEXT: minsd   %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_oge_inverse:
+; FINITE-NEXT: pxor    %xmm1, %xmm1
+; FINITE-NEXT: minsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_oge_inverse(double %x) nounwind {
   %c = fcmp oge double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
@@ -211,6 +271,11 @@ define double @x_oge_inverse(double %x) nounwind {
 ; UNSAFE-NEXT: maxsd   %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ole_inverse:
+; FINITE-NEXT: pxor    %xmm1, %xmm1
+; FINITE-NEXT: maxsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ole_inverse(double %x) nounwind {
   %c = fcmp ole double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
@@ -222,6 +287,9 @@ define double @x_ole_inverse(double %x) nounwind {
 ; UNSAFE:      ugt:
 ; UNSAFE-NEXT: maxsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ugt:
+; FINITE-NEXT: maxsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ugt(double %x, double %y) nounwind {
   %c = fcmp ugt double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -233,6 +301,9 @@ define double @ugt(double %x, double %y) nounwind {
 ; UNSAFE:      ult:
 ; UNSAFE-NEXT: minsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ult:
+; FINITE-NEXT: minsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ult(double %x, double %y) nounwind {
   %c = fcmp ult double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -245,6 +316,10 @@ define double @ult(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: minsd   %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ugt_inverse:
+; FINITE-NEXT: minsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ugt_inverse(double %x, double %y) nounwind {
   %c = fcmp ugt double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -257,6 +332,10 @@ define double @ugt_inverse(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: maxsd   %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ult_inverse:
+; FINITE-NEXT: maxsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ult_inverse(double %x, double %y) nounwind {
   %c = fcmp ult double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -264,11 +343,15 @@ define double @ult_inverse(double %x, double %y) nounwind {
 }
 
 ; CHECK:      uge:
-; CHECK-NEXT: maxsd   %xmm1, %xmm0
+; CHECK-NEXT: maxsd   %xmm0, %xmm1
+; CHECK-NEXT: movapd  %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      uge:
 ; UNSAFE-NEXT: maxsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      uge:
+; FINITE-NEXT: maxsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @uge(double %x, double %y) nounwind {
   %c = fcmp uge double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -276,11 +359,15 @@ define double @uge(double %x, double %y) nounwind {
 }
 
 ; CHECK:      ule:
-; CHECK-NEXT: minsd  %xmm1, %xmm0
+; CHECK-NEXT: minsd  %xmm0, %xmm1
+; CHECK-NEXT: movapd %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      ule:
 ; UNSAFE-NEXT: minsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ule:
+; FINITE-NEXT: minsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ule(double %x, double %y) nounwind {
   %c = fcmp ule double %x, %y
   %d = select i1 %c, double %x, double %y
@@ -288,13 +375,16 @@ define double @ule(double %x, double %y) nounwind {
 }
 
 ; CHECK:      uge_inverse:
-; CHECK-NEXT: minsd %xmm0, %xmm1
-; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: minsd %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      uge_inverse:
 ; UNSAFE-NEXT: minsd %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      uge_inverse:
+; FINITE-NEXT: minsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @uge_inverse(double %x, double %y) nounwind {
   %c = fcmp uge double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -302,13 +392,16 @@ define double @uge_inverse(double %x, double %y) nounwind {
 }
 
 ; CHECK:      ule_inverse:
-; CHECK-NEXT: maxsd %xmm0, %xmm1
-; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: maxsd %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      ule_inverse:
 ; UNSAFE-NEXT: maxsd %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      ule_inverse:
+; FINITE-NEXT: maxsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @ule_inverse(double %x, double %y) nounwind {
   %c = fcmp ule double %x, %y
   %d = select i1 %c, double %y, double %x
@@ -321,6 +414,10 @@ define double @ule_inverse(double %x, double %y) nounwind {
 ; UNSAFE-NEXT: pxor    %xmm1, %xmm1
 ; UNSAFE-NEXT: maxsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ugt:
+; FINITE-NEXT: pxor    %xmm1, %xmm1
+; FINITE-NEXT: maxsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ugt(double %x) nounwind {
   %c = fcmp ugt double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -333,6 +430,10 @@ define double @x_ugt(double %x) nounwind {
 ; UNSAFE-NEXT: pxor    %xmm1, %xmm1
 ; UNSAFE-NEXT: minsd   %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ult:
+; FINITE-NEXT: pxor    %xmm1, %xmm1
+; FINITE-NEXT: minsd   %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ult(double %x) nounwind {
   %c = fcmp ult double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -346,6 +447,11 @@ define double @x_ult(double %x) nounwind {
 ; UNSAFE-NEXT: minsd   %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ugt_inverse:
+; FINITE-NEXT: pxor    %xmm1, %xmm1
+; FINITE-NEXT: minsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ugt_inverse(double %x) nounwind {
   %c = fcmp ugt double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
@@ -359,6 +465,11 @@ define double @x_ugt_inverse(double %x) nounwind {
 ; UNSAFE-NEXT: maxsd   %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ult_inverse:
+; FINITE-NEXT: pxor    %xmm1, %xmm1
+; FINITE-NEXT: maxsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ult_inverse(double %x) nounwind {
   %c = fcmp ult double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
@@ -367,12 +478,17 @@ define double @x_ult_inverse(double %x) nounwind {
 
 ; CHECK:      x_uge:
 ; CHECK-NEXT: pxor   %xmm1, %xmm1
-; CHECK-NEXT: maxsd  %xmm1, %xmm0
+; CHECK-NEXT: maxsd  %xmm0, %xmm1
+; CHECK-NEXT: movapd %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      x_uge:
 ; UNSAFE-NEXT: pxor   %xmm1, %xmm1
 ; UNSAFE-NEXT: maxsd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_uge:
+; FINITE-NEXT: pxor   %xmm1, %xmm1
+; FINITE-NEXT: maxsd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_uge(double %x) nounwind {
   %c = fcmp uge double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -381,12 +497,17 @@ define double @x_uge(double %x) nounwind {
 
 ; CHECK:      x_ule:
 ; CHECK-NEXT: pxor   %xmm1, %xmm1
-; CHECK-NEXT: minsd  %xmm1, %xmm0
+; CHECK-NEXT: minsd  %xmm0, %xmm1
+; CHECK-NEXT: movapd %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      x_ule:
 ; UNSAFE-NEXT: pxor   %xmm1, %xmm1
 ; UNSAFE-NEXT: minsd  %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ule:
+; FINITE-NEXT: pxor   %xmm1, %xmm1
+; FINITE-NEXT: minsd  %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ule(double %x) nounwind {
   %c = fcmp ule double %x, 0.000000e+00
   %d = select i1 %c, double %x, double 0.000000e+00
@@ -395,14 +516,18 @@ define double @x_ule(double %x) nounwind {
 
 ; CHECK:      x_uge_inverse:
 ; CHECK-NEXT: pxor  %xmm1, %xmm1
-; CHECK-NEXT: minsd %xmm0, %xmm1
-; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: minsd %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      x_uge_inverse:
 ; UNSAFE-NEXT: pxor  %xmm1, %xmm1
 ; UNSAFE-NEXT: minsd %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_uge_inverse:
+; FINITE-NEXT: pxor  %xmm1, %xmm1
+; FINITE-NEXT: minsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_uge_inverse(double %x) nounwind {
   %c = fcmp uge double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
@@ -411,26 +536,303 @@ define double @x_uge_inverse(double %x) nounwind {
 
 ; CHECK:      x_ule_inverse:
 ; CHECK-NEXT: pxor  %xmm1, %xmm1
-; CHECK-NEXT: maxsd %xmm0, %xmm1
-; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: maxsd %xmm1, %xmm0
 ; CHECK-NEXT: ret
 ; UNSAFE:      x_ule_inverse:
 ; UNSAFE-NEXT: pxor  %xmm1, %xmm1
 ; UNSAFE-NEXT: maxsd %xmm0, %xmm1
 ; UNSAFE-NEXT: movapd %xmm1, %xmm0
 ; UNSAFE-NEXT: ret
+; FINITE:      x_ule_inverse:
+; FINITE-NEXT: pxor  %xmm1, %xmm1
+; FINITE-NEXT: maxsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
 define double @x_ule_inverse(double %x) nounwind {
   %c = fcmp ule double %x, 0.000000e+00
   %d = select i1 %c, double 0.000000e+00, double %x
   ret double %d
 }
 
+; CHECK:      y_ogt:
+; CHECK-NEXT: maxsd {{[^,]*}}, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_ogt:
+; UNSAFE-NEXT: maxsd {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ogt:
+; FINITE-NEXT: maxsd {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_ogt(double %x) nounwind {
+  %c = fcmp ogt double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_olt:
+; CHECK-NEXT: minsd {{[^,]*}}, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_olt:
+; UNSAFE-NEXT: minsd {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_olt:
+; FINITE-NEXT: minsd {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_olt(double %x) nounwind {
+  %c = fcmp olt double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_ogt_inverse:
+; CHECK-NEXT: movsd  {{[^,]*}}, %xmm1
+; CHECK-NEXT: minsd  %xmm0, %xmm1
+; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_ogt_inverse:
+; UNSAFE-NEXT: movsd  {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: minsd  %xmm0, %xmm1
+; UNSAFE-NEXT: movapd %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ogt_inverse:
+; FINITE-NEXT: movsd  {{[^,]*}}, %xmm1
+; FINITE-NEXT: minsd  %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_ogt_inverse(double %x) nounwind {
+  %c = fcmp ogt double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
+
+; CHECK:      y_olt_inverse:
+; CHECK-NEXT: movsd  {{[^,]*}}, %xmm1
+; CHECK-NEXT: maxsd  %xmm0, %xmm1
+; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_olt_inverse:
+; UNSAFE-NEXT: movsd  {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: maxsd  %xmm0, %xmm1
+; UNSAFE-NEXT: movapd %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_olt_inverse:
+; FINITE-NEXT: movsd  {{[^,]*}}, %xmm1
+; FINITE-NEXT: maxsd  %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_olt_inverse(double %x) nounwind {
+  %c = fcmp olt double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
+
+; CHECK:      y_oge:
+; CHECK:      ucomisd %xmm1, %xmm0
+; UNSAFE:      y_oge:
+; UNSAFE-NEXT: maxsd   {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_oge:
+; FINITE-NEXT: maxsd   {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_oge(double %x) nounwind {
+  %c = fcmp oge double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_ole:
+; CHECK:      ucomisd %xmm0, %xmm1
+; UNSAFE:      y_ole:
+; UNSAFE-NEXT: minsd {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ole:
+; FINITE-NEXT: minsd {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_ole(double %x) nounwind {
+  %c = fcmp ole double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_oge_inverse:
+; CHECK:      ucomisd %xmm1, %xmm0
+; UNSAFE:      y_oge_inverse:
+; UNSAFE-NEXT: movsd   {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: minsd   %xmm0, %xmm1
+; UNSAFE-NEXT: movapd  %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_oge_inverse:
+; FINITE-NEXT: movsd   {{[^,]*}}, %xmm1
+; FINITE-NEXT: minsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_oge_inverse(double %x) nounwind {
+  %c = fcmp oge double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
+
+; CHECK:      y_ole_inverse:
+; CHECK:      ucomisd %xmm0, %xmm1
+; UNSAFE:      y_ole_inverse:
+; UNSAFE-NEXT: movsd   {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: maxsd   %xmm0, %xmm1
+; UNSAFE-NEXT: movapd  %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ole_inverse:
+; FINITE-NEXT: movsd   {{[^,]*}}, %xmm1
+; FINITE-NEXT: maxsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_ole_inverse(double %x) nounwind {
+  %c = fcmp ole double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
+
+; CHECK:      y_ugt:
+; CHECK:      ucomisd %xmm0, %xmm1
+; UNSAFE:      y_ugt:
+; UNSAFE-NEXT: maxsd   {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ugt:
+; FINITE-NEXT: maxsd   {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_ugt(double %x) nounwind {
+  %c = fcmp ugt double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_ult:
+; CHECK:      ucomisd %xmm1, %xmm0
+; UNSAFE:      y_ult:
+; UNSAFE-NEXT: minsd   {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ult:
+; FINITE-NEXT: minsd   {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_ult(double %x) nounwind {
+  %c = fcmp ult double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_ugt_inverse:
+; CHECK:      ucomisd %xmm0, %xmm1
+; UNSAFE:      y_ugt_inverse:
+; UNSAFE-NEXT: movsd   {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: minsd   %xmm0, %xmm1
+; UNSAFE-NEXT: movapd  %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ugt_inverse:
+; FINITE-NEXT: movsd   {{[^,]*}}, %xmm1
+; FINITE-NEXT: minsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_ugt_inverse(double %x) nounwind {
+  %c = fcmp ugt double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
+
+; CHECK:      y_ult_inverse:
+; CHECK:      ucomisd %xmm1, %xmm0
+; UNSAFE:      y_ult_inverse:
+; UNSAFE-NEXT: movsd   {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: maxsd   %xmm0, %xmm1
+; UNSAFE-NEXT: movapd  %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ult_inverse:
+; FINITE-NEXT: movsd   {{[^,]*}}, %xmm1
+; FINITE-NEXT: maxsd   %xmm0, %xmm1
+; FINITE-NEXT: movapd  %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_ult_inverse(double %x) nounwind {
+  %c = fcmp ult double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
+
+; CHECK:      y_uge:
+; CHECK-NEXT: movsd  {{[^,]*}}, %xmm1
+; CHECK-NEXT: maxsd  %xmm0, %xmm1
+; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_uge:
+; UNSAFE-NEXT: maxsd  {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_uge:
+; FINITE-NEXT: maxsd  {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_uge(double %x) nounwind {
+  %c = fcmp uge double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_ule:
+; CHECK-NEXT: movsd  {{[^,]*}}, %xmm1
+; CHECK-NEXT: minsd  %xmm0, %xmm1
+; CHECK-NEXT: movapd %xmm1, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_ule:
+; UNSAFE-NEXT: minsd  {{[^,]*}}, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ule:
+; FINITE-NEXT: minsd  {{[^,]*}}, %xmm0
+; FINITE-NEXT: ret
+define double @y_ule(double %x) nounwind {
+  %c = fcmp ule double %x, -0.000000e+00
+  %d = select i1 %c, double %x, double -0.000000e+00
+  ret double %d
+}
+
+; CHECK:      y_uge_inverse:
+; CHECK-NEXT: minsd {{[^,]*}}, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_uge_inverse:
+; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: minsd %xmm0, %xmm1
+; UNSAFE-NEXT: movapd %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_uge_inverse:
+; FINITE-NEXT: movsd {{[^,]*}}, %xmm1
+; FINITE-NEXT: minsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_uge_inverse(double %x) nounwind {
+  %c = fcmp uge double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
+
+; CHECK:      y_ule_inverse:
+; CHECK-NEXT: maxsd {{[^,]*}}, %xmm0
+; CHECK-NEXT: ret
+; UNSAFE:      y_ule_inverse:
+; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1
+; UNSAFE-NEXT: maxsd %xmm0, %xmm1
+; UNSAFE-NEXT: movapd %xmm1, %xmm0
+; UNSAFE-NEXT: ret
+; FINITE:      y_ule_inverse:
+; FINITE-NEXT: movsd {{[^,]*}}, %xmm1
+; FINITE-NEXT: maxsd %xmm0, %xmm1
+; FINITE-NEXT: movapd %xmm1, %xmm0
+; FINITE-NEXT: ret
+define double @y_ule_inverse(double %x) nounwind {
+  %c = fcmp ule double %x, -0.000000e+00
+  %d = select i1 %c, double -0.000000e+00, double %x
+  ret double %d
+}
 ; Test a few more misc. cases.
 
 ; CHECK: clampTo3k_a:
 ; CHECK: minsd
 ; UNSAFE: clampTo3k_a:
 ; UNSAFE: minsd
+; FINITE: clampTo3k_a:
+; FINITE: minsd
 define double @clampTo3k_a(double %x) nounwind readnone {
 entry:
   %0 = fcmp ogt double %x, 3.000000e+03           ; <i1> [#uses=1]
@@ -442,6 +844,8 @@ entry:
 ; CHECK: minsd
 ; UNSAFE: clampTo3k_b:
 ; UNSAFE: minsd
+; FINITE: clampTo3k_b:
+; FINITE: minsd
 define double @clampTo3k_b(double %x) nounwind readnone {
 entry:
   %0 = fcmp uge double %x, 3.000000e+03           ; <i1> [#uses=1]
@@ -453,6 +857,8 @@ entry:
 ; CHECK: maxsd
 ; UNSAFE: clampTo3k_c:
 ; UNSAFE: maxsd
+; FINITE: clampTo3k_c:
+; FINITE: maxsd
 define double @clampTo3k_c(double %x) nounwind readnone {
 entry:
   %0 = fcmp olt double %x, 3.000000e+03           ; <i1> [#uses=1]
@@ -464,6 +870,8 @@ entry:
 ; CHECK: maxsd
 ; UNSAFE: clampTo3k_d:
 ; UNSAFE: maxsd
+; FINITE: clampTo3k_d:
+; FINITE: maxsd
 define double @clampTo3k_d(double %x) nounwind readnone {
 entry:
   %0 = fcmp ule double %x, 3.000000e+03           ; <i1> [#uses=1]
@@ -475,6 +883,8 @@ entry:
 ; CHECK: maxsd
 ; UNSAFE: clampTo3k_e:
 ; UNSAFE: maxsd
+; FINITE: clampTo3k_e:
+; FINITE: maxsd
 define double @clampTo3k_e(double %x) nounwind readnone {
 entry:
   %0 = fcmp olt double %x, 3.000000e+03           ; <i1> [#uses=1]
@@ -486,6 +896,8 @@ entry:
 ; CHECK: maxsd
 ; UNSAFE: clampTo3k_f:
 ; UNSAFE: maxsd
+; FINITE: clampTo3k_f:
+; FINITE: maxsd
 define double @clampTo3k_f(double %x) nounwind readnone {
 entry:
   %0 = fcmp ule double %x, 3.000000e+03           ; <i1> [#uses=1]
@@ -497,6 +909,8 @@ entry:
 ; CHECK: minsd
 ; UNSAFE: clampTo3k_g:
 ; UNSAFE: minsd
+; FINITE: clampTo3k_g:
+; FINITE: minsd
 define double @clampTo3k_g(double %x) nounwind readnone {
 entry:
   %0 = fcmp ogt double %x, 3.000000e+03           ; <i1> [#uses=1]
@@ -508,6 +922,8 @@ entry:
 ; CHECK: minsd
 ; UNSAFE: clampTo3k_h:
 ; UNSAFE: minsd
+; FINITE: clampTo3k_h:
+; FINITE: minsd
 define double @clampTo3k_h(double %x) nounwind readnone {
 entry:
   %0 = fcmp uge double %x, 3.000000e+03           ; <i1> [#uses=1]