1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

Remove the logic for reasoning about NaNs from the code that forms

SSE min and max instructions. The real thing this code needs to be
concerned about is negative zero.

Update the sse-minmax.ll test accordingly, and add tests for
-enable-unsafe-fp-math mode as well.

llvm-svn: 96775
This commit is contained in:
Dan Gohman 2010-02-22 04:03:39 +00:00
parent c44dee5fbd
commit c281a5da15
2 changed files with 179 additions and 132 deletions

View File

@ -8793,10 +8793,9 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
SDValue RHS = N->getOperand(2); SDValue RHS = N->getOperand(2);
// If we have SSE[12] support, try to form min/max nodes. SSE min/max // If we have SSE[12] support, try to form min/max nodes. SSE min/max
// instructions have the peculiarity that if either operand is a NaN, // instructions match the semantics of the common C idiom x<y?x:y but not
// they chose what we call the RHS operand (and as such are not symmetric). // x<=y?x:y, because of how they handle negative zero (which can be
// It happens that this matches the semantics of the common C idiom // ignored in unsafe-math mode).
// x<y?x:y and related forms, so we can recognize these cases.
if (Subtarget->hasSSE2() && if (Subtarget->hasSSE2() &&
(LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64) && (LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64) &&
Cond.getOpcode() == ISD::SETCC) { Cond.getOpcode() == ISD::SETCC) {
@ -8808,33 +8807,14 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
switch (CC) { switch (CC) {
default: break; default: break;
case ISD::SETULT: case ISD::SETULT:
// This can be a min if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(RHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(LHS))
break;
}
Opcode = X86ISD::FMIN; Opcode = X86ISD::FMIN;
break; break;
case ISD::SETOLE: case ISD::SETOLE:
// This can be a min if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(LHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(RHS))
break;
}
Opcode = X86ISD::FMIN; Opcode = X86ISD::FMIN;
break; break;
case ISD::SETULE: case ISD::SETULE:
// This can be a min, but if either operand is a NaN we need it to
// preserve the original LHS.
std::swap(LHS, RHS);
case ISD::SETOLT: case ISD::SETOLT:
case ISD::SETLT: case ISD::SETLT:
case ISD::SETLE: case ISD::SETLE:
@ -8842,33 +8822,14 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
break; break;
case ISD::SETOGE: case ISD::SETOGE:
// This can be a max if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(LHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(RHS))
break;
}
Opcode = X86ISD::FMAX; Opcode = X86ISD::FMAX;
break; break;
case ISD::SETUGT: case ISD::SETUGT:
// This can be a max if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(RHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(LHS))
break;
}
Opcode = X86ISD::FMAX; Opcode = X86ISD::FMAX;
break; break;
case ISD::SETUGE: case ISD::SETUGE:
// This can be a max, but if either operand is a NaN we need it to
// preserve the original LHS.
std::swap(LHS, RHS);
case ISD::SETOGT: case ISD::SETOGT:
case ISD::SETGT: case ISD::SETGT:
case ISD::SETGE: case ISD::SETGE:
@ -8880,33 +8841,14 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
switch (CC) { switch (CC) {
default: break; default: break;
case ISD::SETOGE: case ISD::SETOGE:
// This can be a min if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(RHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(LHS))
break;
}
Opcode = X86ISD::FMIN; Opcode = X86ISD::FMIN;
break; break;
case ISD::SETUGT: case ISD::SETUGT:
// This can be a min if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(LHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(RHS))
break;
}
Opcode = X86ISD::FMIN; Opcode = X86ISD::FMIN;
break; break;
case ISD::SETUGE: case ISD::SETUGE:
// This can be a min, but if either operand is a NaN we need it to
// preserve the original LHS.
std::swap(LHS, RHS);
case ISD::SETOGT: case ISD::SETOGT:
case ISD::SETGT: case ISD::SETGT:
case ISD::SETGE: case ISD::SETGE:
@ -8914,33 +8856,14 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
break; break;
case ISD::SETULT: case ISD::SETULT:
// This can be a max if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(LHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(RHS))
break;
}
Opcode = X86ISD::FMAX; Opcode = X86ISD::FMAX;
break; break;
case ISD::SETOLE: case ISD::SETOLE:
// This can be a max if we can prove that at least one of the operands if (!UnsafeFPMath) break;
// is not a nan.
if (!FiniteOnlyFPMath()) {
if (DAG.isKnownNeverNaN(RHS)) {
// Put the potential NaN in the RHS so that SSE will preserve it.
std::swap(LHS, RHS);
} else if (!DAG.isKnownNeverNaN(LHS))
break;
}
Opcode = X86ISD::FMAX; Opcode = X86ISD::FMAX;
break; break;
case ISD::SETULE: case ISD::SETULE:
// This can be a max, but if either operand is a NaN we need it to
// preserve the original LHS.
std::swap(LHS, RHS);
case ISD::SETOLT: case ISD::SETOLT:
case ISD::SETLT: case ISD::SETLT:
case ISD::SETLE: case ISD::SETLE:

