forked from OSchip/llvm-project
[WebAssembly] Support for floating point min and max.
llvm-svn: 252653
This commit is contained in:
parent
3809ca9d00
commit
b84ae9bb38
|
@ -132,6 +132,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
||||||
for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT,
|
for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT,
|
||||||
ISD::FRINT})
|
ISD::FRINT})
|
||||||
setOperationAction(Op, T, Legal);
|
setOperationAction(Op, T, Legal);
|
||||||
|
// Support minnan and maxnan, which otherwise default to expand.
|
||||||
|
setOperationAction(ISD::FMINNAN, T, Legal);
|
||||||
|
setOperationAction(ISD::FMAXNAN, T, Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto T : {MVT::i32, MVT::i64}) {
|
for (auto T : {MVT::i32, MVT::i64}) {
|
||||||
|
|
|
@ -22,6 +22,9 @@ defm ABS : UnaryFP<fabs, "abs">;
|
||||||
defm NEG : UnaryFP<fneg, "neg">;
|
defm NEG : UnaryFP<fneg, "neg">;
|
||||||
defm COPYSIGN : BinaryFP<fcopysign, "copysign">;
|
defm COPYSIGN : BinaryFP<fcopysign, "copysign">;
|
||||||
|
|
||||||
|
defm MIN : BinaryFP<fminnan, "min">;
|
||||||
|
defm MAX : BinaryFP<fmaxnan, "max">;
|
||||||
|
|
||||||
defm CEIL : UnaryFP<fceil, "ceil">;
|
defm CEIL : UnaryFP<fceil, "ceil">;
|
||||||
defm FLOOR : UnaryFP<ffloor, "floor">;
|
defm FLOOR : UnaryFP<ffloor, "floor">;
|
||||||
defm TRUNC : UnaryFP<ftrunc, "trunc">;
|
defm TRUNC : UnaryFP<ftrunc, "trunc">;
|
||||||
|
@ -52,13 +55,6 @@ def : Pat<(setle f64:$lhs, f64:$rhs), (LE_F64 f64:$lhs, f64:$rhs)>;
|
||||||
def : Pat<(setgt f64:$lhs, f64:$rhs), (GT_F64 f64:$lhs, f64:$rhs)>;
|
def : Pat<(setgt f64:$lhs, f64:$rhs), (GT_F64 f64:$lhs, f64:$rhs)>;
|
||||||
def : Pat<(setge f64:$lhs, f64:$rhs), (GE_F64 f64:$lhs, f64:$rhs)>;
|
def : Pat<(setge f64:$lhs, f64:$rhs), (GE_F64 f64:$lhs, f64:$rhs)>;
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO(jfb): Add the following for 32-bit and 64-bit.
|
|
||||||
*
|
|
||||||
* f32.min: minimum (binary operator); if either operand is NaN, returns NaN
|
|
||||||
* f32.max: maximum (binary operator); if either operand is NaN, returns NaN
|
|
||||||
*/
|
|
||||||
|
|
||||||
def SELECT_F32 : I<(outs F32:$dst), (ins I32:$cond, F32:$lhs, F32:$rhs),
|
def SELECT_F32 : I<(outs F32:$dst), (ins I32:$cond, F32:$lhs, F32:$rhs),
|
||||||
[(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))],
|
[(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))],
|
||||||
"f32.select $dst, $cond, $lhs, $rhs">;
|
"f32.select $dst, $cond, $lhs, $rhs">;
|
||||||
|
|
|
@ -126,3 +126,27 @@ define float @nearest32_via_rint(float %x) {
|
||||||
%a = call float @llvm.rint.f32(float %x)
|
%a = call float @llvm.rint.f32(float %x)
|
||||||
ret float %a
|
ret float %a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Min and max tests. LLVM currently only forms fminnan and fmaxnan nodes in
|
||||||
|
; cases where there's a single fcmp with a select and it can prove that one
|
||||||
|
; of the arms is never NaN, so we only test that case. In the future if LLVM
|
||||||
|
; learns to form fminnan/fmaxnan in more cases, we can write more general
|
||||||
|
; tests.
|
||||||
|
|
||||||
|
; CHECK-LABEL: fmin32:
|
||||||
|
; CHECK: f32.min push, (get_local 1), (get_local 2){{$}}
|
||||||
|
; CHECK-NEXT: set_local 3, pop{{$}}
|
||||||
|
define float @fmin32(float %x) {
|
||||||
|
%a = fcmp ult float %x, 0.0
|
||||||
|
%b = select i1 %a, float %x, float 0.0
|
||||||
|
ret float %b
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: fmax32:
|
||||||
|
; CHECK: f32.max push, (get_local 1), (get_local 2){{$}}
|
||||||
|
; CHECK-NEXT: set_local 3, pop{{$}}
|
||||||
|
define float @fmax32(float %x) {
|
||||||
|
%a = fcmp ugt float %x, 0.0
|
||||||
|
%b = select i1 %a, float %x, float 0.0
|
||||||
|
ret float %b
|
||||||
|
}
|
||||||
|
|
|
@ -126,3 +126,27 @@ define double @nearest64_via_rint(double %x) {
|
||||||
%a = call double @llvm.rint.f64(double %x)
|
%a = call double @llvm.rint.f64(double %x)
|
||||||
ret double %a
|
ret double %a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Min and max tests. LLVM currently only forms fminnan and fmaxnan nodes in
|
||||||
|
; cases where there's a single fcmp with a select and it can prove that one
|
||||||
|
; of the arms is never NaN, so we only test that case. In the future if LLVM
|
||||||
|
; learns to form fminnan/fmaxnan in more cases, we can write more general
|
||||||
|
; tests.
|
||||||
|
|
||||||
|
; CHECK-LABEL: fmin64:
|
||||||
|
; CHECK: f64.min push, (get_local 1), (get_local 2){{$}}
|
||||||
|
; CHECK-NEXT: set_local 3, pop{{$}}
|
||||||
|
define double @fmin64(double %x) {
|
||||||
|
%a = fcmp ult double %x, 0.0
|
||||||
|
%b = select i1 %a, double %x, double 0.0
|
||||||
|
ret double %b
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: fmax64:
|
||||||
|
; CHECK: f64.max push, (get_local 1), (get_local 2){{$}}
|
||||||
|
; CHECK-NEXT: set_local 3, pop{{$}}
|
||||||
|
define double @fmax64(double %x) {
|
||||||
|
%a = fcmp ugt double %x, 0.0
|
||||||
|
%b = select i1 %a, double %x, double 0.0
|
||||||
|
ret double %b
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue