-
Notifications
You must be signed in to change notification settings - Fork 13.3k
SelectionDAG: Support nofpclass #108350
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
SelectionDAG: Support nofpclass #108350
Conversation
@llvm/pr-subscribers-backend-amdgpu @llvm/pr-subscribers-llvm-selectiondag Author: YunQiang Su (wzssyqa) ChangesCurrently SelectionDAG ignroes the nofpclass information from arguments. Such as define dso_local float @f(float noundef nofpclass(nan zero) %a, float noundef nofpclass(nan zero) %b) #0 { In SelectionDAG::isKnownNeverNaN, a false is returned. TODO:
Full diff: https://github.com/llvm/llvm-project/pull/108350.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1dbcf8fd765101..49d94706d87d3d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -11773,6 +11773,14 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
AssertOp = ISD::AssertSext;
else if (Arg.hasAttribute(Attribute::ZExt))
AssertOp = ISD::AssertZext;
+ if (Arg.hasAttribute(Attribute::NoFPClass)) {
+ SDNodeFlags InValFlags = InVals[i]->getFlags();
+ InValFlags.setNonNeg(Arg.getNoFPClass() & llvm::fcNegative);
+ InValFlags.setNoNaNs(Arg.getNoFPClass() & llvm::fcNan);
+ InValFlags.setNoInfs(Arg.getNoFPClass() & llvm::fcInf);
+ InValFlags.setNoSignedZeros(Arg.getNoFPClass() & llvm::fcNegZero);
+ InVals[i]->setFlags(InValFlags);
+ }
ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
PartVT, VT, nullptr, NewRoot,
diff --git a/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
index bc81966ca0f5c9..92cb05eee27ba7 100644
--- a/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=mipsisa32r6 < %s | FileCheck %s --check-prefix=MIPS32R6
+; RUN: llc --mtriple=mips64 < %s | FileCheck %s --check-prefix=MIPS64
declare float @llvm.maximumnum.f32(float, float)
declare double @llvm.maximumnum.f64(double, double)
@@ -13,6 +14,28 @@ define float @maximumnum_float(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_float:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
@@ -24,6 +47,20 @@ define float @maximumnum_float_nsz(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_float_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: c.ule.s $f12, $f0
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
@@ -33,10 +70,48 @@ define float @maximumnum_float_nnan(float %x, float %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_float_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
+define float @maximumnum_float_nnan_arg(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; MIPS32R6-LABEL: maximumnum_float_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_float_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
define double @maximumnum_double(double %x, double %y) {
; MIPS32R6-LABEL: maximumnum_double:
@@ -45,6 +120,28 @@ define double @maximumnum_double(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_double:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
@@ -56,6 +153,20 @@ define double @maximumnum_double_nsz(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_double_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: c.ule.d $f12, $f0
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
@@ -65,10 +176,49 @@ define double @maximumnum_double_nnan(double %x, double %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_double_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
+define double @maximumnum_double_nnan_arg(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; MIPS32R6-LABEL: maximumnum_double_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_double_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
define float @minimumnum_float(float %x, float %y) {
; MIPS32R6-LABEL: minimumnum_float:
; MIPS32R6: # %bb.0:
@@ -76,6 +226,31 @@ define float @minimumnum_float(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_float:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
@@ -87,6 +262,20 @@ define float @minimumnum_float_nsz(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_float_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: c.olt.s $f12, $f0
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
@@ -96,10 +285,56 @@ define float @minimumnum_float_nnan(float %x, float %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_float_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nnan_arg(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; MIPS32R6-LABEL: minimumnum_float_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_float_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
+
define double @minimumnum_double(double %x, double %y) {
; MIPS32R6-LABEL: minimumnum_double:
; MIPS32R6: # %bb.0:
@@ -107,6 +342,32 @@ define double @minimumnum_double(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_double:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: daddiu $2, $zero, 1
+; MIPS64-NEXT: dsll $2, $2, 63
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
@@ -118,6 +379,20 @@ define double @minimumnum_double_nsz(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_double_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: c.olt.d $f12, $f0
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
@@ -127,6 +402,53 @@ define double @minimumnum_double_nnan(double %x, double %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_double_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: daddiu $1, $zero, 1
+; MIPS64-NEXT: dsll $1, $1, 63
+; MIPS64-NEXT: dmfc1 $2, $f12
+; MIPS64-NEXT: xor $2, $2, $1
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $2
+; MIPS64-NEXT: dmfc1 $2, $f13
+; MIPS64-NEXT: xor $1, $2, $1
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nnan_arg(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; MIPS32R6-LABEL: minimumnum_double_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_double_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: daddiu $1, $zero, 1
+; MIPS64-NEXT: dsll $1, $1, 63
+; MIPS64-NEXT: dmfc1 $2, $f12
+; MIPS64-NEXT: xor $2, $2, $1
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $2
+; MIPS64-NEXT: dmfc1 $2, $f13
+; MIPS64-NEXT: xor $1, $2, $1
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
|
ret float %z | ||
} | ||
|
||
define float @minimumnum_float_nnan_arg(float nofpclass(nan) %x, float nofpclass(nan) %y) { |
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.
These tests won't cover the inf case. You also should test the separate nofpclass(qnan) and nofpclass(snan) cases, which individually are not strong enough to set the corresponding flag
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.
do you have any idea about cases for inf
?
I cannot find one, and we have no isKnownNeverInf()
at all.
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.
The FP tracking code in SelectionDAG is quite poor, and it's a lot of effort to reimplement computeKnownFPClass in SDAG/GlobalISel. We only have stub implementations of isKnownNeverZeroFloat, isKnownNeverNaN, and cannotBeOrderedNegativeFP
; MIPS64-NEXT: c.eq.s $f0, $f2 | ||
; MIPS64-NEXT: jr $ra | ||
; MIPS64-NEXT: movt.s $f0, $f1, $fcc0 | ||
%z = call nnan float @llvm.minimumnum.f32(float %x, float %y) |
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'd prefer to test these with some simpler to understand operation than minimumnum. Is there some other fold that doesn't involve any flavor of fmin?
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 can only find there is only one about FP_TO_BF16.
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.
The fcmp + select to min variant would be more straightforward
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 have a try fcmp + select
with this IR
define dso_local noundef float @max(float noundef nofpclass(nan) %a, float noundef nofpclass(nan) %b) local_unnamed_addr #0 {
entry:
%cmp = fcmp ogt float %a, %b
%cond = select i1 %cmp, float %a, float %b
ret float %cond
}
It is not easy to support it. The problem is that the argument of void SelectionDAGBuilder::visitSelect(const User &I)
is marked as const
, so we have no chance to edit I
if we detect the both LHS
and RHS
are nnan
.
And then visitSelect
calls
SelectPatternResult llvm::matchDecomposedSelectPattern(
CmpInst *CmpI, Value *TrueVal, Value *FalseVal, Value *&LHS, Value *&RHS,
Instruction::CastOps *CastOp, unsigned Depth)
It may be not a good idea to use the methods from SelectionDAG there.
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.
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.
You can use other incoming instructions with nnan flags, this PR is not necessary for test coverage
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.
You can use other incoming instructions with nnan flags, this PR is not necessary for test coverage
ISD::SELECT seems ignoring nnan
.
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.
Means there's a flag dropped or SelectionDAG never learned about select flags. Try something like an fadd? Probably a bug somewhere
c77589f
to
314ccab
Compare
Currently SelectionDAG ignroes the nofpclass information from arguments. Such as define dso_local float @f(float noundef nofpclass(nan zero) %a, float noundef nofpclass(nan zero) %b) #0 { entry: %cond = tail call float @llvm.maximumnum.f32(float %a, float %b) ret float %cond } In SelectionDAG::isKnownNeverNaN, a false is returned. TODO: 1) bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth) needs to process hasNoSNaN; 2) bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op) needs to process Zero and SignedZero. These 2 problems will be fixed with other PRs.
314ccab
to
4566628
Compare
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 think the way to handle this in general is introduce an AssertNoFPClass, similar to AssertZext etc.
Replaced by: #130051 |
Currently SelectionDAG ignroes the nofpclass information from arguments. Such as
define dso_local float @f(float noundef nofpclass(nan zero) %a, float noundef nofpclass(nan zero) %b) #0 {
entry:
%cond = tail call float @llvm.maximumnum.f32(float %a, float %b)
ret float %cond
}
In SelectionDAG::isKnownNeverNaN, a false is returned.
TODO: