[llvm] [InstSimplify] Fold fsub X, X using known non-NaN/non-Inf facts (PR #200782)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 1 03:53:35 PDT 2026


https://github.com/AnkitDubeycs25 created https://github.com/llvm/llvm-project/pull/200782

InstSimplify currently folds 'fsub nnan X, X' to 0.0, but does not perform the same simplification when ValueTracking can already prove that the operand is neither NaN nor Inf.

Extend the self-subtraction fold to use isKnownNeverInfOrNaN(), allowing InstSimplify to exploit facts derived from computeKnownFPClass, such as nofpclass(nan inf).

Add a regression test covering the missed optimization.

>From c4a34dfa77e950329d99899b8e1202e1a09aa17d Mon Sep 17 00:00:00 2001
From: AnkitDubeycs25 <cs25mtech12001 at iith.ac.in>
Date: Mon, 1 Jun 2026 16:03:26 +0530
Subject: [PATCH] [InstSimplify] Fold fsub X, X using known non-NaN/non-Inf
 facts

InstSimplify currently folds 'fsub nnan X, X' to 0.0, but does not
perform the same simplification when ValueTracking can already prove
that the operand is neither NaN nor Inf.

Extend the self-subtraction fold to use isKnownNeverInfOrNaN(),
allowing InstSimplify to exploit facts derived from
computeKnownFPClass, such as nofpclass(nan inf).

Add a regression test covering the missed optimization.
---
 llvm/lib/Analysis/InstructionSimplify.cpp     | 10 ++++----
 .../InstSimplify/fsub-selfsub-nofpclass.ll    | 23 +++++++++++++++++++
 2 files changed, 29 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/Transforms/InstSimplify/fsub-selfsub-nofpclass.ll

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 59a213b47825a..1bd32ff285830 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -5938,11 +5938,13 @@ simplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
   if (!isDefaultFPEnvironment(ExBehavior, Rounding))
     return nullptr;
 
-  if (FMF.noNaNs()) {
-    // fsub nnan x, x ==> 0.0
-    if (Op0 == Op1)
-      return Constant::getNullValue(Op0->getType());
+  // fsub nnan x, x ==> 0.0
+  // fsub x, x ==> 0.0 if x is known never Inf or NaN
+  if (Op0 == Op1 &&
+      (FMF.noNaNs() || isKnownNeverInfOrNaN(Op0, Q)))
+    return Constant::getNullValue(Op0->getType());
 
+  if (FMF.noNaNs()) {
     // With nnan: {+/-}Inf - X --> {+/-}Inf
     if (match(Op0, m_Inf()))
       return Op0;
diff --git a/llvm/test/Transforms/InstSimplify/fsub-selfsub-nofpclass.ll b/llvm/test/Transforms/InstSimplify/fsub-selfsub-nofpclass.ll
new file mode 100644
index 0000000000000..8c192a734f258
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/fsub-selfsub-nofpclass.ll
@@ -0,0 +1,23 @@
+; RUN: opt -S -passes=instcombine %s -o - | FileCheck %s
+
+declare double @llvm.fmuladd.f64(double, double, double)
+
+define double @missed_selfsub_consumer(
+    float nofpclass(nan inf) %x,
+    double %scale,
+    double %acc) {
+entry:
+  %d = fsub float %x, %x
+  %de = fpext float %d to double
+  %mul = fmul double %scale, %de
+  %fma = call double @llvm.fmuladd.f64(
+      double %mul,
+      double %de,
+      double %acc)
+  ret double %fma
+}
+
+; CHECK-LABEL: @missed_selfsub_consumer(
+; CHECK-NOT: fsub
+; CHECK-NOT: fpext
+; CHECK: fmul double %scale, 0.000000e+00
\ No newline at end of file



More information about the llvm-commits mailing list