mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-09 01:38:03 +00:00
Recognize more opportunities to use SSE min and max instructions,
swapping the operands if necessary. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80940 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3653b13c52
commit
8d44b28bc6
@ -840,6 +840,9 @@ public:
|
||||
/// class to allow target nodes to be understood.
|
||||
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const;
|
||||
|
||||
/// isKnownNeverNan - Test whether the given SDValue is known to never be NaN.
|
||||
bool isKnownNeverNaN(SDValue Op) const;
|
||||
|
||||
/// isVerifiedDebugInfoDesc - Returns true if the specified SDValue has
|
||||
/// been verified as a debug information descriptor.
|
||||
bool isVerifiedDebugInfoDesc(SDValue Op) const;
|
||||
|
@ -2198,6 +2198,19 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{
|
||||
return std::max(FirstAnswer, std::min(VTBits, Mask.countLeadingZeros()));
|
||||
}
|
||||
|
||||
bool SelectionDAG::isKnownNeverNaN(SDValue Op) const {
|
||||
// If we're told that NaNs won't happen, assume they won't.
|
||||
if (FiniteOnlyFPMath())
|
||||
return true;
|
||||
|
||||
// If the value is a constant, we can obviously see if it is a NaN or not.
|
||||
if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Op))
|
||||
return !C->getValueAPF().isNaN();
|
||||
|
||||
// TODO: Recognize more cases here.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const {
|
||||
GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
|
||||
|
@ -8250,8 +8250,18 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
|
||||
} else if (LHS == Cond.getOperand(1) && RHS == Cond.getOperand(0)) {
|
||||
switch (CC) {
|
||||
default: break;
|
||||
case ISD::SETOGT: // (X > Y) ? Y : X -> min
|
||||
case ISD::SETUGT:
|
||||
case ISD::SETOGT:
|
||||
// This can use a min only if the LHS isn't NaN.
|
||||
if (DAG.isKnownNeverNaN(LHS))
|
||||
Opcode = X86ISD::FMIN;
|
||||
else if (DAG.isKnownNeverNaN(RHS)) {
|
||||
Opcode = X86ISD::FMIN;
|
||||
// Put the potential NaN in the RHS so that SSE will preserve it.
|
||||
std::swap(LHS, RHS);
|
||||
}
|
||||
break;
|
||||
|
||||
case ISD::SETUGT: // (X > Y) ? Y : X -> min
|
||||
case ISD::SETGT:
|
||||
if (!UnsafeFPMath) break;
|
||||
// FALL THROUGH.
|
||||
@ -8260,8 +8270,18 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
|
||||
Opcode = X86ISD::FMIN;
|
||||
break;
|
||||
|
||||
case ISD::SETOLE: // (X <= Y) ? Y : X -> max
|
||||
case ISD::SETULE:
|
||||
// This can use a max only if the LHS isn't NaN.
|
||||
if (DAG.isKnownNeverNaN(LHS))
|
||||
Opcode = X86ISD::FMAX;
|
||||
else if (DAG.isKnownNeverNaN(RHS)) {
|
||||
Opcode = X86ISD::FMAX;
|
||||
// Put the potential NaN in the RHS so that SSE will preserve it.
|
||||
std::swap(LHS, RHS);
|
||||
}
|
||||
break;
|
||||
|
||||
case ISD::SETOLE: // (X <= Y) ? Y : X -> max
|
||||
case ISD::SETLE:
|
||||
if (!UnsafeFPMath) break;
|
||||
// FALL THROUGH.
|
||||
|
73
test/CodeGen/X86/sse-minmax.ll
Normal file
73
test/CodeGen/X86/sse-minmax.ll
Normal file
@ -0,0 +1,73 @@
|
||||
; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s
|
||||
|
||||
; CHECK: clampTo3k_a:
|
||||
; CHECK: minsd
|
||||
define double @clampTo3k_a(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
||||
|
||||
; CHECK: clampTo3k_b:
|
||||
; CHECK: minsd
|
||||
define double @clampTo3k_b(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
||||
|
||||
; CHECK: clampTo3k_c:
|
||||
; CHECK: maxsd
|
||||
define double @clampTo3k_c(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
||||
|
||||
; CHECK: clampTo3k_d:
|
||||
; CHECK: maxsd
|
||||
define double @clampTo3k_d(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
||||
|
||||
; CHECK: clampTo3k_e:
|
||||
; CHECK: maxsd
|
||||
define double @clampTo3k_e(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp olt double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
||||
|
||||
; CHECK: clampTo3k_f:
|
||||
; CHECK: maxsd
|
||||
define double @clampTo3k_f(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp ule double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
||||
|
||||
; CHECK: clampTo3k_g:
|
||||
; CHECK: minsd
|
||||
define double @clampTo3k_g(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp ogt double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
||||
|
||||
; CHECK: clampTo3k_h:
|
||||
; CHECK: minsd
|
||||
define double @clampTo3k_h(double %x) nounwind readnone {
|
||||
entry:
|
||||
%0 = fcmp uge double %x, 3.000000e+03 ; <i1> [#uses=1]
|
||||
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
|
||||
ret double %x_addr.0
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user