[llvm] Reapply "[ValueTracking] Propagate sign information out of loop" (PR #182512)

Kshitij Paranjape via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 20 08:10:22 PST 2026


https://github.com/kshitijvp updated https://github.com/llvm/llvm-project/pull/182512

>From 4dc56348a911c69a6959b614b18617e3d2e5b9b8 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Mon, 12 Jan 2026 22:20:27 +0530
Subject: [PATCH 01/30] [AggressiveInstCombine] Propogate sign information out
 of loop

LLVM converts sqrt libcall to intrinsic call if the argument
is within the range(greater than or equal to 0.0). In this case
the compiler is not able to deduce the non-negativity on
its own. Extended ValueTracking to understand such loops.

Fixes llvm/llvm-project#174813
---
 llvm/lib/Analysis/ValueTracking.cpp           | 20 +++++++-
 .../libcalltointrinsic.ll                     | 48 +++++++++++++++++++
 2 files changed, 67 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8761b7bcb51a2..d132fe40d6aca 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5884,7 +5884,25 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     // Unreachable blocks may have zero-operand PHI nodes.
     if (P->getNumIncomingValues() == 0)
       break;
-
+    // Look for the case of a for loop which has a positive
+    // initial value and is incremented by a squared value.
+    // This will propogate sign information out of such loops.
+    if (P->getNumIncomingValues() == 2) {
+      Value *Start = P->getIncomingValue(0);
+      Value *RecurValue = P->getIncomingValue(1);
+      Value *X;
+      if (match(RecurValue,
+                m_Intrinsic<Intrinsic::fmuladd>(m_Value(X), m_Value(X), m_Specific(P)))) {
+        KnownFPClass KnownStart;
+        computeKnownFPClass(Start, DemandedElts,
+                            KnownFPClass::OrderedLessThanZeroMask, KnownStart,
+                            Q, Depth + 1);
+        if (KnownStart.cannotBeOrderedLessThanZero()) {
+          Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+        }
+        break;
+      }
+    }
     // Otherwise take the unions of the known bit sets of the operands,
     // taking conservative care to avoid excessive recursion.
     const unsigned PhiRecursionLimit = MaxAnalysisRecursionDepth - 2;
diff --git a/llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll b/llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll
new file mode 100644
index 0000000000000..a734abb6727e3
--- /dev/null
+++ b/llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define dso_local noundef double @CompareDistmats(ptr noundef %distmat1, ptr noundef %distmat2) local_unnamed_addr {
+; CHECK-LABEL: @CompareDistmats(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[TMP2:%.*]], [[FOR_BODY:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, [[ENTRY]] ], [ false, [[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
+; CHECK:       for.cond.cleanup:
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]])
+; CHECK-NEXT:    ret double [[SQRT]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr [[DISTMAT1:%.*]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = load double, ptr [[DISTMAT2:%.*]], align 8
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[TMP2]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
+; CHECK-NEXT:    br label [[FOR_COND]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %2, %for.body ]
+  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %call = call double @sqrt(double noundef %RMSD.0)
+  ret double %call
+
+for.body:                                         ; preds = %for.cond
+  %0 = load double, ptr %distmat1, align 8
+  %1 = load double, ptr %distmat2, align 8
+  %sub = fsub double %0, %1
+  %2 = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
+  br label %for.cond
+}
+
+; Function Attrs: mustprogress nofree nounwind willreturn memory(write)
+declare double @sqrt(double noundef) local_unnamed_addr
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare double @llvm.fmuladd.f64(double, double, double)

>From c9158d5b72e448ec184b329f0a9e4c5c79f98774 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 00:33:51 +0530
Subject: [PATCH 02/30] Added simple recurrence pattern matcher for ternary
 intrinsics

Added functions to match simple recurrence patterns in case
of ternary intrinsics as it was supported only for binary
intrinsics currently. Used the matchSimpleTernaryRecurrence
to match the specific case of for loop in which initial value
is zero and is being incremented by a squared-value. Shifted
the tests to X86 subdirectory and also added negative test
in the case when it is not being incremented by a
squared-value.
---
 llvm/include/llvm/Analysis/ValueTracking.h    |  4 +
 llvm/lib/Analysis/ValueTracking.cpp           | 84 +++++++++++++++----
 .../AggressiveInstCombine/X86/pr175590.ll     | 45 ++++++++++
 .../libcalltointrinsic.ll                     | 48 -----------
 4 files changed, 119 insertions(+), 62 deletions(-)
 create mode 100644 llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
 delete mode 100644 llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 1cd88fd89aea2..eae9b4af93e5c 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -1011,6 +1011,10 @@ LLVM_ABI bool matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I,
 ///  T | T | F
 ///  F | T | T
 /// (A)
+LLVM_ABI bool matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I,
+                                                    PHINode *&P, Value *&Init,
+                                                    Value *&OtherOp0,
+                                                    Value *&OtherOp1);
 LLVM_ABI std::optional<bool>
 isImpliedCondition(const Value *LHS, const Value *RHS, const DataLayout &DL,
                    bool LHSIsTrue = true, unsigned Depth = 0);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index d132fe40d6aca..e811540780a08 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1785,7 +1785,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
     const PHINode *P = cast<PHINode>(I);
     BinaryOperator *BO = nullptr;
     Value *R = nullptr, *L = nullptr;
-    if (matchSimpleRecurrence(P, BO, R, L)) {
+    if (llvm::matchSimpleRecurrence(P, BO, R, L)) {
       // Handle the case of a simple two-predecessor recurrence PHI.
       // There's a lot more that could theoretically be done here, but
       // this is sufficient to catch some interesting cases.
@@ -5886,21 +5886,26 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       break;
     // Look for the case of a for loop which has a positive
     // initial value and is incremented by a squared value.
-    // This will propogate sign information out of such loops.
+    // This will propagate sign information out of such loops.
     if (P->getNumIncomingValues() == 2) {
-      Value *Start = P->getIncomingValue(0);
       Value *RecurValue = P->getIncomingValue(1);
-      Value *X;
-      if (match(RecurValue,
-                m_Intrinsic<Intrinsic::fmuladd>(m_Value(X), m_Value(X), m_Specific(P)))) {
-        KnownFPClass KnownStart;
-        computeKnownFPClass(Start, DemandedElts,
-                            KnownFPClass::OrderedLessThanZeroMask, KnownStart,
-                            Q, Depth + 1);
-        if (KnownStart.cannotBeOrderedLessThanZero()) {
-          Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+      IntrinsicInst* I = dyn_cast<IntrinsicInst>(RecurValue);
+      Value *R, *L;
+      Value *Init;
+      PHINode *PN;
+      if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
+        switch(I->getIntrinsicID()) {
+        case Intrinsic::fmuladd: {
+          KnownFPClass KnownStart;
+          computeKnownFPClass(Init, DemandedElts, 
+                              KnownFPClass::OrderedGreaterThanZeroMask, KnownStart,
+                              Q, Depth + 1 );
+          if (KnownStart.cannotBeOrderedLessThanZero() && R == L) {
+            Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+          }
+          break;
+        }
         }
-        break;
       }
     }
     // Otherwise take the unions of the known bit sets of the operands,
@@ -9266,6 +9271,40 @@ static bool matchTwoInputRecurrence(const PHINode *PN, InstTy *&Inst,
   return false;
 }
 
+template <typename InstTy>
+static bool matchThreeInputRecurrence(const PHINode *PN, InstTy *&Inst,
+                                      Value *&Init, Value *&OtherOp0,
+                                      Value *&OtherOp1) {
+  if (PN->getNumIncomingValues() != 2)
+    return false;
+  
+  for (unsigned I = 0; I != 3; ++I) {
+    if (auto *Operation = dyn_cast<InstTy>(PN->getIncomingValue(I));
+        Operation) {
+      Value *Op0 = Operation->getOperand(0);
+      Value *Op1 = Operation->getOperand(1);
+      Value *Op2 = Operation->getOperand(2);
+
+      if (Op0 != PN && Op1 != PN && Op2 != PN)
+        continue;
+
+      Inst = Operation;
+      Init = PN->getIncomingValue(!I);
+      if (Op0 == PN) {
+        OtherOp0 = Op1;
+        OtherOp1 = Op2;
+      } else if (Op1 == PN) {
+        OtherOp0 = Op0;
+        OtherOp1 = Op2;
+      } else {
+        OtherOp0 = Op0;
+        OtherOp1 = Op1;
+      }
+      return true;
+    }
+  }
+  return false;
+}
 bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
                                  Value *&Start, Value *&Step) {
   // We try to match a recurrence of the form:
@@ -9302,6 +9341,23 @@ bool llvm::matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I,
   return P && matchTwoInputRecurrence(P, II, Init, OtherOp) && II == I;
 }
 
+bool llvm::matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I,
+                                                  PHINode *&P, Value *&Init,
+                                                  Value *&OtherOp0, Value*&OtherOp1) {
+  if (I->arg_size() != 3 || I->getType() != I->getArgOperand(0)->getType() ||
+      I->getType() != I->getArgOperand(1)->getType() ||
+      I->getType() != I->getArgOperand(2)->getType())
+    return false;
+  IntrinsicInst *II = nullptr;
+  P = dyn_cast<PHINode>(I->getArgOperand(0));
+  if (!P) {
+    P = dyn_cast<PHINode>(I->getArgOperand(1));
+    if (!P)
+      P = dyn_cast<PHINode>(I->getArgOperand(2));
+  }
+  return P && matchThreeInputRecurrence(P, II, Init, OtherOp0, OtherOp1) && II == I;
+}
+
 /// Return true if "icmp Pred LHS RHS" is always true.
 static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
                             const Value *RHS) {
@@ -10538,4 +10594,4 @@ bool llvm::collectPossibleValues(const Value *V,
     }
   }
   return true;
-}
+}
\ No newline at end of file
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
new file mode 100644
index 0000000000000..c504762af8cae
--- /dev/null
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+define dso_local noundef double @CompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
+; CHECK-LABEL: define dso_local noundef double @CompareDistmats(
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double 0.000000e+00)
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[TMP0]])
+; CHECK-NEXT:    ret double [[SQRT]]
+;
+entry:
+  %sub = fsub double %distmat1_, %distmat2_
+  %fmacall = tail call double @llvm.fmuladd.f64(double %sub, double %sub, double 0.000000e+00)
+  %call = tail call double @sqrt(double noundef %fmacall) #3
+  ret double %call
+}
+
+define dso_local noundef double @nonSquareCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
+; CHECK-LABEL: define dso_local noundef double @nonSquareCompareDistmats(
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[ADD:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[FMACALL:%.*]] = tail call double @llvm.fmuladd.f64(double [[SUB]], double [[ADD]], double 0.000000e+00)
+; CHECK-NEXT:    [[CALL:%.*]] = tail call double @sqrt(double noundef [[FMACALL]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT:    ret double [[CALL]]
+;
+entry:
+  %sub = fsub double %distmat1_, %distmat2_
+  %add = fsub double %distmat1_, %distmat2_
+  %fmacall = tail call double @llvm.fmuladd.f64(double %sub, double %add, double 0.000000e+00)
+  %call = tail call double @sqrt(double noundef %fmacall) #3
+  ret double %call
+}
+
+declare double @llvm.fmuladd.f64(double, double, double) #1
+
+declare double @sqrt(double noundef) local_unnamed_addr #2
+
+attributes #0 = { mustprogress nofree norecurse nounwind willreturn memory(errnomem: write) uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="znver3" "target-features"="+adx,+aes,+avx,+avx2,+bmi,+bmi2,+clflushopt,+clwb,+clzero,+crc32,+cx16,+cx8,+f16c,+fma,+fsgsbase,+fxsr,+invpcid,+lzcnt,+mmx,+movbe,+mwaitx,+pclmul,+pku,+popcnt,+prfchw,+rdpid,+rdpru,+rdrnd,+rdseed,+sahf,+sha,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+sse4a,+ssse3,+vaes,+vpclmulqdq,+wbnoinvd,+x87,+xsave,+xsavec,+xsaveopt,+xsaves" }
+attributes #1 = { mustprogress nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
+attributes #2 = { mustprogress nocallback nofree nounwind willreturn memory(errnomem: write) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="znver3" "target-features"="+adx,+aes,+avx,+avx2,+bmi,+bmi2,+clflushopt,+clwb,+clzero,+crc32,+cx16,+cx8,+f16c,+fma,+fsgsbase,+fxsr,+invpcid,+lzcnt,+mmx,+movbe,+mwaitx,+pclmul,+pku,+popcnt,+prfchw,+rdpid,+rdpru,+rdrnd,+rdseed,+sahf,+sha,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+sse4a,+ssse3,+vaes,+vpclmulqdq,+wbnoinvd,+x87,+xsave,+xsavec,+xsaveopt,+xsaves" }
+attributes #3 = { nounwind }
diff --git a/llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll b/llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll
deleted file mode 100644
index a734abb6727e3..0000000000000
--- a/llvm/test/Transforms/AggressiveInstCombine/libcalltointrinsic.ll
+++ /dev/null
@@ -1,48 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define dso_local noundef double @CompareDistmats(ptr noundef %distmat1, ptr noundef %distmat2) local_unnamed_addr {
-; CHECK-LABEL: @CompareDistmats(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[FOR_COND:%.*]]
-; CHECK:       for.cond:
-; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[TMP2:%.*]], [[FOR_BODY:%.*]] ]
-; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, [[ENTRY]] ], [ false, [[FOR_BODY]] ]
-; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
-; CHECK:       for.cond.cleanup:
-; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]])
-; CHECK-NEXT:    ret double [[SQRT]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr [[DISTMAT1:%.*]], align 8
-; CHECK-NEXT:    [[TMP1:%.*]] = load double, ptr [[DISTMAT2:%.*]], align 8
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[TMP2]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
-; CHECK-NEXT:    br label [[FOR_COND]]
-;
-entry:
-  br label %for.cond
-
-for.cond:                                         ; preds = %for.body, %entry
-  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %2, %for.body ]
-  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
-  br i1 %cmp, label %for.body, label %for.cond.cleanup
-
-for.cond.cleanup:                                 ; preds = %for.cond
-  %call = call double @sqrt(double noundef %RMSD.0)
-  ret double %call
-
-for.body:                                         ; preds = %for.cond
-  %0 = load double, ptr %distmat1, align 8
-  %1 = load double, ptr %distmat2, align 8
-  %sub = fsub double %0, %1
-  %2 = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
-  br label %for.cond
-}
-
-; Function Attrs: mustprogress nofree nounwind willreturn memory(write)
-declare double @sqrt(double noundef) local_unnamed_addr
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
-declare double @llvm.fmuladd.f64(double, double, double)

