Skip to content

Commit

Permalink
[SDAG] Optimize unordered comparison in soft-float mode (patch by Ant…
Browse files Browse the repository at this point in the history
…on Nadolskiy)

Current implementation handles unordered comparison poorly in soft-float mode. 
Consider (a ULE b) which is a <= b. It is lowered to (ledf2(a, b) <= 0 || unorddf2(a, b) != 0) (in general). We can do better job by lowering it to (__gtdf2(a, b) <= 0). 
Such replacement is true for other CMP's (ult, ugt, uge). In general, we just call same function as for ordered case but negate comparison against zero.
Differential Revision: http://reviews.llvm.org/D10804

llvm-svn: 242280
  • Loading branch information
alexey-bataev committed Jul 15, 2015
1 parent 5d36b23 commit b928860
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 74 deletions.
54 changes: 31 additions & 23 deletions llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ TargetLowering::makeLibCall(SelectionDAG &DAG,
return LowerCallTo(CLI);
}


/// SoftenSetCCOperands - Soften the operands of a comparison. This code is
/// shared among BR_CC, SELECT_CC, and SETCC handlers.
void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
Expand All @@ -127,6 +126,7 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,

// Expand into one or more soft-fp libcall(s).
RTLIB::Libcall LC1 = RTLIB::UNKNOWN_LIBCALL, LC2 = RTLIB::UNKNOWN_LIBCALL;
bool ShouldInvertCC = false;
switch (CCCode) {
case ISD::SETEQ:
case ISD::SETOEQ:
Expand Down Expand Up @@ -166,34 +166,38 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
LC1 = (VT == MVT::f32) ? RTLIB::O_F32 :
(VT == MVT::f64) ? RTLIB::O_F64 : RTLIB::O_F128;
break;
default:
case ISD::SETONE:
// SETONE = SETOLT | SETOGT
LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 :
(VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128;
LC2 = (VT == MVT::f32) ? RTLIB::OGT_F32 :
(VT == MVT::f64) ? RTLIB::OGT_F64 : RTLIB::OGT_F128;
break;
case ISD::SETUEQ:
LC1 = (VT == MVT::f32) ? RTLIB::UO_F32 :
(VT == MVT::f64) ? RTLIB::UO_F64 : RTLIB::UO_F128;
LC2 = (VT == MVT::f32) ? RTLIB::OEQ_F32 :
(VT == MVT::f64) ? RTLIB::OEQ_F64 : RTLIB::OEQ_F128;
break;
default:
// Invert CC for unordered comparisons
ShouldInvertCC = true;
switch (CCCode) {
case ISD::SETONE:
// SETONE = SETOLT | SETOGT
LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 :
(VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128;
// Fallthrough
case ISD::SETUGT:
LC2 = (VT == MVT::f32) ? RTLIB::OGT_F32 :
(VT == MVT::f64) ? RTLIB::OGT_F64 : RTLIB::OGT_F128;
break;
case ISD::SETUGE:
LC2 = (VT == MVT::f32) ? RTLIB::OGE_F32 :
(VT == MVT::f64) ? RTLIB::OGE_F64 : RTLIB::OGE_F128;
break;
case ISD::SETULT:
LC2 = (VT == MVT::f32) ? RTLIB::OLT_F32 :
(VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128;
LC1 = (VT == MVT::f32) ? RTLIB::OGE_F32 :
(VT == MVT::f64) ? RTLIB::OGE_F64 : RTLIB::OGE_F128;
break;
case ISD::SETULE:
LC2 = (VT == MVT::f32) ? RTLIB::OLE_F32 :
LC1 = (VT == MVT::f32) ? RTLIB::OGT_F32 :
(VT == MVT::f64) ? RTLIB::OGT_F64 : RTLIB::OGT_F128;
break;
case ISD::SETUGT:
LC1 = (VT == MVT::f32) ? RTLIB::OLE_F32 :
(VT == MVT::f64) ? RTLIB::OLE_F64 : RTLIB::OLE_F128;
break;
case ISD::SETUEQ:
LC2 = (VT == MVT::f32) ? RTLIB::OEQ_F32 :
(VT == MVT::f64) ? RTLIB::OEQ_F64 : RTLIB::OEQ_F128;
case ISD::SETUGE:
LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 :
(VT == MVT::f64) ? RTLIB::OLT_F64 : RTLIB::OLT_F128;
break;
default: llvm_unreachable("Do not know how to soften this setcc!");
}
Expand All @@ -203,16 +207,20 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
EVT RetVT = getCmpLibcallReturnType();
SDValue Ops[2] = { NewLHS, NewRHS };
NewLHS = makeLibCall(DAG, LC1, RetVT, Ops, 2, false/*sign irrelevant*/,
dl).first;
dl).first;
NewRHS = DAG.getConstant(0, dl, RetVT);

CCCode = getCmpLibcallCC(LC1);
if (ShouldInvertCC)
CCCode = getSetCCInverse(CCCode, /*isInteger=*/true);

if (LC2 != RTLIB::UNKNOWN_LIBCALL) {
SDValue Tmp = DAG.getNode(
ISD::SETCC, dl,
getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), RetVT),
NewLHS, NewRHS, DAG.getCondCode(CCCode));
NewLHS = makeLibCall(DAG, LC2, RetVT, Ops, 2, false/*sign irrelevant*/,
dl).first;
dl).first;
NewLHS = DAG.getNode(
ISD::SETCC, dl,
getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), RetVT),
Expand Down
31 changes: 8 additions & 23 deletions llvm/test/CodeGen/AArch64/arm64-fp128.ll
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,9 @@ define i1 @test_setcc2() {
; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]

