-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Hexagon: sfmax/sfmin instructions are IEEE754-2019 #139056
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The min/max instructions of Hexagon follow IEEE754-2019, aka FMINIMUMNUM and FMAXIMUMNUM instead of FMAXNUM and FMINNUM
@llvm/pr-subscribers-backend-hexagon Author: YunQiang Su (wzssyqa) ChangesThe min/max instructions of Hexagon follow IEEE754-2019, aka Full diff: https://github.com/llvm/llvm-project/pull/139056.diff 6 Files Affected:
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index fe12f99b91cd3..5d91b93f6777b 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1499,8 +1499,9 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
// - indexed loads and stores (pre-/post-incremented),
// - ANY_EXTEND_VECTOR_INREG, ATOMIC_CMP_SWAP_WITH_SUCCESS, CONCAT_VECTORS,
// ConstantFP, FCEIL, FCOPYSIGN, FEXP, FEXP2, FFLOOR, FGETSIGN,
- // FLOG, FLOG2, FLOG10, FMAXNUM, FMINNUM, FNEARBYINT, FRINT, FROUND, TRAP,
- // FTRUNC, PREFETCH, SIGN_EXTEND_VECTOR_INREG, ZERO_EXTEND_VECTOR_INREG,
+ // FLOG, FLOG2, FLOG10, FMAXIMUMNUM, FMINIMUMNUM, FNEARBYINT, FRINT, FROUND,
+ // TRAP, FTRUNC, PREFETCH, SIGN_EXTEND_VECTOR_INREG,
+ // ZERO_EXTEND_VECTOR_INREG,
// which default to "expand" for at least one type.
// Misc operations.
@@ -1639,28 +1640,75 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
// Set the action for vector operations to "expand", then override it with
// either "custom" or "legal" for specific cases.
static const unsigned VectExpOps[] = {
- // Integer arithmetic:
- ISD::ADD, ISD::SUB, ISD::MUL, ISD::SDIV, ISD::UDIV,
- ISD::SREM, ISD::UREM, ISD::SDIVREM, ISD::UDIVREM, ISD::SADDO,
- ISD::UADDO, ISD::SSUBO, ISD::USUBO, ISD::SMUL_LOHI, ISD::UMUL_LOHI,
- // Logical/bit:
- ISD::AND, ISD::OR, ISD::XOR, ISD::ROTL, ISD::ROTR,
- ISD::CTPOP, ISD::CTLZ, ISD::CTTZ, ISD::BSWAP, ISD::BITREVERSE,
- // Floating point arithmetic/math functions:
- ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FMA, ISD::FDIV,
- ISD::FREM, ISD::FNEG, ISD::FABS, ISD::FSQRT, ISD::FSIN,
- ISD::FCOS, ISD::FPOW, ISD::FLOG, ISD::FLOG2,
- ISD::FLOG10, ISD::FEXP, ISD::FEXP2, ISD::FCEIL, ISD::FTRUNC,
- ISD::FRINT, ISD::FNEARBYINT, ISD::FROUND, ISD::FFLOOR,
- ISD::FMINNUM, ISD::FMAXNUM, ISD::FSINCOS, ISD::FLDEXP,
- // Misc:
- ISD::BR_CC, ISD::SELECT_CC, ISD::ConstantPool,
- // Vector:
- ISD::BUILD_VECTOR, ISD::SCALAR_TO_VECTOR,
- ISD::EXTRACT_VECTOR_ELT, ISD::INSERT_VECTOR_ELT,
- ISD::EXTRACT_SUBVECTOR, ISD::INSERT_SUBVECTOR,
- ISD::CONCAT_VECTORS, ISD::VECTOR_SHUFFLE,
- ISD::SPLAT_VECTOR,
+ // Integer arithmetic:
+ ISD::ADD,
+ ISD::SUB,
+ ISD::MUL,
+ ISD::SDIV,
+ ISD::UDIV,
+ ISD::SREM,
+ ISD::UREM,
+ ISD::SDIVREM,
+ ISD::UDIVREM,
+ ISD::SADDO,
+ ISD::UADDO,
+ ISD::SSUBO,
+ ISD::USUBO,
+ ISD::SMUL_LOHI,
+ ISD::UMUL_LOHI,
+ // Logical/bit:
+ ISD::AND,
+ ISD::OR,
+ ISD::XOR,
+ ISD::ROTL,
+ ISD::ROTR,
+ ISD::CTPOP,
+ ISD::CTLZ,
+ ISD::CTTZ,
+ ISD::BSWAP,
+ ISD::BITREVERSE,
+ // Floating point arithmetic/math functions:
+ ISD::FADD,
+ ISD::FSUB,
+ ISD::FMUL,
+ ISD::FMA,
+ ISD::FDIV,
+ ISD::FREM,
+ ISD::FNEG,
+ ISD::FABS,
+ ISD::FSQRT,
+ ISD::FSIN,
+ ISD::FCOS,
+ ISD::FPOW,
+ ISD::FLOG,
+ ISD::FLOG2,
+ ISD::FLOG10,
+ ISD::FEXP,
+ ISD::FEXP2,
+ ISD::FCEIL,
+ ISD::FTRUNC,
+ ISD::FRINT,
+ ISD::FNEARBYINT,
+ ISD::FROUND,
+ ISD::FFLOOR,
+ ISD::FMINIMUMNUM,
+ ISD::FMAXIMUMNUM,
+ ISD::FSINCOS,
+ ISD::FLDEXP,
+ // Misc:
+ ISD::BR_CC,
+ ISD::SELECT_CC,
+ ISD::ConstantPool,
+ // Vector:
+ ISD::BUILD_VECTOR,
+ ISD::SCALAR_TO_VECTOR,
+ ISD::EXTRACT_VECTOR_ELT,
+ ISD::INSERT_VECTOR_ELT,
+ ISD::EXTRACT_SUBVECTOR,
+ ISD::INSERT_SUBVECTOR,
+ ISD::CONCAT_VECTORS,
+ ISD::VECTOR_SHUFFLE,
+ ISD::SPLAT_VECTOR,
};
for (MVT VT : MVT::fixedlen_vector_valuetypes()) {
@@ -1784,8 +1832,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FMUL, MVT::f64, Expand);
setOperationAction(ISD::FDIV, MVT::f32, Custom);
- setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
- setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);
+ setOperationAction(ISD::FMINIMUMNUM, MVT::f32, Legal);
+ setOperationAction(ISD::FMAXIMUMNUM, MVT::f32, Legal);
setOperationAction(ISD::FP_TO_UINT, MVT::i1, Promote);
setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote);
@@ -1833,8 +1881,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FSUB, MVT::f64, Legal);
}
if (Subtarget.hasV67Ops()) {
- setOperationAction(ISD::FMINNUM, MVT::f64, Legal);
- setOperationAction(ISD::FMAXNUM, MVT::f64, Legal);
+ setOperationAction(ISD::FMINIMUMNUM, MVT::f64, Legal);
+ setOperationAction(ISD::FMAXIMUMNUM, MVT::f64, Legal);
setOperationAction(ISD::FMUL, MVT::f64, Legal);
}
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index de2bac6905530..fbbcacf0d713e 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -127,8 +127,8 @@ HexagonTargetLowering::initializeHVXLowering() {
setOperationAction(ISD::FADD, T, Legal);
setOperationAction(ISD::FSUB, T, Legal);
setOperationAction(ISD::FMUL, T, Legal);
- setOperationAction(ISD::FMINNUM, T, Legal);
- setOperationAction(ISD::FMAXNUM, T, Legal);
+ setOperationAction(ISD::FMINIMUMNUM, T, Legal);
+ setOperationAction(ISD::FMAXIMUMNUM, T, Legal);
setOperationAction(ISD::INSERT_SUBVECTOR, T, Custom);
setOperationAction(ISD::EXTRACT_SUBVECTOR, T, Custom);
@@ -164,8 +164,8 @@ HexagonTargetLowering::initializeHVXLowering() {
setOperationAction(ISD::FADD, P, Custom);
setOperationAction(ISD::FSUB, P, Custom);
setOperationAction(ISD::FMUL, P, Custom);
- setOperationAction(ISD::FMINNUM, P, Custom);
- setOperationAction(ISD::FMAXNUM, P, Custom);
+ setOperationAction(ISD::FMINIMUMNUM, P, Custom);
+ setOperationAction(ISD::FMAXIMUMNUM, P, Custom);
setOperationAction(ISD::SETCC, P, Custom);
setOperationAction(ISD::VSELECT, P, Custom);
@@ -3172,8 +3172,8 @@ HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::FADD:
case ISD::FSUB:
case ISD::FMUL:
- case ISD::FMINNUM:
- case ISD::FMAXNUM:
+ case ISD::FMINIMUMNUM:
+ case ISD::FMAXIMUMNUM:
case ISD::MULHS:
case ISD::MULHU:
case ISD::AND:
diff --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td
index 0d872b556d801..2a991bafbf148 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatterns.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td
@@ -1579,8 +1579,8 @@ def: OpR_RR_pat<C2_and, Mul, v8i1, V8I1>;
def: OpR_RR_pat<F2_sfadd, pf2<fadd>, f32, F32>;
def: OpR_RR_pat<F2_sfsub, pf2<fsub>, f32, F32>;
def: OpR_RR_pat<F2_sfmpy, pf2<fmul>, f32, F32>;
-def: OpR_RR_pat<F2_sfmin, pf2<fminnum>, f32, F32>;
-def: OpR_RR_pat<F2_sfmax, pf2<fmaxnum>, f32, F32>;
+def: OpR_RR_pat<F2_sfmin, pf2<fminimumnum>, f32, F32>;
+def: OpR_RR_pat<F2_sfmax, pf2<fmaximumnum>, f32, F32>;
let Predicates = [HasV66] in {
def: OpR_RR_pat<F2_dfadd, pf2<fadd>, f64, F64>;
@@ -1600,8 +1600,8 @@ let Predicates = [HasV67,UseUnsafeMath], AddedComplexity = 50 in {
def: Pat<(fmul F64:$Rs, F64:$Rt), (DfMpy $Rs, $Rt)>;
}
let Predicates = [HasV67] in {
- def: OpR_RR_pat<F2_dfmin, pf2<fminnum>, f64, F64>;
- def: OpR_RR_pat<F2_dfmax, pf2<fmaxnum>, f64, F64>;
+ def: OpR_RR_pat<F2_dfmin, pf2<fminimumnum>, f64, F64>;
+ def: OpR_RR_pat<F2_dfmax, pf2<fmaximumnum>, f64, F64>;
def: Pat<(fmul F64:$Rs, F64:$Rt), (DfMpy (F2_dfmpyfix $Rs, $Rt),
(F2_dfmpyfix $Rt, $Rs))>;
diff --git a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
index 5b8386416a5f0..ba449eaeed34c 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
@@ -508,10 +508,10 @@ let Predicates = [UseHVXV68, UseHVX128B, UseHVXQFloat] in {
defm: MinMax_pats<V6_vmin_sf, V6_vmax_sf, vselect, setgt, VecQ32, HVF32>;
defm: MinMax_pats<V6_vmin_sf, V6_vmax_sf, vselect, setogt, VecQ32, HVF32>;
}
- def: OpR_RR_pat<V6_vmin_hf, pf2<fminnum>, VecF16, HVF16>;
- def: OpR_RR_pat<V6_vmax_hf, pf2<fmaxnum>, VecF16, HVF16>;
- def: OpR_RR_pat<V6_vmin_sf, pf2<fminnum>, VecF32, HVF32>;
- def: OpR_RR_pat<V6_vmax_sf, pf2<fmaxnum>, VecF32, HVF32>;
+ def: OpR_RR_pat<V6_vmin_hf, pf2<fminimumnum>, VecF16, HVF16>;
+ def: OpR_RR_pat<V6_vmax_hf, pf2<fmaximumnum>, VecF16, HVF16>;
+ def: OpR_RR_pat<V6_vmin_sf, pf2<fminimumnum>, VecF32, HVF32>;
+ def: OpR_RR_pat<V6_vmax_sf, pf2<fmaximumnum>, VecF32, HVF32>;
}
let Predicates = [UseHVXV68, UseHVX128B, UseHVXIEEEFP] in {
@@ -521,10 +521,10 @@ let Predicates = [UseHVXV68, UseHVX128B, UseHVXIEEEFP] in {
defm: MinMax_pats<V6_vfmin_sf, V6_vfmax_sf, vselect, setgt, VecQ32, HVF32>;
defm: MinMax_pats<V6_vfmin_sf, V6_vfmax_sf, vselect, setogt, VecQ32, HVF32>;
}
- def: OpR_RR_pat<V6_vfmin_hf, pf2<fminnum>, VecF16, HVF16>;
- def: OpR_RR_pat<V6_vfmax_hf, pf2<fmaxnum>, VecF16, HVF16>;
- def: OpR_RR_pat<V6_vfmin_sf, pf2<fminnum>, VecF32, HVF32>;
- def: OpR_RR_pat<V6_vfmax_sf, pf2<fmaxnum>, VecF32, HVF32>;
+ def: OpR_RR_pat<V6_vfmin_hf, pf2<fminimumnum>, VecF16, HVF16>;
+ def: OpR_RR_pat<V6_vfmax_hf, pf2<fmaximumnum>, VecF16, HVF16>;
+ def: OpR_RR_pat<V6_vfmin_sf, pf2<fminimumnum>, VecF32, HVF32>;
+ def: OpR_RR_pat<V6_vfmax_sf, pf2<fmaximumnum>, VecF32, HVF32>;
}
let Predicates = [UseHVX] in {
diff --git a/llvm/test/CodeGen/Hexagon/fminmax-v67.ll b/llvm/test/CodeGen/Hexagon/fminmax-v67.ll
index d5b803c6c8926..e9696926ea3d5 100644
--- a/llvm/test/CodeGen/Hexagon/fminmax-v67.ll
+++ b/llvm/test/CodeGen/Hexagon/fminmax-v67.ll
@@ -2,7 +2,7 @@
; CHECK-LABEL: t1
-; CHECK: dfmax
+; CHECK-NOT: dfmax
define dso_local double @t1(double %a, double %b) local_unnamed_addr {
entry:
@@ -11,7 +11,7 @@ entry:
}
; CHECK-LABEL: t2
-; CHECK: dfmin
+; CHECK-NOT: dfmin
define dso_local double @t2(double %a, double %b) local_unnamed_addr {
entry:
@@ -20,7 +20,7 @@ entry:
}
; CHECK-LABEL: t3
-; CHECK: sfmax
+; CHECK-NOT: sfmax
define dso_local float @t3(float %a, float %b) local_unnamed_addr {
entry:
@@ -29,7 +29,7 @@ entry:
}
; CHECK-LABEL: t4
-; CHECK: sfmin
+; CHECK-NOT: sfmin
define dso_local float @t4(float %a, float %b) local_unnamed_addr {
entry:
@@ -37,6 +37,43 @@ entry:
ret float %0
}
+; CHECK-LABEL: t1num
+; CHECK: dfmax
+
+define dso_local double @t1num(double %a, double %b) local_unnamed_addr {
+entry:
+ %0 = tail call double @llvm.maximumnum.f64(double %a, double %b)
+ ret double %0
+}
+
+; CHECK-LABEL: t2num
+; CHECK: dfmin
+
+define dso_local double @t2num(double %a, double %b) local_unnamed_addr {
+entry:
+ %0 = tail call double @llvm.minimumnum.f64(double %a, double %b)
+ ret double %0
+}
+
+; CHECK-LABEL: t3num
+; CHECK: sfmax
+
+define dso_local float @t3num(float %a, float %b) local_unnamed_addr {
+entry:
+ %0 = tail call float @llvm.maximumnum.f32(float %a, float %b)
+ ret float %0
+}
+
+; CHECK-LABEL: t4num
+; CHECK: sfmin
+
+define dso_local float @t4num(float %a, float %b) local_unnamed_addr {
+entry:
+ %0 = tail call float @llvm.minimumnum.f32(float %a, float %b)
+ ret float %0
+}
+
+
declare double @llvm.minnum.f64(double, double) #1
declare double @llvm.maxnum.f64(double, double) #1
declare float @llvm.maxnum.f32(float, float) #1
diff --git a/llvm/test/CodeGen/Hexagon/fminmax.ll b/llvm/test/CodeGen/Hexagon/fminmax.ll
index a581bd3b21868..274fc8d1592bd 100644
--- a/llvm/test/CodeGen/Hexagon/fminmax.ll
+++ b/llvm/test/CodeGen/Hexagon/fminmax.ll
@@ -3,22 +3,55 @@
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
target triple = "hexagon"
-; CHECK-LABEL: minimum
-; CHECK: sfmin
-define float @minimum(float %x, float %y) #0 {
+; CHECK-LABEL: cfminf
+; CHECK-NOT: sfmin
+define float @cfminf(float %x, float %y) #0 {
entry:
%call = tail call float @fminf(float %x, float %y) #1
ret float %call
}
-; CHECK-LABEL: maximum
-; CHECK: sfmax
-define float @maximum(float %x, float %y) #0 {
+; CHECK-LABEL: cfmaxf
+; CHECK-NOT: sfmax
+define float @cfmaxf(float %x, float %y) #0 {
entry:
%call = tail call float @fmaxf(float %x, float %y) #1
ret float %call
}
+; CHECK-LABEL: minnum
+; CHECK-NOT: sfmin
+define float @minnum(float %x, float %y) #0 {
+entry:
+ %call = tail call float @llvm.minnum.f32(float %x, float %y) #1
+ ret float %call
+}
+
+; CHECK-LABEL: maxnum
+; CHECK-NOT: sfmax
+define float @maxnum(float %x, float %y) #0 {
+entry:
+ %call = tail call float @llvm.minnum.f32(float %x, float %y) #1
+ ret float %call
+}
+
+; CHECK-LABEL: minimumnum
+; CHECK: sfmin
+define float @minimumnum(float %x, float %y) #0 {
+entry:
+ %call = tail call float @llvm.minimumnum.f32(float %x, float %y) #1
+ ret float %call
+}
+
+; CHECK-LABEL: maximumnum
+; CHECK: sfmax
+define float @maximumnum(float %x, float %y) #0 {
+entry:
+ %call = tail call float @llvm.maximumnum.f32(float %x, float %y) #1
+ ret float %call
+}
+
+
declare float @fminf(float, float) #0
declare float @fmaxf(float, float) #0
|
Can you help me understand the distinction between these? Also: is it safe to remove |
I guess the distinction between FMAXIMUMNUM and FMAXIMUM is in the handling of snan's. FMAXIMUMNUM variant does not distinguish between snan's and qnan's which is what the sfmax instruction does as well. Is my understanding correct @wzssyqa ? |
Mostly signaling nan handling. The 2008 operation nonsensically behaves in a way opposite of how it does with a qnan input. We have this chart now https://llvm.org/docs/LangRef.html#llvm-min-intrinsics-comparation
All 3 pairs of intrinsics should be independently supported, and you can use one set to implement the others. The ISA documentation for these operands is universally poor. The document I found for sfmin states: So if taken at face value, this is correct. The title and description should clarify which operation, as 2019 has both minimum and minimumNumber. This does explicitly not state if -0 is ordered as less than 0, but I'm assuming it is as that's the 2019 behavior for both operations, and also I haven't seen an example of an ISA that didn't have the correct behavior |
Avoid reformatting this whole table -NOT checks are next to useless, this should have positive checks
ping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with the changes. @androm3da do you have any further comments for this PR?
No comments, LGTM |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/11595 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/11/builds/15090 Here is the relevant piece of the build log for the reference
|
The min/max instructions of Hexagon follow IEEE754-2019 minimumNumber/maximumNumber,
aka
FMINIMUMNUM and FMAXIMUMNUM
instead of
FMAXNUM and FMINNUM