@@ -7531,11 +7531,7 @@ MONO_RESTORE_WARNING
75317531 case OP_IMIN_UN:
75327532 case OP_LMIN_UN:
75337533 case OP_IMAX_UN:
7534- case OP_LMAX_UN:
7535- case OP_FMIN:
7536- case OP_FMAX:
7537- case OP_RMIN:
7538- case OP_RMAX: {
7534+ case OP_LMAX_UN: {
75397535 LLVMValueRef v;
75407536
75417537 lhs = convert (ctx, lhs, regtype_to_llvm_type (spec [MONO_INST_DEST]));
@@ -7558,14 +7554,6 @@ MONO_RESTORE_WARNING
75587554 case OP_LMAX_UN:
75597555 v = LLVMBuildICmp (builder, LLVMIntUGE, lhs, rhs, "");
75607556 break;
7561- case OP_FMAX:
7562- case OP_RMAX:
7563- v = LLVMBuildFCmp (builder, LLVMRealUGE, lhs, rhs, "");
7564- break;
7565- case OP_FMIN:
7566- case OP_RMIN:
7567- v = LLVMBuildFCmp (builder, LLVMRealULE, lhs, rhs, "");
7568- break;
75697557 default:
75707558 g_assert_not_reached ();
75717559 break;
@@ -7574,6 +7562,33 @@ MONO_RESTORE_WARNING
75747562 break;
75757563 }
75767564
7565+ case OP_FMIN:
7566+ case OP_FMAX:
7567+ case OP_RMIN:
7568+ case OP_RMAX: {
7569+ /*
7570+ * Use llvm.minimum/maximum (IEEE 754-2019, NaN-propagating) so the
7571+ * Math.Min/Math.Max semantics ("if either argument is NaN, NaN is
7572+ * returned"), as forwarded by MathF.Min/MathF.Max, are honored
7573+ * symmetrically. The old fcmp+select lowering was both asymmetric for
7574+ * NaN and got folded into AArch64 fminnm/fmaxnm by the backend, which
7575+ * discards NaN entirely. See llvm-intrinsics.h.
7576+ */
7577+ gboolean is_r4 = ins->opcode == OP_RMIN || ins->opcode == OP_RMAX;
7578+ LLVMTypeRef t = is_r4 ? LLVMFloatType () : LLVMDoubleType ();
7579+ LLVMValueRef args [2] = { convert (ctx, lhs, t), convert (ctx, rhs, t) };
7580+ IntrinsicId iid;
7581+ switch (ins->opcode) {
7582+ case OP_FMAX: iid = INTRINS_MAXIMUM; break;
7583+ case OP_FMIN: iid = INTRINS_MINIMUM; break;
7584+ case OP_RMAX: iid = INTRINS_MAXIMUMF; break;
7585+ case OP_RMIN: iid = INTRINS_MINIMUMF; break;
7586+ default: g_assert_not_reached (); break;
7587+ }
7588+ values [ins->dreg] = call_intrins (ctx, iid, args, dname);
7589+ break;
7590+ }
7591+
75777592/*
75787593 * See the ARM64 comment in mono/utils/atomic.h for an explanation of why this
75797594 * hack is necessary (for now).
0 commit comments