%val = fcmp ugt fp128 %lhs, %rhs
; CHECK: bl __gttf2
; CHECK: bl __letf2
; CHECK: cmp w0, #0
; CHECK: cset [[GT:w[0-9]+]], gt

; CHECK: bl __unordtf2
; CHECK: cmp w0, #0
; CHECK: cset [[UNORDERED:w[0-9]+]], ne
; CHECK: orr w0, [[UNORDERED]], [[GT]]
; CHECK: cset w0, gt

ret i1 %val
; CHECK: ret
Expand All @@ -169,31 +164,21 @@ define i32 @test_br_cc() {
; CHECK: ldr q0, [{{x[0-9]+}}, :lo12:lhs]
; CHECK: ldr q1, [{{x[0-9]+}}, :lo12:rhs]

; olt == !uge, which LLVM unfortunately "optimizes" this to.
; olt == !uge, which LLVM optimizes this to.
%cond = fcmp olt fp128 %lhs, %rhs
; CHECK: bl __getf2
; CHECK: cmp w0, #0
; CHECK: cset [[OGE:w[0-9]+]], ge

; CHECK: bl __unordtf2
; CHECK: cmp w0, #0
; CHECK: cset [[UNORDERED:w[0-9]+]], ne

; CHECK: orr [[UGE:w[0-9]+]], [[UNORDERED]], [[OGE]]
; CHECK: cbnz [[UGE]], [[RET29:.LBB[0-9]+_[0-9]+]]
; CHECK: bl __lttf2
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: b.ge {{.LBB[0-9]+_[0-9]+}}
br i1 %cond, label %iftrue, label %iffalse

iftrue:
ret i32 42
; CHECK-NEXT: BB#
; CHECK-NEXT: movz w0, #0x2a
; CHECK-NEXT: b [[REALRET:.LBB[0-9]+_[0-9]+]]

; CHECK: ret
iffalse:
ret i32 29
; CHECK: [[RET29]]:
; CHECK-NEXT: movz w0, #0x1d
; CHECK-NEXT: [[REALRET]]:
; CHECK: movz w0, #0x1d
; CHECK: ret
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/Mips/mips16fpe.ll
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ entry:
%and2 = and i1 %lnot, %cmp1
%and = zext i1 %and2 to i32
store i32 %and, i32* @ltsf2_result, align 4
;16hf: lw ${{[0-9]+}}, %call16(__mips16_unordsf2)(${{[0-9]+}})
;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltsf2)(${{[0-9]+}})
;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltsf2)(${{[0-9]+}})
ret void
}
Expand All @@ -313,7 +313,7 @@ entry:
%and2 = and i1 %lnot, %cmp1
%and = zext i1 %and2 to i32
store i32 %and, i32* @ltdf2_result, align 4
;16hf: lw ${{[0-9]+}}, %call16(__mips16_unorddf2)(${{[0-9]+}})
;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltdf2)(${{[0-9]+}})
;16hf: lw ${{[0-9]+}}, %call16(__mips16_ltdf2)(${{[0-9]+}})
ret void
}
Expand Down
44 changes: 20 additions & 24 deletions llvm/test/CodeGen/Thumb2/float-cmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -81,35 +81,39 @@ define i1 @cmp_f_ord(float %a, float %b) {
}
define i1 @cmp_f_ugt(float %a, float %b) {
; CHECK-LABEL: cmp_f_ugt:
; NONE: bl __aeabi_fcmpgt
; NONE: bl __aeabi_fcmpun
; NONE: bl __aeabi_fcmple
; NONE: cmp r0, #0
; NONE-NEXT: it eq
; HARD: vcmpe.f32
; HARD: movhi r0, #1
%1 = fcmp ugt float %a, %b
ret i1 %1
}
define i1 @cmp_f_uge(float %a, float %b) {
; CHECK-LABEL: cmp_f_uge:
; NONE: bl __aeabi_fcmpge
; NONE: bl __aeabi_fcmpun
; NONE: bl __aeabi_fcmplt
; NONE: cmp r0, #0
; NONE-NEXT: it eq
; HARD: vcmpe.f32
; HARD: movpl r0, #1
%1 = fcmp uge float %a, %b
ret i1 %1
}
define i1 @cmp_f_ult(float %a, float %b) {
; CHECK-LABEL: cmp_f_ult:
; NONE: bl __aeabi_fcmplt
; NONE: bl __aeabi_fcmpun
; NONE: bl __aeabi_fcmpge
; NONE: cmp r0, #0
; NONE-NEXT: it eq
; HARD: vcmpe.f32
; HARD: movlt r0, #1
%1 = fcmp ult float %a, %b
ret i1 %1
}
define i1 @cmp_f_ule(float %a, float %b) {
; CHECK-LABEL: cmp_f_ule:
; NONE: bl __aeabi_fcmple
; NONE: bl __aeabi_fcmpun
; NONE: bl __aeabi_fcmpgt
; NONE: cmp r0, #0
; NONE-NEXT: it eq
; HARD: vcmpe.f32
; HARD: movle r0, #1
%1 = fcmp ule float %a, %b
Expand Down Expand Up @@ -214,10 +218,8 @@ define i1 @cmp_d_ord(double %a, double %b) {
}
define i1 @cmp_d_ugt(double %a, double %b) {
; CHECK-LABEL: cmp_d_ugt:
; NONE: bl __aeabi_dcmpgt
; NONE: bl __aeabi_dcmpun
; SP: bl __aeabi_dcmpgt
; SP: bl __aeabi_dcmpun
; NONE: bl __aeabi_dcmple
; SP: bl __aeabi_dcmple
; DP: vcmpe.f64
; DP: movhi r0, #1
%1 = fcmp ugt double %a, %b
Expand All @@ -226,10 +228,8 @@ define i1 @cmp_d_ugt(double %a, double %b) {

define i1 @cmp_d_ult(double %a, double %b) {
; CHECK-LABEL: cmp_d_ult:
; NONE: bl __aeabi_dcmplt
; NONE: bl __aeabi_dcmpun
; SP: bl __aeabi_dcmplt
; SP: bl __aeabi_dcmpun
; NONE: bl __aeabi_dcmpge
; SP: bl __aeabi_dcmpge
; DP: vcmpe.f64
; DP: movlt r0, #1
%1 = fcmp ult double %a, %b
Expand Down Expand Up @@ -268,10 +268,8 @@ define i1 @cmp_d_ueq(double %a, double %b) {

define i1 @cmp_d_uge(double %a, double %b) {
; CHECK-LABEL: cmp_d_uge:
; NONE: bl __aeabi_dcmpge
; NONE: bl __aeabi_dcmpun
; SP: bl __aeabi_dcmpge
; SP: bl __aeabi_dcmpun
; NONE: bl __aeabi_dcmplt
; SP: bl __aeabi_dcmplt
; DP: vcmpe.f64
; DP: movpl r0, #1
%1 = fcmp uge double %a, %b
Expand All @@ -280,10 +278,8 @@ define i1 @cmp_d_uge(double %a, double %b) {

define i1 @cmp_d_ule(double %a, double %b) {
; CHECK-LABEL: cmp_d_ule:
; NONE: bl __aeabi_dcmple
; NONE: bl __aeabi_dcmpun
; SP: bl __aeabi_dcmple
; SP: bl __aeabi_dcmpun
; NONE: bl __aeabi_dcmpgt
; SP: bl __aeabi_dcmpgt
; DP: vcmpe.f64
; DP: movle r0, #1
%1 = fcmp ule double %a, %b
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/CodeGen/Thumb2/float-intrinsics-double.ll
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,8 @@ declare double @llvm.fabs.f64(double %Val)
define double @abs_d(double %a) {
; CHECK-LABEL: abs_d:
; NONE: bic r1, r1, #-2147483648
; SP: bl __aeabi_dcmpgt
; SP: bl __aeabi_dcmpun
; SP: bl __aeabi_dsub
; SP: bl __aeabi_dcmple
; DP: vabs.f64 d0, d0
%1 = call double @llvm.fabs.f64(double %a)
ret double %1
Expand Down
Loading

0 comments on commit b928860

Please sign in to comment.