>From 495c2d1fb4d77333e15bca57d236eac0788f27e9 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 02:01:15 +0530
Subject: [PATCH 03/30] Check for null value after dyn_cast

---
 llvm/lib/Analysis/ValueTracking.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index e811540780a08..29a8dab2d6dfe 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5890,6 +5890,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     if (P->getNumIncomingValues() == 2) {
       Value *RecurValue = P->getIncomingValue(1);
       IntrinsicInst* I = dyn_cast<IntrinsicInst>(RecurValue);
+      if (!I)
+        break;
       Value *R, *L;
       Value *Init;
       PHINode *PN;

>From 0ae8e5b2a3194ce85400611cd4759277902ca6e0 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 12:16:09 +0530
Subject: [PATCH 04/30] Made necessary changes

---
 llvm/include/llvm/Analysis/ValueTracking.h    |  9 ++--
 llvm/lib/Analysis/ValueTracking.cpp           | 53 +++++++++----------
 .../AggressiveInstCombine/X86/pr175590.ll     |  8 +--
 3 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index eae9b4af93e5c..89819ae4777fe 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -1001,6 +1001,11 @@ LLVM_ABI bool matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I,
                                                    PHINode *&P, Value *&Init,
                                                    Value *&OtherOp);
 
+LLVM_ABI bool matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I,
+                                                    PHINode *&P, Value *&Init,
+                                                    Value *&OtherOp0,
+                                                    Value *&OtherOp1);
+
 /// Return true if RHS is known to be implied true by LHS.  Return false if
 /// RHS is known to be implied false by LHS.  Otherwise, return std::nullopt if
 /// no implication can be made. A & B must be i1 (boolean) values or a vector of
@@ -1011,10 +1016,6 @@ LLVM_ABI bool matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I,
 ///  T | T | F
 ///  F | T | T
 /// (A)
-LLVM_ABI bool matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I,
-                                                    PHINode *&P, Value *&Init,
-                                                    Value *&OtherOp0,
-                                                    Value *&OtherOp1);
 LLVM_ABI std::optional<bool>
 isImpliedCondition(const Value *LHS, const Value *RHS, const DataLayout &DL,
                    bool LHSIsTrue = true, unsigned Depth = 0);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 29a8dab2d6dfe..825b89060fb36 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1785,7 +1785,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
     const PHINode *P = cast<PHINode>(I);
     BinaryOperator *BO = nullptr;
     Value *R = nullptr, *L = nullptr;
