mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-30 07:00:45 +00:00
Check for comparisons of +/- zero when optimizing less-than-or-equal and
greater-than-or-equal SELECT_CCs to NEON vmin/vmax instructions. This is only allowed when UnsafeFPMath is set or when at least one of the operands is known to be nonzero. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97065 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c382bc3c0f
commit
e742bb53a3
@ -3879,50 +3879,59 @@ static SDValue PerformSELECT_CCCombine(SDNode *N, SelectionDAG &DAG,
|
|||||||
|
|
||||||
unsigned Opcode = 0;
|
unsigned Opcode = 0;
|
||||||
bool IsReversed;
|
bool IsReversed;
|
||||||
if (LHS == CondLHS && RHS == CondRHS) {
|
if (DAG.isEqualTo(LHS, CondLHS) && DAG.isEqualTo(RHS, CondRHS)) {
|
||||||
IsReversed = false; // x CC y ? x : y
|
IsReversed = false; // x CC y ? x : y
|
||||||
} else if (LHS == CondRHS && RHS == CondLHS) {
|
} else if (DAG.isEqualTo(LHS, CondRHS) && DAG.isEqualTo(RHS, CondLHS)) {
|
||||||
IsReversed = true ; // x CC y ? y : x
|
IsReversed = true ; // x CC y ? y : x
|
||||||
} else {
|
} else {
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsUnordered;
|
||||||
switch (CC) {
|
switch (CC) {
|
||||||
default: break;
|
default: break;
|
||||||
case ISD::SETOLT:
|
case ISD::SETOLT:
|
||||||
case ISD::SETOLE:
|
case ISD::SETOLE:
|
||||||
case ISD::SETLT:
|
case ISD::SETLT:
|
||||||
case ISD::SETLE:
|
case ISD::SETLE:
|
||||||
// This can be vmin if we can prove that the LHS is not a NaN.
|
|
||||||
// (If either operand is NaN, the comparison will be false and the result
|
|
||||||
// will be the RHS, which matches vmin if RHS is the NaN.)
|
|
||||||
if (DAG.isKnownNeverNaN(LHS))
|
|
||||||
Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ISD::SETULT:
|
case ISD::SETULT:
|
||||||
case ISD::SETULE:
|
case ISD::SETULE:
|
||||||
// Likewise, for ULT/ULE we need to know that RHS is not a NaN.
|
// If LHS is NaN, an ordered comparison will be false and the result will
|
||||||
if (DAG.isKnownNeverNaN(RHS))
|
// be the RHS, but vmin(NaN, RHS) = NaN. Avoid this by checking that LHS
|
||||||
Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN;
|
// != NaN. Likewise, for unordered comparisons, check for RHS != NaN.
|
||||||
|
IsUnordered = (CC == ISD::SETULT || CC == ISD::SETULE);
|
||||||
|
if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS))
|
||||||
|
break;
|
||||||
|
// For less-than-or-equal comparisons, "+0 <= -0" will be true but vmin
|
||||||
|
// will return -0, so vmin can only be used for unsafe math or if one of
|
||||||
|
// the operands is known to be nonzero.
|
||||||
|
if ((CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE) &&
|
||||||
|
!UnsafeFPMath &&
|
||||||
|
!(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS)))
|
||||||
|
break;
|
||||||
|
Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ISD::SETOGT:
|
case ISD::SETOGT:
|
||||||
case ISD::SETOGE:
|
case ISD::SETOGE:
|
||||||
case ISD::SETGT:
|
case ISD::SETGT:
|
||||||
case ISD::SETGE:
|
case ISD::SETGE:
|
||||||
// This can be vmax if we can prove that the LHS is not a NaN.
|
|
||||||
// (If either operand is NaN, the comparison will be false and the result
|
|
||||||
// will be the RHS, which matches vmax if RHS is the NaN.)
|
|
||||||
if (DAG.isKnownNeverNaN(LHS))
|
|
||||||
Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ISD::SETUGT:
|
case ISD::SETUGT:
|
||||||
case ISD::SETUGE:
|
case ISD::SETUGE:
|
||||||
// Likewise, for UGT/UGE we need to know that RHS is not a NaN.
|
// If LHS is NaN, an ordered comparison will be false and the result will
|
||||||
if (DAG.isKnownNeverNaN(RHS))
|
// be the RHS, but vmax(NaN, RHS) = NaN. Avoid this by checking that LHS
|
||||||
Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX;
|
// != NaN. Likewise, for unordered comparisons, check for RHS != NaN.
|
||||||
|
IsUnordered = (CC == ISD::SETUGT || CC == ISD::SETUGE);
|
||||||
|
if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS))
|
||||||
|
break;
|
||||||
|
// For greater-than-or-equal comparisons, "-0 >= +0" will be true but vmax
|
||||||
|
// will return +0, so vmax can only be used for unsafe math or if one of
|
||||||
|
// the operands is known to be nonzero.
|
||||||
|
if ((CC == ISD::SETGE || CC == ISD::SETOGE || CC == ISD::SETUGE) &&
|
||||||
|
!UnsafeFPMath &&
|
||||||
|
!(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS)))
|
||||||
|
break;
|
||||||
|
Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,14 @@ define float @fmin_ole(float %x) nounwind {
|
|||||||
ret float %min1
|
ret float %min1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define float @fmin_ole_zero(float %x) nounwind {
|
||||||
|
;CHECK: fmin_ole_zero:
|
||||||
|
;CHECK-NOT: vmin.f32
|
||||||
|
%cond = fcmp ole float 0.0, %x
|
||||||
|
%min1 = select i1 %cond, float 0.0, float %x
|
||||||
|
ret float %min1
|
||||||
|
}
|
||||||
|
|
||||||
define float @fmin_ult(float %x) nounwind {
|
define float @fmin_ult(float %x) nounwind {
|
||||||
;CHECK: fmin_ult:
|
;CHECK: fmin_ult:
|
||||||
;CHECK: vmin.f32
|
;CHECK: vmin.f32
|
||||||
@ -32,6 +40,14 @@ define float @fmax_uge(float %x) nounwind {
|
|||||||
ret float %max1
|
ret float %max1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define float @fmax_uge_zero(float %x) nounwind {
|
||||||
|
;CHECK: fmax_uge_zero:
|
||||||
|
;CHECK-NOT: vmax.f32
|
||||||
|
%cond = fcmp uge float %x, 0.0
|
||||||
|
%max1 = select i1 %cond, float %x, float 0.0
|
||||||
|
ret float %max1
|
||||||
|
}
|
||||||
|
|
||||||
define float @fmax_olt_reverse(float %x) nounwind {
|
define float @fmax_olt_reverse(float %x) nounwind {
|
||||||
;CHECK: fmax_olt_reverse:
|
;CHECK: fmax_olt_reverse:
|
||||||
;CHECK: vmax.f32
|
;CHECK: vmax.f32
|
||||||
|
Loading…
Reference in New Issue
Block a user