Skip to content

Commit

Permalink
Revert r237247 - [AArch64] Codegen VMAX/VMIN.. as it is causing failu…
Browse files Browse the repository at this point in the history
…res in SPEC2000/2006

llvm-svn: 237256
  • Loading branch information
sbaranga-arm committed May 13, 2015
1 parent d0a7ff2 commit 780a3b3
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 94 deletions.
112 changes: 40 additions & 72 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,6 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,

setTargetDAGCombine(ISD::SELECT);
setTargetDAGCombine(ISD::VSELECT);
setTargetDAGCombine(ISD::SELECT_CC);

setTargetDAGCombine(ISD::INTRINSIC_VOID);
setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN);
Expand Down Expand Up @@ -3702,6 +3701,46 @@ SDValue AArch64TargetLowering::LowerSELECT_CC(ISD::CondCode CC, SDValue LHS,
assert(LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64);
assert(LHS.getValueType() == RHS.getValueType());
EVT VT = TVal.getValueType();

// Try to match this select into a max/min operation, which have dedicated
// opcode in the instruction set.
// FIXME: This is not correct in the presence of NaNs, so we only enable this
// in no-NaNs mode.
if (getTargetMachine().Options.NoNaNsFPMath) {
SDValue MinMaxLHS = TVal, MinMaxRHS = FVal;
if (selectCCOpsAreFMaxCompatible(LHS, MinMaxRHS) &&
selectCCOpsAreFMaxCompatible(RHS, MinMaxLHS)) {
CC = ISD::getSetCCSwappedOperands(CC);
std::swap(MinMaxLHS, MinMaxRHS);
}

if (selectCCOpsAreFMaxCompatible(LHS, MinMaxLHS) &&
selectCCOpsAreFMaxCompatible(RHS, MinMaxRHS)) {
switch (CC) {
default:
break;
case ISD::SETGT:
case ISD::SETGE:
case ISD::SETUGT:
case ISD::SETUGE:
case ISD::SETOGT:
case ISD::SETOGE:
return DAG.getNode(AArch64ISD::FMAX, dl, VT, MinMaxLHS, MinMaxRHS);
break;
case ISD::SETLT:
case ISD::SETLE:
case ISD::SETULT:
case ISD::SETULE:
case ISD::SETOLT:
case ISD::SETOLE:
return DAG.getNode(AArch64ISD::FMIN, dl, VT, MinMaxLHS, MinMaxRHS);
break;
}
}
}

// If that fails, we'll need to perform an FCMP + CSEL sequence. Go ahead
// and do the comparison.
SDValue Cmp = emitComparison(LHS, RHS, CC, dl, DAG);

// Unfortunately, the mapping of LLVM FP CC's onto AArch64 CC's isn't totally
Expand Down Expand Up @@ -8696,75 +8735,6 @@ static SDValue performSelectCombine(SDNode *N,
return DAG.getSelect(DL, ResVT, Mask, N->getOperand(1), N->getOperand(2));
}

/// performSelectCCCombine - Target-specific DAG combining for ISD::SELECT_CC
/// to match FMIN/FMAX patterns.
static SDValue performSelectCCCombine(SDNode *N, SelectionDAG &DAG) {
// Try to use FMIN/FMAX instructions for FP selects like "x < y ? x : y".
// Unless the NoNaNsFPMath option is set, be careful about NaNs:
// vmax/vmin return NaN if either operand is a NaN;
// only do the transformation when it matches that behavior.

SDValue CondLHS = N->getOperand(0);
SDValue CondRHS = N->getOperand(1);
SDValue LHS = N->getOperand(2);
SDValue RHS = N->getOperand(3);
ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get();

unsigned Opcode;
bool IsReversed;
if (selectCCOpsAreFMaxCompatible(CondLHS, LHS) &&
selectCCOpsAreFMaxCompatible(CondRHS, RHS)) {
IsReversed = false; // x CC y ? x : y
} else if (selectCCOpsAreFMaxCompatible(CondRHS, LHS) &&
selectCCOpsAreFMaxCompatible(CondLHS, RHS)) {
IsReversed = true ; // x CC y ? y : x
} else {
return SDValue();
}

bool IsUnordered = false, IsOrEqual;
switch (CC) {
default:
return SDValue();
case ISD::SETULT:
case ISD::SETULE:
IsUnordered = true;
case ISD::SETOLT:
case ISD::SETOLE:
case ISD::SETLT:
case ISD::SETLE:
IsOrEqual = (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE);
Opcode = IsReversed ? AArch64ISD::FMAX : AArch64ISD::FMIN;
break;

case ISD::SETUGT:
case ISD::SETUGE:
IsUnordered = true;
case ISD::SETOGT:
case ISD::SETOGE:
case ISD::SETGT:
case ISD::SETGE:
IsOrEqual = (CC == ISD::SETGE || CC == ISD::SETOGE || CC == ISD::SETUGE);
Opcode = IsReversed ? AArch64ISD::FMIN : AArch64ISD::FMAX;
break;
}

// If LHS is NaN, an ordered comparison will be false and the result will be
// the RHS, but FMIN(NaN, RHS) = FMAX(NaN, RHS) = NaN. Avoid this by checking
// that LHS != NaN. Likewise, for unordered comparisons, check for RHS != NaN.
if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS))
return SDValue();