-    if (llvm::matchSimpleRecurrence(P, BO, R, L)) {
+    if (matchSimpleRecurrence(P, BO, R, L)) {
       // Handle the case of a simple two-predecessor recurrence PHI.
       // There's a lot more that could theoretically be done here, but
       // this is sufficient to catch some interesting cases.
@@ -5884,32 +5884,6 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     // Unreachable blocks may have zero-operand PHI nodes.
     if (P->getNumIncomingValues() == 0)
       break;
-    // Look for the case of a for loop which has a positive
-    // initial value and is incremented by a squared value.
-    // This will propagate sign information out of such loops.
-    if (P->getNumIncomingValues() == 2) {
-      Value *RecurValue = P->getIncomingValue(1);
-      IntrinsicInst* I = dyn_cast<IntrinsicInst>(RecurValue);
-      if (!I)
-        break;
-      Value *R, *L;
-      Value *Init;
-      PHINode *PN;
-      if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
-        switch(I->getIntrinsicID()) {
-        case Intrinsic::fmuladd: {
-          KnownFPClass KnownStart;
-          computeKnownFPClass(Init, DemandedElts, 
-                              KnownFPClass::OrderedGreaterThanZeroMask, KnownStart,
-                              Q, Depth + 1 );
-          if (KnownStart.cannotBeOrderedLessThanZero() && R == L) {
-            Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
-          }
-          break;
-        }
-        }
-      }
-    }
     // Otherwise take the unions of the known bit sets of the operands,
     // taking conservative care to avoid excessive recursion.
     const unsigned PhiRecursionLimit = MaxAnalysisRecursionDepth - 2;
@@ -5949,6 +5923,31 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       }
     }
 
+    // Look for the case of a for loop which has a positive
+    // initial value and is incremented by a squared value.
+    // This will propagate sign information out of such loops.
+    if (P->getNumIncomingValues() == 2) {
+      Value *RecurValue = P->getIncomingValue(1);
+      IntrinsicInst *I = dyn_cast<IntrinsicInst>(RecurValue);
+      if (!I)
+        break;
+      Value *R, *L;
+      Value *Init;
+      PHINode *PN;
+      if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
+        switch (I->getIntrinsicID()) {
+        case Intrinsic::fmuladd: {
+          KnownFPClass KnownStart;
+          computeKnownFPClass(Init, DemandedElts,
+                              KnownFPClass::OrderedGreaterThanZeroMask,
+                              KnownStart, Q, Depth + 1);
+          if (KnownStart.cannotBeOrderedLessThanZero() && L == R)
+            Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+          break;
+        }
+        }
+      }
+    }
     break;
   }
   case Instruction::BitCast: {
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index c504762af8cae..e0d8197e2d3ad 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
 target triple = "x86_64-unknown-linux-gnu"
-define dso_local noundef double @CompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
-; CHECK-LABEL: define dso_local noundef double @CompareDistmats(
+define double @CompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
+; CHECK-LABEL: define double @CompareDistmats(
 ; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
@@ -17,8 +17,8 @@ entry:
   ret double %call
 }
 
-define dso_local noundef double @nonSquareCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
-; CHECK-LABEL: define dso_local noundef double @nonSquareCompareDistmats(
+define double @nonSquareCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
+; CHECK-LABEL: define double @nonSquareCompareDistmats(
 ; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) local_unnamed_addr #[[ATTR0]] {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]

>From 561c3518bc53b69a8614492cc6b4b8fe09038e59 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 12:28:30 +0530
Subject: [PATCH 05/30] Modified Tests

---
 .../AggressiveInstCombine/X86/pr175590.ll     | 89 +++++++++++++------
 1 file changed, 61 insertions(+), 28 deletions(-)

diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index e0d8197e2d3ad..5eb3e44191389 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -1,45 +1,78 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
 target triple = "x86_64-unknown-linux-gnu"
-define double @CompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
+define double @CompareDistmats(double %distmat1_, double %distmat2_) {
 ; CHECK-LABEL: define double @CompareDistmats(
-; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double 0.000000e+00)
-; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[TMP0]])
+; CHECK-SAME: double [[DISTMAT1_:%.*]], double [[DISTMAT2_:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[TMP0:%.*]], %[[FOR_BODY:.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
+; CHECK:       [[FOR_COND_CLEANUP]]:
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]])
 ; CHECK-NEXT:    ret double [[SQRT]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[TMP0]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
+; CHECK-NEXT:    br label %[[FOR_COND]]
 ;
 entry:
-  %sub = fsub double %distmat1_, %distmat2_
-  %fmacall = tail call double @llvm.fmuladd.f64(double %sub, double %sub, double 0.000000e+00)
-  %call = tail call double @sqrt(double noundef %fmacall) #3
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %0, %for.body ]
+  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %call = call double @sqrt(double noundef %RMSD.0)
   ret double %call
+
+for.body:                                         ; preds = %for.cond
+  %sub = fsub double %distmat1_, %distmat2_
+  %0 = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
+  br label %for.cond
 }
 
-define double @nonSquareCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) local_unnamed_addr #0 {
+declare double @llvm.fmuladd.f64(double, double, double)
+
+declare double @sqrt(double noundef)
+
+define double @nonSquareCompareDistmats(double %distmat1_, double %distmat2_) {
 ; CHECK-LABEL: define double @nonSquareCompareDistmats(
-; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) local_unnamed_addr #[[ATTR0]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
-; CHECK-NEXT:    [[ADD:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
-; CHECK-NEXT:    [[FMACALL:%.*]] = tail call double @llvm.fmuladd.f64(double [[SUB]], double [[ADD]], double 0.000000e+00)
-; CHECK-NEXT:    [[CALL:%.*]] = tail call double @sqrt(double noundef [[FMACALL]]) #[[ATTR3:[0-9]+]]
+; CHECK-SAME: double [[DISTMAT1_:%.*]], double [[DISTMAT2_:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[TMP0:%.*]], %[[FOR_BODY:.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
+; CHECK:       [[FOR_COND_CLEANUP]]:
+; CHECK-NEXT:    [[CALL:%.*]] = call double @sqrt(double noundef [[RMSD_0]])
 ; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[TMP0]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[ADD]], double [[RMSD_0]])
+; CHECK-NEXT:    br label %[[FOR_COND]]
 ;
 entry:
-  %sub = fsub double %distmat1_, %distmat2_
-  %add = fsub double %distmat1_, %distmat2_
-  %fmacall = tail call double @llvm.fmuladd.f64(double %sub, double %add, double 0.000000e+00)
-  %call = tail call double @sqrt(double noundef %fmacall) #3
-  ret double %call
-}
+  br label %for.cond
 
-declare double @llvm.fmuladd.f64(double, double, double) #1
+for.cond:                                         ; preds = %for.body, %entry
+  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %0, %for.body ]
+  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
 
-declare double @sqrt(double noundef) local_unnamed_addr #2
+for.cond.cleanup:                                 ; preds = %for.cond
+  %call = call double @sqrt(double noundef %RMSD.0)
+  ret double %call
 
-attributes #0 = { mustprogress nofree norecurse nounwind willreturn memory(errnomem: write) uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="znver3" "target-features"="+adx,+aes,+avx,+avx2,+bmi,+bmi2,+clflushopt,+clwb,+clzero,+crc32,+cx16,+cx8,+f16c,+fma,+fsgsbase,+fxsr,+invpcid,+lzcnt,+mmx,+movbe,+mwaitx,+pclmul,+pku,+popcnt,+prfchw,+rdpid,+rdpru,+rdrnd,+rdseed,+sahf,+sha,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+sse4a,+ssse3,+vaes,+vpclmulqdq,+wbnoinvd,+x87,+xsave,+xsavec,+xsaveopt,+xsaves" }
-attributes #1 = { mustprogress nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
-attributes #2 = { mustprogress nocallback nofree nounwind willreturn memory(errnomem: write) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="znver3" "target-features"="+adx,+aes,+avx,+avx2,+bmi,+bmi2,+clflushopt,+clwb,+clzero,+crc32,+cx16,+cx8,+f16c,+fma,+fsgsbase,+fxsr,+invpcid,+lzcnt,+mmx,+movbe,+mwaitx,+pclmul,+pku,+popcnt,+prfchw,+rdpid,+rdpru,+rdrnd,+rdseed,+sahf,+sha,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+sse4a,+ssse3,+vaes,+vpclmulqdq,+wbnoinvd,+x87,+xsave,+xsavec,+xsaveopt,+xsaves" }
-attributes #3 = { nounwind }
+for.body:                                         ; preds = %for.cond
+  %sub = fsub double %distmat1_, %distmat2_
+  %add = fadd double %distmat1_, %distmat2_
+  %0 = call double @llvm.fmuladd.f64(double %sub, double %add, double %RMSD.0)
+  br label %for.cond
+}

>From dc0bce8c1a65d1e0b78ce35114136cd5b6151534 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 12:32:40 +0530
Subject: [PATCH 06/30] Used named values in test

---
 .../test/Transforms/AggressiveInstCombine/X86/pr175590.ll | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index 5eb3e44191389..a26f81c7ea622 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -22,7 +22,7 @@ entry:
   br label %for.cond
 
 for.cond:                                         ; preds = %for.body, %entry
-  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %0, %for.body ]
+  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %fmacall, %for.body ]
   %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
   br i1 %cmp, label %for.body, label %for.cond.cleanup
 
