[llvm] [instcombine][x86]: simplifyx86fpmaxmin - allow negzero for single operand (PR #180418)

Madhur Kumar via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 10 05:35:53 PST 2026


https://github.com/MadhurKumar004 updated https://github.com/llvm/llvm-project/pull/180418

>From c6067764b8d2848a75001785f2b54d20ee958ed6 Mon Sep 17 00:00:00 2001
From: Madhur Kumar <madhurkumar004 at gmail.com>
Date: Sun, 8 Feb 2026 21:15:18 +0530
Subject: [PATCH] [instcombine][x86]: simplifyx86fpmaxmin - allow negzero for
 single operand

---
 .../Target/X86/X86InstCombineIntrinsic.cpp    | 19 +++++--
 .../InstCombine/X86/x86-fp-minmax-negzero.ll  | 57 +++++++++++++++++++
 2 files changed, 70 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/X86/x86-fp-minmax-negzero.ll

diff --git a/llvm/lib/Target/X86/X86InstCombineIntrinsic.cpp b/llvm/lib/Target/X86/X86InstCombineIntrinsic.cpp
index d46dbf178bcff..dd9fbdff0bafb 100644
--- a/llvm/lib/Target/X86/X86InstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/X86/X86InstCombineIntrinsic.cpp
@@ -1745,15 +1745,22 @@ static Value *simplifyX86FPMaxMin(const IntrinsicInst &II, InstCombiner &IC,
   APInt DemandedElts =
       IsScalar ? APInt::getOneBitSet(VWidth, 0) : APInt::getAllOnes(VWidth);
 
-  // Verify that the inputs are not one of (NaN, Inf, Subnormal, NegZero),
-  // otherwise we cannot safely generalize to MAXNUM/MINNUM.
-  FPClassTest Forbidden = fcNan | fcInf | fcSubnormal | fcNegZero;
+  FPClassTest Forbidden0 = fcNan | fcInf | fcSubnormal;
+  FPClassTest Forbidden1 = fcNan | fcInf | fcSubnormal;
+  if (NewIID == Intrinsic::maxnum) {
+    // For maxnum, only forbid NegZero in the second operand.
+    Forbidden1 |= fcNegZero;
+  } else if (NewIID == Intrinsic::minnum) {
+    // For minnum, only forbid NegZero in the first operand.
+    Forbidden0 |= fcNegZero;
+  }
   KnownFPClass KnownArg0 =
-      computeKnownFPClass(Arg0, DemandedElts, Forbidden, SQ);
+      computeKnownFPClass(Arg0, DemandedElts, Forbidden0, SQ);
   KnownFPClass KnownArg1 =
-      computeKnownFPClass(Arg1, DemandedElts, Forbidden, SQ);
+      computeKnownFPClass(Arg1, DemandedElts, Forbidden1, SQ);
 
-  if (KnownArg0.isKnownNever(Forbidden) && KnownArg1.isKnownNever(Forbidden)) {
+  if (KnownArg0.isKnownNever(Forbidden0) &&
+      KnownArg1.isKnownNever(Forbidden1)) {
     if (IsScalar) {
       // It performs the operation on the first element and puts it back into
       // the vector.
diff --git a/llvm/test/Transforms/InstCombine/X86/x86-fp-minmax-negzero.ll b/llvm/test/Transforms/InstCombine/X86/x86-fp-minmax-negzero.ll
new file mode 100644
index 0000000000000..4fbb47355db3f
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/X86/x86-fp-minmax-negzero.ll
@@ -0,0 +1,57 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=instcombine -mtriple=x86_64-unknown-unknown < %s -S | FileCheck %s
+
+; Test relaxed negzero handling for X86 max/min intrinsics.
+
+declare <4 x float> @llvm.x86.sse.max.ps(<4 x float>, <4 x float>)
+declare <4 x float> @llvm.x86.sse.min.ps(<4 x float>, <4 x float>)
+
+; For maxnum, allow -0.0 in the first operand only.
+
+define <4 x float> @test_max_allow_negzero_first() {
+; CHECK-LABEL: define <4 x float> @test_max_allow_negzero_first() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret <4 x float> splat (float 1.000000e+00)
+;
+entry:
+  %r = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> <float -0.0, float -0.0, float -0.0, float -0.0>, <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>)
+  ret <4 x float> %r
+}
+
+; For minnum, allow -0.0 in the second operand only.
+
+define <4 x float> @test_min_allow_negzero_second() {
+; CHECK-LABEL: define <4 x float> @test_min_allow_negzero_second() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret <4 x float> splat (float -0.000000e+00)
+;
+entry:
+  %r = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, <4 x float> <float -0.0, float -0.0, float -0.0, float -0.0>)
+  ret <4 x float> %r
+}
+
+; Negative test: max should not fold when -0.0 is in the second operand.
+
+define <4 x float> @test_max_disallow_negzero_second() {
+; CHECK-LABEL: define <4 x float> @test_max_disallow_negzero_second() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[R:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> splat (float 1.000000e+00), <4 x float> splat (float -0.000000e+00))
+; CHECK-NEXT:    ret <4 x float> [[R]]
+;
+entry:
+  %r = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, <4 x float> <float -0.0, float -0.0, float -0.0, float -0.0>)
+  ret <4 x float> %r
+}
+
+; Negative test: min should not fold when -0.0 is in the first operand.
+
+define <4 x float> @test_min_disallow_negzero_first() {
+; CHECK-LABEL: define <4 x float> @test_min_disallow_negzero_first() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[R:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> splat (float -0.000000e+00), <4 x float> splat (float 1.000000e+00))
+; CHECK-NEXT:    ret <4 x float> [[R]]
+;
+entry:
+  %r = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> <float -0.0, float -0.0, float -0.0, float -0.0>, <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>)
+  ret <4 x float> %r
+}



More information about the llvm-commits mailing list