[llvm] [InstCombine] Enable factorizeMinMaxTree for floating-point values (PR #193195)
Thomas Fry via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 23 02:57:13 PDT 2026
https://github.com/thofry updated https://github.com/llvm/llvm-project/pull/193195
>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/4] 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/4] [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)
>From 5624e99979d4e5fa2cd5c61273283b4acd60bc0d Mon Sep 17 00:00:00 2001
From: Thomas Fry <thomas.fry at arm.com>
Date: Tue, 21 Apr 2026 17:33:55 +0200
Subject: [PATCH 3/4] Fix formatting issue
---
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 7188fbc0de6dd..6be4b493146dd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2878,7 +2878,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
}
if (Instruction *NewMinMax = factorizeMinMaxTree(II))
- return NewMinMax;
+ return NewMinMax;
// m(m(X, C2), C1) -> m(X, C)
const APFloat *C1, *C2;
>From adcebf04d0ce78d75d4ee839def6337215f36442 Mon Sep 17 00:00:00 2001
From: Thomas Fry <thomas.fry at arm.com>
Date: Thu, 23 Apr 2026 11:42:34 +0200
Subject: [PATCH 4/4] Fix sNaN handling for maxnum and minnum
---
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 8 ++++----
llvm/test/Transforms/InstCombine/maxnum.ll | 2 +-
llvm/test/Transforms/InstCombine/minnum.ll | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 6be4b493146dd..9233d16c76397 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1488,12 +1488,12 @@ static Instruction *factorizeMinMaxTree(IntrinsicInst *II) {
(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
+ // minimum, nnan does not rely on the folded instruction's flags. For
+ // maximumnum and minimumnum, it does not rely on II's flags. maxnum and
+ // minnum rely on both so there is no special handling
if (MinMaxID == Intrinsic::maximum || MinMaxID == Intrinsic::minimum)
RetFMF.setNoNaNs(IIFMF.noNaNs());
- if (MinMaxID == Intrinsic::maxnum || MinMaxID == Intrinsic::minnum ||
- MinMaxID == Intrinsic::maximumnum || MinMaxID == Intrinsic::minimumnum)
+ if (MinMaxID == Intrinsic::maximumnum || MinMaxID == Intrinsic::minimumnum)
RetFMF.setNoNaNs(FoldedOpFMF.noNaNs());
RetI->setFastMathFlags(RetFMF);
}
diff --git a/llvm/test/Transforms/InstCombine/maxnum.ll b/llvm/test/Transforms/InstCombine/maxnum.ll
index 94e8c3a4af5a2..6d3eb846b5cbc 100644
--- a/llvm/test/Transforms/InstCombine/maxnum.ll
+++ b/llvm/test/Transforms/InstCombine/maxnum.ll
@@ -298,7 +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: [[M3:%.*]] = call nnan 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)
diff --git a/llvm/test/Transforms/InstCombine/minnum.ll b/llvm/test/Transforms/InstCombine/minnum.ll
index 193c07f4a29c4..10da2152b4747 100644
--- a/llvm/test/Transforms/InstCombine/minnum.ll
+++ b/llvm/test/Transforms/InstCombine/minnum.ll
@@ -299,7 +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: [[M3:%.*]] = call nnan 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)
More information about the llvm-commits
mailing list