@@ -32,7 +32,7 @@ for.cond.cleanup:                                 ; preds = %for.cond
 
 for.body:                                         ; preds = %for.cond
   %sub = fsub double %distmat1_, %distmat2_
-  %0 = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
+  %fmacall = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
   br label %for.cond
 }
 
@@ -62,7 +62,7 @@ entry:
   br label %for.cond
 
 for.cond:                                         ; preds = %for.body, %entry
-  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %0, %for.body ]
+  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %fmacall, %for.body ]
   %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
   br i1 %cmp, label %for.body, label %for.cond.cleanup
 
@@ -73,6 +73,6 @@ for.cond.cleanup:                                 ; preds = %for.cond
 for.body:                                         ; preds = %for.cond
   %sub = fsub double %distmat1_, %distmat2_
   %add = fadd double %distmat1_, %distmat2_
-  %0 = call double @llvm.fmuladd.f64(double %sub, double %add, double %RMSD.0)
+  %fmacall = call double @llvm.fmuladd.f64(double %sub, double %add, double %RMSD.0)
   br label %for.cond
 }

>From 1328ceeb2ec085af4192b918878a19f2374beb28 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 12:42:16 +0530
Subject: [PATCH 07/30] Improved Code Formatting

---
 llvm/lib/Analysis/ValueTracking.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 825b89060fb36..95d4da908da48 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -9278,7 +9278,7 @@ static bool matchThreeInputRecurrence(const PHINode *PN, InstTy *&Inst,
                                       Value *&OtherOp1) {
   if (PN->getNumIncomingValues() != 2)
     return false;
-  
+
   for (unsigned I = 0; I != 3; ++I) {
     if (auto *Operation = dyn_cast<InstTy>(PN->getIncomingValue(I));
         Operation) {
@@ -9343,8 +9343,9 @@ bool llvm::matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I,
 }
 
 bool llvm::matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I,
-                                                  PHINode *&P, Value *&Init,
-                                                  Value *&OtherOp0, Value*&OtherOp1) {
+                                                 PHINode *&P, Value *&Init,
+                                                 Value *&OtherOp0,
+                                                 Value *&OtherOp1) {
   if (I->arg_size() != 3 || I->getType() != I->getArgOperand(0)->getType() ||
       I->getType() != I->getArgOperand(1)->getType() ||
       I->getType() != I->getArgOperand(2)->getType())
@@ -9356,7 +9357,8 @@ bool llvm::matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I,
     if (!P)
       P = dyn_cast<PHINode>(I->getArgOperand(2));
   }
-  return P && matchThreeInputRecurrence(P, II, Init, OtherOp0, OtherOp1) && II == I;
+  return P && matchThreeInputRecurrence(P, II, Init, OtherOp0, OtherOp1) &&
+         II == I;
 }
 
 /// Return true if "icmp Pred LHS RHS" is always true.

>From 15b3961dfc7c8678226bcd50ac180f1b0dc9209a Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 12:46:27 +0530
Subject: [PATCH 08/30] Nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 95d4da908da48..1967596d3ba2f 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5884,6 +5884,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     // Unreachable blocks may have zero-operand PHI nodes.
     if (P->getNumIncomingValues() == 0)
       break;
+
     // Otherwise take the unions of the known bit sets of the operands,
     // taking conservative care to avoid excessive recursion.
     const unsigned PhiRecursionLimit = MaxAnalysisRecursionDepth - 2;

>From 386ba10c76a42d4bb0e5f72ff2ba7d47367b3d34 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 12:48:23 +0530
Subject: [PATCH 09/30] Small Fix

---
 llvm/lib/Analysis/ValueTracking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1967596d3ba2f..5fc7317ada6ea 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -10598,4 +10598,4 @@ bool llvm::collectPossibleValues(const Value *V,
     }
   }
   return true;
-}
\ No newline at end of file
+}

>From 25d7326565e9ff76b7dd9928a72be8a1e6fa6017 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 13:23:14 +0530
Subject: [PATCH 10/30] Adding isGuaranteedNotUndef check

---
 llvm/lib/Analysis/ValueTracking.cpp                       | 2 +-
 .../test/Transforms/AggressiveInstCombine/X86/pr175590.ll | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5fc7317ada6ea..2979833e810c7 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5942,7 +5942,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           computeKnownFPClass(Init, DemandedElts,
                               KnownFPClass::OrderedGreaterThanZeroMask,
                               KnownStart, Q, Depth + 1);
-          if (KnownStart.cannotBeOrderedLessThanZero() && L == R)
+          if (KnownStart.cannotBeOrderedLessThanZero() && L == R && isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
             Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
           break;
         }
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index a26f81c7ea622..0bd25807f3b82 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -1,9 +1,9 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
 target triple = "x86_64-unknown-linux-gnu"
-define double @CompareDistmats(double %distmat1_, double %distmat2_) {
+define double @CompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
 ; CHECK-LABEL: define double @CompareDistmats(
-; CHECK-SAME: double [[DISTMAT1_:%.*]], double [[DISTMAT2_:%.*]]) {
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
 ; CHECK-NEXT:    br label %[[FOR_COND:.*]]
 ; CHECK:       [[FOR_COND]]:
@@ -40,9 +40,9 @@ declare double @llvm.fmuladd.f64(double, double, double)
 
 declare double @sqrt(double noundef)
 
-define double @nonSquareCompareDistmats(double %distmat1_, double %distmat2_) {
+define double @nonSquareCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
 ; CHECK-LABEL: define double @nonSquareCompareDistmats(
-; CHECK-SAME: double [[DISTMAT1_:%.*]], double [[DISTMAT2_:%.*]]) {
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
 ; CHECK-NEXT:    br label %[[FOR_COND:.*]]
 ; CHECK:       [[FOR_COND]]:

>From 0c1e806a6e68f0510773dfe523f9472ec82b5f8f Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 17 Jan 2026 13:27:54 +0530
Subject: [PATCH 11/30] Improve code formatting

---
 llvm/lib/Analysis/ValueTracking.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 2979833e810c7..c494418af1dd1 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5942,7 +5942,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           computeKnownFPClass(Init, DemandedElts,
                               KnownFPClass::OrderedGreaterThanZeroMask,
                               KnownStart, Q, Depth + 1);
-          if (KnownStart.cannotBeOrderedLessThanZero() && L == R && isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
+          if (KnownStart.cannotBeOrderedLessThanZero() && L == R &&
+              isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
             Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
           break;
         }

>From 0421f9f90fb02779135984d30649d480001616ad Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Wed, 21 Jan 2026 00:44:56 +0530
Subject: [PATCH 12/30] Added documentation and more negative tests

---
 llvm/include/llvm/Analysis/ValueTracking.h    | 11 +++++
 .../AggressiveInstCombine/X86/pr175590.ll     | 43 +++++++++++++++++--
 2 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 89819ae4777fe..a01c96445e604 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -1001,6 +1001,17 @@ LLVM_ABI bool matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I,
                                                    PHINode *&P, Value *&Init,
                                                    Value *&OtherOp);
 
+/// Attempt to match a simple value-accumulating recurrence of the form:
+///   %llvm.intrinsic.acc = phi Ty [%Init, %Entry], [%llvm.intrinsic, %backedge]
+///   %llvm.intrinsic = call Ty @llvm.intrinsic(%OtherOp0, %OtherOp1, %llvm.intrinsic.acc)
+/// OR
+///   %llvm.intrinsic.acc = phi Ty [%Init, %Entry], [%llvm.intrinsic, %backedge]
+///   %llvm.intrinsic = call Ty @llvm.intrinsic(%llvm.intrinsic.acc, %OtherOp0, %OtherOp1)
+///
+/// The recurrence relation is of kind:
+///   X_0 = %a (initial value),
+///   X_i = call @llvm.ternary.intrinsic(X_i-1, %b, %c)
+/// Where %b, %c are not required to be loop-invariant.
 LLVM_ABI bool matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I,
                                                     PHINode *&P, Value *&Init,
                                                     Value *&OtherOp0,
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index 0bd25807f3b82..d27dff893918a 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -7,7 +7,7 @@ define double @CompareDistmats(double noundef %distmat1_, double noundef %distma
 ; CHECK-NEXT:  [[ENTRY:.*]]:
 ; CHECK-NEXT:    br label %[[FOR_COND:.*]]
 ; CHECK:       [[FOR_COND]]:
-; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[TMP0:%.*]], %[[FOR_BODY:.*]] ]
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ]
 ; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
 ; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
 ; CHECK:       [[FOR_COND_CLEANUP]]:
@@ -15,7 +15,7 @@ define double @CompareDistmats(double noundef %distmat1_, double noundef %distma
 ; CHECK-NEXT:    ret double [[SQRT]]
 ; CHECK:       [[FOR_BODY]]:
 ; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
-; CHECK-NEXT:    [[TMP0]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
+; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
 ; CHECK-NEXT:    br label %[[FOR_COND]]
 ;
 entry:
@@ -46,7 +46,7 @@ define double @nonSquareCompareDistmats(double noundef %distmat1_, double nounde
 ; CHECK-NEXT:  [[ENTRY:.*]]:
 ; CHECK-NEXT:    br label %[[FOR_COND:.*]]
 ; CHECK:       [[FOR_COND]]:
-; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[TMP0:%.*]], %[[FOR_BODY:.*]] ]
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ]
 ; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
 ; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
 ; CHECK:       [[FOR_COND_CLEANUP]]:
@@ -55,7 +55,7 @@ define double @nonSquareCompareDistmats(double noundef %distmat1_, double nounde
 ; CHECK:       [[FOR_BODY]]:
 ; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[DISTMAT1_]], [[DISTMAT2_]]
-; CHECK-NEXT:    [[TMP0]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[ADD]], double [[RMSD_0]])
+; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[ADD]], double [[RMSD_0]])
 ; CHECK-NEXT:    br label %[[FOR_COND]]
 ;
 entry:
@@ -76,3 +76,38 @@ for.body:                                         ; preds = %for.cond
   %fmacall = call double @llvm.fmuladd.f64(double %sub, double %add, double %RMSD.0)
   br label %for.cond
 }
+
+define double @negInitialCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
+; CHECK-LABEL: define double @negInitialCompareDistmats(
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ -1.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
+; CHECK:       [[FOR_COND_CLEANUP]]:
+; CHECK-NEXT:    [[CALL:%.*]] = call double @sqrt(double noundef [[RMSD_0]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
+; CHECK-NEXT:    br label %[[FOR_COND]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %RMSD.0 = phi double [ -1.000000e+00, %entry ], [ %fmacall, %for.body ]
+  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %call = call double @sqrt(double noundef %RMSD.0)
+  ret double %call
+
+for.body:                                         ; preds = %for.cond
+  %sub = fsub double %distmat1_, %distmat2_
+  %fmacall = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
+  br label %for.cond
+}

>From a8561f727dd5b75c2d84a375ecdacce82274f54f Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Wed, 21 Jan 2026 00:49:42 +0530
Subject: [PATCH 13/30] Fix code formatting

---
 llvm/include/llvm/Analysis/ValueTracking.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index a01c96445e604..5f1e7773be8d3 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -1003,10 +1003,12 @@ LLVM_ABI bool matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I,
 
 /// Attempt to match a simple value-accumulating recurrence of the form:
 ///   %llvm.intrinsic.acc = phi Ty [%Init, %Entry], [%llvm.intrinsic, %backedge]
-///   %llvm.intrinsic = call Ty @llvm.intrinsic(%OtherOp0, %OtherOp1, %llvm.intrinsic.acc)
+///   %llvm.intrinsic = call Ty @llvm.intrinsic(%OtherOp0, %OtherOp1,
+///   %llvm.intrinsic.acc)
 /// OR
 ///   %llvm.intrinsic.acc = phi Ty [%Init, %Entry], [%llvm.intrinsic, %backedge]
-///   %llvm.intrinsic = call Ty @llvm.intrinsic(%llvm.intrinsic.acc, %OtherOp0, %OtherOp1)
+///   %llvm.intrinsic = call Ty @llvm.intrinsic(%llvm.intrinsic.acc, %OtherOp0,
+///   %OtherOp1)
 ///
 /// The recurrence relation is of kind:
 ///   X_0 = %a (initial value),

>From bddef1af50e8e21c9ab42852d0df1226cebae90c Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Wed, 21 Jan 2026 01:29:15 +0530
Subject: [PATCH 14/30] Added handling for fma and more tests

---
 llvm/lib/Analysis/ValueTracking.cpp           |  1 +
 .../AggressiveInstCombine/X86/pr175590.ll     | 76 ++++++++++++++++++-
 2 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c494418af1dd1..9d2bd04707bbf 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5937,6 +5937,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       PHINode *PN;
       if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
         switch (I->getIntrinsicID()) {
+        case Intrinsic::fma:
         case Intrinsic::fmuladd: {
           KnownFPClass KnownStart;
           computeKnownFPClass(Init, DemandedElts,
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index d27dff893918a..c0d92ea4047b3 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -36,9 +36,40 @@ for.body:                                         ; preds = %for.cond
   br label %for.cond
 }
 
-declare double @llvm.fmuladd.f64(double, double, double)
+define double @fmaCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
+; CHECK-LABEL: define double @fmaCompareDistmats(
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
+; CHECK:       [[FOR_COND_CLEANUP]]:
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]])
+; CHECK-NEXT:    ret double [[SQRT]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fma.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
+; CHECK-NEXT:    br label %[[FOR_COND]]
+;
+entry:
+  br label %for.cond
 
-declare double @sqrt(double noundef)
+for.cond:                                         ; preds = %for.body, %entry
+  %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %fmacall, %for.body ]
+  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %call = call double @sqrt(double noundef %RMSD.0)
+  ret double %call
+
+for.body:                                         ; preds = %for.cond
+  %sub = fsub double %distmat1_, %distmat2_
+  %fmacall = call double @llvm.fma.f64(double %sub, double %sub, double %RMSD.0)
+  br label %for.cond
+}
 
 define double @nonSquareCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
 ; CHECK-LABEL: define double @nonSquareCompareDistmats(
@@ -111,3 +142,44 @@ for.body:                                         ; preds = %for.cond
   %fmacall = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
   br label %for.cond
 }
+
+define double @notMatchingRecurrenceCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
+; CHECK-LABEL: define double @notMatchingRecurrenceCompareDistmats(
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ -1.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
+; CHECK:       [[FOR_COND_CLEANUP]]:
+; CHECK-NEXT:    [[CALL:%.*]] = call double @sqrt(double noundef [[RMSD_0]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[SUB]])
+; CHECK-NEXT:    br label %[[FOR_COND]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %RMSD.0 = phi double [ -1.000000e+00, %entry ], [ %fmacall, %for.body ]
+  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %call = call double @sqrt(double noundef %RMSD.0)
+  ret double %call
+
+for.body:                                         ; preds = %for.cond
+  %sub = fsub double %distmat1_, %distmat2_
+  %fmacall = call double @llvm.fmuladd.f64(double %sub, double %sub, double %sub)
+  br label %for.cond
+}
+
+declare double @llvm.fmuladd.f64(double, double, double)
+
+declare double @llvm.fma.f64(double, double, double)
+
+declare double @sqrt(double noundef)

>From 1e2140ac45603abe9c5dc9ea25febac9aa8e4c9e Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Thu, 29 Jan 2026 21:05:03 +0530
Subject: [PATCH 15/30] Avoid use of core fmuladd class logic

---
 llvm/lib/Analysis/ValueTracking.cpp                    | 10 ++++++----
 .../Transforms/AggressiveInstCombine/X86/pr175590.ll   |  4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 9d2bd04707bbf..14a950a006e5a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5939,13 +5939,15 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
         switch (I->getIntrinsicID()) {
         case Intrinsic::fma:
         case Intrinsic::fmuladd: {
-          KnownFPClass KnownStart;
+          KnownFPClass KnownStart, KnownL;
           computeKnownFPClass(Init, DemandedElts,
                               KnownFPClass::OrderedGreaterThanZeroMask,
                               KnownStart, Q, Depth + 1);
-          if (KnownStart.cannotBeOrderedLessThanZero() && L == R &&
-              isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
-            Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+          computeKnownFPClass(L, DemandedElts,
+                              KnownFPClass::OrderedGreaterThanZeroMask,
+                              KnownL, Q, Depth + 1);
+          if (L == R && isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1)) 
+            Known = KnownFPClass::fma_square(KnownL, KnownStart);
           break;
         }
         }
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index c0d92ea4047b3..b0e3818bc02b8 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -15,7 +15,7 @@ define double @CompareDistmats(double noundef %distmat1_, double noundef %distma
 ; CHECK-NEXT:    ret double [[SQRT]]
 ; CHECK:       [[FOR_BODY]]:
 ; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
-; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]])
+; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fmuladd.f64(double noundef [[SUB]], double noundef [[SUB]], double [[RMSD_0]])
 ; CHECK-NEXT:    br label %[[FOR_COND]]
 ;
 entry:
@@ -32,7 +32,7 @@ for.cond.cleanup:                                 ; preds = %for.cond
 
 for.body:                                         ; preds = %for.cond
   %sub = fsub double %distmat1_, %distmat2_
-  %fmacall = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0)
+  %fmacall = call double @llvm.fmuladd.f64(double noundef %sub, double noundef %sub, double %RMSD.0)
   br label %for.cond
 }
 