View File

@ -1,4 +1,5 @@
; RUN: llc < %s -march=x86-64 -asm-verbose=false | FileCheck %s ; 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
; Some of these patterns can be matched as SSE min or max. Some of ; Some of these patterns can be matched as SSE min or max. Some of
; then can be matched provided that the operands are swapped. ; then can be matched provided that the operands are swapped.
@ -12,6 +13,9 @@
; CHECK: ogt: ; CHECK: ogt:
; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: maxsd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: ogt:
; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ogt(double %x, double %y) nounwind { define double @ogt(double %x, double %y) nounwind {
%c = fcmp ogt double %x, %y %c = fcmp ogt double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -21,6 +25,9 @@ define double @ogt(double %x, double %y) nounwind {
; CHECK: olt: ; CHECK: olt:
; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: minsd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: olt:
; uNSAFE-NEXT: minsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @olt(double %x, double %y) nounwind { define double @olt(double %x, double %y) nounwind {
%c = fcmp olt double %x, %y %c = fcmp olt double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -31,6 +38,10 @@ define double @olt(double %x, double %y) nounwind {
; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: minsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: ogt_inverse:
; uNSAFE-NEXT: minsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ogt_inverse(double %x, double %y) nounwind { define double @ogt_inverse(double %x, double %y) nounwind {
%c = fcmp ogt double %x, %y %c = fcmp ogt double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -41,6 +52,10 @@ define double @ogt_inverse(double %x, double %y) nounwind {
; CHECK-NEXT: maxsd %xmm0, %xmm1 ; CHECK-NEXT: maxsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: olt_inverse:
; uNSAFE-NEXT: maxsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @olt_inverse(double %x, double %y) nounwind { define double @olt_inverse(double %x, double %y) nounwind {
%c = fcmp olt double %x, %y %c = fcmp olt double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -49,6 +64,9 @@ define double @olt_inverse(double %x, double %y) nounwind {
; CHECK: oge: ; CHECK: oge:
; CHECK-NEXT: ucomisd %xmm1, %xmm0 ; CHECK-NEXT: ucomisd %xmm1, %xmm0
; uNSAFE: oge:
; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @oge(double %x, double %y) nounwind { define double @oge(double %x, double %y) nounwind {
%c = fcmp oge double %x, %y %c = fcmp oge double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -57,6 +75,8 @@ define double @oge(double %x, double %y) nounwind {
; CHECK: ole: ; CHECK: ole:
; CHECK-NEXT: ucomisd %xmm0, %xmm1 ; CHECK-NEXT: ucomisd %xmm0, %xmm1
; uNSAFE: ole:
; uNSAFE-NEXT: minsd %xmm1, %xmm0
define double @ole(double %x, double %y) nounwind { define double @ole(double %x, double %y) nounwind {
%c = fcmp ole double %x, %y %c = fcmp ole double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -65,6 +85,10 @@ define double @ole(double %x, double %y) nounwind {
; CHECK: oge_inverse: ; CHECK: oge_inverse:
; CHECK-NEXT: ucomisd %xmm1, %xmm0 ; CHECK-NEXT: ucomisd %xmm1, %xmm0
; uNSAFE: oge_inverse:
; uNSAFE-NEXT: minsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @oge_inverse(double %x, double %y) nounwind { define double @oge_inverse(double %x, double %y) nounwind {
%c = fcmp oge double %x, %y %c = fcmp oge double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -73,6 +97,10 @@ define double @oge_inverse(double %x, double %y) nounwind {
; CHECK: ole_inverse: ; CHECK: ole_inverse:
; CHECK-NEXT: ucomisd %xmm0, %xmm1 ; CHECK-NEXT: ucomisd %xmm0, %xmm1
; uNSAFE: ole_inverse:
; uNSAFE-NEXT: maxsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ole_inverse(double %x, double %y) nounwind { define double @ole_inverse(double %x, double %y) nounwind {
%c = fcmp ole double %x, %y %c = fcmp ole double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -83,6 +111,10 @@ define double @ole_inverse(double %x, double %y) nounwind {
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: maxsd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: x_ogt:
; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ogt(double %x) nounwind { define double @x_ogt(double %x) nounwind {
%c = fcmp ogt double %x, 0.000000e+00 %c = fcmp ogt double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -93,6 +125,10 @@ define double @x_ogt(double %x) nounwind {
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: minsd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: x_olt:
; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: minsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_olt(double %x) nounwind { define double @x_olt(double %x) nounwind {
%c = fcmp olt double %x, 0.000000e+00 %c = fcmp olt double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -104,6 +140,11 @@ define double @x_olt(double %x) nounwind {
; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: minsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: x_ogt_inverse:
; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: minsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ogt_inverse(double %x) nounwind { define double @x_ogt_inverse(double %x) nounwind {
%c = fcmp ogt double %x, 0.000000e+00 %c = fcmp ogt double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -115,6 +156,11 @@ define double @x_ogt_inverse(double %x) nounwind {
; CHECK-NEXT: maxsd %xmm0, %xmm1 ; CHECK-NEXT: maxsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: x_olt_inverse:
; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: maxsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_olt_inverse(double %x) nounwind { define double @x_olt_inverse(double %x) nounwind {
%c = fcmp olt double %x, 0.000000e+00 %c = fcmp olt double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -122,9 +168,11 @@ define double @x_olt_inverse(double %x) nounwind {
} }
; CHECK: x_oge: ; CHECK: x_oge:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm1, %xmm0
; CHECK-NEXT: maxsd %xmm1, %xmm0 ; uNSAFE: x_oge:
; CHECK-NEXT: ret ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_oge(double %x) nounwind { define double @x_oge(double %x) nounwind {
%c = fcmp oge double %x, 0.000000e+00 %c = fcmp oge double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -132,9 +180,11 @@ define double @x_oge(double %x) nounwind {
} }
; CHECK: x_ole: ; CHECK: x_ole:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm0, %xmm1
; CHECK-NEXT: minsd %xmm1, %xmm0 ; uNSAFE: x_ole:
; CHECK-NEXT: ret ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: minsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ole(double %x) nounwind { define double @x_ole(double %x) nounwind {
%c = fcmp ole double %x, 0.000000e+00 %c = fcmp ole double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -142,10 +192,12 @@ define double @x_ole(double %x) nounwind {
} }
; CHECK: x_oge_inverse: ; CHECK: x_oge_inverse:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm1, %xmm0
; CHECK-NEXT: minsd %xmm0, %xmm1 ; uNSAFE: x_oge_inverse:
; CHECK-NEXT: movapd %xmm1, %xmm0 ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: ret ; uNSAFE-NEXT: minsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_oge_inverse(double %x) nounwind { define double @x_oge_inverse(double %x) nounwind {
%c = fcmp oge double %x, 0.000000e+00 %c = fcmp oge double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -153,10 +205,12 @@ define double @x_oge_inverse(double %x) nounwind {
} }
; CHECK: x_ole_inverse: ; CHECK: x_ole_inverse:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm0, %xmm1
; CHECK-NEXT: maxsd %xmm0, %xmm1 ; uNSAFE: x_ole_inverse:
; CHECK-NEXT: movapd %xmm1, %xmm0 ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: ret ; uNSAFE-NEXT: maxsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ole_inverse(double %x) nounwind { define double @x_ole_inverse(double %x) nounwind {
%c = fcmp ole double %x, 0.000000e+00 %c = fcmp ole double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -164,7 +218,10 @@ define double @x_ole_inverse(double %x) nounwind {
} }
; CHECK: ugt: ; CHECK: ugt:
; CHECK-NEXT: ucomisd %xmm0, %xmm1 ; CHECK: ucomisd %xmm0, %xmm1
; uNSAFE: ugt:
; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ugt(double %x, double %y) nounwind { define double @ugt(double %x, double %y) nounwind {
%c = fcmp ugt double %x, %y %c = fcmp ugt double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -172,7 +229,10 @@ define double @ugt(double %x, double %y) nounwind {
} }
; CHECK: ult: ; CHECK: ult:
; CHECK-NEXT: ucomisd %xmm1, %xmm0 ; CHECK: ucomisd %xmm1, %xmm0
; uNSAFE: ult:
; uNSAFE-NEXT: minsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ult(double %x, double %y) nounwind { define double @ult(double %x, double %y) nounwind {
%c = fcmp ult double %x, %y %c = fcmp ult double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -180,7 +240,11 @@ define double @ult(double %x, double %y) nounwind {
} }
; CHECK: ugt_inverse: ; CHECK: ugt_inverse:
; CHECK-NEXT: ucomisd %xmm0, %xmm1 ; CHECK: ucomisd %xmm0, %xmm1
; uNSAFE: ugt_inverse:
; uNSAFE-NEXT: minsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ugt_inverse(double %x, double %y) nounwind { define double @ugt_inverse(double %x, double %y) nounwind {
%c = fcmp ugt double %x, %y %c = fcmp ugt double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -188,7 +252,11 @@ define double @ugt_inverse(double %x, double %y) nounwind {
} }
; CHECK: ult_inverse: ; CHECK: ult_inverse:
; CHECK-NEXT: ucomisd %xmm1, %xmm0 ; CHECK: ucomisd %xmm1, %xmm0
; uNSAFE: ult_inverse:
; uNSAFE-NEXT: maxsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ult_inverse(double %x, double %y) nounwind { define double @ult_inverse(double %x, double %y) nounwind {
%c = fcmp ult double %x, %y %c = fcmp ult double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -196,9 +264,11 @@ define double @ult_inverse(double %x, double %y) nounwind {
} }
; CHECK: uge: ; CHECK: uge:
; CHECK-NEXT: maxsd %xmm0, %xmm1 ; CHECK-NEXT: maxsd %xmm1, %xmm0
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: uge:
; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @uge(double %x, double %y) nounwind { define double @uge(double %x, double %y) nounwind {
%c = fcmp uge double %x, %y %c = fcmp uge double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -206,9 +276,11 @@ define double @uge(double %x, double %y) nounwind {
} }
; CHECK: ule: ; CHECK: ule:
; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: minsd %xmm1, %xmm0
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: ule:
; uNSAFE-NEXT: minsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ule(double %x, double %y) nounwind { define double @ule(double %x, double %y) nounwind {
%c = fcmp ule double %x, %y %c = fcmp ule double %x, %y
%d = select i1 %c, double %x, double %y %d = select i1 %c, double %x, double %y
@ -216,8 +288,13 @@ define double @ule(double %x, double %y) nounwind {
} }
; CHECK: uge_inverse: ; CHECK: uge_inverse:
; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: minsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: uge_inverse:
; uNSAFE-NEXT: minsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @uge_inverse(double %x, double %y) nounwind { define double @uge_inverse(double %x, double %y) nounwind {
%c = fcmp uge double %x, %y %c = fcmp uge double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -225,8 +302,13 @@ define double @uge_inverse(double %x, double %y) nounwind {
} }
; CHECK: ule_inverse: ; CHECK: ule_inverse:
; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: maxsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: ule_inverse:
; uNSAFE-NEXT: maxsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @ule_inverse(double %x, double %y) nounwind { define double @ule_inverse(double %x, double %y) nounwind {
%c = fcmp ule double %x, %y %c = fcmp ule double %x, %y
%d = select i1 %c, double %y, double %x %d = select i1 %c, double %y, double %x
@ -234,10 +316,11 @@ define double @ule_inverse(double %x, double %y) nounwind {
} }
; CHECK: x_ugt: ; CHECK: x_ugt:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm0, %xmm1
; CHECK-NEXT: maxsd %xmm0, %xmm1 ; uNSAFE: x_ugt:
; CHECK-NEXT: movapd %xmm1, %xmm0 ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: ret ; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ugt(double %x) nounwind { define double @x_ugt(double %x) nounwind {
%c = fcmp ugt double %x, 0.000000e+00 %c = fcmp ugt double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -245,10 +328,11 @@ define double @x_ugt(double %x) nounwind {
} }
; CHECK: x_ult: ; CHECK: x_ult:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm1, %xmm0
; CHECK-NEXT: minsd %xmm0, %xmm1 ; uNSAFE: x_ult:
; CHECK-NEXT: movapd %xmm1, %xmm0 ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: ret ; uNSAFE-NEXT: minsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ult(double %x) nounwind { define double @x_ult(double %x) nounwind {
%c = fcmp ult double %x, 0.000000e+00 %c = fcmp ult double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -256,9 +340,12 @@ define double @x_ult(double %x) nounwind {
} }
; CHECK: x_ugt_inverse: ; CHECK: x_ugt_inverse:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm0, %xmm1
; CHECK-NEXT: minsd %xmm1, %xmm0 ; uNSAFE: x_ugt_inverse:
; CHECK-NEXT: ret ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: minsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ugt_inverse(double %x) nounwind { define double @x_ugt_inverse(double %x) nounwind {
%c = fcmp ugt double %x, 0.000000e+00 %c = fcmp ugt double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -266,9 +353,12 @@ define double @x_ugt_inverse(double %x) nounwind {
} }
; CHECK: x_ult_inverse: ; CHECK: x_ult_inverse:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK: ucomisd %xmm1, %xmm0
; CHECK-NEXT: maxsd %xmm1, %xmm0 ; uNSAFE: x_ult_inverse:
; CHECK-NEXT: ret ; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: maxsd %xmm0, %xmm1
; uNSAFE-NEXT: movapd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ult_inverse(double %x) nounwind { define double @x_ult_inverse(double %x) nounwind {
%c = fcmp ult double %x, 0.000000e+00 %c = fcmp ult double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -277,9 +367,12 @@ define double @x_ult_inverse(double %x) nounwind {
; CHECK: x_uge: ; CHECK: x_uge:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: maxsd %xmm0, %xmm1 ; CHECK-NEXT: maxsd %xmm1, %xmm0
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: x_uge:
; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: maxsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_uge(double %x) nounwind { define double @x_uge(double %x) nounwind {
%c = fcmp uge double %x, 0.000000e+00 %c = fcmp uge double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -288,9 +381,12 @@ define double @x_uge(double %x) nounwind {
; CHECK: x_ule: ; CHECK: x_ule:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: minsd %xmm1, %xmm0
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; CHECK-NEXT: ret
; uNSAFE: x_ule:
; uNSAFE-NEXT: pxor %xmm1, %xmm1
; uNSAFE-NEXT: minsd %xmm1, %xmm0
; uNSAFE-NEXT: ret
define double @x_ule(double %x) nounwind { define double @x_ule(double %x) nounwind {
%c = fcmp ule double %x, 0.000000e+00 %c = fcmp ule double %x, 0.000000e+00
%d = select i1 %c, double %x, double 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00
@ -299,8 +395,14 @@ define double @x_ule(double %x) nounwind {
; CHECK: x_uge_inverse: ; CHECK: x_uge_inverse:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: minsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; 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
define double @x_uge_inverse(double %x) nounwind { define double @x_uge_inverse(double %x) nounwind {
%c = fcmp uge double %x, 0.000000e+00 %c = fcmp uge double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -309,8 +411,14 @@ define double @x_uge_inverse(double %x) nounwind {
; CHECK: x_ule_inverse: ; CHECK: x_ule_inverse:
; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: pxor %xmm1, %xmm1
; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: maxsd %xmm0, %xmm1
; CHECK-NEXT: movapd %xmm1, %xmm0
; CHECK-NEXT: ret ; 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
define double @x_ule_inverse(double %x) nounwind { define double @x_ule_inverse(double %x) nounwind {
%c = fcmp ule double %x, 0.000000e+00 %c = fcmp ule double %x, 0.000000e+00
%d = select i1 %c, double 0.000000e+00, double %x %d = select i1 %c, double 0.000000e+00, double %x
@ -321,6 +429,8 @@ define double @x_ule_inverse(double %x) nounwind {
; CHECK: clampTo3k_a: ; CHECK: clampTo3k_a:
; CHECK: minsd ; CHECK: minsd
; uNSAFE: clampTo3k_a:
; uNSAFE: minsd
define double @clampTo3k_a(double %x) nounwind readnone { define double @clampTo3k_a(double %x) nounwind readnone {
entry: entry:
%0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1]
@ -330,6 +440,8 @@ entry:
; CHECK: clampTo3k_b: ; CHECK: clampTo3k_b:
; CHECK: minsd ; CHECK: minsd
; uNSAFE: clampTo3k_b:
; uNSAFE: minsd
define double @clampTo3k_b(double %x) nounwind readnone { define double @clampTo3k_b(double %x) nounwind readnone {
entry: entry:
%0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1]
@ -339,6 +451,8 @@ entry:
; CHECK: clampTo3k_c: ; CHECK: clampTo3k_c:
; CHECK: maxsd ; CHECK: maxsd
; uNSAFE: clampTo3k_c:
; uNSAFE: maxsd
define double @clampTo3k_c(double %x) nounwind readnone { define double @clampTo3k_c(double %x) nounwind readnone {
entry: entry:
%0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1]
@ -348,6 +462,8 @@ entry:
; CHECK: clampTo3k_d: ; CHECK: clampTo3k_d:
; CHECK: maxsd ; CHECK: maxsd
; uNSAFE: clampTo3k_d:
; uNSAFE: maxsd
define double @clampTo3k_d(double %x) nounwind readnone { define double @clampTo3k_d(double %x) nounwind readnone {
entry: entry:
%0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1]
@ -357,6 +473,8 @@ entry:
; CHECK: clampTo3k_e: ; CHECK: clampTo3k_e:
; CHECK: maxsd ; CHECK: maxsd
; uNSAFE: clampTo3k_e:
; uNSAFE: maxsd
define double @clampTo3k_e(double %x) nounwind readnone { define double @clampTo3k_e(double %x) nounwind readnone {
entry: entry:
%0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1]
@ -366,6 +484,8 @@ entry:
; CHECK: clampTo3k_f: ; CHECK: clampTo3k_f:
; CHECK: maxsd ; CHECK: maxsd
; uNSAFE: clampTo3k_f:
; uNSAFE: maxsd
define double @clampTo3k_f(double %x) nounwind readnone { define double @clampTo3k_f(double %x) nounwind readnone {
entry: entry:
%0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1]
@ -375,6 +495,8 @@ entry:
; CHECK: clampTo3k_g: ; CHECK: clampTo3k_g:
; CHECK: minsd ; CHECK: minsd
; uNSAFE: clampTo3k_g:
; uNSAFE: minsd
define double @clampTo3k_g(double %x) nounwind readnone { define double @clampTo3k_g(double %x) nounwind readnone {
entry: entry:
%0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1]
@ -384,6 +506,8 @@ entry:
; CHECK: clampTo3k_h: ; CHECK: clampTo3k_h:
; CHECK: minsd ; CHECK: minsd
; uNSAFE: clampTo3k_h:
; uNSAFE: minsd
define double @clampTo3k_h(double %x) nounwind readnone { define double @clampTo3k_h(double %x) nounwind readnone {
entry: entry:
%0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1] %0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1]