// For xxx-or-equal comparisons, "+0 <= -0" and "-0 >= +0" will both be true,
// but FMIN will return -0, and FMAX will return +0. So FMIN/FMAX can only be
// used for unsafe math or if one of the operands is known to be nonzero.
if (IsOrEqual && !DAG.getTarget().Options.UnsafeFPMath &&
!(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS)))
return SDValue();

return DAG.getNode(Opcode, SDLoc(N), N->getValueType(0), LHS, RHS);
}

SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
Expand Down Expand Up @@ -8797,8 +8767,6 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
return performSelectCombine(N, DCI);
case ISD::VSELECT:
return performVSelectCombine(N, DCI.DAG);
case ISD::SELECT_CC:
return performSelectCCCombine(N, DCI.DAG);
case ISD::STORE:
return performSTORECombine(N, DCI, DAG, Subtarget);
case AArch64ISD::BRCOND:
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3521,6 +3521,9 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
// c = fcmp [?gt, ?ge, ?lt, ?le] a, b
// select c, a, b
// In NoNaNsFPMath the CC will have been changed from, e.g., 'ogt' to 'gt'.
// FIXME: There is similar code that allows some extensions in
// AArch64TargetLowering::LowerSELECT_CC that should be shared with this
// code.
bool swapSides = false;
if (!getTargetMachine().Options.NoNaNsFPMath) {
// transformability may depend on which way around we compare
Expand Down
23 changes: 1 addition & 22 deletions llvm/test/CodeGen/AArch64/arm64-fmax.ll
Original file line number Diff line number Diff line change
@@ -1,55 +1,34 @@
; RUN: llc -march=arm64 -enable-no-nans-fp-math < %s | FileCheck %s
; RUN: llc -march=arm64 < %s | FileCheck %s --check-prefix=CHECK-SAFE

define double @test_direct(float %in) #1 {
; CHECK-LABEL: test_direct:
; CHECK-SAFE-LABEL: test_direct:
%cmp = fcmp olt float %in, 0.000000e+00
%longer = fpext float %in to double
%val = select i1 %cmp, double 0.000000e+00, double %longer
ret double %val

; CHECK: fmax
; CHECK-SAFE: fmax
}

define double @test_cross(float %in) #1 {
; CHECK-LABEL: test_cross:
; CHECK-SAFE-LABEL: test_cross:
%cmp = fcmp ult float %in, 0.000000e+00
%longer = fpext float %in to double
%val = select i1 %cmp, double %longer, double 0.000000e+00
ret double %val

; CHECK: fmin
; CHECK-SAFE: fmin
}

; Same as previous, but with ordered comparison;
; can't be converted in safe-math mode.
define double @test_cross_fail_nan(float %in) #1 {
; CHECK-LABEL: test_cross_fail_nan:
; CHECK-SAFE-LABEL: test_cross_fail_nan:
%cmp = fcmp olt float %in, 0.000000e+00
%longer = fpext float %in to double
%val = select i1 %cmp, double %longer, double 0.000000e+00
ret double %val

; CHECK: fmin
; CHECK-SAFE: fcsel d0, d1, d0, mi
}

; This isn't a min or a max, but passes the first condition for swapping the
; results. Make sure they're put back before we resort to the normal fcsel.
define float @test_cross_fail(float %lhs, float %rhs) {
; CHECK-LABEL: test_cross_fail:
; CHECK-SAFE-LABEL: test_cross_fail:
%tst = fcmp une float %lhs, %rhs
%res = select i1 %tst, float %rhs, float %lhs
ret float %res

; The register allocator would have to decide to be deliberately obtuse before
; other register were used.
; CHECK: fcsel s0, s1, s0, ne
; CHECK-SAFE: fcsel s0, s1, s0, ne
}
}

0 comments on commit 780a3b3

Please sign in to comment.