>From 136b53799e387c1a4cb27fe3297d7f798807c9f4 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Thu, 29 Jan 2026 21:14:17 +0530
Subject: [PATCH 16/30] Correct code formatting

---
 llvm/lib/Analysis/ValueTracking.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 14a950a006e5a..8e9982c3d3269 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5946,7 +5946,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           computeKnownFPClass(L, DemandedElts,
                               KnownFPClass::OrderedGreaterThanZeroMask,
                               KnownL, Q, Depth + 1);
-          if (L == R && isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1)) 
+          if (L == R &&
+              isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1)) 
             Known = KnownFPClass::fma_square(KnownL, KnownStart);
           break;
         }

>From 3ed5a7475c1c035f7b19bc364caee67828986ef3 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Thu, 29 Jan 2026 21:20:01 +0530
Subject: [PATCH 17/30] Improve code formatting

---
 llvm/lib/Analysis/ValueTracking.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8e9982c3d3269..0f2831315415e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5944,10 +5944,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
                               KnownFPClass::OrderedGreaterThanZeroMask,
                               KnownStart, Q, Depth + 1);
           computeKnownFPClass(L, DemandedElts,
-                              KnownFPClass::OrderedGreaterThanZeroMask,
-                              KnownL, Q, Depth + 1);
+                              KnownFPClass::OrderedGreaterThanZeroMask, KnownL,
+                              Q, Depth + 1);
           if (L == R &&
-              isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1)) 
+              isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
             Known = KnownFPClass::fma_square(KnownL, KnownStart);
           break;
         }

>From 597bd84ed844a1b59bafe1c19deaf7ef23452473 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Thu, 29 Jan 2026 21:48:55 +0530
Subject: [PATCH 18/30] Nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0f2831315415e..1fd47ab36ae59 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5941,14 +5941,17 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
         case Intrinsic::fmuladd: {
           KnownFPClass KnownStart, KnownL;
           computeKnownFPClass(Init, DemandedElts,
-                              KnownFPClass::OrderedGreaterThanZeroMask,
+                              InterestedClasses,
                               KnownStart, Q, Depth + 1);
+          if (KnownStart.isUnknown())
+            break;
           computeKnownFPClass(L, DemandedElts,
-                              KnownFPClass::OrderedGreaterThanZeroMask, KnownL,
+                              InterestedClasses, KnownL,
                               Q, Depth + 1);
           if (L == R &&
               isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
-            Known = KnownFPClass::fma_square(KnownL, KnownStart);
+            Known = KnownFPClass::fma_square(KnownL, KnownStart,
+                                            DenormalMode::getDynamic());
           break;
         }
         }

>From d56d64fb71804200a666cd46194e585196186495 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Thu, 29 Jan 2026 21:54:30 +0530
Subject: [PATCH 19/30] Nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1fd47ab36ae59..0909d9376fdf1 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5940,18 +5940,16 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
         case Intrinsic::fma:
         case Intrinsic::fmuladd: {
           KnownFPClass KnownStart, KnownL;
-          computeKnownFPClass(Init, DemandedElts,
-                              InterestedClasses,
-                              KnownStart, Q, Depth + 1);
+          computeKnownFPClass(Init, DemandedElts, InterestedClasses, KnownStart,
+                              Q, Depth + 1);
           if (KnownStart.isUnknown())
             break;
-          computeKnownFPClass(L, DemandedElts,
-                              InterestedClasses, KnownL,
-                              Q, Depth + 1);
+          computeKnownFPClass(L, DemandedElts, InterestedClasses, KnownL, Q,
+                              Depth + 1);
           if (L == R &&
               isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
             Known = KnownFPClass::fma_square(KnownL, KnownStart,
-                                            DenormalMode::getDynamic());
+                                             DenormalMode::getDynamic());
           break;
         }
         }

>From 15b8a93d35c283d7c393f2e2c2096694d5d99724 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 31 Jan 2026 14:38:24 +0530
Subject: [PATCH 20/30] Make transform independent of order of PHI operands

