[llvm] [InstCombine] Enable factorizeMinMaxTree for floating-point values (PR #193195)

Thomas Fry via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 21 04:21:26 PDT 2026


https://github.com/thofry created https://github.com/llvm/llvm-project/pull/193195

This patch extends `factorizeMinMaxTree` to floating point types by introducing handling for fast math flags.

The test coverage was copied from the integer case with additional tests for the handling of fast math flags

## Proofs
Proof of base case (times out but runs in <5 mins locally): https://alive2.llvm.org/ce/z/vt-Kxf
FMF proofs timed out after 12 hours

Manual proof for the `nnan` fast math flag special handling:
Assume WLOG the optimisation is `m1(m2(a, b), m3(c, b)) -> m4(m2(a, b), c)`

-  `minimum/maximum`

`m1` is marked `nnan`
=> results of `m2` and `m3 ` are not `NaN` 
=> `a`, `b`, and `c` are not `NaN` as minimum and maximum return `NaN` when either argument is  `NaN`
=> neither of the arguments to `m4` nor the result can be `NaN`
=> `m4` can be marked `nnan`

Therefore `m4` can safely copy `nnan` from `m1`

- `minnum/minimumnum/maxnum/maximumnum`

`m3` is marked `nnan`
=> `b` and `c` are not `NaN`
=> the result of `m2` is not `NaN` as it has at least one non-`NaN` argument
=> neither of the arguments to `m4` nor the result can be `NaN`
=> `m4` can be marked `nnan`

Therefore `m4` can safely copy `nnan` from `m3`

>From e9894a926480ca5f82d4d0af5ecfcb82a76ed8d0 Mon Sep 17 00:00:00 2001
From: Thomas Fry <thomas.fry at arm.com>
Date: Mon, 20 Apr 2026 13:09:54 +0200
Subject: [PATCH 1/2] Precommit tests

---
 llvm/test/Transforms/InstCombine/maximum.ll   | 125 +++++++++++++++-
 .../test/Transforms/InstCombine/maximumnum.ll | 133 +++++++++++++++++-
 llvm/test/Transforms/InstCombine/maxnum.ll    | 125 +++++++++++++++-
 llvm/test/Transforms/InstCombine/minimum.ll   | 123 ++++++++++++++++
 .../test/Transforms/InstCombine/minimumnum.ll | 132 +++++++++++++++++
 llvm/test/Transforms/InstCombine/minnum.ll    | 123 ++++++++++++++++
 6 files changed, 758 insertions(+), 3 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/maximum.ll b/llvm/test/Transforms/InstCombine/maximum.ll
index c79449472235b..296a231c7b86a 100644
--- a/llvm/test/Transforms/InstCombine/maximum.ll
+++ b/llvm/test/Transforms/InstCombine/maximum.ll
@@ -8,6 +8,8 @@ declare <4 x float> @llvm.maximum.v4f32(<4 x float>, <4 x float>)
 declare double @llvm.maximum.f64(double, double)
 declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
 
+declare void @use(float)
+
 define float @constant_fold_maximum_f32() {
 ; CHECK-LABEL: @constant_fold_maximum_f32(
 ; CHECK-NEXT:    ret float 2.000000e+00
@@ -238,6 +240,128 @@ define float @maximum4(float %x, float %y, float %z, float %w) {
   ret float %c
 }
 
+define float @maximum_common_op(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_common_op(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %x, float %y)
+  %m2 = call float @llvm.maximum.f32(float %x, float %z)
+  %m3 = call float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximum_reuse_lhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_reuse_lhs(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maximum.f32(float %z, float %x)
+  %m3 = call float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximum_reuse_rhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_reuse_rhs(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    call void @use(float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %y, float %x)
+  %m2 = call float @llvm.maximum.f32(float %z, float %x)
+  call void @use(float %m2)
+  %m3 = call float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximum_reuse_lhs_nnan(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_reuse_lhs_nnan(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maximum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maximum.f32(float %z, float %x)
+  %m3 = call nnan float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_reuse_lhs_nnan_folded_only(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call nnan float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call nnan float @llvm.maximum.f32(float %z, float %x)
+  %m3 = call float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_reuse_lhs_fmf_intersection(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.maximum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.maximum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call afn ninf float @llvm.maximum.f32(float %z, float %x)
+  %m3 = call arcp ninf float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - too many uses.
+
+define float @maximum_common_op_uses(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_common_op_uses(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Z:%.*]])
+; CHECK-NEXT:    call void @use(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maximum.f32(float %x, float %z)
+  call void @use(float %m2)
+  %m3 = call float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - must have common operand.
+
+define float @maximum_no_common_op(float %x, float %y, float %z, float %w) {
+; CHECK-LABEL: @maximum_no_common_op(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximum.f32(float [[W:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximum.f32(float %x, float %y)
+  %m2 = call float @llvm.maximum.f32(float %w, float %z)
+  %m3 = call float @llvm.maximum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
 ; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404
 
 define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) {
@@ -293,7 +417,6 @@ define float @unary_neg_neg_vec_fmf(float %x, float %y) {
 ; 1 extra use of an intermediate value should still allow the fold,
 ; but 2 would require more instructions than we started with.
 
-declare void @use(float)
 define float @neg_neg_extra_use_x(float %x, float %y) {
 ; CHECK-LABEL: @neg_neg_extra_use_x(
 ; CHECK-NEXT:    [[NEGX:%.*]] = fneg float [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/maximumnum.ll b/llvm/test/Transforms/InstCombine/maximumnum.ll
index 0d20be9062e77..b405e2ea34360 100644
--- a/llvm/test/Transforms/InstCombine/maximumnum.ll
+++ b/llvm/test/Transforms/InstCombine/maximumnum.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
 
+declare void @use(float)
+
 define float @maximumnum_f32_1_maximumnum_val_p0(float %x) {
 ; CHECK-LABEL: define float @maximumnum_f32_1_maximumnum_val_p0(
 ; CHECK-SAME: float [[X:%.*]]) {
@@ -103,6 +105,136 @@ define float @maximumnum4(float %x, float %y, float %z, float %w) {
   ret float %c
 }
 
+define float @maximumnum_common_op(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @maximumnum_common_op(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
+  %m2 = call float @llvm.maximumnum.f32(float %x, float %z)
+  %m3 = call float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximumnum_reuse_lhs(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @maximumnum_reuse_lhs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maximumnum.f32(float %z, float %x)
+  %m3 = call float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximumnum_reuse_rhs(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @maximumnum_reuse_rhs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[Y]], float [[X]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    call void @use(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %y, float %x)
+  %m2 = call float @llvm.maximumnum.f32(float %z, float %x)
+  call void @use(float %m2)
+  %m3 = call float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximumnum_reuse_lhs_nnan(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @maximumnum_reuse_lhs_nnan(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maximumnum.f32(float %z, float %x)
+  %m3 = call nnan float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximumnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @maximumnum_reuse_lhs_nnan_folded_only(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.maximumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call nnan float @llvm.maximumnum.f32(float %z, float %x)
+  %m3 = call float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maximumnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @maximumnum_reuse_lhs_fmf_intersection(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.maximumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call afn ninf float @llvm.maximumnum.f32(float %z, float %x)
+  %m3 = call arcp ninf float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - too many uses.
+
+define float @maximumnum_common_op_uses(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @maximumnum_common_op_uses(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Z]])
+; CHECK-NEXT:    call void @use(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maximumnum.f32(float %x, float %z)
+  call void @use(float %m2)
+  %m3 = call float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - must have common operand.
+
+define float @maximumnum_no_common_op(float %x, float %y, float %z, float %w) {
+; CHECK-LABEL: define float @maximumnum_no_common_op(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]], float [[W:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[W]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
+  %m2 = call float @llvm.maximumnum.f32(float %w, float %z)
+  %m3 = call float @llvm.maximumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
 ; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404
 
 define <2 x float> @maximumnum_neg_neg(<2 x float> %x, <2 x float> %y) {
@@ -149,7 +281,6 @@ define float @maximumnum_unary_neg_neg_vec_fmf(float %x, float %y) {
 ; 1 extra use of an intermediate value should still allow the fold,
 ; but 2 would require more instructions than we started with.
 
-declare void @use(float)
 define float @maximumnum_neg_neg_extra_use_x(float %x, float %y) {
 ; CHECK-LABEL: define float @maximumnum_neg_neg_extra_use_x(
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
diff --git a/llvm/test/Transforms/InstCombine/maxnum.ll b/llvm/test/Transforms/InstCombine/maxnum.ll
index 5e275627414cb..fa4e7e42951f8 100644
--- a/llvm/test/Transforms/InstCombine/maxnum.ll
+++ b/llvm/test/Transforms/InstCombine/maxnum.ll
@@ -8,6 +8,8 @@ declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>)
 declare double @llvm.maxnum.f64(double, double)
 declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
 
+declare void @use(float)
+
 define float @constant_fold_maxnum_f32() {
 ; CHECK-LABEL: @constant_fold_maxnum_f32(
 ; CHECK-NEXT:    ret float 2.000000e+00
@@ -238,6 +240,128 @@ define float @maxnum4(float %x, float %y, float %z, float %w) {
   ret float %c
 }
 
+define float @maxnum_common_op(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_common_op(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maxnum.f32(float [[X]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %x, float %y)
+  %m2 = call float @llvm.maxnum.f32(float %x, float %z)
+  %m3 = call float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maxnum_reuse_lhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_reuse_lhs(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.maxnum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maxnum.f32(float %z, float %x)
+  %m3 = call float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maxnum_reuse_rhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_reuse_rhs(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maxnum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    call void @use(float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %y, float %x)
+  %m2 = call float @llvm.maxnum.f32(float %z, float %x)
+  call void @use(float %m2)
+  %m3 = call float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maxnum_reuse_lhs_nnan(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_reuse_lhs_nnan(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maxnum.f32(float %z, float %x)
+  %m3 = call nnan float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maxnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_reuse_lhs_nnan_folded_only(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.maxnum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call nnan float @llvm.maxnum.f32(float %z, float %x)
+  %m3 = call float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @maxnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_reuse_lhs_fmf_intersection(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.maxnum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call afn ninf float @llvm.maxnum.f32(float %z, float %x)
+  %m3 = call arcp ninf float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - too many uses.
+
+define float @maxnum_common_op_uses(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_common_op_uses(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[X]], float [[Z:%.*]])
+; CHECK-NEXT:    call void @use(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %x, float %y)
+  call void @use(float %m1)
+  %m2 = call float @llvm.maxnum.f32(float %x, float %z)
+  call void @use(float %m2)
+  %m3 = call float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - must have common operand.
+
+define float @maxnum_no_common_op(float %x, float %y, float %z, float %w) {
+; CHECK-LABEL: @maxnum_no_common_op(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[W:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.maxnum.f32(float %x, float %y)
+  %m2 = call float @llvm.maxnum.f32(float %w, float %z)
+  %m3 = call float @llvm.maxnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
 ; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404
 
 define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) {
@@ -281,7 +405,6 @@ define float @unary_neg_neg_vec_fmf(float %x, float %y) {
 ; 1 extra use of an intermediate value should still allow the fold,
 ; but 2 would require more instructions than we started with.
 
-declare void @use(float)
 define float @neg_neg_extra_use_x(float %x, float %y) {
 ; CHECK-LABEL: @neg_neg_extra_use_x(
 ; CHECK-NEXT:    [[NEGX:%.*]] = fneg float [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/minimum.ll b/llvm/test/Transforms/InstCombine/minimum.ll
index eb6eadf96e132..ab3375a0f4e2a 100644
--- a/llvm/test/Transforms/InstCombine/minimum.ll
+++ b/llvm/test/Transforms/InstCombine/minimum.ll
@@ -9,6 +9,7 @@ declare double @llvm.minimum.f64(double, double)
 declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
 
 declare float @llvm.maximum.f32(float, float)
+declare void @use.f32(float)
 
 define float @constant_fold_minimum_f32() {
 ; CHECK-LABEL: @constant_fold_minimum_f32(
@@ -240,6 +241,128 @@ define float @minimum4(float %x, float %y, float %z, float %w) {
   ret float %c
 }
 
+define float @minimum_common_op(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_common_op(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %x, float %y)
+  %m2 = call float @llvm.minimum.f32(float %x, float %z)
+  %m3 = call float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimum_reuse_lhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_reuse_lhs(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minimum.f32(float %z, float %x)
+  %m3 = call float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimum_reuse_rhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_reuse_rhs(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    call void @use.f32(float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %y, float %x)
+  %m2 = call float @llvm.minimum.f32(float %z, float %x)
+  call void @use.f32(float %m2)
+  %m3 = call float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimum_reuse_lhs_nnan(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_reuse_lhs_nnan(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minimum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minimum.f32(float %z, float %x)
+  %m3 = call nnan float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_reuse_lhs_nnan_folded_only(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call nnan float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call nnan float @llvm.minimum.f32(float %z, float %x)
+  %m3 = call float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_reuse_lhs_fmf_intersection(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.minimum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.minimum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call afn ninf float @llvm.minimum.f32(float %z, float %x)
+  %m3 = call arcp ninf float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - too many uses.
+
+define float @minimum_common_op_uses(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_common_op_uses(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Z:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minimum.f32(float %x, float %z)
+  call void @use.f32(float %m2)
+  %m3 = call float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - must have common operand.
+
+define float @minimum_no_common_op(float %x, float %y, float %z, float %w) {
+; CHECK-LABEL: @minimum_no_common_op(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimum.f32(float [[W:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimum.f32(float %x, float %y)
+  %m2 = call float @llvm.minimum.f32(float %w, float %z)
+  %m3 = call float @llvm.minimum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
 define float @minimum_x_maximum_x_y(float %x, float %y) {
 ; CHECK-LABEL: @minimum_x_maximum_x_y(
 ; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
diff --git a/llvm/test/Transforms/InstCombine/minimumnum.ll b/llvm/test/Transforms/InstCombine/minimumnum.ll
index 9262a71939158..9117c69bc07df 100644
--- a/llvm/test/Transforms/InstCombine/minimumnum.ll
+++ b/llvm/test/Transforms/InstCombine/minimumnum.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
 
+declare void @use.f32(float)
+
 define float @minimumnum_f32_1_minimumnum_val_p0(float %x) {
 ; CHECK-LABEL: define float @minimumnum_f32_1_minimumnum_val_p0(
 ; CHECK-SAME: float [[X:%.*]]) {
@@ -103,6 +105,136 @@ define float @minimumnum4(float %x, float %y, float %z, float %w) {
   ret float %c
 }
 
+define float @minimumnum_common_op(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @minimumnum_common_op(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
+  %m2 = call float @llvm.minimumnum.f32(float %x, float %z)
+  %m3 = call float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimumnum_reuse_lhs(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @minimumnum_reuse_lhs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minimumnum.f32(float %z, float %x)
+  %m3 = call float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimumnum_reuse_rhs(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @minimumnum_reuse_rhs(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[Y]], float [[X]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    call void @use.f32(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %y, float %x)
+  %m2 = call float @llvm.minimumnum.f32(float %z, float %x)
+  call void @use.f32(float %m2)
+  %m3 = call float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimumnum_reuse_lhs_nnan(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @minimumnum_reuse_lhs_nnan(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minimumnum.f32(float %z, float %x)
+  %m3 = call nnan float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimumnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @minimumnum_reuse_lhs_nnan_folded_only(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.minimumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call nnan float @llvm.minimumnum.f32(float %z, float %x)
+  %m3 = call float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minimumnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @minimumnum_reuse_lhs_fmf_intersection(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.minimumnum.f32(float [[Z]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call afn ninf float @llvm.minimumnum.f32(float %z, float %x)
+  %m3 = call arcp ninf float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - too many uses.
+
+define float @minimumnum_common_op_uses(float %x, float %y, float %z) {
+; CHECK-LABEL: define float @minimumnum_common_op_uses(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Z]])
+; CHECK-NEXT:    call void @use.f32(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minimumnum.f32(float %x, float %z)
+  call void @use.f32(float %m2)
+  %m3 = call float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - must have common operand.
+
+define float @minimumnum_no_common_op(float %x, float %y, float %z, float %w) {
+; CHECK-LABEL: define float @minimumnum_no_common_op(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]], float [[W:%.*]]) {
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[W]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
+  %m2 = call float @llvm.minimumnum.f32(float %w, float %z)
+  %m3 = call float @llvm.minimumnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
 define float @minimumnum_x_maximumnum_x_y(float %x, float %y) {
 ; CHECK-LABEL: define float @minimumnum_x_maximumnum_x_y(
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
diff --git a/llvm/test/Transforms/InstCombine/minnum.ll b/llvm/test/Transforms/InstCombine/minnum.ll
index 7ac83bf91163e..ebc9d6320ab5c 100644
--- a/llvm/test/Transforms/InstCombine/minnum.ll
+++ b/llvm/test/Transforms/InstCombine/minnum.ll
@@ -9,6 +9,7 @@ declare double @llvm.minnum.f64(double, double)
 declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
 
 declare float @llvm.maxnum.f32(float, float)
+declare void @use.f32(float)
 
 define float @constant_fold_minnum_f32() {
 ; CHECK-LABEL: @constant_fold_minnum_f32(
@@ -240,6 +241,128 @@ define float @minnum4(float %x, float %y, float %z, float %w) {
   ret float %c
 }
 
+define float @minnum_common_op(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_common_op(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %x, float %y)
+  %m2 = call float @llvm.minnum.f32(float %x, float %z)
+  %m3 = call float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minnum_reuse_lhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_reuse_lhs(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.minnum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minnum.f32(float %z, float %x)
+  %m3 = call float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minnum_reuse_rhs(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_reuse_rhs(
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[X:%.*]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minnum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    call void @use.f32(float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %y, float %x)
+  %m2 = call float @llvm.minnum.f32(float %z, float %x)
+  call void @use.f32(float %m2)
+  %m3 = call float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minnum_reuse_lhs_nnan(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_reuse_lhs_nnan(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minnum.f32(float %z, float %x)
+  %m3 = call nnan float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_reuse_lhs_nnan_folded_only(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.minnum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call nnan float @llvm.minnum.f32(float %z, float %x)
+  %m3 = call float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+define float @minnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_reuse_lhs_fmf_intersection(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.minnum.f32(float [[Z:%.*]], float [[X]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call afn ninf float @llvm.minnum.f32(float %z, float %x)
+  %m3 = call arcp ninf float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - too many uses.
+
+define float @minnum_common_op_uses(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_common_op_uses(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M1]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Z:%.*]])
+; CHECK-NEXT:    call void @use.f32(float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %x, float %y)
+  call void @use.f32(float %m1)
+  %m2 = call float @llvm.minnum.f32(float %x, float %z)
+  call void @use.f32(float %m2)
+  %m3 = call float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
+; Negative test - must have common operand.
+
+define float @minnum_no_common_op(float %x, float %y, float %z, float %w) {
+; CHECK-LABEL: @minnum_no_common_op(
+; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[W:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    ret float [[M3]]
+;
+  %m1 = call float @llvm.minnum.f32(float %x, float %y)
+  %m2 = call float @llvm.minnum.f32(float %w, float %z)
+  %m3 = call float @llvm.minnum.f32(float %m1, float %m2)
+  ret float %m3
+}
+
 define float @minnum_x_maxnum_x_y(float %x, float %y) {
 ; CHECK-LABEL: @minnum_x_maxnum_x_y(
 ; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])

>From 0c9bd594daefa070f8fd1111ab2fd3285f835573 Mon Sep 17 00:00:00 2001
From: Thomas Fry <thomas.fry at arm.com>
Date: Mon, 20 Apr 2026 13:09:54 +0200
Subject: [PATCH 2/2] [InstCombine] Enable factorizeMinMaxTree for
 floating-point values

---
 .../InstCombine/InstCombineCalls.cpp          | 21 +++++++++++++++++-
 llvm/test/Transforms/InstCombine/maximum.ll   | 22 +++++++------------
 .../test/Transforms/InstCombine/maximumnum.ll | 18 +++++----------
 llvm/test/Transforms/InstCombine/maxnum.ll    | 22 +++++++------------
 llvm/test/Transforms/InstCombine/minimum.ll   | 22 +++++++------------
 .../test/Transforms/InstCombine/minimumnum.ll | 18 +++++----------
 llvm/test/Transforms/InstCombine/minnum.ll    | 22 +++++++------------
 7 files changed, 64 insertions(+), 81 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index d97c66025cee7..7188fbc0de6dd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1481,7 +1481,23 @@ static Instruction *factorizeMinMaxTree(IntrinsicInst *II) {
   Module *Mod = II->getModule();
   Function *MinMax =
       Intrinsic::getOrInsertDeclaration(Mod, MinMaxID, II->getType());
-  return CallInst::Create(MinMax, { MinMaxOp, ThirdOp });
+  Instruction *RetI = CallInst::Create(MinMax, {MinMaxOp, ThirdOp});
+  if (isa<FPMathOperator>(II)) {
+    FastMathFlags IIFMF = II->getFastMathFlags();
+    FastMathFlags FoldedOpFMF =
+        (MinMaxOp == LHS ? RHS : LHS)->getFastMathFlags();
+    FastMathFlags RetFMF = IIFMF & FoldedOpFMF;
+    // Different intrinsics handle NaN propagation differently. For maximum and
+    // minimum, nnan does not rely on the folded instruction's flags. For the
+    // others, it does not rely on II's flags
+    if (MinMaxID == Intrinsic::maximum || MinMaxID == Intrinsic::minimum)
+      RetFMF.setNoNaNs(IIFMF.noNaNs());
+    if (MinMaxID == Intrinsic::maxnum || MinMaxID == Intrinsic::minnum ||
+        MinMaxID == Intrinsic::maximumnum || MinMaxID == Intrinsic::minimumnum)
+      RetFMF.setNoNaNs(FoldedOpFMF.noNaNs());
+    RetI->setFastMathFlags(RetFMF);
+  }
+  return RetI;
 }
 
 /// If all arguments of the intrinsic are unary shuffles with the same mask,
@@ -2861,6 +2877,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       return FNeg;
     }
 
+    if (Instruction *NewMinMax = factorizeMinMaxTree(II))
+       return NewMinMax;
+
     // m(m(X, C2), C1) -> m(X, C)
     const APFloat *C1, *C2;
     if (auto *M = dyn_cast<IntrinsicInst>(Arg0)) {
diff --git a/llvm/test/Transforms/InstCombine/maximum.ll b/llvm/test/Transforms/InstCombine/maximum.ll
index 296a231c7b86a..906a6644ba3d5 100644
--- a/llvm/test/Transforms/InstCombine/maximum.ll
+++ b/llvm/test/Transforms/InstCombine/maximum.ll
@@ -242,9 +242,8 @@ define float @maximum4(float %x, float %y, float %z, float %w) {
 
 define float @maximum_common_op(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maximum_common_op(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Z:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Z1:%.*]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximum.f32(float %x, float %y)
@@ -257,8 +256,7 @@ define float @maximum_reuse_lhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maximum_reuse_lhs(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximum.f32(float %x, float %y)
@@ -270,10 +268,9 @@ define float @maximum_reuse_lhs(float %x, float %y, float %z) {
 
 define float @maximum_reuse_rhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maximum_reuse_rhs(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[X:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maximum.f32(float [[Z1:%.*]], float [[X:%.*]])
 ; CHECK-NEXT:    call void @use(float [[Y]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximum.f32(float %y, float %x)
@@ -287,8 +284,7 @@ define float @maximum_reuse_lhs_nnan(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maximum_reuse_lhs_nnan(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maximum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maximum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximum.f32(float %x, float %y)
@@ -302,8 +298,7 @@ define float @maximum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maximum_reuse_lhs_nnan_folded_only(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call nnan float @llvm.maximum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximum.f32(float %x, float %y)
@@ -317,8 +312,7 @@ define float @maximum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maximum_reuse_lhs_fmf_intersection(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.maximum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.maximum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf float @llvm.maximum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximum.f32(float %x, float %y)
diff --git a/llvm/test/Transforms/InstCombine/maximumnum.ll b/llvm/test/Transforms/InstCombine/maximumnum.ll
index b405e2ea34360..5860e75fadda3 100644
--- a/llvm/test/Transforms/InstCombine/maximumnum.ll
+++ b/llvm/test/Transforms/InstCombine/maximumnum.ll
@@ -108,9 +108,8 @@ define float @maximumnum4(float %x, float %y, float %z, float %w) {
 define float @maximumnum_common_op(float %x, float %y, float %z) {
 ; CHECK-LABEL: define float @maximumnum_common_op(
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
-; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Z]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M2]], float [[Y]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
@@ -124,8 +123,7 @@ define float @maximumnum_reuse_lhs(float %x, float %y, float %z) {
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
@@ -138,10 +136,9 @@ define float @maximumnum_reuse_lhs(float %x, float %y, float %z) {
 define float @maximumnum_reuse_rhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: define float @maximumnum_reuse_rhs(
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
-; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[Y]], float [[X]])
 ; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[Z]], float [[X]])
 ; CHECK-NEXT:    call void @use(float [[M2]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M2]], float [[Y]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximumnum.f32(float %y, float %x)
@@ -156,8 +153,7 @@ define float @maximumnum_reuse_lhs_nnan(float %x, float %y, float %z) {
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maximumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
@@ -172,8 +168,7 @@ define float @maximumnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.maximumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maximumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
@@ -188,8 +183,7 @@ define float @maximumnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.maximumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.maximumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf float @llvm.maximumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maximumnum.f32(float %x, float %y)
diff --git a/llvm/test/Transforms/InstCombine/maxnum.ll b/llvm/test/Transforms/InstCombine/maxnum.ll
index fa4e7e42951f8..94e8c3a4af5a2 100644
--- a/llvm/test/Transforms/InstCombine/maxnum.ll
+++ b/llvm/test/Transforms/InstCombine/maxnum.ll
@@ -242,9 +242,8 @@ define float @maxnum4(float %x, float %y, float %z, float %w) {
 
 define float @maxnum_common_op(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maxnum_common_op(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Z:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maxnum.f32(float [[X]], float [[Z1:%.*]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maxnum.f32(float %x, float %y)
@@ -257,8 +256,7 @@ define float @maxnum_reuse_lhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maxnum_reuse_lhs(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.maxnum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maxnum.f32(float %x, float %y)
@@ -270,10 +268,9 @@ define float @maxnum_reuse_lhs(float %x, float %y, float %z) {
 
 define float @maxnum_reuse_rhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maxnum_reuse_rhs(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[X:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maxnum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.maxnum.f32(float [[Z1:%.*]], float [[X:%.*]])
 ; CHECK-NEXT:    call void @use(float [[Y]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maxnum.f32(float %y, float %x)
@@ -287,8 +284,7 @@ define float @maxnum_reuse_lhs_nnan(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maxnum_reuse_lhs_nnan(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maxnum.f32(float %x, float %y)
@@ -302,8 +298,7 @@ define float @maxnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maxnum_reuse_lhs_nnan_folded_only(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.maxnum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.maxnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maxnum.f32(float %x, float %y)
@@ -317,8 +312,7 @@ define float @maxnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
 ; CHECK-LABEL: @maxnum_reuse_lhs_fmf_intersection(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.maxnum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.maxnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf float @llvm.maxnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.maxnum.f32(float %x, float %y)
diff --git a/llvm/test/Transforms/InstCombine/minimum.ll b/llvm/test/Transforms/InstCombine/minimum.ll
index ab3375a0f4e2a..c0ea78d9d59de 100644
--- a/llvm/test/Transforms/InstCombine/minimum.ll
+++ b/llvm/test/Transforms/InstCombine/minimum.ll
@@ -243,9 +243,8 @@ define float @minimum4(float %x, float %y, float %z, float %w) {
 
 define float @minimum_common_op(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minimum_common_op(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Z:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Z1:%.*]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimum.f32(float %x, float %y)
@@ -258,8 +257,7 @@ define float @minimum_reuse_lhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minimum_reuse_lhs(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimum.f32(float %x, float %y)
@@ -271,10 +269,9 @@ define float @minimum_reuse_lhs(float %x, float %y, float %z) {
 
 define float @minimum_reuse_rhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minimum_reuse_rhs(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[X:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minimum.f32(float [[Z1:%.*]], float [[X:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[Y]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimum.f32(float %y, float %x)
@@ -288,8 +285,7 @@ define float @minimum_reuse_lhs_nnan(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minimum_reuse_lhs_nnan(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minimum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minimum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimum.f32(float %x, float %y)
@@ -303,8 +299,7 @@ define float @minimum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minimum_reuse_lhs_nnan_folded_only(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call nnan float @llvm.minimum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimum.f32(float %x, float %y)
@@ -318,8 +313,7 @@ define float @minimum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minimum_reuse_lhs_fmf_intersection(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.minimum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.minimum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf float @llvm.minimum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimum.f32(float %x, float %y)
diff --git a/llvm/test/Transforms/InstCombine/minimumnum.ll b/llvm/test/Transforms/InstCombine/minimumnum.ll
index 9117c69bc07df..d06464edd53a5 100644
--- a/llvm/test/Transforms/InstCombine/minimumnum.ll
+++ b/llvm/test/Transforms/InstCombine/minimumnum.ll
@@ -108,9 +108,8 @@ define float @minimumnum4(float %x, float %y, float %z, float %w) {
 define float @minimumnum_common_op(float %x, float %y, float %z) {
 ; CHECK-LABEL: define float @minimumnum_common_op(
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
-; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Z]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M2]], float [[Y]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
@@ -124,8 +123,7 @@ define float @minimumnum_reuse_lhs(float %x, float %y, float %z) {
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
@@ -138,10 +136,9 @@ define float @minimumnum_reuse_lhs(float %x, float %y, float %z) {
 define float @minimumnum_reuse_rhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: define float @minimumnum_reuse_rhs(
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
-; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[Y]], float [[X]])
 ; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[Z]], float [[X]])
 ; CHECK-NEXT:    call void @use.f32(float [[M2]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M2]], float [[Y]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimumnum.f32(float %y, float %x)
@@ -156,8 +153,7 @@ define float @minimumnum_reuse_lhs_nnan(float %x, float %y, float %z) {
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minimumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
@@ -172,8 +168,7 @@ define float @minimumnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.minimumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minimumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
@@ -188,8 +183,7 @@ define float @minimumnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) {
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.minimumnum.f32(float [[Z]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.minimumnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf float @llvm.minimumnum.f32(float [[M1]], float [[Z]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minimumnum.f32(float %x, float %y)
diff --git a/llvm/test/Transforms/InstCombine/minnum.ll b/llvm/test/Transforms/InstCombine/minnum.ll
index ebc9d6320ab5c..193c07f4a29c4 100644
--- a/llvm/test/Transforms/InstCombine/minnum.ll
+++ b/llvm/test/Transforms/InstCombine/minnum.ll
@@ -243,9 +243,8 @@ define float @minnum4(float %x, float %y, float %z, float %w) {
 
 define float @minnum_common_op(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minnum_common_op(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Z:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Z1:%.*]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Z1:%.*]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minnum.f32(float %x, float %y)
@@ -258,8 +257,7 @@ define float @minnum_reuse_lhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minnum_reuse_lhs(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[Z:%.*]] = call float @llvm.minnum.f32(float [[Z1:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[Z]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minnum.f32(float %x, float %y)
@@ -271,10 +269,9 @@ define float @minnum_reuse_lhs(float %x, float %y, float %z) {
 
 define float @minnum_reuse_rhs(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minnum_reuse_rhs(
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[X:%.*]])
-; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minnum.f32(float [[Z1:%.*]], float [[X]])
+; CHECK-NEXT:    [[Y:%.*]] = call float @llvm.minnum.f32(float [[Z1:%.*]], float [[X:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[Y]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M2]], float [[Y]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minnum.f32(float %y, float %x)
@@ -288,8 +285,7 @@ define float @minnum_reuse_lhs_nnan(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minnum_reuse_lhs_nnan(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minnum.f32(float %x, float %y)
@@ -303,8 +299,7 @@ define float @minnum_reuse_lhs_nnan_folded_only(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minnum_reuse_lhs_nnan_folded_only(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call nnan float @llvm.minnum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call nnan float @llvm.minnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minnum.f32(float %x, float %y)
@@ -318,8 +313,7 @@ define float @minnum_reuse_lhs_fmf_intersection(float %x, float %y, float %z) {
 ; CHECK-LABEL: @minnum_reuse_lhs_fmf_intersection(
 ; CHECK-NEXT:    [[M1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    call void @use.f32(float [[M1]])
-; CHECK-NEXT:    [[M2:%.*]] = call ninf afn float @llvm.minnum.f32(float [[Z:%.*]], float [[X]])
-; CHECK-NEXT:    [[M3:%.*]] = call ninf arcp float @llvm.minnum.f32(float [[M1]], float [[M2]])
+; CHECK-NEXT:    [[M3:%.*]] = call ninf float @llvm.minnum.f32(float [[M1]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[M3]]
 ;
   %m1 = call float @llvm.minnum.f32(float %x, float %y)



More information about the llvm-commits mailing list