[llvm] [NFC][InstSimplify] Refactor fminmax-folds.ll test (PR #160504)
Lewis Crawford via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 25 02:36:12 PDT 2025
https://github.com/LewisCrawford updated https://github.com/llvm/llvm-project/pull/160504
>From 9d94e548cfd5b49889640d99b5d51ad804c1f19f Mon Sep 17 00:00:00 2001
From: Lewis Crawford <lcrawford at nvidia.com>
Date: Wed, 24 Sep 2025 11:07:22 +0000
Subject: [PATCH] [NFC][InstSimplify] Refactor fminmax-folds.ll test
Refactor all the tests in fminmax-folds.ll so that they are
grouped by optimization, rather than by intrinsic.
Instead of calling 1 intrinsic per function, each function now
tests all 6 variants of the intrinsic. Results are stored to named
pointers to maintain readability in this more compact form. This
makes it much easier to compare the outputs from each intrinsic,
rather than having them scattered in different functions in different
parts of the file. It is also much more compact, so despite adding
>50% more tests, the file is ~500 lines shorter.
The tests added include:
* Adding maximumnum and minimumnum everywhere (currently not optimized,
but added as a baseline for future optimizations in #139581).
* Adding separate tests for SNaN and QNaN (as a baseline for
correctness improvements in #139581)
* Adding tests for scalable vectors
* Increasing the variety of types used in various tests by using
more f16, f64, and vector types in tests.
The only coverage removed is for tests with undef (only poison is now
tested for).
Overall, this refactor should increase coverage, improve readability
with more comments and clear section headers, and make the tests
much more compact and easier to review in #139581 by providing a
clear baseline for each intrinsic's current behaviour.
---
.../Transforms/InstSimplify/fminmax-folds.ll | 2234 +++++++----------
1 file changed, 850 insertions(+), 1384 deletions(-)
diff --git a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
index fff6cfd8a3b4b..26b51146057e9 100644
--- a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
+++ b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll
@@ -1,1388 +1,854 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
-declare half @llvm.minimum.f16(half, half)
-declare half @llvm.maximum.f16(half, half)
-
-declare float @llvm.minnum.f32(float, float)
-declare float @llvm.maxnum.f32(float, float)
-declare float @llvm.minimum.f32(float, float)
-declare float @llvm.maximum.f32(float, float)
-declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>)
-declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>)
-declare <2 x float> @llvm.minimum.v2f32(<2 x float>, <2 x float>)
-declare <2 x float> @llvm.maximum.v2f32(<2 x float>, <2 x float>)
-
-declare double @llvm.minnum.f64(double, double)
-declare double @llvm.maxnum.f64(double, double)
-declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
-declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
-declare double @llvm.minimum.f64(double, double)
-declare double @llvm.maximum.f64(double, double)
-declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
-declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
-
-define float @test_minnum_const_nan(float %x) {
-; CHECK-LABEL: @test_minnum_const_nan(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call float @llvm.minnum.f32(float %x, float 0x7fff000000000000)
- ret float %r
-}
-
-define float @test_maxnum_const_nan(float %x) {
-; CHECK-LABEL: @test_maxnum_const_nan(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call float @llvm.maxnum.f32(float %x, float 0x7fff000000000000)
- ret float %r
-}
-
-define float @test_maximum_const_nan(float %x) {
-; CHECK-LABEL: @test_maximum_const_nan(
-; CHECK-NEXT: ret float 0x7FFF000000000000
-;
- %r = call float @llvm.maximum.f32(float %x, float 0x7fff000000000000)
- ret float %r
-}
-
-define float @test_minimum_const_nan(float %x) {
-; CHECK-LABEL: @test_minimum_const_nan(
-; CHECK-NEXT: ret float 0x7FFF000000000000
-;
- %r = call float @llvm.minimum.f32(float %x, float 0x7fff000000000000)
- ret float %r
-}
-
-define float @test_minnum_const_inf(float %x) {
-; CHECK-LABEL: @test_minnum_const_inf(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0x7FF0000000000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.minnum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_maxnum_const_inf(float %x) {
-; CHECK-LABEL: @test_maxnum_const_inf(
-; CHECK-NEXT: ret float 0x7FF0000000000000
-;
- %r = call float @llvm.maxnum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_maximum_const_inf(float %x) {
-; CHECK-LABEL: @test_maximum_const_inf(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 0x7FF0000000000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.maximum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_minimum_const_inf(float %x) {
-; CHECK-LABEL: @test_minimum_const_inf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call float @llvm.minimum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_minnum_const_neg_inf(float %x) {
-; CHECK-LABEL: @test_minnum_const_neg_inf(
-; CHECK-NEXT: ret float 0xFFF0000000000000
-;
- %r = call float @llvm.minnum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_maxnum_const_neg_inf(float %x) {
-; CHECK-LABEL: @test_maxnum_const_neg_inf(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0xFFF0000000000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.maxnum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_maximum_const_neg_inf(float %x) {
-; CHECK-LABEL: @test_maximum_const_neg_inf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call float @llvm.maximum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_minimum_const_neg_inf(float %x) {
-; CHECK-LABEL: @test_minimum_const_neg_inf(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float 0xFFF0000000000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.minimum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_minnum_const_inf_nnan(float %x) {
-; CHECK-LABEL: @test_minnum_const_inf_nnan(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan float @llvm.minnum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_maxnum_const_inf_nnan(float %x) {
-; CHECK-LABEL: @test_maxnum_const_inf_nnan(
-; CHECK-NEXT: ret float 0x7FF0000000000000
-;
- %r = call nnan float @llvm.maxnum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_maximum_const_inf_nnan(float %x) {
-; CHECK-LABEL: @test_maximum_const_inf_nnan(
-; CHECK-NEXT: ret float 0x7FF0000000000000
-;
- %r = call nnan float @llvm.maximum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_minimum_const_inf_nnan(float %x) {
-; CHECK-LABEL: @test_minimum_const_inf_nnan(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan float @llvm.minimum.f32(float %x, float 0x7ff0000000000000)
- ret float %r
-}
-
-define float @test_minnum_const_inf_nnan_comm(float %x) {
-; CHECK-LABEL: @test_minnum_const_inf_nnan_comm(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan float @llvm.minnum.f32(float 0x7ff0000000000000, float %x)
- ret float %r
-}
-
-define float @test_maxnum_const_inf_nnan_comm(float %x) {
-; CHECK-LABEL: @test_maxnum_const_inf_nnan_comm(
-; CHECK-NEXT: ret float 0x7FF0000000000000
-;
- %r = call nnan float @llvm.maxnum.f32(float 0x7ff0000000000000, float %x)
- ret float %r
-}
-
-define float @test_maximum_const_inf_nnan_comm(float %x) {
-; CHECK-LABEL: @test_maximum_const_inf_nnan_comm(
-; CHECK-NEXT: ret float 0x7FF0000000000000
-;
- %r = call nnan float @llvm.maximum.f32(float 0x7ff0000000000000, float %x)
- ret float %r
-}
-
-define float @test_minimum_const_inf_nnan_comm(float %x) {
-; CHECK-LABEL: @test_minimum_const_inf_nnan_comm(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan float @llvm.minimum.f32(float 0x7ff0000000000000, float %x)
- ret float %r
-}
-
-define <2 x float> @test_minnum_const_inf_nnan_comm_vec(<2 x float> %x) {
-; CHECK-LABEL: @test_minnum_const_inf_nnan_comm_vec(
-; CHECK-NEXT: ret <2 x float> [[X:%.*]]
-;
- %r = call nnan <2 x float> @llvm.minnum.v2f32(<2 x float> <float 0x7ff0000000000000, float 0x7ff0000000000000>, <2 x float> %x)
- ret <2 x float> %r
-}
-
-define <2 x float> @test_maxnum_const_inf_nnan_comm_vec(<2 x float> %x) {
-; CHECK-LABEL: @test_maxnum_const_inf_nnan_comm_vec(
-; CHECK-NEXT: ret <2 x float> splat (float 0x7FF0000000000000)
-;
- %r = call nnan <2 x float> @llvm.maxnum.v2f32(<2 x float> <float 0x7ff0000000000000, float 0x7ff0000000000000>, <2 x float> %x)
- ret <2 x float> %r
-}
-
-define <2 x float> @test_maximum_const_inf_nnan_comm_vec(<2 x float> %x) {
-; CHECK-LABEL: @test_maximum_const_inf_nnan_comm_vec(
-; CHECK-NEXT: ret <2 x float> splat (float 0x7FF0000000000000)
-;
- %r = call nnan <2 x float> @llvm.maximum.v2f32(<2 x float> <float 0x7ff0000000000000, float 0x7ff0000000000000>, <2 x float> %x)
- ret <2 x float> %r
-}
-
-define <2 x float> @test_minimum_const_inf_nnan_comm_vec(<2 x float> %x) {
-; CHECK-LABEL: @test_minimum_const_inf_nnan_comm_vec(
-; CHECK-NEXT: ret <2 x float> [[X:%.*]]
-;
- %r = call nnan <2 x float> @llvm.minimum.v2f32(<2 x float> <float 0x7ff0000000000000, float 0x7ff0000000000000>, <2 x float> %x)
- ret <2 x float> %r
-}
-
-define float @test_minnum_const_neg_inf_nnan(float %x) {
-; CHECK-LABEL: @test_minnum_const_neg_inf_nnan(
-; CHECK-NEXT: ret float 0xFFF0000000000000
-;
- %r = call nnan float @llvm.minnum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_maxnum_const_neg_inf_nnan(float %x) {
-; CHECK-LABEL: @test_maxnum_const_neg_inf_nnan(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan float @llvm.maxnum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_maximum_const_neg_inf_nnan(float %x) {
-; CHECK-LABEL: @test_maximum_const_neg_inf_nnan(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan float @llvm.maximum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_minimum_const_neg_inf_nnan(float %x) {
-; CHECK-LABEL: @test_minimum_const_neg_inf_nnan(
-; CHECK-NEXT: ret float 0xFFF0000000000000
-;
- %r = call nnan float @llvm.minimum.f32(float %x, float 0xfff0000000000000)
- ret float %r
-}
-
-define float @test_minnum_const_max(float %x) {
-; CHECK-LABEL: @test_minnum_const_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.minnum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_maxnum_const_max(float %x) {
-; CHECK-LABEL: @test_maxnum_const_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.maxnum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_maximum_const_max(float %x) {
-; CHECK-LABEL: @test_maximum_const_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.maximum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_minimum_const_max(float %x) {
-; CHECK-LABEL: @test_minimum_const_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.minimum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_minnum_const_neg_max(float %x) {
-; CHECK-LABEL: @test_minnum_const_neg_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.minnum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_maxnum_const_neg_max(float %x) {
-; CHECK-LABEL: @test_maxnum_const_neg_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.maxnum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_maximum_const_neg_max(float %x) {
-; CHECK-LABEL: @test_maximum_const_neg_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.maximum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_minimum_const_neg_max(float %x) {
-; CHECK-LABEL: @test_minimum_const_neg_max(
-; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call float @llvm.minimum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_minnum_const_max_ninf(float %x) {
-; CHECK-LABEL: @test_minnum_const_max_ninf(
-; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.minnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call ninf float @llvm.minnum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_maxnum_const_max_ninf(float %x) {
-; CHECK-LABEL: @test_maxnum_const_max_ninf(
-; CHECK-NEXT: ret float 0x47EFFFFFE0000000
-;
- %r = call ninf float @llvm.maxnum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_maximum_const_max_ninf(float %x) {
-; CHECK-LABEL: @test_maximum_const_max_ninf(
-; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.maximum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call ninf float @llvm.maximum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_minimum_const_max_ninf(float %x) {
-; CHECK-LABEL: @test_minimum_const_max_ninf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call ninf float @llvm.minimum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_minnum_const_neg_max_ninf(float %x) {
-; CHECK-LABEL: @test_minnum_const_neg_max_ninf(
-; CHECK-NEXT: ret float 0xC7EFFFFFE0000000
-;
- %r = call ninf float @llvm.minnum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_maxnum_const_neg_max_ninf(float %x) {
-; CHECK-LABEL: @test_maxnum_const_neg_max_ninf(
-; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.maxnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call ninf float @llvm.maxnum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_maximum_const_neg_max_ninf(float %x) {
-; CHECK-LABEL: @test_maximum_const_neg_max_ninf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call ninf float @llvm.maximum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_minimum_const_neg_max_ninf(float %x) {
-; CHECK-LABEL: @test_minimum_const_neg_max_ninf(
-; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.minimum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
-; CHECK-NEXT: ret float [[R]]
-;
- %r = call ninf float @llvm.minimum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_minnum_const_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_minnum_const_max_nnan_ninf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan ninf float @llvm.minnum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_maxnum_const_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_maxnum_const_max_nnan_ninf(
-; CHECK-NEXT: ret float 0x47EFFFFFE0000000
-;
- %r = call nnan ninf float @llvm.maxnum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_maximum_const_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_maximum_const_max_nnan_ninf(
-; CHECK-NEXT: ret float 0x47EFFFFFE0000000
-;
- %r = call nnan ninf float @llvm.maximum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_minimum_const_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_minimum_const_max_nnan_ninf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan ninf float @llvm.minimum.f32(float %x, float 0x47efffffe0000000)
- ret float %r
-}
-
-define float @test_minnum_const_neg_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_minnum_const_neg_max_nnan_ninf(
-; CHECK-NEXT: ret float 0xC7EFFFFFE0000000
-;
- %r = call nnan ninf float @llvm.minnum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_maxnum_const_neg_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_maxnum_const_neg_max_nnan_ninf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan ninf float @llvm.maxnum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_maximum_const_neg_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_maximum_const_neg_max_nnan_ninf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %r = call nnan ninf float @llvm.maximum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-define float @test_minimum_const_neg_max_nnan_ninf(float %x) {
-; CHECK-LABEL: @test_minimum_const_neg_max_nnan_ninf(
-; CHECK-NEXT: ret float 0xC7EFFFFFE0000000
-;
- %r = call nnan ninf float @llvm.minimum.f32(float %x, float 0xc7efffffe0000000)
- ret float %r
-}
-
-; From the LangRef for minnum/maxnum:
-; "If either operand is a NaN, returns the other non-NaN operand."
-
-define double @maxnum_nan_op0(double %x) {
-; CHECK-LABEL: @maxnum_nan_op0(
-; CHECK-NEXT: ret double [[X:%.*]]
-;
- %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x)
- ret double %r
-}
-
-define double @maxnum_nan_op1(double %x) {
-; CHECK-LABEL: @maxnum_nan_op1(
-; CHECK-NEXT: ret double [[X:%.*]]
-;
- %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead)
- ret double %r
-}
-
-define double @minnum_nan_op0(double %x) {
-; CHECK-LABEL: @minnum_nan_op0(
-; CHECK-NEXT: ret double [[X:%.*]]
-;
- %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x)
- ret double %r
-}
-
-define double @minnum_nan_op1(double %x) {
-; CHECK-LABEL: @minnum_nan_op1(
-; CHECK-NEXT: ret double [[X:%.*]]
-;
- %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead)
- ret double %r
-}
-
-define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) {
-; CHECK-LABEL: @maxnum_nan_op0_vec(
-; CHECK-NEXT: ret <2 x double> [[X:%.*]]
-;
- %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double poison>, <2 x double> %x)
- ret <2 x double> %r
-}
-
-define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) {
-; CHECK-LABEL: @maxnum_nan_op1_vec(
-; CHECK-NEXT: ret <2 x double> [[X:%.*]]
-;
- %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
- ret <2 x double> %r
-}
-
-define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) {
-; CHECK-LABEL: @minnum_nan_op0_vec(
-; CHECK-NEXT: ret <2 x double> [[X:%.*]]
-;
- %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double poison, double 0x7ff8000dead00000>, <2 x double> %x)
- ret <2 x double> %r
-}
-
-define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) {
-; CHECK-LABEL: @minnum_nan_op1_vec(
-; CHECK-NEXT: ret <2 x double> [[X:%.*]]
-;
- %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
- ret <2 x double> %r
-}
-
-define float @maxnum_undef_op1(float %x) {
-; CHECK-LABEL: @maxnum_undef_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maxnum.f32(float %x, float undef)
- ret float %val
-}
-
-define float @maxnum_poison_op1(float %x) {
-; CHECK-LABEL: @maxnum_poison_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maxnum.f32(float %x, float poison)
- ret float %val
-}
-
-define float @maxnum_undef_op0(float %x) {
-; CHECK-LABEL: @maxnum_undef_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maxnum.f32(float undef, float %x)
- ret float %val
-}
-
-define float @maxnum_poison_op0(float %x) {
-; CHECK-LABEL: @maxnum_poison_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maxnum.f32(float poison, float %x)
- ret float %val
-}
-
-define float @minnum_undef_op1(float %x) {
-; CHECK-LABEL: @minnum_undef_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minnum.f32(float %x, float undef)
- ret float %val
-}
-
-define float @minnum_poison_op1(float %x) {
-; CHECK-LABEL: @minnum_poison_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minnum.f32(float %x, float poison)
- ret float %val
-}
-
-define float @minnum_undef_op0(float %x) {
-; CHECK-LABEL: @minnum_undef_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minnum.f32(float undef, float %x)
- ret float %val
-}
-
-define float @minnum_poison_op0(float %x) {
-; CHECK-LABEL: @minnum_poison_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minnum.f32(float poison, float %x)
- ret float %val
-}
-
-define float @minnum_undef_undef(float %x) {
-; CHECK-LABEL: @minnum_undef_undef(
-; CHECK-NEXT: ret float undef
-;
- %val = call float @llvm.minnum.f32(float undef, float undef)
- ret float %val
-}
-
-define float @minnum_poison_undef(float %x) {
-; CHECK-LABEL: @minnum_poison_undef(
-; CHECK-NEXT: ret float undef
-;
- %val = call float @llvm.minnum.f32(float poison, float undef)
- ret float %val
-}
-
-define float @minnum_undef_poison(float %x) {
-; CHECK-LABEL: @minnum_undef_poison(
-; CHECK-NEXT: ret float poison
-;
- %val = call float @llvm.minnum.f32(float undef, float poison)
- ret float %val
-}
-
-define float @maxnum_undef_undef(float %x) {
-; CHECK-LABEL: @maxnum_undef_undef(
-; CHECK-NEXT: ret float undef
-;
- %val = call float @llvm.maxnum.f32(float undef, float undef)
- ret float %val
-}
-
-define float @maxnum_poison_undef(float %x) {
-; CHECK-LABEL: @maxnum_poison_undef(
-; CHECK-NEXT: ret float undef
-;
- %val = call float @llvm.maxnum.f32(float poison, float undef)
- ret float %val
-}
-
-define float @maxnum_undef_poison(float %x) {
-; CHECK-LABEL: @maxnum_undef_poison(
-; CHECK-NEXT: ret float poison
-;
- %val = call float @llvm.maxnum.f32(float undef, float poison)
- ret float %val
-}
-
-define float @minnum_same_args(float %x) {
-; CHECK-LABEL: @minnum_same_args(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %y = call float @llvm.minnum.f32(float %x, float %x)
- ret float %y
-}
-
-define float @maxnum_same_args(float %x) {
-; CHECK-LABEL: @maxnum_same_args(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %y = call float @llvm.maxnum.f32(float %x, float %x)
- ret float %y
-}
-
-define float @minnum_x_minnum_x_y(float %x, float %y) {
-; CHECK-LABEL: @minnum_x_minnum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minnum.f32(float %x, float %y)
- %b = call float @llvm.minnum.f32(float %x, float %a)
- ret float %b
-}
-
-define float @minnum_y_minnum_x_y(float %x, float %y) {
-; CHECK-LABEL: @minnum_y_minnum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minnum.f32(float %x, float %y)
- %b = call float @llvm.minnum.f32(float %y, float %a)
- ret float %b
-}
-
-define float @minnum_x_y_minnum_x(float %x, float %y) {
-; CHECK-LABEL: @minnum_x_y_minnum_x(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minnum.f32(float %x, float %y)
- %b = call float @llvm.minnum.f32(float %a, float %x)
- ret float %b
-}
-
-define float @minnum_x_y_minnum_y(float %x, float %y) {
-; CHECK-LABEL: @minnum_x_y_minnum_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minnum.f32(float %x, float %y)
- %b = call float @llvm.minnum.f32(float %a, float %y)
- ret float %b
-}
-
-; negative test
-
-define float @minnum_z_minnum_x_y(float %x, float %y, float %z) {
-; CHECK-LABEL: @minnum_z_minnum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[A]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.minnum.f32(float %x, float %y)
- %b = call float @llvm.minnum.f32(float %z, float %a)
- ret float %b
-}
-
-; negative test
-
-define float @minnum_x_y_minnum_z(float %x, float %y, float %z) {
-; CHECK-LABEL: @minnum_x_y_minnum_z(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.minnum.f32(float [[A]], float [[Z:%.*]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.minnum.f32(float %x, float %y)
- %b = call float @llvm.minnum.f32(float %a, float %z)
- ret float %b
-}
-
-; minnum(X, -INF) --> -INF
-
-define float @minnum_neginf(float %x) {
-; CHECK-LABEL: @minnum_neginf(
-; CHECK-NEXT: ret float 0xFFF0000000000000
-;
- %val = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
- ret float %val
-}
-
-define <2 x double> @minnum_neginf_commute_vec(<2 x double> %x) {
-; CHECK-LABEL: @minnum_neginf_commute_vec(
-; CHECK-NEXT: ret <2 x double> splat (double 0xFFF0000000000000)
-;
- %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
- ret <2 x double> %r
-}
-
-; negative test
-
-define float @minnum_inf(float %x) {
-; CHECK-LABEL: @minnum_inf(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.minnum.f32(float 0x7FF0000000000000, float [[X:%.*]])
-; CHECK-NEXT: ret float [[VAL]]
-;
- %val = call float @llvm.minnum.f32(float 0x7FF0000000000000, float %x)
- ret float %val
-}
-define float @maxnum_x_maxnum_x_y(float %x, float %y) {
-; CHECK-LABEL: @maxnum_x_maxnum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maxnum.f32(float %x, float %y)
- %b = call float @llvm.maxnum.f32(float %x, float %a)
- ret float %b
-}
-
-define float @maxnum_y_maxnum_x_y(float %x, float %y) {
-; CHECK-LABEL: @maxnum_y_maxnum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maxnum.f32(float %x, float %y)
- %b = call float @llvm.maxnum.f32(float %y, float %a)
- ret float %b
-}
-
-define float @maxnum_x_y_maxnum_x(float %x, float %y) {
-; CHECK-LABEL: @maxnum_x_y_maxnum_x(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maxnum.f32(float %x, float %y)
- %b = call float @llvm.maxnum.f32(float %a, float %x)
- ret float %b
-}
-
-define float @maxnum_x_y_maxnum_y(float %x, float %y) {
-; CHECK-LABEL: @maxnum_x_y_maxnum_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maxnum.f32(float %x, float %y)
- %b = call float @llvm.maxnum.f32(float %a, float %y)
- ret float %b
-}
-
-; negative test
-
-define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) {
-; CHECK-LABEL: @maxnum_z_maxnum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[A]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.maxnum.f32(float %x, float %y)
- %b = call float @llvm.maxnum.f32(float %z, float %a)
- ret float %b
-}
-
-; negative test
-
-define float @maxnum_x_y_maxnum_z(float %x, float %y, float %z) {
-; CHECK-LABEL: @maxnum_x_y_maxnum_z(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[Z:%.*]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.maxnum.f32(float %x, float %y)
- %b = call float @llvm.maxnum.f32(float %a, float %z)
- ret float %b
-}
-
-; maxnum(X, INF) --> INF
-
-define <2 x double> @maxnum_inf(<2 x double> %x) {
-; CHECK-LABEL: @maxnum_inf(
-; CHECK-NEXT: ret <2 x double> splat (double 0x7FF0000000000000)
-;
- %val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
- ret <2 x double> %val
-}
-
-define float @maxnum_inf_commute(float %x) {
-; CHECK-LABEL: @maxnum_inf_commute(
-; CHECK-NEXT: ret float 0x7FF0000000000000
-;
- %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x)
- ret float %val
-}
-
-; negative test
-
-define float @maxnum_neginf(float %x) {
-; CHECK-LABEL: @maxnum_neginf(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float [[X:%.*]])
-; CHECK-NEXT: ret float [[VAL]]
-;
- %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x)
- ret float %val
-}
-
-; From the LangRef for minimum/maximum:
-; "If either operand is a NaN, returns NaN."
-
-define double @maximum_nan_op0(double %x) {
-; CHECK-LABEL: @maximum_nan_op0(
-; CHECK-NEXT: ret double 0x7FF8000000000000
-;
- %r = call double @llvm.maximum.f64(double 0x7ff8000000000000, double %x)
- ret double %r
-}
-
-define double @maximum_nan_op1(double %x) {
-; CHECK-LABEL: @maximum_nan_op1(
-; CHECK-NEXT: ret double 0x7FF800000000DEAD
-;
- %r = call double @llvm.maximum.f64(double %x, double 0x7ff800000000dead)
- ret double %r
-}
-
-define double @minimum_nan_op0(double %x) {
-; CHECK-LABEL: @minimum_nan_op0(
-; CHECK-NEXT: ret double 0x7FF8000DEAD00000
-;
- %r = call double @llvm.minimum.f64(double 0x7ff8000dead00000, double %x)
- ret double %r
-}
-
-define double @minimum_nan_op1(double %x) {
-; CHECK-LABEL: @minimum_nan_op1(
-; CHECK-NEXT: ret double 0x7FF800DEAD00DEAD
-;
- %r = call double @llvm.minimum.f64(double %x, double 0x7ff800dead00dead)
- ret double %r
-}
-
-define <2 x double> @maximum_nan_op0_vec_partial_poison(<2 x double> %x) {
-; CHECK-LABEL: @maximum_nan_op0_vec_partial_poison(
-; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double poison>
-;
- %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7ff8000000000000, double poison>, <2 x double> %x)
- ret <2 x double> %r
-}
-
-define <2 x double> @maximum_nan_op1_vec_partial_poison(<2 x double> %x) {
-; CHECK-LABEL: @maximum_nan_op1_vec_partial_poison(
-; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double poison>
-;
- %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff8000000000000, double poison>)
- ret <2 x double> %r
-}
-
-define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) {
-; CHECK-LABEL: @maximum_nan_op1_vec(
-; CHECK-NEXT: ret <2 x double> <double 0x7FF800000000DEAD, double 0x7FF8FFFFFFFFFFFF>
-;
- %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
- ret <2 x double> %r
-}
-
-define <2 x double> @minimum_nan_op0_vec_partial_poison(<2 x double> %x) {
-; CHECK-LABEL: @minimum_nan_op0_vec_partial_poison(
-; CHECK-NEXT: ret <2 x double> <double poison, double 0x7FF8000DEAD00000>
-;
- %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double poison, double 0x7ff8000dead00000>, <2 x double> %x)
- ret <2 x double> %r
-}
-
-define <2 x double> @minimum_nan_op1_vec_partial_poison(<2 x double> %x) {
-; CHECK-LABEL: @minimum_nan_op1_vec_partial_poison(
-; CHECK-NEXT: ret <2 x double> <double poison, double 0x7FF8000DEAD00000>
-;
- %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double poison, double 0x7ff8000dead00000>)
- ret <2 x double> %r
-}
-
-define <2 x double> @minimum_nan_op1_vec(<2 x double> %x) {
-; CHECK-LABEL: @minimum_nan_op1_vec(
-; CHECK-NEXT: ret <2 x double> splat (double 0x7FF800DEAD00DEAD)
-;
- %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
- ret <2 x double> %r
-}
-
-define float @maximum_undef_op1(float %x) {
-; CHECK-LABEL: @maximum_undef_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maximum.f32(float %x, float undef)
- ret float %val
-}
-
-define float @maximum_poison_op1(float %x) {
-; CHECK-LABEL: @maximum_poison_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maximum.f32(float %x, float poison)
- ret float %val
-}
-
-define float @maximum_undef_op0(float %x) {
-; CHECK-LABEL: @maximum_undef_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maximum.f32(float undef, float %x)
- ret float %val
-}
-
-define float @maximum_poison_op0(float %x) {
-; CHECK-LABEL: @maximum_poison_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.maximum.f32(float poison, float %x)
- ret float %val
-}
-
-define float @minimum_undef_op1(float %x) {
-; CHECK-LABEL: @minimum_undef_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minimum.f32(float %x, float undef)
- ret float %val
-}
-
-define float @minimum_poison_op1(float %x) {
-; CHECK-LABEL: @minimum_poison_op1(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minimum.f32(float %x, float poison)
- ret float %val
-}
-
-define float @minimum_undef_op0(float %x) {
-; CHECK-LABEL: @minimum_undef_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minimum.f32(float undef, float %x)
- ret float %val
-}
-
-define float @minimum_poison_op0(float %x) {
-; CHECK-LABEL: @minimum_poison_op0(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minimum.f32(float poison, float %x)
- ret float %val
-}
-
-define float @minimum_undef_undef(float %x) {
-; CHECK-LABEL: @minimum_undef_undef(
-; CHECK-NEXT: ret float undef
-;
- %val = call float @llvm.minimum.f32(float undef, float undef)
- ret float %val
-}
-
-define float @maximum_undef_undef(float %x) {
-; CHECK-LABEL: @maximum_undef_undef(
-; CHECK-NEXT: ret float undef
-;
- %val = call float @llvm.maximum.f32(float undef, float undef)
- ret float %val
-}
-
-define float @minimum_same_args(float %x) {
-; CHECK-LABEL: @minimum_same_args(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %y = call float @llvm.minimum.f32(float %x, float %x)
- ret float %y
-}
-
-define float @maximum_same_args(float %x) {
-; CHECK-LABEL: @maximum_same_args(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %y = call float @llvm.maximum.f32(float %x, float %x)
- ret float %y
-}
-
-define float @minimum_x_minimum_x_y(float %x, float %y) {
-; CHECK-LABEL: @minimum_x_minimum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minimum.f32(float %x, float %y)
- %b = call float @llvm.minimum.f32(float %x, float %a)
- ret float %b
-}
-
-define float @minimum_y_minimum_x_y(float %x, float %y) {
-; CHECK-LABEL: @minimum_y_minimum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minimum.f32(float %x, float %y)
- %b = call float @llvm.minimum.f32(float %y, float %a)
- ret float %b
-}
-
-define float @minimum_x_y_minimum_x(float %x, float %y) {
-; CHECK-LABEL: @minimum_x_y_minimum_x(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minimum.f32(float %x, float %y)
- %b = call float @llvm.minimum.f32(float %a, float %x)
- ret float %b
-}
-
-define float @minimum_x_y_minimum_y(float %x, float %y) {
-; CHECK-LABEL: @minimum_x_y_minimum_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.minimum.f32(float %x, float %y)
- %b = call float @llvm.minimum.f32(float %a, float %y)
- ret float %b
-}
-
-; negative test
-
-define float @minimum_z_minimum_x_y(float %x, float %y, float %z) {
-; CHECK-LABEL: @minimum_z_minimum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[A]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.minimum.f32(float %x, float %y)
- %b = call float @llvm.minimum.f32(float %z, float %a)
- ret float %b
-}
-
-; negative test
-
-define float @minimum_x_y_minimum_z(float %x, float %y, float %z) {
-; CHECK-LABEL: @minimum_x_y_minimum_z(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.minimum.f32(float [[A]], float [[Z:%.*]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.minimum.f32(float %x, float %y)
- %b = call float @llvm.minimum.f32(float %a, float %z)
- ret float %b
-}
-
-define float @maximum_x_maximum_x_y(float %x, float %y) {
-; CHECK-LABEL: @maximum_x_maximum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maximum.f32(float %x, float %y)
- %b = call float @llvm.maximum.f32(float %x, float %a)
- ret float %b
-}
-
-define float @maximum_y_maximum_x_y(float %x, float %y) {
-; CHECK-LABEL: @maximum_y_maximum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maximum.f32(float %x, float %y)
- %b = call float @llvm.maximum.f32(float %y, float %a)
- ret float %b
-}
-
-define float @maximum_x_y_maximum_x(float %x, float %y) {
-; CHECK-LABEL: @maximum_x_y_maximum_x(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maximum.f32(float %x, float %y)
- %b = call float @llvm.maximum.f32(float %a, float %x)
- ret float %b
-}
-
-define float @maximum_x_y_maximum_y(float %x, float %y) {
-; CHECK-LABEL: @maximum_x_y_maximum_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[A]]
-;
- %a = call float @llvm.maximum.f32(float %x, float %y)
- %b = call float @llvm.maximum.f32(float %a, float %y)
- ret float %b
-}
-
-; negative test
-
-define float @maximum_z_maximum_x_y(float %x, float %y, float %z) {
-; CHECK-LABEL: @maximum_z_maximum_x_y(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[A]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.maximum.f32(float %x, float %y)
- %b = call float @llvm.maximum.f32(float %z, float %a)
- ret float %b
-}
-
-; negative test
-
-define float @maximum_x_y_maximum_z(float %x, float %y, float %z) {
-; CHECK-LABEL: @maximum_x_y_maximum_z(
-; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[Z:%.*]])
-; CHECK-NEXT: ret float [[B]]
-;
- %a = call float @llvm.maximum.f32(float %x, float %y)
- %b = call float @llvm.maximum.f32(float %a, float %z)
- ret float %b
-}
-
-; negative test - minimum(X, -INF) != -INF because X could be NaN
-
-define float @minimum_neginf(float %x) {
-; CHECK-LABEL: @minimum_neginf(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float 0xFFF0000000000000)
-; CHECK-NEXT: ret float [[VAL]]
-;
- %val = call float @llvm.minimum.f32(float %x, float 0xFFF0000000000000)
- ret float %val
-}
-
-; negative test - minimum(-INF, X) != -INF because X could be NaN
-
-define <2 x double> @minimum_neginf_commute_vec(<2 x double> %x) {
-; CHECK-LABEL: @minimum_neginf_commute_vec(
-; CHECK-NEXT: [[R:%.*]] = call <2 x double> @llvm.minimum.v2f64(<2 x double> splat (double 0xFFF0000000000000), <2 x double> [[X:%.*]])
-; CHECK-NEXT: ret <2 x double> [[R]]
-;
- %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
- ret <2 x double> %r
-}
-
-; TODO: minimum(INF, X) --> X
-
-define float @minimum_inf(float %x) {
-; CHECK-LABEL: @minimum_inf(
-; CHECK-NEXT: ret float [[X:%.*]]
-;
- %val = call float @llvm.minimum.f32(float 0x7FF0000000000000, float %x)
- ret float %val
-}
-
-; negative test - maximum(X, INF) != INF because X could be NaN
-
-define <2 x double> @maximum_inf(<2 x double> %x) {
-; CHECK-LABEL: @maximum_inf(
-; CHECK-NEXT: [[VAL:%.*]] = call <2 x double> @llvm.maximum.v2f64(<2 x double> [[X:%.*]], <2 x double> splat (double 0x7FF0000000000000))
-; CHECK-NEXT: ret <2 x double> [[VAL]]
-;
- %val = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
- ret <2 x double> %val
-}
-
-; negative test - maximum(INF, X) != INF because X could be NaN
-
-define float @maximum_inf_commute(float %x) {
-; CHECK-LABEL: @maximum_inf_commute(
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.maximum.f32(float 0x7FF0000000000000, float [[X:%.*]])
-; CHECK-NEXT: ret float [[VAL]]
-;
- %val = call float @llvm.maximum.f32(float 0x7FF0000000000000, float %x)
- ret float %val
-}
-
-define float @maximum_maximum_minimum(float %x, float %y) {
-; CHECK-LABEL: @maximum_maximum_minimum(
-; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[MAX]]
-;
- %max = call float @llvm.maximum.f32(float %x, float %y)
- %min = call float @llvm.minimum.f32(float %x, float %y)
- %val = call float @llvm.maximum.f32(float %max, float %min)
- ret float %val
-}
-
-define double @maximum_minimum_maximum(double %x, double %y) {
-; CHECK-LABEL: @maximum_minimum_maximum(
-; CHECK-NEXT: [[MAX:%.*]] = call double @llvm.maximum.f64(double [[X:%.*]], double [[Y:%.*]])
-; CHECK-NEXT: ret double [[MAX]]
-;
- %max = call double @llvm.maximum.f64(double %x, double %y)
- %min = call double @llvm.minimum.f64(double %x, double %y)
- %val = call double @llvm.maximum.f64(double %min, double %max)
- ret double %val
-}
-
-define float @maximum_minimum_minimum(float %x, float %y) {
-; CHECK-LABEL: @maximum_minimum_minimum(
-; CHECK-NEXT: [[MIN1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[MIN2:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]])
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.maximum.f32(float [[MIN1]], float [[MIN2]])
-; CHECK-NEXT: ret float [[VAL]]
-;
- %min1 = call float @llvm.minimum.f32(float %x, float %y)
- %min2 = call float @llvm.minimum.f32(float %x, float %y)
- %val = call float @llvm.maximum.f32(float %min1, float %min2)
- ret float %val
-}
-
-define half @maximum_maximum_maximum(half %x, half %y) {
-; CHECK-LABEL: @maximum_maximum_maximum(
-; CHECK-NEXT: [[MAX1:%.*]] = call half @llvm.maximum.f16(half [[X:%.*]], half [[Y:%.*]])
-; CHECK-NEXT: ret half [[MAX1]]
-;
- %max1 = call half @llvm.maximum.f16(half %x, half %y)
- %max2 = call half @llvm.maximum.f16(half %x, half %y)
- %val = call half @llvm.maximum.f16(half %max1, half %max2)
- ret half %val
-}
-
-define <2 x float> @minimum_maximum_minimum(<2 x float> %x, <2 x float> %y) {
-; CHECK-LABEL: @minimum_maximum_minimum(
-; CHECK-NEXT: [[MIN:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])
-; CHECK-NEXT: ret <2 x float> [[MIN]]
-;
- %max = call <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> %y)
- %min = call <2 x float> @llvm.minimum.v2f32(<2 x float> %x, <2 x float> %y)
- %val = call <2 x float> @llvm.minimum.v2f32(<2 x float> %max, <2 x float> %min)
- ret <2 x float> %val
-}
-
-define <2 x double> @minimum_minimum_maximum(<2 x double> %x, <2 x double> %y) {
-; CHECK-LABEL: @minimum_minimum_maximum(
-; CHECK-NEXT: [[MIN:%.*]] = call <2 x double> @llvm.minimum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]])
-; CHECK-NEXT: ret <2 x double> [[MIN]]
-;
- %max = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> %y)
- %min = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> %y)
- %val = call <2 x double> @llvm.minimum.v2f64(<2 x double> %min, <2 x double> %max)
- ret <2 x double> %val
-}
-
-define float @minimum_maximum_maximum(float %x, float %y) {
-; CHECK-LABEL: @minimum_maximum_maximum(
-; CHECK-NEXT: [[MAX1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: [[MAX2:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
-; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.minimum.f32(float [[MAX1]], float [[MAX2]])
-; CHECK-NEXT: ret float [[VAL]]
-;
- %max1 = call float @llvm.maximum.f32(float %x, float %y)
- %max2 = call float @llvm.maximum.f32(float %x, float %y)
- %val = call float @llvm.minimum.f32(float %max1, float %max2)
- ret float %val
-}
-
-define float @minimum_minimum_minimum(float %x, float %y) {
-; CHECK-LABEL: @minimum_minimum_minimum(
-; CHECK-NEXT: [[MIN1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[MIN1]]
-;
- %min1 = call float @llvm.minimum.f32(float %x, float %y)
- %min2 = call float @llvm.minimum.f32(float %x, float %y)
- %val = call float @llvm.minimum.f32(float %min1, float %min2)
- ret float %val
-}
-
-define double @maxnum_maxnum_minnum(double %x, double %y) {
-; CHECK-LABEL: @maxnum_maxnum_minnum(
-; CHECK-NEXT: [[MAX:%.*]] = call double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
-; CHECK-NEXT: ret double [[MAX]]
-;
- %max = call double @llvm.maxnum.f64(double %x, double %y)
- %min = call double @llvm.minnum.f64(double %x, double %y)
- %val = call double @llvm.maxnum.f64(double %max, double %min)
- ret double %val
-}
-
-define <2 x float> @maxnum_minnum_maxnum(<2 x float> %x, <2 x float> %y) {
-; CHECK-LABEL: @maxnum_minnum_maxnum(
-; CHECK-NEXT: [[MAX:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])
-; CHECK-NEXT: ret <2 x float> [[MAX]]
-;
- %max = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> %y)
- %min = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> %y)
- %val = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %min, <2 x float> %max)
- ret <2 x float> %val
-}
-
-define <2 x double> @maxnum_minnum_minmum(<2 x double> %x, <2 x double> %y) {
-; CHECK-LABEL: @maxnum_minnum_minmum(
-; CHECK-NEXT: [[MIN1:%.*]] = call <2 x double> @llvm.minnum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]])
-; CHECK-NEXT: [[MIN2:%.*]] = call <2 x double> @llvm.minnum.v2f64(<2 x double> [[X]], <2 x double> [[Y]])
-; CHECK-NEXT: [[VAL:%.*]] = call <2 x double> @llvm.maxnum.v2f64(<2 x double> [[MIN1]], <2 x double> [[MIN2]])
-; CHECK-NEXT: ret <2 x double> [[VAL]]
-;
- %min1 = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> %y)
- %min2 = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> %y)
- %val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %min1, <2 x double> %min2)
- ret <2 x double> %val
-}
-
-define float @maxnum_maxnum_maxnum(float %x, float %y) {
-; CHECK-LABEL: @maxnum_maxnum_maxnum(
-; CHECK-NEXT: [[MAX1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[MAX1]]
-;
- %max1 = call float @llvm.maxnum.f32(float %x, float %y)
- %max2 = call float @llvm.maxnum.f32(float %x, float %y)
- %val = call float @llvm.maxnum.f32(float %max1, float %max2)
- ret float %val
-}
-
-define double @minnum_maxnum_minnum(double %x, double %y) {
-; CHECK-LABEL: @minnum_maxnum_minnum(
-; CHECK-NEXT: [[MIN:%.*]] = call double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
-; CHECK-NEXT: ret double [[MIN]]
-;
- %max = call double @llvm.maxnum.f64(double %x, double %y)
- %min = call double @llvm.minnum.f64(double %x, double %y)
- %val = call double @llvm.minnum.f64(double %max, double %min)
- ret double %val
-}
-
-define float @minnum_minnum_maxnum(float %x, float %y) {
-; CHECK-LABEL: @minnum_minnum_maxnum(
-; CHECK-NEXT: [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
-; CHECK-NEXT: ret float [[MIN]]
-;
- %max = call float @llvm.maxnum.f32(float %x, float %y)
- %min = call float @llvm.minnum.f32(float %x, float %y)
- %val = call float @llvm.minnum.f32(float %min, float %max)
- ret float %val
-}
-
-define <2 x float> @minnum_maxnum_maxnum(<2 x float> %x, <2 x float> %y) {
-; CHECK-LABEL: @minnum_maxnum_maxnum(
-; CHECK-NEXT: [[MAX1:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])
-; CHECK-NEXT: [[MAX2:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
-; CHECK-NEXT: [[VAL:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[MAX1]], <2 x float> [[MAX2]])
-; CHECK-NEXT: ret <2 x float> [[VAL]]
-;
- %max1 = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> %y)
- %max2 = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> %y)
- %val = call <2 x float> @llvm.minnum.v2f32(<2 x float> %max1, <2 x float> %max2)
- ret <2 x float> %val
-}
-
-define <2 x double> @minnum_minnum_minmum(<2 x double> %x, <2 x double> %y) {
-; CHECK-LABEL: @minnum_minnum_minmum(
-; CHECK-NEXT: [[MIN1:%.*]] = call <2 x double> @llvm.minnum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]])
-; CHECK-NEXT: ret <2 x double> [[MIN1]]
-;
- %min1 = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> %y)
- %min2 = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> %y)
- %val = call <2 x double> @llvm.minnum.v2f64(<2 x double> %min1, <2 x double> %min2)
- ret <2 x double> %val
+;###############################################################
+;# NaN Tests #
+;###############################################################
+; minnum(X, qnan) -> X
+; maxnum(X, qnan) -> X
+; TODO: minnum(X, snan) -> qnan (currently we treat SNaN the same as QNaN)
+; TODO: maxnum(X, snan) -> qnan (currently we treat SNaN the same as QNaN)
+; minimum(X, nan) -> qnan
+; maximum(X, nan) -> qnan
+; TODO: minimumnum(X, nan) -> X
+; TODO: maximumnum(X, nan) -> X
+
+define void @minmax_qnan_f32(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_qnan_f32(
+; CHECK-NEXT: store float [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float 0x7FFF000000000000, ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: store float 0x7FFF000000000000, ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float 0x7FFF000000000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float 0x7FFF000000000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call float @llvm.minnum.f32(float %x, float 0x7FFF000000000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call float @llvm.maxnum.f32(float %x, float 0x7FFF000000000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call float @llvm.minimum.f32(float %x, float 0x7FFF000000000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call float @llvm.maximum.f32(float %x, float 0x7FFF000000000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call float @llvm.minimumnum.f32(float %x, float 0x7FFF000000000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call float @llvm.maximumnum.f32(float %x, float 0x7FFF000000000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; TODO currently snan is treated the same as qnan, but maxnum/minnum should really return qnan for these cases, not X
+define void @minmax_snan_f32(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_snan_f32(
+; CHECK-NEXT: store float [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float 0x7FFC000000000000, ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: store float 0x7FFC000000000000, ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float 0x7FF4000000000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float 0x7FF4000000000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call float @llvm.minnum.f32(float %x, float 0x7FF4000000000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call float @llvm.maxnum.f32(float %x, float 0x7FF4000000000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call float @llvm.minimum.f32(float %x, float 0x7FF4000000000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call float @llvm.maximum.f32(float %x, float 0x7FF4000000000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call float @llvm.minimumnum.f32(float %x, float 0x7FF4000000000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call float @llvm.maximumnum.f32(float %x, float 0x7FF4000000000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+define void @minmax_qnan_nxv2f64_op0(<vscale x 2 x double> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_qnan_nxv2f64_op0(
+; CHECK-NEXT: store <vscale x 2 x double> [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> [[X]], ptr [[MAXNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> splat (double 0x7FF8000DEAD00000), ptr [[MINIMUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> splat (double 0x7FF8000DEAD00000), ptr [[MAXIMUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call <vscale x 2 x double> @llvm.minimumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> [[X]])
+; CHECK-NEXT: store <vscale x 2 x double> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call <vscale x 2 x double> @llvm.maximumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> [[X]])
+; CHECK-NEXT: store <vscale x 2 x double> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: ret void
+;
+ %minnum = call <vscale x 2 x double> @llvm.minnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %minnum, ptr %minnum_res
+ %maxnum = call <vscale x 2 x double> @llvm.maxnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %maxnum, ptr %maxnum_res
+
+ %minimum = call <vscale x 2 x double> @llvm.minimum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %minimum, ptr %minimum_res
+ %maximum = call <vscale x 2 x double> @llvm.maximum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %maximum, ptr %maximum_res
+
+ %minimumnum = call <vscale x 2 x double> @llvm.minimumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call <vscale x 2 x double> @llvm.maximumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF8000DEAD00000), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; TODO currently snan is treated the same as qnan, but maxnum/minnum should really return qnan for these cases, not X
+define void @minmax_snan_nxv2f64_op1(<vscale x 2 x double> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_snan_nxv2f64_op1(
+; CHECK-NEXT: store <vscale x 2 x double> [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> [[X]], ptr [[MAXNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> splat (double 0x7FFC00DEAD00DEAD), ptr [[MINIMUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> splat (double 0x7FFC00DEAD00DEAD), ptr [[MAXIMUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call <vscale x 2 x double> @llvm.minimumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> [[X]])
+; CHECK-NEXT: store <vscale x 2 x double> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call <vscale x 2 x double> @llvm.maximumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> [[X]])
+; CHECK-NEXT: store <vscale x 2 x double> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: ret void
+;
+ %minnum = call <vscale x 2 x double> @llvm.minnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %minnum, ptr %minnum_res
+ %maxnum = call <vscale x 2 x double> @llvm.maxnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %maxnum, ptr %maxnum_res
+
+ %minimum = call <vscale x 2 x double> @llvm.minimum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %minimum, ptr %minimum_res
+ %maximum = call <vscale x 2 x double> @llvm.maximum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %maximum, ptr %maximum_res
+
+ %minimumnum = call <vscale x 2 x double> @llvm.minimumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call <vscale x 2 x double> @llvm.maximumnum.nxv2f64(<vscale x 2 x double> splat (double 0x7FF400DEAD00DEAD), <vscale x 2 x double> %x)
+ store <vscale x 2 x double> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; TODO Currently, we treat SNaN and QNaN the same. However, for maxnum and minnum, we should not optimize this, as we should return <%x0, QNaN> instead of <%x0, %x1>
+define void @minmax_mixed_snan_qnan_v2f64(<2 x double> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_mixed_snan_qnan_v2f64(
+; CHECK-NEXT: store <2 x double> [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> [[X]], ptr [[MAXNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> <double 0x7FFC00DEAD00DEAD, double 0x7FF8000FEED00000>, ptr [[MINIMUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> <double 0x7FFC00DEAD00DEAD, double 0x7FF8000FEED00000>, ptr [[MAXIMUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> [[X]])
+; CHECK-NEXT: store <2 x double> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> [[X]])
+; CHECK-NEXT: store <2 x double> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: ret void
+;
+ %minnum = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> %x)
+ store <2 x double> %minnum, ptr %minnum_res
+ %maxnum = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> %x)
+ store <2 x double> %maxnum, ptr %maxnum_res
+
+ %minimum = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> %x)
+ store <2 x double> %minimum, ptr %minimum_res
+ %maximum = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> %x)
+ store <2 x double> %maximum, ptr %maximum_res
+
+ %minimumnum = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> %x)
+ store <2 x double> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> <double 0x7FF400DEAD00DEAD, double 0x7FF8000FEED00000>, <2 x double> %x)
+ store <2 x double> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; Test with vector variants (v2f64) with NaN and poison
+; Use the poison element for flexibility to choose to return either the constant arg or the other arg X
+define void @minmax_mixed_qnan_poison_v2f64(<2 x double> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_mixed_qnan_poison_v2f64(
+; CHECK-NEXT: store <2 x double> [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> [[X]], ptr [[MAXNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> <double poison, double 0x7FF8000DEAD00000>, ptr [[MINIMUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> <double poison, double 0x7FF8000DEAD00000>, ptr [[MAXIMUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> [[X]])
+; CHECK-NEXT: store <2 x double> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> [[X]])
+; CHECK-NEXT: store <2 x double> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: ret void
+;
+ %minnum = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> %x)
+ store <2 x double> %minnum, ptr %minnum_res
+ %maxnum = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> %x)
+ store <2 x double> %maxnum, ptr %maxnum_res
+
+ %minimum = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> %x)
+ store <2 x double> %minimum, ptr %minimum_res
+ %maximum = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> %x)
+ store <2 x double> %maximum, ptr %maximum_res
+
+ %minimumnum = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> %x)
+ store <2 x double> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> <double poison, double 0x7FF8000DEAD00000>, <2 x double> %x)
+ store <2 x double> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Poison Tests #
+;###############################################################
+define void @minmax_poison_op0_f16(half %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_poison_op0_f16(
+; CHECK-NEXT: store half [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 2
+; CHECK-NEXT: store half [[X]], ptr [[MAXNUM_RES:%.*]], align 2
+; CHECK-NEXT: store half [[X]], ptr [[MINIMUM_RES:%.*]], align 2
+; CHECK-NEXT: store half [[X]], ptr [[MAXIMUM_RES:%.*]], align 2
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call half @llvm.minimumnum.f16(half poison, half [[X]])
+; CHECK-NEXT: store half [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 2
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call half @llvm.maximumnum.f16(half poison, half [[X]])
+; CHECK-NEXT: store half [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 2
+; CHECK-NEXT: ret void
+;
+ %minnum = call half @llvm.minnum.f16(half poison, half %x)
+ store half %minnum, ptr %minnum_res
+ %maxnum = call half @llvm.maxnum.f16(half poison, half %x)
+ store half %maxnum, ptr %maxnum_res
+
+ %minimum = call half @llvm.minimum.f16(half poison, half %x)
+ store half %minimum, ptr %minimum_res
+ %maximum = call half @llvm.maximum.f16(half poison, half %x)
+ store half %maximum, ptr %maximum_res
+
+ %minimumnum = call half @llvm.minimumnum.f16(half poison, half %x)
+ store half %minimumnum, ptr %minimumnum_res
+ %maximumnum = call half @llvm.maximumnum.f16(half poison, half %x)
+ store half %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+define void @minmax_poison_op1_nxv2f64(<vscale x 2 x double> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_poison_op1_nxv2f64(
+; CHECK-NEXT: store <vscale x 2 x double> [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> [[X]], ptr [[MAXNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> [[X]], ptr [[MINIMUM_RES:%.*]], align 16
+; CHECK-NEXT: store <vscale x 2 x double> [[X]], ptr [[MAXIMUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call nnan <vscale x 2 x double> @llvm.minimumnum.nxv2f64(<vscale x 2 x double> [[X]], <vscale x 2 x double> poison)
+; CHECK-NEXT: store <vscale x 2 x double> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call nnan <vscale x 2 x double> @llvm.maximumnum.nxv2f64(<vscale x 2 x double> [[X]], <vscale x 2 x double> poison)
+; CHECK-NEXT: store <vscale x 2 x double> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: ret void
+;
+ %minnum = call nnan <vscale x 2 x double> @llvm.minnum.nxv2f64(<vscale x 2 x double> %x, <vscale x 2 x double> poison)
+ store <vscale x 2 x double> %minnum, ptr %minnum_res
+ %maxnum = call nnan <vscale x 2 x double> @llvm.maxnum.nxv2f64(<vscale x 2 x double> %x, <vscale x 2 x double> poison)
+ store <vscale x 2 x double> %maxnum, ptr %maxnum_res
+
+ %minimum = call nnan <vscale x 2 x double> @llvm.minimum.nxv2f64(<vscale x 2 x double> %x, <vscale x 2 x double> poison)
+ store <vscale x 2 x double> %minimum, ptr %minimum_res
+ %maximum = call nnan <vscale x 2 x double> @llvm.maximum.nxv2f64(<vscale x 2 x double> %x, <vscale x 2 x double> poison)
+ store <vscale x 2 x double> %maximum, ptr %maximum_res
+
+ %minimumnum = call nnan <vscale x 2 x double> @llvm.minimumnum.nxv2f64(<vscale x 2 x double> %x, <vscale x 2 x double> poison)
+ store <vscale x 2 x double> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call nnan <vscale x 2 x double> @llvm.maximumnum.nxv2f64(<vscale x 2 x double> %x, <vscale x 2 x double> poison)
+ store <vscale x 2 x double> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Positive Infinity Tests #
+;###############################################################
+; maxnum(X, +inf) -> +inf (ignoring SNaN -> QNaN propagation)
+; minnum(X, +inf) -> X if nnan (ignoring NaN quieting)
+; maximum(X, +inf) -> +inf if nnan
+; minimum(X, +inf) -> X (ignoring NaN quieting)
+; TODO: maximumnum(X, +inf) -> +inf
+; TODO: minimumnum(X, +inf) -> X if nnan (ignoring NaN quieting)
+
+; Can only optimize maxnum and minimum without the nnan flag
+define void @minmax_pos_inf_f32(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_pos_inf_f32(
+; CHECK-NEXT: [[MINNUM:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0x7FF0000000000000)
+; CHECK-NEXT: store float [[MINNUM]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float 0x7FF0000000000000, ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUM:%.*]] = call float @llvm.maximum.f32(float [[X]], float 0x7FF0000000000000)
+; CHECK-NEXT: store float [[MAXIMUM]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float 0x7FF0000000000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float 0x7FF0000000000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call float @llvm.minnum.f32(float %x, float 0x7FF0000000000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call float @llvm.maxnum.f32(float %x, float 0x7FF0000000000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call float @llvm.minimum.f32(float %x, float 0x7FF0000000000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call float @llvm.maximum.f32(float %x, float 0x7FF0000000000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call float @llvm.minimumnum.f32(float %x, float 0x7FF0000000000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call float @llvm.maximumnum.f32(float %x, float 0x7FF0000000000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; Can optimize all minmax variants if the nnan flag is set
+; TODO maximumnum/minimumnum
+define void @minmax_pos_inf_nnan_v2f32(<2 x float> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_pos_inf_nnan_v2f32(
+; CHECK-NEXT: store <2 x float> [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 8
+; CHECK-NEXT: store <2 x float> splat (float 0x7FF0000000000000), ptr [[MAXNUM_RES:%.*]], align 8
+; CHECK-NEXT: store <2 x float> [[X]], ptr [[MINIMUM_RES:%.*]], align 8
+; CHECK-NEXT: store <2 x float> splat (float 0x7FF0000000000000), ptr [[MAXIMUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call nnan <2 x float> @llvm.minimumnum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> [[X]])
+; CHECK-NEXT: store <2 x float> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call nnan <2 x float> @llvm.maximumnum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> [[X]])
+; CHECK-NEXT: store <2 x float> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: ret void
+;
+ %minnum = call nnan <2 x float> @llvm.minnum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> %x)
+ store <2 x float> %minnum, ptr %minnum_res
+ %maxnum = call nnan <2 x float> @llvm.maxnum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> %x)
+ store <2 x float> %maxnum, ptr %maxnum_res
+
+ %minimum = call nnan <2 x float> @llvm.minimum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> %x)
+ store <2 x float> %minimum, ptr %minimum_res
+ %maximum = call nnan <2 x float> @llvm.maximum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> %x)
+ store <2 x float> %maximum, ptr %maximum_res
+
+ %minimumnum = call nnan <2 x float> @llvm.minimumnum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> %x)
+ store <2 x float> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call nnan <2 x float> @llvm.maximumnum.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> %x)
+ store <2 x float> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Negative Infinity Tests #
+;###############################################################
+; minnum(X, -inf) -> -inf (Ignoring SNaN -> QNaN propagation)
+; maxnum(X, -inf) -> X if nnan
+; minimum(X, -inf) -> -inf if nnan
+; maximum(X, -inf) -> X (Ignoring NaN quieting)
+; TODO: minimumnum(X, -inf) -> -inf
+; TODO: maximumnum(X, -inf) -> X if nnan
+
+; Can only optimize minnum and maximum without the nnan flag
+define void @minmax_neg_inf_f32(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_neg_inf_f32(
+; CHECK-NEXT: store float 0xFFF0000000000000, ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXNUM:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0xFFF0000000000000)
+; CHECK-NEXT: store float [[MAXNUM]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUM:%.*]] = call float @llvm.minimum.f32(float [[X]], float 0xFFF0000000000000)
+; CHECK-NEXT: store float [[MINIMUM]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float 0xFFF0000000000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float 0xFFF0000000000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call float @llvm.maxnum.f32(float %x, float 0xFFF0000000000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call float @llvm.minimum.f32(float %x, float 0xFFF0000000000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call float @llvm.maximum.f32(float %x, float 0xFFF0000000000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call float @llvm.minimumnum.f32(float %x, float 0xFFF0000000000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call float @llvm.maximumnum.f32(float %x, float 0xFFF0000000000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; Can optimize all minmax variants if the nnan flag is set
+; TODO maximumnum/minimumnum
+define void @minmax_neg_inf_nnan_v2f64(<2 x double> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_neg_inf_nnan_v2f64(
+; CHECK-NEXT: store <2 x double> splat (double 0xFFF0000000000000), ptr [[MINNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> [[X:%.*]], ptr [[MAXNUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> splat (double 0xFFF0000000000000), ptr [[MINIMUM_RES:%.*]], align 16
+; CHECK-NEXT: store <2 x double> [[X]], ptr [[MAXIMUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call nnan <2 x double> @llvm.minimumnum.v2f64(<2 x double> [[X]], <2 x double> splat (double 0xFFF0000000000000))
+; CHECK-NEXT: store <2 x double> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call nnan <2 x double> @llvm.maximumnum.v2f64(<2 x double> [[X]], <2 x double> splat (double 0xFFF0000000000000))
+; CHECK-NEXT: store <2 x double> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 16
+; CHECK-NEXT: ret void
+;
+ %minnum = call nnan <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> splat (double 0xFFF0000000000000))
+ store <2 x double> %minnum, ptr %minnum_res
+ %maxnum = call nnan <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> splat (double 0xFFF0000000000000))
+ store <2 x double> %maxnum, ptr %maxnum_res
+
+ %minimum = call nnan <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> splat (double 0xFFF0000000000000))
+ store <2 x double> %minimum, ptr %minimum_res
+ %maximum = call nnan <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> splat (double 0xFFF0000000000000))
+ store <2 x double> %maximum, ptr %maximum_res
+
+ %minimumnum = call nnan <2 x double> @llvm.minimumnum.v2f64(<2 x double> %x, <2 x double> splat (double 0xFFF0000000000000))
+ store <2 x double> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call nnan <2 x double> @llvm.maximumnum.v2f64(<2 x double> %x, <2 x double> splat (double 0xFFF0000000000000))
+ store <2 x double> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Largest Positive Float Constant Tests #
+;###############################################################
+; maxnum(X, +largest) -> +largest if ninf (ignoring SNaN -> QNaN propagation)
+; minnum(X, +largest) -> X if ninf && nnan
+; maximum(X, +largest) -> +largest if ninf && nnan
+; minimum(X, +largest) -> X if ninf (ignoring quieting of sNaNs)
+; TODO: maximumnum(X, +largest) -> +largest if ninf && nnan
+; TODO: minimumnum(X, +largest) -> X if ninf && nnan
+
+; None of these should be optimized away without the nnan/ninf flags
+define void @minmax_largest_f32(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_largest_f32(
+; CHECK-NEXT: [[MINNUM:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINNUM]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXNUM:%.*]] = call float @llvm.maxnum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXNUM]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUM:%.*]] = call float @llvm.minimum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINIMUM]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUM:%.*]] = call float @llvm.maximum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXIMUM]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call float @llvm.minnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call float @llvm.maxnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call float @llvm.minimum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call float @llvm.maximum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call float @llvm.minimumnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call float @llvm.maximumnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; We can optimize maxnum and minimum if we know ninf is set
+define void @minmax_largest_f32_ninf(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_largest_f32_ninf(
+; CHECK-NEXT: [[MINNUM:%.*]] = call ninf float @llvm.minnum.f32(float [[X:%.*]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINNUM]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float 0x47EFFFFFE0000000, ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUM:%.*]] = call ninf float @llvm.maximum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXIMUM]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call ninf float @llvm.minimumnum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call ninf float @llvm.maximumnum.f32(float [[X]], float 0x47EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call ninf float @llvm.minnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call ninf float @llvm.maxnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call ninf float @llvm.minimum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call ninf float @llvm.maximum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call ninf float @llvm.minimumnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call ninf float @llvm.maximumnum.f32(float %x, float 0x47EFFFFFE0000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; All can be optimized if both the ninf and nnan flags are set (ignoring SNaN propagation in minnum/maxnum)
+; TODO maximumnum/minimumnum
+define void @minmax_largest_v2f32_ninf_nnan(<2 x float> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_largest_v2f32_ninf_nnan(
+; CHECK-NEXT: store <2 x float> [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 8
+; CHECK-NEXT: store <2 x float> splat (float 0x47EFFFFFE0000000), ptr [[MAXNUM_RES:%.*]], align 8
+; CHECK-NEXT: store <2 x float> [[X]], ptr [[MINIMUM_RES:%.*]], align 8
+; CHECK-NEXT: store <2 x float> splat (float 0x47EFFFFFE0000000), ptr [[MAXIMUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call nnan ninf <2 x float> @llvm.minimumnum.v2f32(<2 x float> [[X]], <2 x float> splat (float 0x47EFFFFFE0000000))
+; CHECK-NEXT: store <2 x float> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call nnan ninf <2 x float> @llvm.maximumnum.v2f32(<2 x float> [[X]], <2 x float> splat (float 0x47EFFFFFE0000000))
+; CHECK-NEXT: store <2 x float> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: ret void
+;
+ %minnum = call ninf nnan <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> splat (float 0x47EFFFFFE0000000))
+ store <2 x float> %minnum, ptr %minnum_res
+ %maxnum = call ninf nnan <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> splat (float 0x47EFFFFFE0000000))
+ store <2 x float> %maxnum, ptr %maxnum_res
+
+ %minimum = call ninf nnan <2 x float> @llvm.minimum.v2f32(<2 x float> %x, <2 x float> splat (float 0x47EFFFFFE0000000))
+ store <2 x float> %minimum, ptr %minimum_res
+ %maximum = call ninf nnan <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> splat (float 0x47EFFFFFE0000000))
+ store <2 x float> %maximum, ptr %maximum_res
+
+ %minimumnum = call ninf nnan <2 x float> @llvm.minimumnum.v2f32(<2 x float> %x, <2 x float> splat (float 0x47EFFFFFE0000000))
+ store <2 x float> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call ninf nnan <2 x float> @llvm.maximumnum.v2f32(<2 x float> %x, <2 x float> splat (float 0x47EFFFFFE0000000))
+ store <2 x float> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Largest Negative Float Constant Tests #
+;###############################################################
+; maxnum(X, -largest) -> X if ninf && nnan
+; minnum(X, -largest) -> -largest if ninf (ignoring SNaN -> QNaN propagation)
+; maximum(X, -largest) -> X if ninf (ignoring quieting of sNaNs)
+; minimum(X, -largest) -> -largest if ninf && nnan
+; TODO: maximumnum(X, -largest) -> X if ninf && nnan
+; TODO: minimumnum(X, -largest) -> -largest if ninf
+
+; None of these should be optimized away without the nnan/ninf flags
+define void @minmax_neg_largest_f32(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_neg_largest_f32(
+; CHECK-NEXT: [[MINNUM:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINNUM]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXNUM:%.*]] = call float @llvm.maxnum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXNUM]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUM:%.*]] = call float @llvm.minimum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINIMUM]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUM:%.*]] = call float @llvm.maximum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXIMUM]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call float @llvm.minnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call float @llvm.maxnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call float @llvm.minimum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call float @llvm.maximum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call float @llvm.minimumnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call float @llvm.maximumnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; We can optimize minnum and maximum if we know ninf is set
+define void @minmax_neg_largest_f32_ninf(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_neg_largest_f32_ninf(
+; CHECK-NEXT: store float 0xC7EFFFFFE0000000, ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXNUM:%.*]] = call ninf float @llvm.maxnum.f32(float [[X:%.*]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXNUM]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUM:%.*]] = call ninf float @llvm.minimum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINIMUM]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call ninf float @llvm.minimumnum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call ninf float @llvm.maximumnum.f32(float [[X]], float 0xC7EFFFFFE0000000)
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call ninf float @llvm.minnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call ninf float @llvm.maxnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call ninf float @llvm.minimum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %minimum, ptr %minimum_res
+ %maximum = call ninf float @llvm.maximum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call ninf float @llvm.minimumnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call ninf float @llvm.maximumnum.f32(float %x, float 0xC7EFFFFFE0000000)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; All can be optimized if both the ninf and nnan flags are set (ignoring SNaN propagation in minnum/maxnum)
+; TODO maximumnum/minimumnum
+define void @minmax_neg_largest_nxv2f32_nnan_ninf(<vscale x 2 x float> %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_neg_largest_nxv2f32_nnan_ninf(
+; CHECK-NEXT: store <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000), ptr [[MINNUM_RES:%.*]], align 8
+; CHECK-NEXT: store <vscale x 2 x float> [[X:%.*]], ptr [[MAXNUM_RES:%.*]], align 8
+; CHECK-NEXT: store <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000), ptr [[MINIMUM_RES:%.*]], align 8
+; CHECK-NEXT: store <vscale x 2 x float> [[X]], ptr [[MAXIMUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call nnan ninf <vscale x 2 x float> @llvm.minimumnum.nxv2f32(<vscale x 2 x float> [[X]], <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+; CHECK-NEXT: store <vscale x 2 x float> [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call nnan ninf <vscale x 2 x float> @llvm.maximumnum.nxv2f32(<vscale x 2 x float> [[X]], <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+; CHECK-NEXT: store <vscale x 2 x float> [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: ret void
+;
+ %minnum = call nnan ninf <vscale x 2 x float> @llvm.minnum.nxv2f32(<vscale x 2 x float> %x, <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+ store <vscale x 2 x float> %minnum, ptr %minnum_res
+ %maxnum = call nnan ninf <vscale x 2 x float> @llvm.maxnum.nxv2f32(<vscale x 2 x float> %x, <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+ store <vscale x 2 x float> %maxnum, ptr %maxnum_res
+
+ %minimum = call nnan ninf <vscale x 2 x float> @llvm.minimum.nxv2f32(<vscale x 2 x float> %x, <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+ store <vscale x 2 x float> %minimum, ptr %minimum_res
+ %maximum = call nnan ninf <vscale x 2 x float> @llvm.maximum.nxv2f32(<vscale x 2 x float> %x, <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+ store <vscale x 2 x float> %maximum, ptr %maximum_res
+
+ %minimumnum = call nnan ninf <vscale x 2 x float> @llvm.minimumnum.nxv2f32(<vscale x 2 x float> %x, <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+ store <vscale x 2 x float> %minimumnum, ptr %minimumnum_res
+ %maximumnum = call nnan ninf <vscale x 2 x float> @llvm.maximumnum.nxv2f32(<vscale x 2 x float> %x, <vscale x 2 x float> splat (float 0xC7EFFFFFE0000000))
+ store <vscale x 2 x float> %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Min(x, x) / Max(x, x) #
+;###############################################################
+; min(x, x) -> x and max(x, x) -> x for all variants (ignoring SNaN quieting)
+define void @minmax_same_args(float %x, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_same_args(
+; CHECK-NEXT: store float [[X:%.*]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: store float [[X]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[X]])
+; CHECK-NEXT: store float [[MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[X]])
+; CHECK-NEXT: store float [[MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum = call float @llvm.minnum.f32(float %x, float %x)
+ store float %minnum, ptr %minnum_res
+ %maxnum = call float @llvm.maxnum.f32(float %x, float %x)
+ store float %maxnum, ptr %maxnum_res
+
+ %minimum = call float @llvm.minimum.f32(float %x, float %x)
+ store float %minimum, ptr %minimum_res
+ %maximum = call float @llvm.maximum.f32(float %x, float %x)
+ store float %maximum, ptr %maximum_res
+
+ %minimumnum = call float @llvm.minimumnum.f32(float %x, float %x)
+ store float %minimumnum, ptr %minimumnum_res
+ %maximumnum = call float @llvm.maximumnum.f32(float %x, float %x)
+ store float %maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Nested calls: M(x, M(x, y)) -> M(x, y) #
+;###############################################################
+define void @minmax_x_minmax_xy(<2 x float> %x, <2 x float> %y, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_x_minmax_xy(
+; CHECK-NEXT: [[MINNUM_XY:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])
+; CHECK-NEXT: store <2 x float> [[MINNUM_XY]], ptr [[MINNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXNUM_XY:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
+; CHECK-NEXT: store <2 x float> [[MAXNUM_XY]], ptr [[MAXNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MINIMUM_XY:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
+; CHECK-NEXT: store <2 x float> [[MINIMUM_XY]], ptr [[MINIMUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXIMUM_XY:%.*]] = call <2 x float> @llvm.maximum.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
+; CHECK-NEXT: store <2 x float> [[MAXIMUM_XY]], ptr [[MAXIMUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MINIMUMNUM_XY:%.*]] = call <2 x float> @llvm.minimumnum.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
+; CHECK-NEXT: [[MINIMUMNUM_NESTED:%.*]] = call <2 x float> @llvm.minimumnum.v2f32(<2 x float> [[X]], <2 x float> [[MINIMUMNUM_XY]])
+; CHECK-NEXT: store <2 x float> [[MINIMUMNUM_NESTED]], ptr [[MINIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXIMUMNUM_XY:%.*]] = call <2 x float> @llvm.maximumnum.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
+; CHECK-NEXT: [[MAXIMUMNUM_NESTED:%.*]] = call <2 x float> @llvm.maximumnum.v2f32(<2 x float> [[X]], <2 x float> [[MAXIMUMNUM_XY]])
+; CHECK-NEXT: store <2 x float> [[MAXIMUMNUM_NESTED]], ptr [[MAXIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: ret void
+;
+ %minnum_xy = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> %y)
+ %minnum_nested = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> %minnum_xy)
+ store <2 x float> %minnum_nested, ptr %minnum_res
+
+ %maxnum_xy = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> %y)
+ %maxnum_nested = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> %maxnum_xy)
+ store <2 x float> %maxnum_nested, ptr %maxnum_res
+
+ %minimum_xy = call <2 x float> @llvm.minimum.v2f32(<2 x float> %x, <2 x float> %y)
+ %minimum_nested = call <2 x float> @llvm.minimum.v2f32(<2 x float> %x, <2 x float> %minimum_xy)
+ store <2 x float> %minimum_nested, ptr %minimum_res
+
+ %maximum_xy = call <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> %y)
+ %maximum_nested = call <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> %maximum_xy)
+ store <2 x float> %maximum_nested, ptr %maximum_res
+
+ %minimumnum_xy = call <2 x float> @llvm.minimumnum.v2f32(<2 x float> %x, <2 x float> %y)
+ %minimumnum_nested = call <2 x float> @llvm.minimumnum.v2f32(<2 x float> %x, <2 x float> %minimumnum_xy)
+ store <2 x float> %minimumnum_nested, ptr %minimumnum_res
+
+ %maximumnum_xy = call <2 x float> @llvm.maximumnum.v2f32(<2 x float> %x, <2 x float> %y)
+ %maximumnum_nested = call <2 x float> @llvm.maximumnum.v2f32(<2 x float> %x, <2 x float> %maximumnum_xy)
+ store <2 x float> %maximumnum_nested, ptr %maximumnum_res
+ ret void
+}
+
+; Negative test: m(Z, m(X,Y)) cannot be optimized to m(x, y)
+define void @minmax_z_minmax_xy(float %x, float %y, float %z, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_z_minmax_xy(
+; CHECK-NEXT: [[MINNUM_XY:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: [[MINNUM_NESTED:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[MINNUM_XY]])
+; CHECK-NEXT: store float [[MINNUM_NESTED]], ptr [[MINNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXNUM_XY:%.*]] = call float @llvm.maxnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[MAXNUM_NESTED:%.*]] = call float @llvm.maxnum.f32(float [[Z]], float [[MAXNUM_XY]])
+; CHECK-NEXT: store float [[MAXNUM_NESTED]], ptr [[MAXNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUM_XY:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[MINIMUM_NESTED:%.*]] = call float @llvm.minimum.f32(float [[Z]], float [[MINIMUM_XY]])
+; CHECK-NEXT: store float [[MINIMUM_NESTED]], ptr [[MINIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUM_XY:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[MAXIMUM_NESTED:%.*]] = call float @llvm.maximum.f32(float [[Z]], float [[MAXIMUM_XY]])
+; CHECK-NEXT: store float [[MAXIMUM_NESTED]], ptr [[MAXIMUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MINIMUMNUM_XY:%.*]] = call float @llvm.minimumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[MINIMUMNUM_NESTED:%.*]] = call float @llvm.minimumnum.f32(float [[Z]], float [[MINIMUMNUM_XY]])
+; CHECK-NEXT: store float [[MINIMUMNUM_NESTED]], ptr [[MINIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: [[MAXIMUMNUM_XY:%.*]] = call float @llvm.maximumnum.f32(float [[X]], float [[Y]])
+; CHECK-NEXT: [[MAXIMUMNUM_NESTED:%.*]] = call float @llvm.maximumnum.f32(float [[Z]], float [[MAXIMUMNUM_XY]])
+; CHECK-NEXT: store float [[MAXIMUMNUM_NESTED]], ptr [[MAXIMUMNUM_RES:%.*]], align 4
+; CHECK-NEXT: ret void
+;
+ %minnum_xy = call float @llvm.minnum.f32(float %x, float %y)
+ %minnum_nested = call float @llvm.minnum.f32(float %z, float %minnum_xy)
+ store float %minnum_nested, ptr %minnum_res
+
+ %maxnum_xy = call float @llvm.maxnum.f32(float %x, float %y)
+ %maxnum_nested = call float @llvm.maxnum.f32(float %z, float %maxnum_xy)
+ store float %maxnum_nested, ptr %maxnum_res
+
+ %minimum_xy = call float @llvm.minimum.f32(float %x, float %y)
+ %minimum_nested = call float @llvm.minimum.f32(float %z, float %minimum_xy)
+ store float %minimum_nested, ptr %minimum_res
+
+ %maximum_xy = call float @llvm.maximum.f32(float %x, float %y)
+ %maximum_nested = call float @llvm.maximum.f32(float %z, float %maximum_xy)
+ store float %maximum_nested, ptr %maximum_res
+
+ %minimumnum_xy = call float @llvm.minimumnum.f32(float %x, float %y)
+ %minimumnum_nested = call float @llvm.minimumnum.f32(float %z, float %minimumnum_xy)
+ store float %minimumnum_nested, ptr %minimumnum_res
+
+ %maximumnum_xy = call float @llvm.maximumnum.f32(float %x, float %y)
+ %maximumnum_nested = call float @llvm.maximumnum.f32(float %z, float %maximumnum_xy)
+ store float %maximumnum_nested, ptr %maximumnum_res
+ ret void
+}
+
+;###############################################################
+;# Nested calls: M(M(x, y), M'(x, y)) -> M(x, y) #
+;###############################################################
+; m(m(X,Y), m'(Y,X)) -> m(X, Y)
+; Test where m' is the same op as m
+define void @minmax_minmax_xy_minmax_yx(half %x, half %y, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_minmax_xy_minmax_yx(
+; CHECK-NEXT: [[MINNUM_XY:%.*]] = call half @llvm.minnum.f16(half [[X:%.*]], half [[Y:%.*]])
+; CHECK-NEXT: store half [[MINNUM_XY]], ptr [[MINNUM_RES:%.*]], align 2
+; CHECK-NEXT: [[MAXNUM_XY:%.*]] = call half @llvm.maxnum.f16(half [[X]], half [[Y]])
+; CHECK-NEXT: store half [[MAXNUM_XY]], ptr [[MAXNUM_RES:%.*]], align 2
+; CHECK-NEXT: [[MINIMUM_XY:%.*]] = call half @llvm.minimum.f16(half [[X]], half [[Y]])
+; CHECK-NEXT: store half [[MINIMUM_XY]], ptr [[MINIMUM_RES:%.*]], align 2
+; CHECK-NEXT: [[MAXIMUM_XY:%.*]] = call half @llvm.maximum.f16(half [[X]], half [[Y]])
+; CHECK-NEXT: store half [[MAXIMUM_XY]], ptr [[MAXIMUM_RES:%.*]], align 2
+; CHECK-NEXT: [[MINIMUMNUM_XY:%.*]] = call half @llvm.minimumnum.f16(half [[X]], half [[Y]])
+; CHECK-NEXT: [[MINIMUMNUM_YX:%.*]] = call half @llvm.minimumnum.f16(half [[Y]], half [[X]])
+; CHECK-NEXT: [[FINAL_MINIMUMNUM:%.*]] = call half @llvm.minimumnum.f16(half [[MINIMUMNUM_XY]], half [[MINIMUMNUM_YX]])
+; CHECK-NEXT: store half [[FINAL_MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 2
+; CHECK-NEXT: [[MAXIMUMNUM_XY:%.*]] = call half @llvm.maximumnum.f16(half [[X]], half [[Y]])
+; CHECK-NEXT: [[MAXIMUMNUM_YX:%.*]] = call half @llvm.maximumnum.f16(half [[Y]], half [[X]])
+; CHECK-NEXT: [[FINAL_MAXIMUMNUM:%.*]] = call half @llvm.maximumnum.f16(half [[MAXIMUMNUM_XY]], half [[MAXIMUMNUM_YX]])
+; CHECK-NEXT: store half [[FINAL_MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 2
+; CHECK-NEXT: ret void
+;
+ %minnum_xy = call half @llvm.minnum.f16(half %x, half %y)
+ %minnum_yx = call half @llvm.minnum.f16(half %y, half %x)
+ %final_minnum = call half @llvm.minnum.f16(half %minnum_xy, half %minnum_yx)
+ store half %final_minnum, ptr %minnum_res
+
+ %maxnum_xy = call half @llvm.maxnum.f16(half %x, half %y)
+ %maxnum_yx = call half @llvm.maxnum.f16(half %y, half %x)
+ %final_maxnum = call half @llvm.maxnum.f16(half %maxnum_xy, half %maxnum_yx)
+ store half %final_maxnum, ptr %maxnum_res
+
+ %minimum_xy = call half @llvm.minimum.f16(half %x, half %y)
+ %minimum_yx = call half @llvm.minimum.f16(half %y, half %x)
+ %final_minimum = call half @llvm.minimum.f16(half %minimum_xy, half %minimum_yx)
+ store half %final_minimum, ptr %minimum_res
+
+ %maximum_xy = call half @llvm.maximum.f16(half %x, half %y)
+ %maximum_yx = call half @llvm.maximum.f16(half %y, half %x)
+ %final_maximum = call half @llvm.maximum.f16(half %maximum_xy, half %maximum_yx)
+ store half %final_maximum, ptr %maximum_res
+
+ %minimumnum_xy = call half @llvm.minimumnum.f16(half %x, half %y)
+ %minimumnum_yx = call half @llvm.minimumnum.f16(half %y, half %x)
+ %final_minimumnum = call half @llvm.minimumnum.f16(half %minimumnum_xy, half %minimumnum_yx)
+ store half %final_minimumnum, ptr %minimumnum_res
+
+ %maximumnum_xy = call half @llvm.maximumnum.f16(half %x, half %y)
+ %maximumnum_yx = call half @llvm.maximumnum.f16(half %y, half %x)
+ %final_maximumnum = call half @llvm.maximumnum.f16(half %maximumnum_xy, half %maximumnum_yx)
+ store half %final_maximumnum, ptr %maximumnum_res
+ ret void
+}
+
+; m(m(X,Y), m'(Y,X)) -> m(X, Y)
+; Test where m' is the opposite op from m
+define void @minmax_minmax_xy_maxmin_yx(double %x, double %y, ptr %minnum_res, ptr %maxnum_res, ptr %minimum_res, ptr %maximum_res, ptr %minimumnum_res, ptr %maximumnum_res) {
+; CHECK-LABEL: @minmax_minmax_xy_maxmin_yx(
+; CHECK-NEXT: [[MINNUM_XY:%.*]] = call double @llvm.minnum.f64(double [[Y:%.*]], double [[X:%.*]])
+; CHECK-NEXT: store double [[MINNUM_XY]], ptr [[MINNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXNUM_XY:%.*]] = call double @llvm.maxnum.f64(double [[Y]], double [[X]])
+; CHECK-NEXT: store double [[MAXNUM_XY]], ptr [[MAXNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MINIMUM_XY:%.*]] = call double @llvm.minimum.f64(double [[Y]], double [[X]])
+; CHECK-NEXT: store double [[MINIMUM_XY]], ptr [[MINIMUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXIMUM_XY:%.*]] = call double @llvm.maximum.f64(double [[Y]], double [[X]])
+; CHECK-NEXT: store double [[MAXIMUM_XY]], ptr [[MAXIMUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MINIMUMNUM_XY:%.*]] = call double @llvm.minimumnum.f64(double [[Y]], double [[X]])
+; CHECK-NEXT: [[MAXIMUMNUM_XY:%.*]] = call double @llvm.maximumnum.f64(double [[X]], double [[Y]])
+; CHECK-NEXT: [[FINAL_MINIMUMNUM:%.*]] = call double @llvm.minimumnum.f64(double [[MINIMUMNUM_XY]], double [[MAXIMUMNUM_XY]])
+; CHECK-NEXT: store double [[FINAL_MINIMUMNUM]], ptr [[MINIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: [[MAXIMUMNUM_XY1:%.*]] = call double @llvm.maximumnum.f64(double [[Y]], double [[X]])
+; CHECK-NEXT: [[MINIMUMNUM_YX:%.*]] = call double @llvm.minimumnum.f64(double [[X]], double [[Y]])
+; CHECK-NEXT: [[FINAL_MAXIMUMNUM:%.*]] = call double @llvm.maximumnum.f64(double [[MAXIMUMNUM_XY1]], double [[MINIMUMNUM_YX]])
+; CHECK-NEXT: store double [[FINAL_MAXIMUMNUM]], ptr [[MAXIMUMNUM_RES:%.*]], align 8
+; CHECK-NEXT: ret void
+;
+ %minnum_xy = call double @llvm.minnum.f64(double %x, double %y)
+ %maxnum_yx = call double @llvm.maxnum.f64(double %y, double %x)
+ %final_minnum = call double @llvm.minnum.f64(double %minnum_xy, double %maxnum_yx)
+ store double %final_minnum, ptr %minnum_res
+
+ %maxnum_xy = call double @llvm.maxnum.f64(double %x, double %y)
+ %minnum_yx = call double @llvm.minnum.f64(double %y, double %x)
+ %final_maxnum = call double @llvm.maxnum.f64(double %maxnum_xy, double %minnum_yx)
+ store double %final_maxnum, ptr %maxnum_res
+
+ %minimum_xy = call double @llvm.minimum.f64(double %x, double %y)
+ %maximum_yx = call double @llvm.maximum.f64(double %y, double %x)
+ %final_minimum = call double @llvm.minimum.f64(double %minimum_xy, double %maximum_yx)
+ store double %final_minimum, ptr %minimum_res
+
+ %maximum_xy = call double @llvm.maximum.f64(double %x, double %y)
+ %minimum_yx = call double @llvm.minimum.f64(double %y, double %x)
+ %final_maximum = call double @llvm.maximum.f64(double %maximum_xy, double %minimum_yx)
+ store double %final_maximum, ptr %maximum_res
+
+ %minimumnum_xy = call double @llvm.minimumnum.f64(double %x, double %y)
+ %maximumnum_yx = call double @llvm.maximumnum.f64(double %y, double %x)
+ %final_minimumnum = call double @llvm.minimumnum.f64(double %minimumnum_xy, double %maximumnum_yx)
+ store double %final_minimumnum, ptr %minimumnum_res
+
+ %maximumnum_xy = call double @llvm.maximumnum.f64(double %x, double %y)
+ %minimumnum_yx = call double @llvm.minimumnum.f64(double %y, double %x)
+ %final_maximumnum = call double @llvm.maximumnum.f64(double %maximumnum_xy, double %minimumnum_yx)
+ store double %final_maximumnum, ptr %maximumnum_res
+ ret void
}
More information about the llvm-commits
mailing list