---
 llvm/lib/Analysis/ValueTracking.cpp           | 55 +++++++++++--------
 .../AggressiveInstCombine/X86/pr175590.ll     | 35 ++++++++++++
 2 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0909d9376fdf1..784dbc9a30183 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5928,30 +5928,37 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     // initial value and is incremented by a squared value.
     // This will propagate sign information out of such loops.
     if (P->getNumIncomingValues() == 2) {
-      Value *RecurValue = P->getIncomingValue(1);
-      IntrinsicInst *I = dyn_cast<IntrinsicInst>(RecurValue);
-      if (!I)
-        break;
-      Value *R, *L;
-      Value *Init;
-      PHINode *PN;
-      if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
-        switch (I->getIntrinsicID()) {
-        case Intrinsic::fma:
-        case Intrinsic::fmuladd: {
-          KnownFPClass KnownStart, KnownL;
-          computeKnownFPClass(Init, DemandedElts, InterestedClasses, KnownStart,
-                              Q, Depth + 1);
-          if (KnownStart.isUnknown())
-            break;
-          computeKnownFPClass(L, DemandedElts, InterestedClasses, KnownL, Q,
-                              Depth + 1);
-          if (L == R &&
-              isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
-            Known = KnownFPClass::fma_square(KnownL, KnownStart,
-                                             DenormalMode::getDynamic());
-          break;
-        }
+      for (int i = 0; i < 2; i++) {
+        Value *RecurValue = P->getIncomingValue(1 - i);
+        IntrinsicInst *I = dyn_cast<IntrinsicInst>(RecurValue);
+        if (I) {
+          Value *R, *L;
+          Value *Init;
+          PHINode *PN;
+          const Function *F = I->getFunction();
+          const fltSemantics &FltSem =
+              I->getType()->getScalarType()->getFltSemantics();
+          DenormalMode Mode =
+              F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
+          if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
+            switch (I->getIntrinsicID()) {
+            case Intrinsic::fma:
+            case Intrinsic::fmuladd: {
+              KnownFPClass KnownStart, KnownL;
+              computeKnownFPClass(Init, DemandedElts, InterestedClasses, KnownStart,
+                                  Q, Depth + 1);
+              if (KnownStart.isUnknown())
+                break;
+              computeKnownFPClass(L, DemandedElts, InterestedClasses, KnownL, Q,
+                                  Depth + 1);
+              if (L == R &&
+                  isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
+                Known = KnownFPClass::fma_square(KnownL, KnownStart,
+                                                Mode);
+              break;
+            }
+            }
+          }
         }
       }
     }
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index b0e3818bc02b8..242d7868d6fce 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -36,6 +36,41 @@ for.body:                                         ; preds = %for.cond
   br label %for.cond
 }
 
+define double @shuffledCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
+; CHECK-LABEL: define double @shuffledCompareDistmats(
+; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[RMSD_0:%.*]] = phi double [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ], [ 0.000000e+00, %[[ENTRY]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]]
+; CHECK:       [[FOR_COND_CLEANUP]]:
+; CHECK-NEXT:    [[CALL:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]]
+; CHECK-NEXT:    [[FMACALL]] = call double @llvm.fmuladd.f64(double noundef [[SUB]], double noundef [[SUB]], double [[RMSD_0]])
+; CHECK-NEXT:    br label %[[FOR_COND]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %RMSD.0 = phi double [ %fmacall, %for.body ], [ 0.000000e+00, %entry ]
+  %cmp = phi i1 [ true, %entry ], [ false, %for.body ]
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %call = call double @sqrt(double noundef %RMSD.0)
+  ret double %call
+
+for.body:                                         ; preds = %for.cond
+  %sub = fsub double %distmat1_, %distmat2_
+  %fmacall = call double @llvm.fmuladd.f64(double noundef %sub, double noundef %sub, double %RMSD.0)
+  br label %for.cond
+}
+
 define double @fmaCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) {
 ; CHECK-LABEL: define double @fmaCompareDistmats(
 ; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) {

>From d305c29b0b0cbd6a543de3a618d872d0b0d5267c Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 31 Jan 2026 14:43:11 +0530
Subject: [PATCH 21/30] nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 784dbc9a30183..857dcec65b45b 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5945,16 +5945,15 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
             case Intrinsic::fma:
             case Intrinsic::fmuladd: {
               KnownFPClass KnownStart, KnownL;
-              computeKnownFPClass(Init, DemandedElts, InterestedClasses, KnownStart,
-                                  Q, Depth + 1);
+              computeKnownFPClass(Init, DemandedElts, InterestedClasses,
+                                  KnownStart, Q, Depth + 1);
               if (KnownStart.isUnknown())
                 break;
               computeKnownFPClass(L, DemandedElts, InterestedClasses, KnownL, Q,
                                   Depth + 1);
               if (L == R &&
                   isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
-                Known = KnownFPClass::fma_square(KnownL, KnownStart,
-                                                Mode);
+                Known = KnownFPClass::fma_square(KnownL, KnownStart, Mode);
               break;
             }
             }

>From e5033ccfb243605b23ec5b11081627912b7a8905 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 7 Feb 2026 22:11:44 +0530
Subject: [PATCH 22/30] Fix crash

---
 llvm/lib/Analysis/ValueTracking.cpp           |  2 +-
 .../AggressiveInstCombine/X86/pr175590.ll     | 49 +++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 857dcec65b45b..7c62f5e9a2ec2 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -9292,7 +9292,7 @@ static bool matchThreeInputRecurrence(const PHINode *PN, InstTy *&Inst,
   if (PN->getNumIncomingValues() != 2)
     return false;
 
-  for (unsigned I = 0; I != 3; ++I) {
+  for (unsigned I = 0; I != 2; ++I) {
     if (auto *Operation = dyn_cast<InstTy>(PN->getIncomingValue(I));
         Operation) {
       Value *Op0 = Operation->getOperand(0);
diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index 242d7868d6fce..16ccea79fbb45 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -213,6 +213,55 @@ for.body:                                         ; preds = %for.cond
   br label %for.cond
 }
 
+define fastcc i1 @ShouldMergeBlock(ptr %arena, i1 %exitcond) {
+; CHECK-LABEL: define fastcc i1 @ShouldMergeBlock(
+; CHECK-SAME: ptr [[ARENA:%.*]], i1 [[EXITCOND:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[DOT026:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ 1.000000e+00, %[[LOOP_BACKEDGE:.*]] ]
+; CHECK-NEXT:    br i1 true, label %[[LOAD_BLOCK:.*]], label %[[ZERO_BLOCK:.*]]
+; CHECK:       [[ZERO_BLOCK]]:
+; CHECK-NEXT:    br label %[[LOOP_BACKEDGE]]
+; CHECK:       [[LOAD_BLOCK]]:
+; CHECK-NEXT:    [[LOADED_VAL:%.*]] = load double, ptr [[ARENA]], align 8
+; CHECK-NEXT:    br label %[[LOOP_BACKEDGE]]
+; CHECK:       [[LOOP_BACKEDGE]]:
+; CHECK-NEXT:    [[DOT0_I22:%.*]] = phi double [ [[LOADED_VAL]], %[[LOAD_BLOCK]] ], [ 0.000000e+00, %[[ZERO_BLOCK]] ]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[FMA_RESULT:%.*]] = tail call double @llvm.fmuladd.f64(double 0.000000e+00, double [[DOT0_I22]], double [[DOT026]])
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge double [[FMA_RESULT]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  br label %loop
+
+loop:
+  %.026 = phi double [ 0.000000e+00, %entry ],
+  [ 1.000000e+00, %loop_backedge ]
+  br i1 true, label %load_block, label %zero_block
+
+zero_block:
+  br label %loop_backedge
+
+load_block:
+  %loaded_val = load double, ptr %arena, align 8
+  br label %loop_backedge
+
+loop_backedge:
+  %.0.i22 = phi double [ %loaded_val, %load_block ],
+  [ 0.000000e+00, %zero_block ]
+  br i1 %exitcond, label %loop, label %exit
+
+exit:
+  %fma_result = tail call double @llvm.fmuladd.f64(double 0.000000e+00,
+  double %.0.i22,
+  double %.026)
+  %cmp = fcmp oge double %fma_result, 0.000000e+00
+  ret i1 %cmp
+}
+
 declare double @llvm.fmuladd.f64(double, double, double)
 
 declare double @llvm.fma.f64(double, double, double)

>From 31a91df5125660e890eecbecf30d63b1bf94423d Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 7 Feb 2026 22:58:44 +0530
Subject: [PATCH 23/30] Nitpick

---
 .../Transforms/AggressiveInstCombine/X86/pr175590.ll   | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index 16ccea79fbb45..07a732c4e9985 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -213,7 +213,7 @@ for.body:                                         ; preds = %for.cond
   br label %for.cond
 }
 
-define fastcc i1 @ShouldMergeBlock(ptr %arena, i1 %exitcond) {
+define i1 @test_phi_operand_crash(ptr %arena, i1 %exitcond) {
 ; CHECK-LABEL: define fastcc i1 @ShouldMergeBlock(
 ; CHECK-SAME: ptr [[ARENA:%.*]], i1 [[EXITCOND:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
@@ -239,7 +239,7 @@ entry:
 
 loop:
   %.026 = phi double [ 0.000000e+00, %entry ],
-  [ 1.000000e+00, %loop_backedge ]
+                     [ 1.000000e+00, %loop_backedge ]
   br i1 true, label %load_block, label %zero_block
 
 zero_block:
@@ -251,13 +251,13 @@ load_block:
 
 loop_backedge:
   %.0.i22 = phi double [ %loaded_val, %load_block ],
-  [ 0.000000e+00, %zero_block ]
+                       [ 0.000000e+00, %zero_block ]
   br i1 %exitcond, label %loop, label %exit
 
 exit:
   %fma_result = tail call double @llvm.fmuladd.f64(double 0.000000e+00,
-  double %.0.i22,
-  double %.026)
+                                                   double %.0.i22,
+                                                   double %.026)
   %cmp = fcmp oge double %fma_result, 0.000000e+00
   ret i1 %cmp
 }

>From 816d046361b696fa323c98e993afb1e5afafcd01 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sun, 8 Feb 2026 00:39:38 +0530
Subject: [PATCH 24/30] Nitpick

---
 .../Transforms/AggressiveInstCombine/X86/pr175590.ll | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
index 07a732c4e9985..71167c2c6aef5 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll
@@ -214,7 +214,7 @@ for.body:                                         ; preds = %for.cond
 }
 
 define i1 @test_phi_operand_crash(ptr %arena, i1 %exitcond) {
-; CHECK-LABEL: define fastcc i1 @ShouldMergeBlock(
+; CHECK-LABEL: define i1 @test_phi_operand_crash(
 ; CHECK-SAME: ptr [[ARENA:%.*]], i1 [[EXITCOND:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
@@ -238,8 +238,7 @@ entry:
   br label %loop
 
 loop:
-  %.026 = phi double [ 0.000000e+00, %entry ],
-                     [ 1.000000e+00, %loop_backedge ]
+  %.026 = phi double [ 0.000000e+00, %entry ], [ 1.000000e+00, %loop_backedge ]
   br i1 true, label %load_block, label %zero_block
 
 zero_block:
@@ -250,14 +249,11 @@ load_block:
   br label %loop_backedge
 
 loop_backedge:
-  %.0.i22 = phi double [ %loaded_val, %load_block ],
-                       [ 0.000000e+00, %zero_block ]
+  %.0.i22 = phi double [ %loaded_val, %load_block ], [ 0.000000e+00, %zero_block ]
   br i1 %exitcond, label %loop, label %exit
 
 exit:
-  %fma_result = tail call double @llvm.fmuladd.f64(double 0.000000e+00,
-                                                   double %.0.i22,
-                                                   double %.026)
+  %fma_result = tail call double @llvm.fmuladd.f64(double 0.000000e+00, double %.0.i22, double %.026)
   %cmp = fcmp oge double %fma_result, 0.000000e+00
   ret i1 %cmp
 }

>From 71355d690776a86375b64d52e6db4c7b620638cf Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Thu, 12 Feb 2026 11:53:33 +0530
Subject: [PATCH 25/30] nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7c62f5e9a2ec2..52f6f7bcad64d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -718,6 +718,8 @@ bool llvm::willNotFreeBetween(const Instruction *Assume,
 
   // Make sure the current function cannot arrange for another thread to free on
   // its behalf.
+  llvm::outs() << "CtxI is:";
+  CtxI->dump();
   if (!CtxI->getFunction()->hasNoSync())
     return false;
 
@@ -5927,11 +5929,15 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     // Look for the case of a for loop which has a positive
     // initial value and is incremented by a squared value.
     // This will propagate sign information out of such loops.
-    if (P->getNumIncomingValues() == 2) {
+    if (P->getNumIncomingValues() != 2)
+      break;
+    else {
       for (int i = 0; i < 2; i++) {
         Value *RecurValue = P->getIncomingValue(1 - i);
         IntrinsicInst *I = dyn_cast<IntrinsicInst>(RecurValue);
-        if (I) {
+        if (!I)
+          continue;
+        else {
           Value *R, *L;
           Value *Init;
           PHINode *PN;

>From f754f3b381bb23dec2747660b73825a3cd41549c Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Thu, 12 Feb 2026 11:54:53 +0530
Subject: [PATCH 26/30] nit

---
 llvm/lib/Analysis/ValueTracking.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 52f6f7bcad64d..fbe867ffd451c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -718,8 +718,6 @@ bool llvm::willNotFreeBetween(const Instruction *Assume,
 
   // Make sure the current function cannot arrange for another thread to free on
   // its behalf.
-  llvm::outs() << "CtxI is:";
-  CtxI->dump();
   if (!CtxI->getFunction()->hasNoSync())
     return false;
 

>From da7eadaa57127d3579e279061bc3243438f95dfd Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 20 Feb 2026 20:57:08 +0530
Subject: [PATCH 27/30] Fix BuildBot Crash

---
 llvm/lib/Analysis/ValueTracking.cpp | 65 ++++++++++++++---------------
 1 file changed, 32 insertions(+), 33 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index fbe867ffd451c..bdb25b412e30b 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5929,39 +5929,35 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     // This will propagate sign information out of such loops.
     if (P->getNumIncomingValues() != 2)
       break;
-    else {
-      for (int i = 0; i < 2; i++) {
-        Value *RecurValue = P->getIncomingValue(1 - i);
-        IntrinsicInst *I = dyn_cast<IntrinsicInst>(RecurValue);
-        if (!I)
-          continue;
-        else {
-          Value *R, *L;
-          Value *Init;
-          PHINode *PN;
-          const Function *F = I->getFunction();
-          const fltSemantics &FltSem =
-              I->getType()->getScalarType()->getFltSemantics();
-          DenormalMode Mode =
-              F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
-          if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
-            switch (I->getIntrinsicID()) {
-            case Intrinsic::fma:
-            case Intrinsic::fmuladd: {
-              KnownFPClass KnownStart, KnownL;
-              computeKnownFPClass(Init, DemandedElts, InterestedClasses,
-                                  KnownStart, Q, Depth + 1);
-              if (KnownStart.isUnknown())
-                break;
-              computeKnownFPClass(L, DemandedElts, InterestedClasses, KnownL, Q,
-                                  Depth + 1);
-              if (L == R &&
-                  isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
-                Known = KnownFPClass::fma_square(KnownL, KnownStart, Mode);
-              break;
-            }
-            }
-          }
+    for (unsigned i = 0; i < 2; i++) {
+      Value *RecurValue = P->getIncomingValue(1 - i);
+      IntrinsicInst *I = dyn_cast<IntrinsicInst>(RecurValue);
+      if (!I)
+        continue;
+      Value *R, *L;
+      Value *Init;
+      PHINode *PN;
+      const Function *F = I->getFunction();
+      const fltSemantics &FltSem =
+          I->getType()->getScalarType()->getFltSemantics();
+      DenormalMode Mode =
+          F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
+      if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {
+        switch (I->getIntrinsicID()) {
+        case Intrinsic::fma:
+        case Intrinsic::fmuladd: {
+          KnownFPClass KnownStart, KnownL;
+          computeKnownFPClass(Init, DemandedElts, InterestedClasses,
+                              KnownStart, Q, Depth + 1);
+          if (KnownStart.isUnknown())
+            break;
+          computeKnownFPClass(L, DemandedElts, InterestedClasses, KnownL, Q,
+                              Depth + 1);
+          if (L == R &&
+              isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1))
+            Known = KnownFPClass::fma_square(KnownL, KnownStart, Mode);
+          break;
+        }
         }
       }
     }
@@ -9299,6 +9295,9 @@ static bool matchThreeInputRecurrence(const PHINode *PN, InstTy *&Inst,
   for (unsigned I = 0; I != 2; ++I) {
     if (auto *Operation = dyn_cast<InstTy>(PN->getIncomingValue(I));
         Operation) {
+      if (Operation->getNumOperands() < 3)
+          continue;
+
       Value *Op0 = Operation->getOperand(0);
       Value *Op1 = Operation->getOperand(1);
       Value *Op2 = Operation->getOperand(2);

>From 339dea112c4d781bbecd09762ea58ab0421e02d7 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 20 Feb 2026 21:03:10 +0530
Subject: [PATCH 28/30] Nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index bdb25b412e30b..c021de15c20e2 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5947,8 +5947,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
         case Intrinsic::fma:
         case Intrinsic::fmuladd: {
           KnownFPClass KnownStart, KnownL;
-          computeKnownFPClass(Init, DemandedElts, InterestedClasses,
-                              KnownStart, Q, Depth + 1);
+          computeKnownFPClass(Init, DemandedElts, InterestedClasses, KnownStart,
+                              Q, Depth + 1);
           if (KnownStart.isUnknown())
             break;
           computeKnownFPClass(L, DemandedElts, InterestedClasses, KnownL, Q,
@@ -9296,7 +9296,7 @@ static bool matchThreeInputRecurrence(const PHINode *PN, InstTy *&Inst,
     if (auto *Operation = dyn_cast<InstTy>(PN->getIncomingValue(I));
         Operation) {
       if (Operation->getNumOperands() < 3)
-          continue;
+        continue;
 
       Value *Op0 = Operation->getOperand(0);
       Value *Op1 = Operation->getOperand(1);

>From b2ecf18999b10014991ccf38eb4cdb9ae68936fd Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 20 Feb 2026 21:34:49 +0530
Subject: [PATCH 29/30] nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c021de15c20e2..eba65724a910b 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5934,11 +5934,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       IntrinsicInst *I = dyn_cast<IntrinsicInst>(RecurValue);
       if (!I)
         continue;
-      Value *R, *L;
-      Value *Init;
+      Value *R, *L, *Init;
       PHINode *PN;
       const Function *F = I->getFunction();
-      const fltSemantics &FltSem =
+      const auto &FltSem =
           I->getType()->getScalarType()->getFltSemantics();
       DenormalMode Mode =
           F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
@@ -9294,10 +9293,7 @@ static bool matchThreeInputRecurrence(const PHINode *PN, InstTy *&Inst,
 
   for (unsigned I = 0; I != 2; ++I) {
     if (auto *Operation = dyn_cast<InstTy>(PN->getIncomingValue(I));
-        Operation) {
-      if (Operation->getNumOperands() < 3)
-        continue;
-
+        Operation && Operation->arg_size() == 3) {
       Value *Op0 = Operation->getOperand(0);
       Value *Op1 = Operation->getOperand(1);
       Value *Op2 = Operation->getOperand(2);

>From b72a59b306b078f4a54e5ffe20197ccf36bf0e9c Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 20 Feb 2026 21:39:49 +0530
Subject: [PATCH 30/30] nitpick

---
 llvm/lib/Analysis/ValueTracking.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index eba65724a910b..86d9de3655b25 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5937,8 +5937,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       Value *R, *L, *Init;
       PHINode *PN;
       const Function *F = I->getFunction();
-      const auto &FltSem =
-          I->getType()->getScalarType()->getFltSemantics();
+      const auto &FltSem = I->getType()->getScalarType()->getFltSemantics();
       DenormalMode Mode =
           F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
       if (matchSimpleTernaryIntrinsicRecurrence(I, PN, Init, L, R)) {



More information about the llvm-commits mailing list