[llvm] [SDAG] Fix fmaximum legalization errors (PR #142170)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri May 30 08:52:37 PDT 2025


https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/142170

>From ee1c82f21ab84e16b322ea5e154405fc32e9ed27 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 28 May 2025 16:00:58 +0200
Subject: [PATCH 1/5] Use bitcast instead of IS_FPCLASS

---
 .../CodeGen/SelectionDAG/TargetLowering.cpp   |  17 +-
 llvm/test/CodeGen/NVPTX/bf16-instructions.ll  |  22 +-
 llvm/test/CodeGen/NVPTX/math-intrins.ll       | 128 ++++-----
 .../test/CodeGen/PowerPC/fminimum-fmaximum.ll | 263 +++++++++---------
 4 files changed, 214 insertions(+), 216 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 22d0bc9914585..450d7dcb6ac7f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8610,16 +8610,17 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
   // fminimum/fmaximum requires -0.0 less than +0.0
   if (!MinMaxMustRespectOrderedZero && !N->getFlags().hasNoSignedZeros() &&
       !DAG.isKnownNeverZeroFloat(RHS) && !DAG.isKnownNeverZeroFloat(LHS)) {
+    auto IsSpecificZero = [&](SDValue F) {
+      EVT IntVT = VT.changeTypeToInteger();
+      SDValue Int = DAG.getBitcast(IntVT, F);
+      return DAG.getSetCC(DL, CCVT, Int, DAG.getConstant(0, DL, IntVT),
+                          IsMax ? ISD::SETEQ : ISD::SETNE);
+    };
     SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
                                   DAG.getConstantFP(0.0, DL, VT), ISD::SETOEQ);
-    SDValue TestZero =
-        DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
-    SDValue LCmp = DAG.getSelect(
-        DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, LHS, TestZero), LHS,
-        MinMax, Flags);
-    SDValue RCmp = DAG.getSelect(
-        DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, RHS, TestZero), RHS,
-        LCmp, Flags);
+    SDValue LCmp =
+        DAG.getSelect(DL, VT, IsSpecificZero(LHS), LHS, MinMax, Flags);
+    SDValue RCmp = DAG.getSelect(DL, VT, IsSpecificZero(RHS), RHS, LCmp, Flags);
     MinMax = DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
   }
 
diff --git a/llvm/test/CodeGen/NVPTX/bf16-instructions.ll b/llvm/test/CodeGen/NVPTX/bf16-instructions.ll
index 32225ed04e2d9..096649e5bde43 100644
--- a/llvm/test/CodeGen/NVPTX/bf16-instructions.ll
+++ b/llvm/test/CodeGen/NVPTX/bf16-instructions.ll
@@ -1476,7 +1476,7 @@ define <2 x bfloat> @test_maximum_v2(<2 x bfloat> %a, <2 x bfloat> %b) {
 ; SM70-LABEL: test_maximum_v2(
 ; SM70:       {
 ; SM70-NEXT:    .reg .pred %p<11>;
-; SM70-NEXT:    .reg .b16 %rs<15>;
+; SM70-NEXT:    .reg .b16 %rs<19>;
 ; SM70-NEXT:    .reg .b32 %r<16>;
 ; SM70-EMPTY:
 ; SM70-NEXT:  // %bb.0:
@@ -1493,30 +1493,30 @@ define <2 x bfloat> @test_maximum_v2(<2 x bfloat> %a, <2 x bfloat> %b) {
 ; SM70-NEXT:    setp.nan.f32 %p2, %r6, %r4;
 ; SM70-NEXT:    selp.b16 %rs6, 0x7FC0, %rs5, %p2;
 ; SM70-NEXT:    setp.eq.s16 %p3, %rs4, 0;
-; SM70-NEXT:    selp.b16 %rs7, %rs4, %rs6, %p3;
+; SM70-NEXT:    selp.b16 %rs9, %rs4, %rs6, %p3;
 ; SM70-NEXT:    setp.eq.s16 %p4, %rs2, 0;
-; SM70-NEXT:    selp.b16 %rs8, %rs2, %rs7, %p4;
+; SM70-NEXT:    selp.b16 %rs12, %rs2, %rs9, %p4;
 ; SM70-NEXT:    cvt.u32.u16 %r7, %rs6;
 ; SM70-NEXT:    shl.b32 %r8, %r7, 16;
 ; SM70-NEXT:    setp.eq.f32 %p5, %r8, 0f00000000;
-; SM70-NEXT:    selp.b16 %rs9, %rs8, %rs6, %p5;
+; SM70-NEXT:    selp.b16 %rs13, %rs12, %rs6, %p5;
 ; SM70-NEXT:    cvt.u32.u16 %r9, %rs1;
 ; SM70-NEXT:    shl.b32 %r10, %r9, 16;
 ; SM70-NEXT:    cvt.u32.u16 %r11, %rs3;
 ; SM70-NEXT:    shl.b32 %r12, %r11, 16;
 ; SM70-NEXT:    setp.gt.f32 %p6, %r12, %r10;
-; SM70-NEXT:    selp.b16 %rs10, %rs3, %rs1, %p6;
+; SM70-NEXT:    selp.b16 %rs14, %rs3, %rs1, %p6;
 ; SM70-NEXT:    setp.nan.f32 %p7, %r12, %r10;
-; SM70-NEXT:    selp.b16 %rs11, 0x7FC0, %rs10, %p7;
+; SM70-NEXT:    selp.b16 %rs15, 0x7FC0, %rs14, %p7;
 ; SM70-NEXT:    setp.eq.s16 %p8, %rs3, 0;
-; SM70-NEXT:    selp.b16 %rs12, %rs3, %rs11, %p8;
+; SM70-NEXT:    selp.b16 %rs16, %rs3, %rs15, %p8;
 ; SM70-NEXT:    setp.eq.s16 %p9, %rs1, 0;
-; SM70-NEXT:    selp.b16 %rs13, %rs1, %rs12, %p9;
-; SM70-NEXT:    cvt.u32.u16 %r13, %rs11;
+; SM70-NEXT:    selp.b16 %rs17, %rs1, %rs16, %p9;
+; SM70-NEXT:    cvt.u32.u16 %r13, %rs15;
 ; SM70-NEXT:    shl.b32 %r14, %r13, 16;
 ; SM70-NEXT:    setp.eq.f32 %p10, %r14, 0f00000000;
-; SM70-NEXT:    selp.b16 %rs14, %rs13, %rs11, %p10;
-; SM70-NEXT:    mov.b32 %r15, {%rs14, %rs9};
+; SM70-NEXT:    selp.b16 %rs18, %rs17, %rs15, %p10;
+; SM70-NEXT:    mov.b32 %r15, {%rs18, %rs13};
 ; SM70-NEXT:    st.param.b32 [func_retval0], %r15;
 ; SM70-NEXT:    ret;
 ;
diff --git a/llvm/test/CodeGen/NVPTX/math-intrins.ll b/llvm/test/CodeGen/NVPTX/math-intrins.ll
index 71af7a7d475d3..441fdec7ce5c0 100644
--- a/llvm/test/CodeGen/NVPTX/math-intrins.ll
+++ b/llvm/test/CodeGen/NVPTX/math-intrins.ll
@@ -625,9 +625,9 @@ define half @minimum_half(half %a, half %b) {
 ; CHECK-NOF16-NEXT:    selp.b16 %rs3, %rs1, %rs2, %p1;
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p2, %r2, %r1;
 ; CHECK-NOF16-NEXT:    selp.b16 %rs4, 0x7E00, %rs3, %p2;
-; CHECK-NOF16-NEXT:    setp.eq.s16 %p3, %rs1, -32768;
+; CHECK-NOF16-NEXT:    setp.ne.s16 %p3, %rs1, 0;
 ; CHECK-NOF16-NEXT:    selp.b16 %rs5, %rs1, %rs4, %p3;
-; CHECK-NOF16-NEXT:    setp.eq.s16 %p4, %rs2, -32768;
+; CHECK-NOF16-NEXT:    setp.ne.s16 %p4, %rs2, 0;
 ; CHECK-NOF16-NEXT:    selp.b16 %rs6, %rs2, %rs5, %p4;
 ; CHECK-NOF16-NEXT:    cvt.f32.f16 %r3, %rs4;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p5, %r3, 0f00000000;
@@ -661,9 +661,9 @@ define half @minimum_half(half %a, half %b) {
 ; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs3, %rs1, %rs2, %p1;
 ; CHECK-SM80-NOF16-NEXT:    setp.nan.f32 %p2, %r2, %r1;
 ; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs4, 0x7E00, %rs3, %p2;
-; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p3, %rs1, -32768;
+; CHECK-SM80-NOF16-NEXT:    setp.ne.s16 %p3, %rs1, 0;
 ; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs5, %rs1, %rs4, %p3;
-; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p4, %rs2, -32768;
+; CHECK-SM80-NOF16-NEXT:    setp.ne.s16 %p4, %rs2, 0;
 ; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs6, %rs2, %rs5, %p4;
 ; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r3, %rs4;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.f32 %p5, %r3, 0f00000000;
@@ -686,9 +686,9 @@ define float @minimum_float(float %a, float %b) {
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p1, %r1, %r2;
 ; CHECK-NOF16-NEXT:    min.f32 %r3, %r1, %r2;
 ; CHECK-NOF16-NEXT:    selp.f32 %r4, 0f7FC00000, %r3, %p1;
-; CHECK-NOF16-NEXT:    setp.eq.s32 %p2, %r1, -2147483648;
+; CHECK-NOF16-NEXT:    setp.ne.s32 %p2, %r1, 0;
 ; CHECK-NOF16-NEXT:    selp.f32 %r5, %r1, %r4, %p2;
-; CHECK-NOF16-NEXT:    setp.eq.s32 %p3, %r2, -2147483648;
+; CHECK-NOF16-NEXT:    setp.ne.s32 %p3, %r2, 0;
 ; CHECK-NOF16-NEXT:    selp.f32 %r6, %r2, %r5, %p3;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p4, %r4, 0f00000000;
 ; CHECK-NOF16-NEXT:    selp.f32 %r7, %r6, %r4, %p4;
@@ -731,7 +731,7 @@ define float @minimum_imm1(float %a) {
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p1, %r1, %r1;
 ; CHECK-NOF16-NEXT:    min.f32 %r2, %r1, 0f00000000;
 ; CHECK-NOF16-NEXT:    selp.f32 %r3, 0f7FC00000, %r2, %p1;
-; CHECK-NOF16-NEXT:    setp.eq.s32 %p2, %r1, -2147483648;
+; CHECK-NOF16-NEXT:    setp.ne.s32 %p2, %r1, 0;
 ; CHECK-NOF16-NEXT:    selp.f32 %r4, %r1, %r3, %p2;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p3, %r3, 0f00000000;
 ; CHECK-NOF16-NEXT:    selp.f32 %r5, %r4, %r3, %p3;
@@ -772,7 +772,7 @@ define float @minimum_imm2(float %a) {
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p1, %r1, %r1;
 ; CHECK-NOF16-NEXT:    min.f32 %r2, %r1, 0f00000000;
 ; CHECK-NOF16-NEXT:    selp.f32 %r3, 0f7FC00000, %r2, %p1;
-; CHECK-NOF16-NEXT:    setp.eq.s32 %p2, %r1, -2147483648;
+; CHECK-NOF16-NEXT:    setp.ne.s32 %p2, %r1, 0;
 ; CHECK-NOF16-NEXT:    selp.f32 %r4, %r1, %r3, %p2;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p3, %r3, 0f00000000;
 ; CHECK-NOF16-NEXT:    selp.f32 %r5, %r4, %r3, %p3;
@@ -814,9 +814,9 @@ define float @minimum_float_ftz(float %a, float %b) #1 {
 ; CHECK-NOF16-NEXT:    setp.nan.ftz.f32 %p1, %r1, %r2;
 ; CHECK-NOF16-NEXT:    min.ftz.f32 %r3, %r1, %r2;
 ; CHECK-NOF16-NEXT:    selp.f32 %r4, 0f7FC00000, %r3, %p1;
-; CHECK-NOF16-NEXT:    setp.eq.s32 %p2, %r1, -2147483648;
+; CHECK-NOF16-NEXT:    setp.ne.s32 %p2, %r1, 0;
 ; CHECK-NOF16-NEXT:    selp.f32 %r5, %r1, %r4, %p2;
-; CHECK-NOF16-NEXT:    setp.eq.s32 %p3, %r2, -2147483648;
+; CHECK-NOF16-NEXT:    setp.ne.s32 %p3, %r2, 0;
 ; CHECK-NOF16-NEXT:    selp.f32 %r6, %r2, %r5, %p3;
 ; CHECK-NOF16-NEXT:    setp.eq.ftz.f32 %p4, %r4, 0f00000000;
 ; CHECK-NOF16-NEXT:    selp.f32 %r7, %r6, %r4, %p4;
@@ -860,9 +860,9 @@ define double @minimum_double(double %a, double %b) {
 ; CHECK-NEXT:    setp.nan.f64 %p1, %rd1, %rd2;
 ; CHECK-NEXT:    min.f64 %rd3, %rd1, %rd2;
 ; CHECK-NEXT:    selp.f64 %rd4, 0d7FF8000000000000, %rd3, %p1;
-; CHECK-NEXT:    setp.eq.s64 %p2, %rd1, -9223372036854775808;
+; CHECK-NEXT:    setp.ne.s64 %p2, %rd1, 0;
 ; CHECK-NEXT:    selp.f64 %rd5, %rd1, %rd4, %p2;
-; CHECK-NEXT:    setp.eq.s64 %p3, %rd2, -9223372036854775808;
+; CHECK-NEXT:    setp.ne.s64 %p3, %rd2, 0;
 ; CHECK-NEXT:    selp.f64 %rd6, %rd2, %rd5, %p3;
 ; CHECK-NEXT:    setp.eq.f64 %p4, %rd4, 0d0000000000000000;
 ; CHECK-NEXT:    selp.f64 %rd7, %rd6, %rd4, %p4;
@@ -876,7 +876,7 @@ define <2 x half> @minimum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-NOF16-LABEL: minimum_v2half(
 ; CHECK-NOF16:       {
 ; CHECK-NOF16-NEXT:    .reg .pred %p<11>;
-; CHECK-NOF16-NEXT:    .reg .b16 %rs<15>;
+; CHECK-NOF16-NEXT:    .reg .b16 %rs<19>;
 ; CHECK-NOF16-NEXT:    .reg .b32 %r<10>;
 ; CHECK-NOF16-EMPTY:
 ; CHECK-NOF16-NEXT:  // %bb.0:
@@ -890,27 +890,27 @@ define <2 x half> @minimum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-NOF16-NEXT:    selp.b16 %rs5, %rs4, %rs2, %p1;
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p2, %r4, %r3;
 ; CHECK-NOF16-NEXT:    selp.b16 %rs6, 0x7E00, %rs5, %p2;
-; CHECK-NOF16-NEXT:    setp.eq.s16 %p3, %rs4, -32768;
-; CHECK-NOF16-NEXT:    selp.b16 %rs7, %rs4, %rs6, %p3;
-; CHECK-NOF16-NEXT:    setp.eq.s16 %p4, %rs2, -32768;
-; CHECK-NOF16-NEXT:    selp.b16 %rs8, %rs2, %rs7, %p4;
+; CHECK-NOF16-NEXT:    setp.ne.s16 %p3, %rs4, 0;
+; CHECK-NOF16-NEXT:    selp.b16 %rs9, %rs4, %rs6, %p3;
+; CHECK-NOF16-NEXT:    setp.ne.s16 %p4, %rs2, 0;
+; CHECK-NOF16-NEXT:    selp.b16 %rs12, %rs2, %rs9, %p4;
 ; CHECK-NOF16-NEXT:    cvt.f32.f16 %r5, %rs6;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p5, %r5, 0f00000000;
-; CHECK-NOF16-NEXT:    selp.b16 %rs9, %rs8, %rs6, %p5;
+; CHECK-NOF16-NEXT:    selp.b16 %rs13, %rs12, %rs6, %p5;
 ; CHECK-NOF16-NEXT:    cvt.f32.f16 %r6, %rs1;
 ; CHECK-NOF16-NEXT:    cvt.f32.f16 %r7, %rs3;
 ; CHECK-NOF16-NEXT:    setp.lt.f32 %p6, %r7, %r6;
-; CHECK-NOF16-NEXT:    selp.b16 %rs10, %rs3, %rs1, %p6;
+; CHECK-NOF16-NEXT:    selp.b16 %rs14, %rs3, %rs1, %p6;
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p7, %r7, %r6;
-; CHECK-NOF16-NEXT:    selp.b16 %rs11, 0x7E00, %rs10, %p7;
-; CHECK-NOF16-NEXT:    setp.eq.s16 %p8, %rs3, -32768;
-; CHECK-NOF16-NEXT:    selp.b16 %rs12, %rs3, %rs11, %p8;
-; CHECK-NOF16-NEXT:    setp.eq.s16 %p9, %rs1, -32768;
-; CHECK-NOF16-NEXT:    selp.b16 %rs13, %rs1, %rs12, %p9;
-; CHECK-NOF16-NEXT:    cvt.f32.f16 %r8, %rs11;
+; CHECK-NOF16-NEXT:    selp.b16 %rs15, 0x7E00, %rs14, %p7;
+; CHECK-NOF16-NEXT:    setp.ne.s16 %p8, %rs3, 0;
+; CHECK-NOF16-NEXT:    selp.b16 %rs16, %rs3, %rs15, %p8;
+; CHECK-NOF16-NEXT:    setp.ne.s16 %p9, %rs1, 0;
+; CHECK-NOF16-NEXT:    selp.b16 %rs17, %rs1, %rs16, %p9;
+; CHECK-NOF16-NEXT:    cvt.f32.f16 %r8, %rs15;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p10, %r8, 0f00000000;
-; CHECK-NOF16-NEXT:    selp.b16 %rs14, %rs13, %rs11, %p10;
-; CHECK-NOF16-NEXT:    mov.b32 %r9, {%rs14, %rs9};
+; CHECK-NOF16-NEXT:    selp.b16 %rs18, %rs17, %rs15, %p10;
+; CHECK-NOF16-NEXT:    mov.b32 %r9, {%rs18, %rs13};
 ; CHECK-NOF16-NEXT:    st.param.b32 [func_retval0], %r9;
 ; CHECK-NOF16-NEXT:    ret;
 ;
@@ -928,7 +928,7 @@ define <2 x half> @minimum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-SM80-NOF16-LABEL: minimum_v2half(
 ; CHECK-SM80-NOF16:       {
 ; CHECK-SM80-NOF16-NEXT:    .reg .pred %p<11>;
-; CHECK-SM80-NOF16-NEXT:    .reg .b16 %rs<15>;
+; CHECK-SM80-NOF16-NEXT:    .reg .b16 %rs<19>;
 ; CHECK-SM80-NOF16-NEXT:    .reg .b32 %r<10>;
 ; CHECK-SM80-NOF16-EMPTY:
 ; CHECK-SM80-NOF16-NEXT:  // %bb.0:
@@ -942,27 +942,27 @@ define <2 x half> @minimum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs5, %rs4, %rs2, %p1;
 ; CHECK-SM80-NOF16-NEXT:    setp.nan.f32 %p2, %r4, %r3;
 ; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs6, 0x7E00, %rs5, %p2;
-; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p3, %rs4, -32768;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs7, %rs4, %rs6, %p3;
-; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p4, %rs2, -32768;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs8, %rs2, %rs7, %p4;
+; CHECK-SM80-NOF16-NEXT:    setp.ne.s16 %p3, %rs4, 0;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs9, %rs4, %rs6, %p3;
+; CHECK-SM80-NOF16-NEXT:    setp.ne.s16 %p4, %rs2, 0;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs12, %rs2, %rs9, %p4;
 ; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r5, %rs6;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.f32 %p5, %r5, 0f00000000;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs9, %rs8, %rs6, %p5;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs13, %rs12, %rs6, %p5;
 ; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r6, %rs1;
 ; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r7, %rs3;
 ; CHECK-SM80-NOF16-NEXT:    setp.lt.f32 %p6, %r7, %r6;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs10, %rs3, %rs1, %p6;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs14, %rs3, %rs1, %p6;
 ; CHECK-SM80-NOF16-NEXT:    setp.nan.f32 %p7, %r7, %r6;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs11, 0x7E00, %rs10, %p7;
-; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p8, %rs3, -32768;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs12, %rs3, %rs11, %p8;
-; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p9, %rs1, -32768;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs13, %rs1, %rs12, %p9;
-; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r8, %rs11;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs15, 0x7E00, %rs14, %p7;
+; CHECK-SM80-NOF16-NEXT:    setp.ne.s16 %p8, %rs3, 0;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs16, %rs3, %rs15, %p8;
+; CHECK-SM80-NOF16-NEXT:    setp.ne.s16 %p9, %rs1, 0;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs17, %rs1, %rs16, %p9;
+; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r8, %rs15;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.f32 %p10, %r8, 0f00000000;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs14, %rs13, %rs11, %p10;
-; CHECK-SM80-NOF16-NEXT:    mov.b32 %r9, {%rs14, %rs9};
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs18, %rs17, %rs15, %p10;
+; CHECK-SM80-NOF16-NEXT:    mov.b32 %r9, {%rs18, %rs13};
 ; CHECK-SM80-NOF16-NEXT:    st.param.b32 [func_retval0], %r9;
 ; CHECK-SM80-NOF16-NEXT:    ret;
   %x = call <2 x half> @llvm.minimum.v2f16(<2 x half> %a, <2 x half> %b)
@@ -1413,7 +1413,7 @@ define <2 x half> @maximum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-NOF16-LABEL: maximum_v2half(
 ; CHECK-NOF16:       {
 ; CHECK-NOF16-NEXT:    .reg .pred %p<11>;
-; CHECK-NOF16-NEXT:    .reg .b16 %rs<15>;
+; CHECK-NOF16-NEXT:    .reg .b16 %rs<19>;
 ; CHECK-NOF16-NEXT:    .reg .b32 %r<10>;
 ; CHECK-NOF16-EMPTY:
 ; CHECK-NOF16-NEXT:  // %bb.0:
@@ -1428,26 +1428,26 @@ define <2 x half> @maximum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p2, %r4, %r3;
 ; CHECK-NOF16-NEXT:    selp.b16 %rs6, 0x7E00, %rs5, %p2;
 ; CHECK-NOF16-NEXT:    setp.eq.s16 %p3, %rs4, 0;
-; CHECK-NOF16-NEXT:    selp.b16 %rs7, %rs4, %rs6, %p3;
+; CHECK-NOF16-NEXT:    selp.b16 %rs9, %rs4, %rs6, %p3;
 ; CHECK-NOF16-NEXT:    setp.eq.s16 %p4, %rs2, 0;
-; CHECK-NOF16-NEXT:    selp.b16 %rs8, %rs2, %rs7, %p4;
+; CHECK-NOF16-NEXT:    selp.b16 %rs12, %rs2, %rs9, %p4;
 ; CHECK-NOF16-NEXT:    cvt.f32.f16 %r5, %rs6;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p5, %r5, 0f00000000;
-; CHECK-NOF16-NEXT:    selp.b16 %rs9, %rs8, %rs6, %p5;
+; CHECK-NOF16-NEXT:    selp.b16 %rs13, %rs12, %rs6, %p5;
 ; CHECK-NOF16-NEXT:    cvt.f32.f16 %r6, %rs1;
 ; CHECK-NOF16-NEXT:    cvt.f32.f16 %r7, %rs3;
 ; CHECK-NOF16-NEXT:    setp.gt.f32 %p6, %r7, %r6;
-; CHECK-NOF16-NEXT:    selp.b16 %rs10, %rs3, %rs1, %p6;
+; CHECK-NOF16-NEXT:    selp.b16 %rs14, %rs3, %rs1, %p6;
 ; CHECK-NOF16-NEXT:    setp.nan.f32 %p7, %r7, %r6;
-; CHECK-NOF16-NEXT:    selp.b16 %rs11, 0x7E00, %rs10, %p7;
+; CHECK-NOF16-NEXT:    selp.b16 %rs15, 0x7E00, %rs14, %p7;
 ; CHECK-NOF16-NEXT:    setp.eq.s16 %p8, %rs3, 0;
-; CHECK-NOF16-NEXT:    selp.b16 %rs12, %rs3, %rs11, %p8;
+; CHECK-NOF16-NEXT:    selp.b16 %rs16, %rs3, %rs15, %p8;
 ; CHECK-NOF16-NEXT:    setp.eq.s16 %p9, %rs1, 0;
-; CHECK-NOF16-NEXT:    selp.b16 %rs13, %rs1, %rs12, %p9;
-; CHECK-NOF16-NEXT:    cvt.f32.f16 %r8, %rs11;
+; CHECK-NOF16-NEXT:    selp.b16 %rs17, %rs1, %rs16, %p9;
+; CHECK-NOF16-NEXT:    cvt.f32.f16 %r8, %rs15;
 ; CHECK-NOF16-NEXT:    setp.eq.f32 %p10, %r8, 0f00000000;
-; CHECK-NOF16-NEXT:    selp.b16 %rs14, %rs13, %rs11, %p10;
-; CHECK-NOF16-NEXT:    mov.b32 %r9, {%rs14, %rs9};
+; CHECK-NOF16-NEXT:    selp.b16 %rs18, %rs17, %rs15, %p10;
+; CHECK-NOF16-NEXT:    mov.b32 %r9, {%rs18, %rs13};
 ; CHECK-NOF16-NEXT:    st.param.b32 [func_retval0], %r9;
 ; CHECK-NOF16-NEXT:    ret;
 ;
@@ -1465,7 +1465,7 @@ define <2 x half> @maximum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-SM80-NOF16-LABEL: maximum_v2half(
 ; CHECK-SM80-NOF16:       {
 ; CHECK-SM80-NOF16-NEXT:    .reg .pred %p<11>;
-; CHECK-SM80-NOF16-NEXT:    .reg .b16 %rs<15>;
+; CHECK-SM80-NOF16-NEXT:    .reg .b16 %rs<19>;
 ; CHECK-SM80-NOF16-NEXT:    .reg .b32 %r<10>;
 ; CHECK-SM80-NOF16-EMPTY:
 ; CHECK-SM80-NOF16-NEXT:  // %bb.0:
@@ -1480,26 +1480,26 @@ define <2 x half> @maximum_v2half(<2 x half> %a, <2 x half> %b) {
 ; CHECK-SM80-NOF16-NEXT:    setp.nan.f32 %p2, %r4, %r3;
 ; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs6, 0x7E00, %rs5, %p2;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p3, %rs4, 0;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs7, %rs4, %rs6, %p3;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs9, %rs4, %rs6, %p3;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p4, %rs2, 0;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs8, %rs2, %rs7, %p4;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs12, %rs2, %rs9, %p4;
 ; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r5, %rs6;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.f32 %p5, %r5, 0f00000000;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs9, %rs8, %rs6, %p5;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs13, %rs12, %rs6, %p5;
 ; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r6, %rs1;
 ; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r7, %rs3;
 ; CHECK-SM80-NOF16-NEXT:    setp.gt.f32 %p6, %r7, %r6;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs10, %rs3, %rs1, %p6;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs14, %rs3, %rs1, %p6;
 ; CHECK-SM80-NOF16-NEXT:    setp.nan.f32 %p7, %r7, %r6;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs11, 0x7E00, %rs10, %p7;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs15, 0x7E00, %rs14, %p7;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p8, %rs3, 0;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs12, %rs3, %rs11, %p8;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs16, %rs3, %rs15, %p8;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.s16 %p9, %rs1, 0;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs13, %rs1, %rs12, %p9;
-; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r8, %rs11;
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs17, %rs1, %rs16, %p9;
+; CHECK-SM80-NOF16-NEXT:    cvt.f32.f16 %r8, %rs15;
 ; CHECK-SM80-NOF16-NEXT:    setp.eq.f32 %p10, %r8, 0f00000000;
-; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs14, %rs13, %rs11, %p10;
-; CHECK-SM80-NOF16-NEXT:    mov.b32 %r9, {%rs14, %rs9};
+; CHECK-SM80-NOF16-NEXT:    selp.b16 %rs18, %rs17, %rs15, %p10;
+; CHECK-SM80-NOF16-NEXT:    mov.b32 %r9, {%rs18, %rs13};
 ; CHECK-SM80-NOF16-NEXT:    st.param.b32 [func_retval0], %r9;
 ; CHECK-SM80-NOF16-NEXT:    ret;
   %x = call <2 x half> @llvm.maximum.v2f16(<2 x half> %a, <2 x half> %b)
diff --git a/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll b/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll
index a99c25a4e4479..2e65938b7c18e 100644
--- a/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll
+++ b/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll
@@ -7,40 +7,39 @@ define float @f32_minimum(float %a, float %b) {
 ; NOVSX-LABEL: f32_minimum:
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
-; NOVSX-NEXT:    fmr 0, 1
-; NOVSX-NEXT:    stfs 2, -8(1)
-; NOVSX-NEXT:    stfs 1, -4(1)
+; NOVSX-NEXT:    fmr 3, 1
+; NOVSX-NEXT:    stfs 2, -4(1)
+; NOVSX-NEXT:    stfs 1, -8(1)
 ; NOVSX-NEXT:    bc 12, 0, .LBB0_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
-; NOVSX-NEXT:    fmr 0, 2
+; NOVSX-NEXT:    fmr 3, 2
 ; NOVSX-NEXT:  .LBB0_2: # %entry
-; NOVSX-NEXT:    lwz 3, -4(1)
+; NOVSX-NEXT:    lwz 3, -8(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB0_4
 ; NOVSX-NEXT:  # %bb.3:
 ; NOVSX-NEXT:    addis 4, 2, .LCPI0_0 at toc@ha
-; NOVSX-NEXT:    lfs 0, .LCPI0_0 at toc@l(4)
+; NOVSX-NEXT:    lfs 3, .LCPI0_0 at toc@l(4)
 ; NOVSX-NEXT:  .LBB0_4: # %entry
-; NOVSX-NEXT:    xoris 3, 3, 32768
-; NOVSX-NEXT:    lwz 4, -8(1)
-; NOVSX-NEXT:    cmplwi 3, 0
+; NOVSX-NEXT:    fmr 0, 3
+; NOVSX-NEXT:    cmpwi 3, 0
+; NOVSX-NEXT:    lwz 4, -4(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB0_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
-; NOVSX-NEXT:    fmr 1, 0
+; NOVSX-NEXT:    fmr 0, 1
 ; NOVSX-NEXT:  .LBB0_6: # %entry
-; NOVSX-NEXT:    xoris 3, 4, 32768
-; NOVSX-NEXT:    cmplwi 3, 0
+; NOVSX-NEXT:    cmpwi 4, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB0_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
-; NOVSX-NEXT:    fmr 2, 1
+; NOVSX-NEXT:    fmr 0, 2
 ; NOVSX-NEXT:  .LBB0_8: # %entry
 ; NOVSX-NEXT:    addis 3, 2, .LCPI0_1 at toc@ha
 ; NOVSX-NEXT:    lfs 1, .LCPI0_1 at toc@l(3)
-; NOVSX-NEXT:    fcmpu 0, 0, 1
+; NOVSX-NEXT:    fcmpu 0, 3, 1
 ; NOVSX-NEXT:    bc 12, 2, .LBB0_10
 ; NOVSX-NEXT:  # %bb.9: # %entry
-; NOVSX-NEXT:    fmr 2, 0
+; NOVSX-NEXT:    fmr 0, 3
 ; NOVSX-NEXT:  .LBB0_10: # %entry
-; NOVSX-NEXT:    fmr 1, 2
+; NOVSX-NEXT:    fmr 1, 0
 ; NOVSX-NEXT:    blr
 ;
 ; VSX-LABEL: f32_minimum:
@@ -76,20 +75,20 @@ define float @f32_maximum(float %a, float %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
 ; NOVSX-NEXT:    fmr 0, 1
-; NOVSX-NEXT:    stfs 2, -8(1)
-; NOVSX-NEXT:    stfs 1, -4(1)
+; NOVSX-NEXT:    stfs 2, -4(1)
+; NOVSX-NEXT:    stfs 1, -8(1)
 ; NOVSX-NEXT:    bc 12, 1, .LBB1_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 0, 2
 ; NOVSX-NEXT:  .LBB1_2: # %entry
-; NOVSX-NEXT:    lwz 3, -4(1)
+; NOVSX-NEXT:    lwz 3, -8(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB1_4
 ; NOVSX-NEXT:  # %bb.3:
 ; NOVSX-NEXT:    addis 4, 2, .LCPI1_0 at toc@ha
 ; NOVSX-NEXT:    lfs 0, .LCPI1_0 at toc@l(4)
 ; NOVSX-NEXT:  .LBB1_4: # %entry
 ; NOVSX-NEXT:    cmpwi 3, 0
-; NOVSX-NEXT:    lwz 4, -8(1)
+; NOVSX-NEXT:    lwz 4, -4(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB1_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 1, 0
@@ -141,40 +140,39 @@ define double @f64_minimum(double %a, double %b) {
 ; NOVSX-LABEL: f64_minimum:
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
-; NOVSX-NEXT:    fmr 0, 1
-; NOVSX-NEXT:    stfd 2, -16(1)
-; NOVSX-NEXT:    stfd 1, -8(1)
+; NOVSX-NEXT:    fmr 3, 1
+; NOVSX-NEXT:    stfd 2, -8(1)
+; NOVSX-NEXT:    stfd 1, -16(1)
 ; NOVSX-NEXT:    bc 12, 0, .LBB2_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
-; NOVSX-NEXT:    fmr 0, 2
+; NOVSX-NEXT:    fmr 3, 2
 ; NOVSX-NEXT:  .LBB2_2: # %entry
-; NOVSX-NEXT:    ld 3, -8(1)
+; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB2_4
 ; NOVSX-NEXT:  # %bb.3:
 ; NOVSX-NEXT:    addis 4, 2, .LCPI2_0 at toc@ha
-; NOVSX-NEXT:    lfs 0, .LCPI2_0 at toc@l(4)
+; NOVSX-NEXT:    lfs 3, .LCPI2_0 at toc@l(4)
 ; NOVSX-NEXT:  .LBB2_4: # %entry
-; NOVSX-NEXT:    li 5, 1
-; NOVSX-NEXT:    ld 4, -16(1)
-; NOVSX-NEXT:    rldic 5, 5, 63, 0
-; NOVSX-NEXT:    cmpd 3, 5
+; NOVSX-NEXT:    fmr 0, 3
+; NOVSX-NEXT:    cmpdi 3, 0
+; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB2_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
-; NOVSX-NEXT:    fmr 1, 0
+; NOVSX-NEXT:    fmr 0, 1
 ; NOVSX-NEXT:  .LBB2_6: # %entry
-; NOVSX-NEXT:    cmpd 4, 5
+; NOVSX-NEXT:    cmpdi 4, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB2_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
-; NOVSX-NEXT:    fmr 2, 1
+; NOVSX-NEXT:    fmr 0, 2
 ; NOVSX-NEXT:  .LBB2_8: # %entry
 ; NOVSX-NEXT:    addis 3, 2, .LCPI2_1 at toc@ha
 ; NOVSX-NEXT:    lfs 1, .LCPI2_1 at toc@l(3)
-; NOVSX-NEXT:    fcmpu 0, 0, 1
+; NOVSX-NEXT:    fcmpu 0, 3, 1
 ; NOVSX-NEXT:    bc 12, 2, .LBB2_10
 ; NOVSX-NEXT:  # %bb.9: # %entry
-; NOVSX-NEXT:    fmr 2, 0
+; NOVSX-NEXT:    fmr 0, 3
 ; NOVSX-NEXT:  .LBB2_10: # %entry
-; NOVSX-NEXT:    fmr 1, 2
+; NOVSX-NEXT:    fmr 1, 0
 ; NOVSX-NEXT:    blr
 ;
 ; VSX-LABEL: f64_minimum:
@@ -210,20 +208,20 @@ define double @f64_maximum(double %a, double %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
 ; NOVSX-NEXT:    fmr 0, 1
-; NOVSX-NEXT:    stfd 2, -16(1)
-; NOVSX-NEXT:    stfd 1, -8(1)
+; NOVSX-NEXT:    stfd 2, -8(1)
+; NOVSX-NEXT:    stfd 1, -16(1)
 ; NOVSX-NEXT:    bc 12, 1, .LBB3_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 0, 2
 ; NOVSX-NEXT:  .LBB3_2: # %entry
-; NOVSX-NEXT:    ld 3, -8(1)
+; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB3_4
 ; NOVSX-NEXT:  # %bb.3:
 ; NOVSX-NEXT:    addis 4, 2, .LCPI3_0 at toc@ha
 ; NOVSX-NEXT:    lfs 0, .LCPI3_0 at toc@l(4)
 ; NOVSX-NEXT:  .LBB3_4: # %entry
 ; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    ld 4, -16(1)
+; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB3_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 1, 0
@@ -274,26 +272,26 @@ entry:
 define <4 x float> @v4f32_minimum(<4 x float> %a, <4 x float> %b) {
 ; NOVSX-LABEL: v4f32_minimum:
 ; NOVSX:       # %bb.0: # %entry
-; NOVSX-NEXT:    vcmpeqfp 0, 3, 3
-; NOVSX-NEXT:    vcmpeqfp 1, 2, 2
+; NOVSX-NEXT:    vcmpeqfp 5, 3, 3
+; NOVSX-NEXT:    vcmpeqfp 0, 2, 2
 ; NOVSX-NEXT:    addis 3, 2, .LCPI4_0 at toc@ha
 ; NOVSX-NEXT:    addi 3, 3, .LCPI4_0 at toc@l
+; NOVSX-NEXT:    vnot 5, 5
+; NOVSX-NEXT:    vnot 0, 0
+; NOVSX-NEXT:    vcmpgtfp 4, 3, 2
+; NOVSX-NEXT:    vor 5, 0, 5
+; NOVSX-NEXT:    lvx 0, 0, 3
+; NOVSX-NEXT:    vsel 4, 3, 2, 4
+; NOVSX-NEXT:    vsel 4, 4, 0, 5
+; NOVSX-NEXT:    vxor 5, 5, 5
+; NOVSX-NEXT:    vcmpequw 0, 2, 5
+; NOVSX-NEXT:    vnot 0, 0
+; NOVSX-NEXT:    vsel 2, 4, 2, 0
+; NOVSX-NEXT:    vcmpequw 0, 3, 5
 ; NOVSX-NEXT:    vnot 0, 0
-; NOVSX-NEXT:    vnot 1, 1
-; NOVSX-NEXT:    vspltisb 4, -1
-; NOVSX-NEXT:    vcmpgtfp 5, 3, 2
-; NOVSX-NEXT:    vslw 4, 4, 4
-; NOVSX-NEXT:    vor 0, 1, 0
-; NOVSX-NEXT:    lvx 1, 0, 3
-; NOVSX-NEXT:    vsel 5, 3, 2, 5
-; NOVSX-NEXT:    vsel 5, 5, 1, 0
-; NOVSX-NEXT:    vcmpequw 0, 2, 4
-; NOVSX-NEXT:    vcmpequw 4, 3, 4
-; NOVSX-NEXT:    vsel 2, 5, 2, 0
-; NOVSX-NEXT:    vsel 2, 2, 3, 4
-; NOVSX-NEXT:    vxor 3, 3, 3
-; NOVSX-NEXT:    vcmpeqfp 3, 5, 3
-; NOVSX-NEXT:    vsel 2, 5, 2, 3
+; NOVSX-NEXT:    vsel 2, 2, 3, 0
+; NOVSX-NEXT:    vcmpeqfp 3, 4, 5
+; NOVSX-NEXT:    vsel 2, 4, 2, 3
 ; NOVSX-NEXT:    blr
 ;
 ; VSX-LABEL: v4f32_minimum:
@@ -301,21 +299,21 @@ define <4 x float> @v4f32_minimum(<4 x float> %a, <4 x float> %b) {
 ; VSX-NEXT:    xvcmpeqsp 1, 35, 35
 ; VSX-NEXT:    xvcmpeqsp 2, 34, 34
 ; VSX-NEXT:    addis 3, 2, .LCPI4_0 at toc@ha
-; VSX-NEXT:    xxleqv 36, 36, 36
-; VSX-NEXT:    xvminsp 0, 34, 35
-; VSX-NEXT:    vslw 4, 4, 4
 ; VSX-NEXT:    addi 3, 3, .LCPI4_0 at toc@l
 ; VSX-NEXT:    xxlnor 1, 1, 1
 ; VSX-NEXT:    xxlnor 2, 2, 2
+; VSX-NEXT:    xxlxor 36, 36, 36
+; VSX-NEXT:    xvminsp 0, 34, 35
 ; VSX-NEXT:    vcmpequw 5, 2, 4
 ; VSX-NEXT:    xxlor 1, 2, 1
 ; VSX-NEXT:    lxvd2x 2, 0, 3
 ; VSX-NEXT:    xxsel 0, 0, 2, 1
-; VSX-NEXT:    xxlxor 2, 2, 2
-; VSX-NEXT:    xvcmpeqsp 2, 0, 2
-; VSX-NEXT:    xxsel 1, 0, 34, 37
+; VSX-NEXT:    xxlnor 1, 37, 37
+; VSX-NEXT:    xxsel 1, 0, 34, 1
 ; VSX-NEXT:    vcmpequw 2, 3, 4
-; VSX-NEXT:    xxsel 1, 1, 35, 34
+; VSX-NEXT:    xxlnor 2, 34, 34
+; VSX-NEXT:    xxsel 1, 1, 35, 2
+; VSX-NEXT:    xvcmpeqsp 2, 0, 36
 ; VSX-NEXT:    xxsel 34, 0, 1, 2
 ; VSX-NEXT:    blr
 ;
@@ -324,20 +322,20 @@ define <4 x float> @v4f32_minimum(<4 x float> %a, <4 x float> %b) {
 ; AIX-NEXT:    xvcmpeqsp 1, 35, 35
 ; AIX-NEXT:    xvcmpeqsp 2, 34, 34
 ; AIX-NEXT:    ld 3, L..C4(2) # %const.0
-; AIX-NEXT:    xxleqv 36, 36, 36
+; AIX-NEXT:    xxlxor 36, 36, 36
 ; AIX-NEXT:    xvminsp 0, 34, 35
-; AIX-NEXT:    vslw 4, 4, 4
 ; AIX-NEXT:    xxlnor 1, 1, 1
 ; AIX-NEXT:    xxlnor 2, 2, 2
 ; AIX-NEXT:    vcmpequw 5, 2, 4
 ; AIX-NEXT:    xxlor 1, 2, 1
 ; AIX-NEXT:    lxvw4x 2, 0, 3
 ; AIX-NEXT:    xxsel 0, 0, 2, 1
-; AIX-NEXT:    xxlxor 2, 2, 2
-; AIX-NEXT:    xvcmpeqsp 2, 0, 2
-; AIX-NEXT:    xxsel 1, 0, 34, 37
+; AIX-NEXT:    xxlnor 1, 37, 37
+; AIX-NEXT:    xxsel 1, 0, 34, 1
 ; AIX-NEXT:    vcmpequw 2, 3, 4
-; AIX-NEXT:    xxsel 1, 1, 35, 34
+; AIX-NEXT:    xxlnor 2, 34, 34
+; AIX-NEXT:    xxsel 1, 1, 35, 2
+; AIX-NEXT:    xvcmpeqsp 2, 0, 36
 ; AIX-NEXT:    xxsel 34, 0, 1, 2
 ; AIX-NEXT:    blr
 entry:
@@ -417,78 +415,78 @@ define <2 x double> @v2f64_minimum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX-LABEL: v2f64_minimum:
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 3
-; NOVSX-NEXT:    fmr 6, 1
-; NOVSX-NEXT:    stfd 4, -16(1)
-; NOVSX-NEXT:    stfd 2, -8(1)
-; NOVSX-NEXT:    stfd 3, -32(1)
-; NOVSX-NEXT:    stfd 1, -24(1)
+; NOVSX-NEXT:    fmr 0, 1
+; NOVSX-NEXT:    stfd 4, -24(1)
+; NOVSX-NEXT:    stfd 2, -32(1)
+; NOVSX-NEXT:    stfd 3, -8(1)
+; NOVSX-NEXT:    stfd 1, -16(1)
 ; NOVSX-NEXT:    bc 12, 0, .LBB6_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
-; NOVSX-NEXT:    fmr 6, 3
+; NOVSX-NEXT:    fmr 1, 3
 ; NOVSX-NEXT:  .LBB6_2: # %entry
-; NOVSX-NEXT:    addis 3, 2, .LCPI6_0 at toc@ha
-; NOVSX-NEXT:    ld 4, -24(1)
-; NOVSX-NEXT:    lfs 0, .LCPI6_0 at toc@l(3)
-; NOVSX-NEXT:    fmr 5, 0
+; NOVSX-NEXT:    addis 4, 2, .LCPI6_0 at toc@ha
+; NOVSX-NEXT:    ld 3, -16(1)
+; NOVSX-NEXT:    lfs 5, .LCPI6_0 at toc@l(4)
+; NOVSX-NEXT:    fmr 6, 5
 ; NOVSX-NEXT:    bc 12, 3, .LBB6_4
 ; NOVSX-NEXT:  # %bb.3: # %entry
-; NOVSX-NEXT:    fmr 5, 6
+; NOVSX-NEXT:    fmr 6, 1
 ; NOVSX-NEXT:  .LBB6_4: # %entry
-; NOVSX-NEXT:    li 3, 1
-; NOVSX-NEXT:    ld 5, -32(1)
-; NOVSX-NEXT:    rldic 3, 3, 63, 0
-; NOVSX-NEXT:    cmpd 4, 3
+; NOVSX-NEXT:    fmr 1, 6
+; NOVSX-NEXT:    cmpdi 3, 0
+; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB6_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
-; NOVSX-NEXT:    fmr 1, 5
+; NOVSX-NEXT:    fmr 1, 0
 ; NOVSX-NEXT:  .LBB6_6: # %entry
-; NOVSX-NEXT:    cmpd 5, 3
+; NOVSX-NEXT:    cmpdi 4, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB6_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
-; NOVSX-NEXT:    fmr 3, 1
+; NOVSX-NEXT:    fmr 1, 3
 ; NOVSX-NEXT:  .LBB6_8: # %entry
-; NOVSX-NEXT:    addis 4, 2, .LCPI6_1 at toc@ha
-; NOVSX-NEXT:    lfs 1, .LCPI6_1 at toc@l(4)
-; NOVSX-NEXT:    fcmpu 0, 5, 1
+; NOVSX-NEXT:    addis 3, 2, .LCPI6_1 at toc@ha
+; NOVSX-NEXT:    lfs 3, .LCPI6_1 at toc@l(3)
+; NOVSX-NEXT:    fcmpu 0, 6, 3
 ; NOVSX-NEXT:    bc 12, 2, .LBB6_10
 ; NOVSX-NEXT:  # %bb.9: # %entry
-; NOVSX-NEXT:    fmr 3, 5
+; NOVSX-NEXT:    fmr 1, 6
 ; NOVSX-NEXT:  .LBB6_10: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 2, 4
-; NOVSX-NEXT:    fmr 5, 2
+; NOVSX-NEXT:    fmr 0, 2
 ; NOVSX-NEXT:    bc 12, 0, .LBB6_12
 ; NOVSX-NEXT:  # %bb.11: # %entry
-; NOVSX-NEXT:    fmr 5, 4
+; NOVSX-NEXT:    fmr 0, 4
 ; NOVSX-NEXT:  .LBB6_12: # %entry
-; NOVSX-NEXT:    ld 5, -8(1)
+; NOVSX-NEXT:    ld 4, -32(1)
 ; NOVSX-NEXT:    bc 12, 3, .LBB6_14
 ; NOVSX-NEXT:  # %bb.13: # %entry
-; NOVSX-NEXT:    fmr 0, 5
+; NOVSX-NEXT:    fmr 5, 0
 ; NOVSX-NEXT:  .LBB6_14: # %entry
-; NOVSX-NEXT:    cmpd 5, 3
-; NOVSX-NEXT:    ld 4, -16(1)
-; NOVSX-NEXT:    bc 4, 2, .LBB6_19
+; NOVSX-NEXT:    fmr 0, 5
+; NOVSX-NEXT:    cmpdi 4, 0
+; NOVSX-NEXT:    ld 3, -24(1)
+; NOVSX-NEXT:    bc 4, 2, .LBB6_18
 ; NOVSX-NEXT:  # %bb.15: # %entry
-; NOVSX-NEXT:    cmpd 4, 3
-; NOVSX-NEXT:    bc 4, 2, .LBB6_20
+; NOVSX-NEXT:    cmpdi 3, 0
+; NOVSX-NEXT:    bc 4, 2, .LBB6_19
 ; NOVSX-NEXT:  .LBB6_16: # %entry
-; NOVSX-NEXT:    fcmpu 0, 0, 1
-; NOVSX-NEXT:    bc 12, 2, .LBB6_18
+; NOVSX-NEXT:    fcmpu 0, 5, 3
+; NOVSX-NEXT:    bc 4, 2, .LBB6_20
 ; NOVSX-NEXT:  .LBB6_17: # %entry
-; NOVSX-NEXT:    fmr 4, 0
-; NOVSX-NEXT:  .LBB6_18: # %entry
-; NOVSX-NEXT:    fmr 1, 3
-; NOVSX-NEXT:    fmr 2, 4
-; NOVSX-NEXT:    blr
-; NOVSX-NEXT:  .LBB6_19: # %entry
 ; NOVSX-NEXT:    fmr 2, 0
-; NOVSX-NEXT:    cmpd 4, 3
+; NOVSX-NEXT:    blr
+; NOVSX-NEXT:  .LBB6_18: # %entry
+; NOVSX-NEXT:    fmr 0, 2
+; NOVSX-NEXT:    cmpdi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB6_16
+; NOVSX-NEXT:  .LBB6_19: # %entry
+; NOVSX-NEXT:    fmr 0, 4
+; NOVSX-NEXT:    fcmpu 0, 5, 3
+; NOVSX-NEXT:    bc 12, 2, .LBB6_17
 ; NOVSX-NEXT:  .LBB6_20: # %entry
-; NOVSX-NEXT:    fmr 4, 2
-; NOVSX-NEXT:    fcmpu 0, 0, 1
-; NOVSX-NEXT:    bc 4, 2, .LBB6_17
-; NOVSX-NEXT:    b .LBB6_18
+; NOVSX-NEXT:    fmr 0, 5
+; NOVSX-NEXT:    fmr 2, 0
+; NOVSX-NEXT:    blr
 ;
 ; VSX-LABEL: v2f64_minimum:
 ; VSX:       # %bb.0: # %entry
@@ -500,39 +498,38 @@ define <2 x double> @v2f64_minimum(<2 x double> %a, <2 x double> %b) {
 ; VSX-NEXT:    xxlnor 37, 37, 37
 ; VSX-NEXT:    xvmindp 0, 34, 35
 ; VSX-NEXT:    lxvd2x 2, 0, 3
-; VSX-NEXT:    addis 3, 2, .LCPI6_1 at toc@ha
 ; VSX-NEXT:    xxlor 1, 37, 36
-; VSX-NEXT:    addi 3, 3, .LCPI6_1 at toc@l
-; VSX-NEXT:    lxvd2x 36, 0, 3
+; VSX-NEXT:    xxlxor 36, 36, 36
 ; VSX-NEXT:    vcmpequd 5, 2, 4
+; VSX-NEXT:    xxlnor 37, 37, 37
 ; VSX-NEXT:    xxsel 0, 0, 2, 1
-; VSX-NEXT:    xxlxor 2, 2, 2
 ; VSX-NEXT:    xxsel 1, 0, 34, 37
 ; VSX-NEXT:    vcmpequd 2, 3, 4
+; VSX-NEXT:    xxlnor 34, 34, 34
 ; VSX-NEXT:    xxsel 1, 1, 35, 34
-; VSX-NEXT:    xvcmpeqdp 34, 0, 2
+; VSX-NEXT:    xvcmpeqdp 34, 0, 36
 ; VSX-NEXT:    xxsel 34, 0, 1, 34
 ; VSX-NEXT:    blr
 ;
 ; AIX-LABEL: v2f64_minimum:
 ; AIX:       # %bb.0: # %entry
-; AIX-NEXT:    ld 3, L..C6(2) # %const.0
 ; AIX-NEXT:    xvcmpeqdp 36, 35, 35
 ; AIX-NEXT:    xvcmpeqdp 37, 34, 34
+; AIX-NEXT:    ld 3, L..C6(2) # %const.0
 ; AIX-NEXT:    lxvd2x 2, 0, 3
-; AIX-NEXT:    ld 3, L..C7(2) # %const.1
 ; AIX-NEXT:    xxlnor 36, 36, 36
 ; AIX-NEXT:    xxlnor 37, 37, 37
 ; AIX-NEXT:    xvmindp 0, 34, 35
 ; AIX-NEXT:    xxlor 1, 37, 36
-; AIX-NEXT:    lxvd2x 36, 0, 3
+; AIX-NEXT:    xxlxor 36, 36, 36
 ; AIX-NEXT:    vcmpequd 5, 2, 4
+; AIX-NEXT:    xxlnor 37, 37, 37
 ; AIX-NEXT:    xxsel 0, 0, 2, 1
-; AIX-NEXT:    xxlxor 2, 2, 2
 ; AIX-NEXT:    xxsel 1, 0, 34, 37
 ; AIX-NEXT:    vcmpequd 2, 3, 4
+; AIX-NEXT:    xxlnor 34, 34, 34
 ; AIX-NEXT:    xxsel 1, 1, 35, 34
-; AIX-NEXT:    xvcmpeqdp 34, 0, 2
+; AIX-NEXT:    xvcmpeqdp 34, 0, 36
 ; AIX-NEXT:    xxsel 34, 0, 1, 34
 ; AIX-NEXT:    blr
 entry:
@@ -545,16 +542,16 @@ define <2 x double> @v2f64_maximum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 3
 ; NOVSX-NEXT:    fmr 6, 1
-; NOVSX-NEXT:    stfd 4, -16(1)
-; NOVSX-NEXT:    stfd 2, -8(1)
-; NOVSX-NEXT:    stfd 3, -32(1)
-; NOVSX-NEXT:    stfd 1, -24(1)
+; NOVSX-NEXT:    stfd 4, -24(1)
+; NOVSX-NEXT:    stfd 2, -32(1)
+; NOVSX-NEXT:    stfd 3, -8(1)
+; NOVSX-NEXT:    stfd 1, -16(1)
 ; NOVSX-NEXT:    bc 12, 1, .LBB7_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 6, 3
 ; NOVSX-NEXT:  .LBB7_2: # %entry
 ; NOVSX-NEXT:    addis 4, 2, .LCPI7_0 at toc@ha
-; NOVSX-NEXT:    ld 3, -24(1)
+; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    lfs 0, .LCPI7_0 at toc@l(4)
 ; NOVSX-NEXT:    fmr 5, 0
 ; NOVSX-NEXT:    bc 12, 3, .LBB7_4
@@ -562,7 +559,7 @@ define <2 x double> @v2f64_maximum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX-NEXT:    fmr 5, 6
 ; NOVSX-NEXT:  .LBB7_4: # %entry
 ; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    ld 4, -32(1)
+; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB7_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 1, 5
@@ -585,13 +582,13 @@ define <2 x double> @v2f64_maximum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX-NEXT:  # %bb.11: # %entry
 ; NOVSX-NEXT:    fmr 5, 4
 ; NOVSX-NEXT:  .LBB7_12: # %entry
-; NOVSX-NEXT:    ld 4, -8(1)
+; NOVSX-NEXT:    ld 4, -32(1)
 ; NOVSX-NEXT:    bc 12, 3, .LBB7_14
 ; NOVSX-NEXT:  # %bb.13: # %entry
 ; NOVSX-NEXT:    fmr 0, 5
 ; NOVSX-NEXT:  .LBB7_14: # %entry
 ; NOVSX-NEXT:    cmpdi 4, 0
-; NOVSX-NEXT:    ld 3, -16(1)
+; NOVSX-NEXT:    ld 3, -24(1)
 ; NOVSX-NEXT:    bc 4, 2, .LBB7_19
 ; NOVSX-NEXT:  # %bb.15: # %entry
 ; NOVSX-NEXT:    cmpdi 3, 0
@@ -638,7 +635,7 @@ define <2 x double> @v2f64_maximum(<2 x double> %a, <2 x double> %b) {
 ;
 ; AIX-LABEL: v2f64_maximum:
 ; AIX:       # %bb.0: # %entry
-; AIX-NEXT:    ld 3, L..C8(2) # %const.0
+; AIX-NEXT:    ld 3, L..C7(2) # %const.0
 ; AIX-NEXT:    xvcmpeqdp 36, 35, 35
 ; AIX-NEXT:    xvcmpeqdp 37, 34, 34
 ; AIX-NEXT:    lxvd2x 2, 0, 3

>From 0020c2b7d7d90a1d91d6d44292ff46280bd79fe3 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 30 May 2025 16:39:32 +0200
Subject: [PATCH 2/5] Move FloatSignAsInt helpers to SelectionDAG.h

---
 llvm/include/llvm/CodeGen/SelectionDAG.h      |  24 +++++
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 100 ++----------------
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  60 +++++++++++
 3 files changed, 91 insertions(+), 93 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index a98e46c587273..7dc70d5c50c03 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -215,6 +215,20 @@ class SDDbgInfo {
 
 LLVM_ABI void checkForCycles(const SelectionDAG *DAG, bool force = false);
 
+/// Keeps track of state when getting the sign of a floating-point value as an
+/// integer.
+struct FloatSignAsInt {
+  EVT FloatVT;
+  SDValue Chain;
+  SDValue FloatPtr;
+  SDValue IntPtr;
+  MachinePointerInfo IntPointerInfo;
+  MachinePointerInfo FloatPointerInfo;
+  SDValue IntValue;
+  APInt SignMask;
+  uint8_t SignBit;
+};
+
 /// This is used to represent a portion of an LLVM function in a low-level
 /// Data Dependence DAG representation suitable for instruction selection.
 /// This DAG is constructed as the first step of instruction selection in order
@@ -2017,6 +2031,16 @@ class SelectionDAG {
   /// value types.
   LLVM_ABI SDValue CreateStackTemporary(EVT VT1, EVT VT2);
 
+  /// Bitcast a floating-point value to an integer value. Only bitcast the part
+  /// containing the sign bit if the target has no integer value capable of
+  /// holding all bits of the floating-point value.
+  void getSignAsIntValue(FloatSignAsInt &State, const SDLoc &DL, SDValue Value);
+
+  /// Replace the integer value produced by getSignAsIntValue() with a new value
+  /// and cast the result back to a floating-point type.
+  SDValue modifySignAsInt(const FloatSignAsInt &State, const SDLoc &DL,
+                          SDValue NewIntValue);
+
   LLVM_ABI SDValue FoldSymbolOffset(unsigned Opcode, EVT VT,
                                     const GlobalAddressSDNode *GA,
                                     const SDNode *N2);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 528c07cc5549d..2c41a871b6d6c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -59,20 +59,6 @@ using namespace llvm;
 
 namespace {
 
-/// Keeps track of state when getting the sign of a floating-point value as an
-/// integer.
-struct FloatSignAsInt {
-  EVT FloatVT;
-  SDValue Chain;
-  SDValue FloatPtr;
-  SDValue IntPtr;
-  MachinePointerInfo IntPointerInfo;
-  MachinePointerInfo FloatPointerInfo;
-  SDValue IntValue;
-  APInt SignMask;
-  uint8_t SignBit;
-};
-
 //===----------------------------------------------------------------------===//
 /// This takes an arbitrary SelectionDAG as input and
 /// hacks on it until the target machine can handle it.  This involves
@@ -166,10 +152,6 @@ class SelectionDAGLegalize {
   SDValue ExpandSCALAR_TO_VECTOR(SDNode *Node);
   void ExpandDYNAMIC_STACKALLOC(SDNode *Node,
                                 SmallVectorImpl<SDValue> &Results);
-  void getSignAsIntValue(FloatSignAsInt &State, const SDLoc &DL,
-                         SDValue Value) const;
-  SDValue modifySignAsInt(const FloatSignAsInt &State, const SDLoc &DL,
-                          SDValue NewIntValue) const;
   SDValue ExpandFCOPYSIGN(SDNode *Node) const;
   SDValue ExpandFABS(SDNode *Node) const;
   SDValue ExpandFNEG(SDNode *Node) const;
@@ -1620,74 +1602,6 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) {
   return DAG.getLoad(VT, dl, StoreChain, FIPtr, PtrInfo);
 }
 
-/// Bitcast a floating-point value to an integer value. Only bitcast the part
-/// containing the sign bit if the target has no integer value capable of
-/// holding all bits of the floating-point value.
-void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State,
-                                             const SDLoc &DL,
-                                             SDValue Value) const {
-  EVT FloatVT = Value.getValueType();
-  unsigned NumBits = FloatVT.getScalarSizeInBits();
-  State.FloatVT = FloatVT;
-  EVT IVT = EVT::getIntegerVT(*DAG.getContext(), NumBits);
-  // Convert to an integer of the same size.
-  if (TLI.isTypeLegal(IVT)) {
-    State.IntValue = DAG.getNode(ISD::BITCAST, DL, IVT, Value);
-    State.SignMask = APInt::getSignMask(NumBits);
-    State.SignBit = NumBits - 1;
-    return;
-  }
-
-  auto &DataLayout = DAG.getDataLayout();
-  // Store the float to memory, then load the sign part out as an integer.
-  MVT LoadTy = TLI.getRegisterType(MVT::i8);
-  // First create a temporary that is aligned for both the load and store.
-  SDValue StackPtr = DAG.CreateStackTemporary(FloatVT, LoadTy);
-  int FI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
-  // Then store the float to it.
-  State.FloatPtr = StackPtr;
-  MachineFunction &MF = DAG.getMachineFunction();
-  State.FloatPointerInfo = MachinePointerInfo::getFixedStack(MF, FI);
-  State.Chain = DAG.getStore(DAG.getEntryNode(), DL, Value, State.FloatPtr,
-                             State.FloatPointerInfo);
-
-  SDValue IntPtr;
-  if (DataLayout.isBigEndian()) {
-    assert(FloatVT.isByteSized() && "Unsupported floating point type!");
-    // Load out a legal integer with the same sign bit as the float.
-    IntPtr = StackPtr;
-    State.IntPointerInfo = State.FloatPointerInfo;
-  } else {
-    // Advance the pointer so that the loaded byte will contain the sign bit.
-    unsigned ByteOffset = (NumBits / 8) - 1;
-    IntPtr =
-        DAG.getMemBasePlusOffset(StackPtr, TypeSize::getFixed(ByteOffset), DL);
-    State.IntPointerInfo = MachinePointerInfo::getFixedStack(MF, FI,
-                                                             ByteOffset);
-  }
-
-  State.IntPtr = IntPtr;
-  State.IntValue = DAG.getExtLoad(ISD::EXTLOAD, DL, LoadTy, State.Chain, IntPtr,
-                                  State.IntPointerInfo, MVT::i8);
-  State.SignMask = APInt::getOneBitSet(LoadTy.getScalarSizeInBits(), 7);
-  State.SignBit = 7;
-}
-
-/// Replace the integer value produced by getSignAsIntValue() with a new value
-/// and cast the result back to a floating-point type.
-SDValue SelectionDAGLegalize::modifySignAsInt(const FloatSignAsInt &State,
-                                              const SDLoc &DL,
-                                              SDValue NewIntValue) const {
-  if (!State.Chain)
-    return DAG.getNode(ISD::BITCAST, DL, State.FloatVT, NewIntValue);
-
-  // Override the part containing the sign bit in the value stored on the stack.
-  SDValue Chain = DAG.getTruncStore(State.Chain, DL, NewIntValue, State.IntPtr,
-                                    State.IntPointerInfo, MVT::i8);
-  return DAG.getLoad(State.FloatVT, DL, Chain, State.FloatPtr,
-                     State.FloatPointerInfo);
-}
-
 SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
   SDLoc DL(Node);
   SDValue Mag = Node->getOperand(0);
@@ -1695,7 +1609,7 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
 
   // Get sign bit into an integer value.
   FloatSignAsInt SignAsInt;
-  getSignAsIntValue(SignAsInt, DL, Sign);
+  DAG.getSignAsIntValue(SignAsInt, DL, Sign);
 
   EVT IntVT = SignAsInt.IntValue.getValueType();
   SDValue SignMask = DAG.getConstant(SignAsInt.SignMask, DL, IntVT);
@@ -1716,7 +1630,7 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
 
   // Transform Mag value to integer, and clear the sign bit.
   FloatSignAsInt MagAsInt;
-  getSignAsIntValue(MagAsInt, DL, Mag);
+  DAG.getSignAsIntValue(MagAsInt, DL, Mag);
   EVT MagVT = MagAsInt.IntValue.getValueType();
   SDValue ClearSignMask = DAG.getConstant(~MagAsInt.SignMask, DL, MagVT);
   SDValue ClearedSign = DAG.getNode(ISD::AND, DL, MagVT, MagAsInt.IntValue,
@@ -1746,14 +1660,14 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
   SDValue CopiedSign = DAG.getNode(ISD::OR, DL, MagVT, ClearedSign, SignBit,
                                    SDNodeFlags::Disjoint);
 
-  return modifySignAsInt(MagAsInt, DL, CopiedSign);
+  return DAG.modifySignAsInt(MagAsInt, DL, CopiedSign);
 }
 
 SDValue SelectionDAGLegalize::ExpandFNEG(SDNode *Node) const {
   // Get the sign bit as an integer.
   SDLoc DL(Node);
   FloatSignAsInt SignAsInt;
-  getSignAsIntValue(SignAsInt, DL, Node->getOperand(0));
+  DAG.getSignAsIntValue(SignAsInt, DL, Node->getOperand(0));
   EVT IntVT = SignAsInt.IntValue.getValueType();
 
   // Flip the sign.
@@ -1762,7 +1676,7 @@ SDValue SelectionDAGLegalize::ExpandFNEG(SDNode *Node) const {
       DAG.getNode(ISD::XOR, DL, IntVT, SignAsInt.IntValue, SignMask);
 
   // Convert back to float.
-  return modifySignAsInt(SignAsInt, DL, SignFlip);
+  return DAG.modifySignAsInt(SignAsInt, DL, SignFlip);
 }
 
 SDValue SelectionDAGLegalize::ExpandFABS(SDNode *Node) const {
@@ -1778,12 +1692,12 @@ SDValue SelectionDAGLegalize::ExpandFABS(SDNode *Node) const {
 
   // Transform value to integer, clear the sign bit and transform back.
   FloatSignAsInt ValueAsInt;
-  getSignAsIntValue(ValueAsInt, DL, Value);
+  DAG.getSignAsIntValue(ValueAsInt, DL, Value);
   EVT IntVT = ValueAsInt.IntValue.getValueType();
   SDValue ClearSignMask = DAG.getConstant(~ValueAsInt.SignMask, DL, IntVT);
   SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, ValueAsInt.IntValue,
                                     ClearSignMask);
-  return modifySignAsInt(ValueAsInt, DL, ClearedSign);
+  return DAG.modifySignAsInt(ValueAsInt, DL, ClearedSign);
 }
 
 void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC(SDNode* Node,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 1506bc4ee187d..f74c4fa240530 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2760,6 +2760,66 @@ SDValue SelectionDAG::CreateStackTemporary(EVT VT1, EVT VT2) {
   return CreateStackTemporary(Bytes, Align);
 }
 
+void SelectionDAG::getSignAsIntValue(FloatSignAsInt &State, const SDLoc &DL,
+                                     SDValue Value) {
+  EVT FloatVT = Value.getValueType();
+  unsigned NumBits = FloatVT.getScalarSizeInBits();
+  State.FloatVT = FloatVT;
+  EVT IVT = EVT::getIntegerVT(*getContext(), NumBits);
+  // Convert to an integer of the same size.
+  if (TLI->isTypeLegal(IVT)) {
+    State.IntValue = getNode(ISD::BITCAST, DL, IVT, Value);
+    State.SignMask = APInt::getSignMask(NumBits);
+    State.SignBit = NumBits - 1;
+    return;
+  }
+
+  auto &DataLayout = getDataLayout();
+  // Store the float to memory, then load the sign part out as an integer.
+  MVT LoadTy = TLI->getRegisterType(MVT::i8);
+  // First create a temporary that is aligned for both the load and store.
+  SDValue StackPtr = CreateStackTemporary(FloatVT, LoadTy);
+  int FI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
+  // Then store the float to it.
+  State.FloatPtr = StackPtr;
+  MachineFunction &MF = getMachineFunction();
+  State.FloatPointerInfo = MachinePointerInfo::getFixedStack(MF, FI);
+  State.Chain = getStore(getEntryNode(), DL, Value, State.FloatPtr,
+                         State.FloatPointerInfo);
+
+  SDValue IntPtr;
+  if (DataLayout.isBigEndian()) {
+    assert(FloatVT.isByteSized() && "Unsupported floating point type!");
+    // Load out a legal integer with the same sign bit as the float.
+    IntPtr = StackPtr;
+    State.IntPointerInfo = State.FloatPointerInfo;
+  } else {
+    // Advance the pointer so that the loaded byte will contain the sign bit.
+    unsigned ByteOffset = (NumBits / 8) - 1;
+    IntPtr = getMemBasePlusOffset(StackPtr, TypeSize::getFixed(ByteOffset), DL);
+    State.IntPointerInfo =
+        MachinePointerInfo::getFixedStack(MF, FI, ByteOffset);
+  }
+
+  State.IntPtr = IntPtr;
+  State.IntValue = getExtLoad(ISD::EXTLOAD, DL, LoadTy, State.Chain, IntPtr,
+                              State.IntPointerInfo, MVT::i8);
+  State.SignMask = APInt::getOneBitSet(LoadTy.getScalarSizeInBits(), 7);
+  State.SignBit = 7;
+}
+
+SDValue SelectionDAG::modifySignAsInt(const FloatSignAsInt &State,
+                                      const SDLoc &DL, SDValue NewIntValue) {
+  if (!State.Chain)
+    return getNode(ISD::BITCAST, DL, State.FloatVT, NewIntValue);
+
+  // Override the part containing the sign bit in the value stored on the stack.
+  SDValue Chain = getTruncStore(State.Chain, DL, NewIntValue, State.IntPtr,
+                                State.IntPointerInfo, MVT::i8);
+  return getLoad(State.FloatVT, DL, Chain, State.FloatPtr,
+                 State.FloatPointerInfo);
+}
+
 SDValue SelectionDAG::FoldSetCC(EVT VT, SDValue N1, SDValue N2,
                                 ISD::CondCode Cond, const SDLoc &dl) {
   EVT OpVT = N1.getValueType();

>From e0da636fd6def617cea542eca04b84172f7d5a4c Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 30 May 2025 16:45:15 +0200
Subject: [PATCH 3/5] Use FloatSignAsInt helper

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |   2 +-
 .../CodeGen/SelectionDAG/TargetLowering.cpp   |   7 +-
 .../CodeGen/PowerPC/fminimum-fmaximum-f128.ll |  96 ++++++-------
 .../test/CodeGen/PowerPC/fminimum-fmaximum.ll | 131 +++++++++---------
 4 files changed, 113 insertions(+), 123 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index f74c4fa240530..023d53f24ed19 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2765,7 +2765,7 @@ void SelectionDAG::getSignAsIntValue(FloatSignAsInt &State, const SDLoc &DL,
   EVT FloatVT = Value.getValueType();
   unsigned NumBits = FloatVT.getScalarSizeInBits();
   State.FloatVT = FloatVT;
-  EVT IVT = EVT::getIntegerVT(*getContext(), NumBits);
+  EVT IVT = FloatVT.changeTypeToInteger();
   // Convert to an integer of the same size.
   if (TLI->isTypeLegal(IVT)) {
     State.IntValue = getNode(ISD::BITCAST, DL, IVT, Value);
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 450d7dcb6ac7f..13315fed7ed2a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8611,9 +8611,10 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
   if (!MinMaxMustRespectOrderedZero && !N->getFlags().hasNoSignedZeros() &&
       !DAG.isKnownNeverZeroFloat(RHS) && !DAG.isKnownNeverZeroFloat(LHS)) {
     auto IsSpecificZero = [&](SDValue F) {
-      EVT IntVT = VT.changeTypeToInteger();
-      SDValue Int = DAG.getBitcast(IntVT, F);
-      return DAG.getSetCC(DL, CCVT, Int, DAG.getConstant(0, DL, IntVT),
+      FloatSignAsInt State;
+      DAG.getSignAsIntValue(State, DL, F);
+      return DAG.getSetCC(DL, CCVT, State.IntValue,
+                          DAG.getConstant(0, DL, State.IntValue.getValueType()),
                           IsMax ? ISD::SETEQ : ISD::SETNE);
     };
     SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
diff --git a/llvm/test/CodeGen/PowerPC/fminimum-fmaximum-f128.ll b/llvm/test/CodeGen/PowerPC/fminimum-fmaximum-f128.ll
index 6d9eb13376827..48107c8f63727 100644
--- a/llvm/test/CodeGen/PowerPC/fminimum-fmaximum-f128.ll
+++ b/llvm/test/CodeGen/PowerPC/fminimum-fmaximum-f128.ll
@@ -4,44 +4,42 @@
 define fp128 @f128_minimum(fp128 %a, fp128 %b) {
 ; CHECK-LABEL: f128_minimum:
 ; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    stxv 34, -16(1)
+; CHECK-NEXT:    stxv 35, -32(1)
 ; CHECK-NEXT:    xscmpuqp 0, 2, 3
 ; CHECK-NEXT:    vmr 4, 2
-; CHECK-NEXT:    bge 0, .LBB0_8
+; CHECK-NEXT:    blt 0, .LBB0_2
 ; CHECK-NEXT:  # %bb.1: # %entry
-; CHECK-NEXT:    bun 0, .LBB0_9
+; CHECK-NEXT:    vmr 4, 3
 ; CHECK-NEXT:  .LBB0_2: # %entry
-; CHECK-NEXT:    xststdcqp 0, 2, 4
-; CHECK-NEXT:    bc 4, 2, .LBB0_10
-; CHECK-NEXT:  .LBB0_3: # %entry
-; CHECK-NEXT:    xststdcqp 0, 3, 4
-; CHECK-NEXT:    bc 12, 2, .LBB0_5
+; CHECK-NEXT:    bnu 0, .LBB0_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    addis 3, 2, .LCPI0_0 at toc@ha
+; CHECK-NEXT:    addi 3, 3, .LCPI0_0 at toc@l
+; CHECK-NEXT:    lxv 36, 0(3)
 ; CHECK-NEXT:  .LBB0_4: # %entry
+; CHECK-NEXT:    lbz 3, -1(1)
+; CHECK-NEXT:    cmplwi 3, 0
+; CHECK-NEXT:    bne 0, .LBB0_6
+; CHECK-NEXT:  # %bb.5: # %entry
+; CHECK-NEXT:    vmr 2, 4
+; CHECK-NEXT:  .LBB0_6: # %entry
+; CHECK-NEXT:    lbz 3, -17(1)
+; CHECK-NEXT:    cmplwi 3, 0
+; CHECK-NEXT:    bne 0, .LBB0_8
+; CHECK-NEXT:  # %bb.7: # %entry
 ; CHECK-NEXT:    vmr 3, 2
-; CHECK-NEXT:  .LBB0_5: # %entry
+; CHECK-NEXT:  .LBB0_8: # %entry
 ; CHECK-NEXT:    addis 3, 2, .LCPI0_1 at toc@ha
 ; CHECK-NEXT:    addi 3, 3, .LCPI0_1 at toc@l
 ; CHECK-NEXT:    lxv 34, 0(3)
 ; CHECK-NEXT:    xscmpuqp 0, 4, 2
-; CHECK-NEXT:    beq 0, .LBB0_7
-; CHECK-NEXT:  # %bb.6: # %entry
+; CHECK-NEXT:    beq 0, .LBB0_10
+; CHECK-NEXT:  # %bb.9: # %entry
 ; CHECK-NEXT:    vmr 3, 4
-; CHECK-NEXT:  .LBB0_7: # %entry
+; CHECK-NEXT:  .LBB0_10: # %entry
 ; CHECK-NEXT:    vmr 2, 3
 ; CHECK-NEXT:    blr
-; CHECK-NEXT:  .LBB0_8: # %entry
-; CHECK-NEXT:    vmr 4, 3
-; CHECK-NEXT:    bnu 0, .LBB0_2
-; CHECK-NEXT:  .LBB0_9:
-; CHECK-NEXT:    addis 3, 2, .LCPI0_0 at toc@ha
-; CHECK-NEXT:    addi 3, 3, .LCPI0_0 at toc@l
-; CHECK-NEXT:    lxv 36, 0(3)
-; CHECK-NEXT:    xststdcqp 0, 2, 4
-; CHECK-NEXT:    bc 12, 2, .LBB0_3
-; CHECK-NEXT:  .LBB0_10: # %entry
-; CHECK-NEXT:    vmr 2, 4
-; CHECK-NEXT:    xststdcqp 0, 3, 4
-; CHECK-NEXT:    bc 4, 2, .LBB0_4
-; CHECK-NEXT:    b .LBB0_5
 entry:
   %m = call fp128 @llvm.minimum.f128(fp128 %a, fp128 %b)
   ret fp128 %m
@@ -50,44 +48,42 @@ entry:
 define fp128 @f128_maximum(fp128 %a, fp128 %b) {
 ; CHECK-LABEL: f128_maximum:
 ; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    stxv 34, -16(1)
+; CHECK-NEXT:    stxv 35, -32(1)
 ; CHECK-NEXT:    xscmpuqp 0, 2, 3
 ; CHECK-NEXT:    vmr 4, 2
-; CHECK-NEXT:    ble 0, .LBB1_8
+; CHECK-NEXT:    bgt 0, .LBB1_2
 ; CHECK-NEXT:  # %bb.1: # %entry
-; CHECK-NEXT:    bun 0, .LBB1_9
+; CHECK-NEXT:    vmr 4, 3
 ; CHECK-NEXT:  .LBB1_2: # %entry
-; CHECK-NEXT:    xststdcqp 0, 2, 8
-; CHECK-NEXT:    bc 4, 2, .LBB1_10
-; CHECK-NEXT:  .LBB1_3: # %entry
-; CHECK-NEXT:    xststdcqp 0, 3, 8
-; CHECK-NEXT:    bc 12, 2, .LBB1_5
+; CHECK-NEXT:    bnu 0, .LBB1_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    addis 3, 2, .LCPI1_0 at toc@ha
+; CHECK-NEXT:    addi 3, 3, .LCPI1_0 at toc@l
+; CHECK-NEXT:    lxv 36, 0(3)
 ; CHECK-NEXT:  .LBB1_4: # %entry
+; CHECK-NEXT:    lbz 3, -1(1)
+; CHECK-NEXT:    cmplwi 3, 0
+; CHECK-NEXT:    beq 0, .LBB1_6
+; CHECK-NEXT:  # %bb.5: # %entry
+; CHECK-NEXT:    vmr 2, 4
+; CHECK-NEXT:  .LBB1_6: # %entry
+; CHECK-NEXT:    lbz 3, -17(1)
+; CHECK-NEXT:    cmplwi 3, 0
+; CHECK-NEXT:    beq 0, .LBB1_8
+; CHECK-NEXT:  # %bb.7: # %entry
 ; CHECK-NEXT:    vmr 3, 2
-; CHECK-NEXT:  .LBB1_5: # %entry
+; CHECK-NEXT:  .LBB1_8: # %entry
 ; CHECK-NEXT:    addis 3, 2, .LCPI1_1 at toc@ha
 ; CHECK-NEXT:    addi 3, 3, .LCPI1_1 at toc@l
 ; CHECK-NEXT:    lxv 34, 0(3)
 ; CHECK-NEXT:    xscmpuqp 0, 4, 2
-; CHECK-NEXT:    beq 0, .LBB1_7
-; CHECK-NEXT:  # %bb.6: # %entry
+; CHECK-NEXT:    beq 0, .LBB1_10
+; CHECK-NEXT:  # %bb.9: # %entry
 ; CHECK-NEXT:    vmr 3, 4
-; CHECK-NEXT:  .LBB1_7: # %entry
+; CHECK-NEXT:  .LBB1_10: # %entry
 ; CHECK-NEXT:    vmr 2, 3
 ; CHECK-NEXT:    blr
-; CHECK-NEXT:  .LBB1_8: # %entry
-; CHECK-NEXT:    vmr 4, 3
-; CHECK-NEXT:    bnu 0, .LBB1_2
-; CHECK-NEXT:  .LBB1_9:
-; CHECK-NEXT:    addis 3, 2, .LCPI1_0 at toc@ha
-; CHECK-NEXT:    addi 3, 3, .LCPI1_0 at toc@l
-; CHECK-NEXT:    lxv 36, 0(3)
-; CHECK-NEXT:    xststdcqp 0, 2, 8
-; CHECK-NEXT:    bc 12, 2, .LBB1_3
-; CHECK-NEXT:  .LBB1_10: # %entry
-; CHECK-NEXT:    vmr 2, 4
-; CHECK-NEXT:    xststdcqp 0, 3, 8
-; CHECK-NEXT:    bc 4, 2, .LBB1_4
-; CHECK-NEXT:    b .LBB1_5
 entry:
   %m = call fp128 @llvm.maximum.f128(fp128 %a, fp128 %b)
   ret fp128 %m
diff --git a/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll b/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll
index 2e65938b7c18e..e199a1eab49d5 100644
--- a/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll
+++ b/llvm/test/CodeGen/PowerPC/fminimum-fmaximum.ll
@@ -8,26 +8,26 @@ define float @f32_minimum(float %a, float %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
 ; NOVSX-NEXT:    fmr 3, 1
-; NOVSX-NEXT:    stfs 2, -4(1)
 ; NOVSX-NEXT:    stfs 1, -8(1)
+; NOVSX-NEXT:    stfs 2, -4(1)
 ; NOVSX-NEXT:    bc 12, 0, .LBB0_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 3, 2
 ; NOVSX-NEXT:  .LBB0_2: # %entry
-; NOVSX-NEXT:    lwz 3, -8(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB0_4
 ; NOVSX-NEXT:  # %bb.3:
-; NOVSX-NEXT:    addis 4, 2, .LCPI0_0 at toc@ha
-; NOVSX-NEXT:    lfs 3, .LCPI0_0 at toc@l(4)
+; NOVSX-NEXT:    addis 3, 2, .LCPI0_0 at toc@ha
+; NOVSX-NEXT:    lfs 3, .LCPI0_0 at toc@l(3)
 ; NOVSX-NEXT:  .LBB0_4: # %entry
+; NOVSX-NEXT:    lwz 3, -8(1)
 ; NOVSX-NEXT:    fmr 0, 3
 ; NOVSX-NEXT:    cmpwi 3, 0
-; NOVSX-NEXT:    lwz 4, -4(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB0_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 0, 1
 ; NOVSX-NEXT:  .LBB0_6: # %entry
-; NOVSX-NEXT:    cmpwi 4, 0
+; NOVSX-NEXT:    lwz 3, -4(1)
+; NOVSX-NEXT:    cmpwi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB0_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
 ; NOVSX-NEXT:    fmr 0, 2
@@ -75,25 +75,25 @@ define float @f32_maximum(float %a, float %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
 ; NOVSX-NEXT:    fmr 0, 1
-; NOVSX-NEXT:    stfs 2, -4(1)
 ; NOVSX-NEXT:    stfs 1, -8(1)
+; NOVSX-NEXT:    stfs 2, -4(1)
 ; NOVSX-NEXT:    bc 12, 1, .LBB1_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 0, 2
 ; NOVSX-NEXT:  .LBB1_2: # %entry
-; NOVSX-NEXT:    lwz 3, -8(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB1_4
 ; NOVSX-NEXT:  # %bb.3:
-; NOVSX-NEXT:    addis 4, 2, .LCPI1_0 at toc@ha
-; NOVSX-NEXT:    lfs 0, .LCPI1_0 at toc@l(4)
+; NOVSX-NEXT:    addis 3, 2, .LCPI1_0 at toc@ha
+; NOVSX-NEXT:    lfs 0, .LCPI1_0 at toc@l(3)
 ; NOVSX-NEXT:  .LBB1_4: # %entry
+; NOVSX-NEXT:    lwz 3, -8(1)
 ; NOVSX-NEXT:    cmpwi 3, 0
-; NOVSX-NEXT:    lwz 4, -4(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB1_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 1, 0
 ; NOVSX-NEXT:  .LBB1_6: # %entry
-; NOVSX-NEXT:    cmpwi 4, 0
+; NOVSX-NEXT:    lwz 3, -4(1)
+; NOVSX-NEXT:    cmpwi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB1_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
 ; NOVSX-NEXT:    fmr 2, 1
@@ -141,26 +141,26 @@ define double @f64_minimum(double %a, double %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
 ; NOVSX-NEXT:    fmr 3, 1
-; NOVSX-NEXT:    stfd 2, -8(1)
 ; NOVSX-NEXT:    stfd 1, -16(1)
+; NOVSX-NEXT:    stfd 2, -8(1)
 ; NOVSX-NEXT:    bc 12, 0, .LBB2_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 3, 2
 ; NOVSX-NEXT:  .LBB2_2: # %entry
-; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB2_4
 ; NOVSX-NEXT:  # %bb.3:
-; NOVSX-NEXT:    addis 4, 2, .LCPI2_0 at toc@ha
-; NOVSX-NEXT:    lfs 3, .LCPI2_0 at toc@l(4)
+; NOVSX-NEXT:    addis 3, 2, .LCPI2_0 at toc@ha
+; NOVSX-NEXT:    lfs 3, .LCPI2_0 at toc@l(3)
 ; NOVSX-NEXT:  .LBB2_4: # %entry
+; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    fmr 0, 3
 ; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB2_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 0, 1
 ; NOVSX-NEXT:  .LBB2_6: # %entry
-; NOVSX-NEXT:    cmpdi 4, 0
+; NOVSX-NEXT:    ld 3, -8(1)
+; NOVSX-NEXT:    cmpdi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB2_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
 ; NOVSX-NEXT:    fmr 0, 2
@@ -208,25 +208,25 @@ define double @f64_maximum(double %a, double %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 2
 ; NOVSX-NEXT:    fmr 0, 1
-; NOVSX-NEXT:    stfd 2, -8(1)
 ; NOVSX-NEXT:    stfd 1, -16(1)
+; NOVSX-NEXT:    stfd 2, -8(1)
 ; NOVSX-NEXT:    bc 12, 1, .LBB3_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 0, 2
 ; NOVSX-NEXT:  .LBB3_2: # %entry
-; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    bc 4, 3, .LBB3_4
 ; NOVSX-NEXT:  # %bb.3:
-; NOVSX-NEXT:    addis 4, 2, .LCPI3_0 at toc@ha
-; NOVSX-NEXT:    lfs 0, .LCPI3_0 at toc@l(4)
+; NOVSX-NEXT:    addis 3, 2, .LCPI3_0 at toc@ha
+; NOVSX-NEXT:    lfs 0, .LCPI3_0 at toc@l(3)
 ; NOVSX-NEXT:  .LBB3_4: # %entry
+; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB3_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 1, 0
 ; NOVSX-NEXT:  .LBB3_6: # %entry
-; NOVSX-NEXT:    cmpdi 4, 0
+; NOVSX-NEXT:    ld 3, -8(1)
+; NOVSX-NEXT:    cmpdi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB3_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
 ; NOVSX-NEXT:    fmr 2, 1
@@ -416,30 +416,30 @@ define <2 x double> @v2f64_minimum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 3
 ; NOVSX-NEXT:    fmr 0, 1
-; NOVSX-NEXT:    stfd 4, -24(1)
-; NOVSX-NEXT:    stfd 2, -32(1)
-; NOVSX-NEXT:    stfd 3, -8(1)
 ; NOVSX-NEXT:    stfd 1, -16(1)
+; NOVSX-NEXT:    stfd 3, -8(1)
+; NOVSX-NEXT:    stfd 2, -32(1)
+; NOVSX-NEXT:    stfd 4, -24(1)
 ; NOVSX-NEXT:    bc 12, 0, .LBB6_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 1, 3
 ; NOVSX-NEXT:  .LBB6_2: # %entry
-; NOVSX-NEXT:    addis 4, 2, .LCPI6_0 at toc@ha
-; NOVSX-NEXT:    ld 3, -16(1)
-; NOVSX-NEXT:    lfs 5, .LCPI6_0 at toc@l(4)
+; NOVSX-NEXT:    addis 3, 2, .LCPI6_0 at toc@ha
+; NOVSX-NEXT:    lfs 5, .LCPI6_0 at toc@l(3)
 ; NOVSX-NEXT:    fmr 6, 5
 ; NOVSX-NEXT:    bc 12, 3, .LBB6_4
 ; NOVSX-NEXT:  # %bb.3: # %entry
 ; NOVSX-NEXT:    fmr 6, 1
 ; NOVSX-NEXT:  .LBB6_4: # %entry
+; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    fmr 1, 6
 ; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB6_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 1, 0
 ; NOVSX-NEXT:  .LBB6_6: # %entry
-; NOVSX-NEXT:    cmpdi 4, 0
+; NOVSX-NEXT:    ld 3, -8(1)
+; NOVSX-NEXT:    cmpdi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB6_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
 ; NOVSX-NEXT:    fmr 1, 3
@@ -457,32 +457,30 @@ define <2 x double> @v2f64_minimum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX-NEXT:  # %bb.11: # %entry
 ; NOVSX-NEXT:    fmr 0, 4
 ; NOVSX-NEXT:  .LBB6_12: # %entry
-; NOVSX-NEXT:    ld 4, -32(1)
 ; NOVSX-NEXT:    bc 12, 3, .LBB6_14
 ; NOVSX-NEXT:  # %bb.13: # %entry
 ; NOVSX-NEXT:    fmr 5, 0
 ; NOVSX-NEXT:  .LBB6_14: # %entry
+; NOVSX-NEXT:    ld 3, -32(1)
 ; NOVSX-NEXT:    fmr 0, 5
-; NOVSX-NEXT:    cmpdi 4, 0
-; NOVSX-NEXT:    ld 3, -24(1)
-; NOVSX-NEXT:    bc 4, 2, .LBB6_18
+; NOVSX-NEXT:    cmpdi 3, 0
+; NOVSX-NEXT:    bc 12, 2, .LBB6_16
 ; NOVSX-NEXT:  # %bb.15: # %entry
+; NOVSX-NEXT:    fmr 0, 2
+; NOVSX-NEXT:  .LBB6_16: # %entry
+; NOVSX-NEXT:    ld 3, -24(1)
 ; NOVSX-NEXT:    cmpdi 3, 0
 ; NOVSX-NEXT:    bc 4, 2, .LBB6_19
-; NOVSX-NEXT:  .LBB6_16: # %entry
+; NOVSX-NEXT:  # %bb.17: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 5, 3
 ; NOVSX-NEXT:    bc 4, 2, .LBB6_20
-; NOVSX-NEXT:  .LBB6_17: # %entry
+; NOVSX-NEXT:  .LBB6_18: # %entry
 ; NOVSX-NEXT:    fmr 2, 0
 ; NOVSX-NEXT:    blr
-; NOVSX-NEXT:  .LBB6_18: # %entry
-; NOVSX-NEXT:    fmr 0, 2
-; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    bc 12, 2, .LBB6_16
 ; NOVSX-NEXT:  .LBB6_19: # %entry
 ; NOVSX-NEXT:    fmr 0, 4
 ; NOVSX-NEXT:    fcmpu 0, 5, 3
-; NOVSX-NEXT:    bc 12, 2, .LBB6_17
+; NOVSX-NEXT:    bc 12, 2, .LBB6_18
 ; NOVSX-NEXT:  .LBB6_20: # %entry
 ; NOVSX-NEXT:    fmr 0, 5
 ; NOVSX-NEXT:    fmr 2, 0
@@ -542,29 +540,29 @@ define <2 x double> @v2f64_maximum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX:       # %bb.0: # %entry
 ; NOVSX-NEXT:    fcmpu 0, 1, 3
 ; NOVSX-NEXT:    fmr 6, 1
-; NOVSX-NEXT:    stfd 4, -24(1)
-; NOVSX-NEXT:    stfd 2, -32(1)
-; NOVSX-NEXT:    stfd 3, -8(1)
 ; NOVSX-NEXT:    stfd 1, -16(1)
+; NOVSX-NEXT:    stfd 3, -8(1)
+; NOVSX-NEXT:    stfd 2, -32(1)
+; NOVSX-NEXT:    stfd 4, -24(1)
 ; NOVSX-NEXT:    bc 12, 1, .LBB7_2
 ; NOVSX-NEXT:  # %bb.1: # %entry
 ; NOVSX-NEXT:    fmr 6, 3
 ; NOVSX-NEXT:  .LBB7_2: # %entry
-; NOVSX-NEXT:    addis 4, 2, .LCPI7_0 at toc@ha
-; NOVSX-NEXT:    ld 3, -16(1)
-; NOVSX-NEXT:    lfs 0, .LCPI7_0 at toc@l(4)
+; NOVSX-NEXT:    addis 3, 2, .LCPI7_0 at toc@ha
+; NOVSX-NEXT:    lfs 0, .LCPI7_0 at toc@l(3)
 ; NOVSX-NEXT:    fmr 5, 0
 ; NOVSX-NEXT:    bc 12, 3, .LBB7_4
 ; NOVSX-NEXT:  # %bb.3: # %entry
 ; NOVSX-NEXT:    fmr 5, 6
 ; NOVSX-NEXT:  .LBB7_4: # %entry
+; NOVSX-NEXT:    ld 3, -16(1)
 ; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    ld 4, -8(1)
 ; NOVSX-NEXT:    bc 12, 2, .LBB7_6
 ; NOVSX-NEXT:  # %bb.5: # %entry
 ; NOVSX-NEXT:    fmr 1, 5
 ; NOVSX-NEXT:  .LBB7_6: # %entry
-; NOVSX-NEXT:    cmpdi 4, 0
+; NOVSX-NEXT:    ld 3, -8(1)
+; NOVSX-NEXT:    cmpdi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB7_8
 ; NOVSX-NEXT:  # %bb.7: # %entry
 ; NOVSX-NEXT:    fmr 3, 1
@@ -582,35 +580,30 @@ define <2 x double> @v2f64_maximum(<2 x double> %a, <2 x double> %b) {
 ; NOVSX-NEXT:  # %bb.11: # %entry
 ; NOVSX-NEXT:    fmr 5, 4
 ; NOVSX-NEXT:  .LBB7_12: # %entry
-; NOVSX-NEXT:    ld 4, -32(1)
 ; NOVSX-NEXT:    bc 12, 3, .LBB7_14
 ; NOVSX-NEXT:  # %bb.13: # %entry
 ; NOVSX-NEXT:    fmr 0, 5
 ; NOVSX-NEXT:  .LBB7_14: # %entry
-; NOVSX-NEXT:    cmpdi 4, 0
-; NOVSX-NEXT:    ld 3, -24(1)
-; NOVSX-NEXT:    bc 4, 2, .LBB7_19
-; NOVSX-NEXT:  # %bb.15: # %entry
+; NOVSX-NEXT:    ld 3, -32(1)
 ; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    bc 4, 2, .LBB7_20
+; NOVSX-NEXT:    bc 12, 2, .LBB7_16
+; NOVSX-NEXT:  # %bb.15: # %entry
+; NOVSX-NEXT:    fmr 2, 0
 ; NOVSX-NEXT:  .LBB7_16: # %entry
-; NOVSX-NEXT:    fcmpu 0, 0, 1
+; NOVSX-NEXT:    ld 3, -24(1)
+; NOVSX-NEXT:    cmpdi 3, 0
 ; NOVSX-NEXT:    bc 12, 2, .LBB7_18
-; NOVSX-NEXT:  .LBB7_17: # %entry
-; NOVSX-NEXT:    fmr 4, 0
+; NOVSX-NEXT:  # %bb.17: # %entry
+; NOVSX-NEXT:    fmr 4, 2
 ; NOVSX-NEXT:  .LBB7_18: # %entry
+; NOVSX-NEXT:    fcmpu 0, 0, 1
+; NOVSX-NEXT:    bc 12, 2, .LBB7_20
+; NOVSX-NEXT:  # %bb.19: # %entry
+; NOVSX-NEXT:    fmr 4, 0
+; NOVSX-NEXT:  .LBB7_20: # %entry
 ; NOVSX-NEXT:    fmr 1, 3
 ; NOVSX-NEXT:    fmr 2, 4
 ; NOVSX-NEXT:    blr
-; NOVSX-NEXT:  .LBB7_19: # %entry
-; NOVSX-NEXT:    fmr 2, 0
-; NOVSX-NEXT:    cmpdi 3, 0
-; NOVSX-NEXT:    bc 12, 2, .LBB7_16
-; NOVSX-NEXT:  .LBB7_20: # %entry
-; NOVSX-NEXT:    fmr 4, 2
-; NOVSX-NEXT:    fcmpu 0, 0, 1
-; NOVSX-NEXT:    bc 4, 2, .LBB7_17
-; NOVSX-NEXT:    b .LBB7_18
 ;
 ; VSX-LABEL: v2f64_maximum:
 ; VSX:       # %bb.0: # %entry

>From 468a8938a869a9e68a5ba44ead8e8f8ce23095a4 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 30 May 2025 17:26:09 +0200
Subject: [PATCH 4/5] Add tests for issues

---
 .../CodeGen/AArch64/fmaximum-legalization.ll  |  56 ++++++
 .../CodeGen/ARM/fp-maximum-legalization.ll    |  49 +++++
 llvm/test/CodeGen/X86/fminimum-fmaximum.ll    | 177 ++++++++++++++++++
 3 files changed, 282 insertions(+)
 create mode 100644 llvm/test/CodeGen/ARM/fp-maximum-legalization.ll

diff --git a/llvm/test/CodeGen/AArch64/fmaximum-legalization.ll b/llvm/test/CodeGen/AArch64/fmaximum-legalization.ll
index 86c1474068482..9f542abcb80f7 100644
--- a/llvm/test/CodeGen/AArch64/fmaximum-legalization.ll
+++ b/llvm/test/CodeGen/AArch64/fmaximum-legalization.ll
@@ -41,3 +41,59 @@ define <4 x half> @fmaximum_v4f16(<4 x half> %x, <4 x half> %y) {
   %r = call <4 x half> @llvm.maximum.v4f16(<4 x half> %x, <4 x half> %y)
   ret <4 x half> %r
 }
+
+define fp128 @maximum_fp128(fp128 %x, fp128 %y) nounwind {
+; CHECK-LABEL: maximum_fp128:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sub sp, sp, #96
+; CHECK-NEXT:    str x30, [sp, #80] // 8-byte Folded Spill
+; CHECK-NEXT:    stp q0, q1, [sp] // 32-byte Folded Spill
+; CHECK-NEXT:    stp q1, q0, [sp, #48]
+; CHECK-NEXT:    bl __gttf2
+; CHECK-NEXT:    ldp q0, q1, [sp] // 32-byte Folded Reload
+; CHECK-NEXT:    cmp w0, #0
+; CHECK-NEXT:    b.le .LBB1_2
+; CHECK-NEXT:  // %bb.1:
+; CHECK-NEXT:    mov v1.16b, v0.16b
+; CHECK-NEXT:  .LBB1_2:
+; CHECK-NEXT:    str q1, [sp, #32] // 16-byte Folded Spill
+; CHECK-NEXT:    ldr q1, [sp, #16] // 16-byte Folded Reload
+; CHECK-NEXT:    bl __unordtf2
+; CHECK-NEXT:    ldr q0, [sp, #32] // 16-byte Folded Reload
+; CHECK-NEXT:    cmp w0, #0
+; CHECK-NEXT:    b.eq .LBB1_4
+; CHECK-NEXT:  // %bb.3:
+; CHECK-NEXT:    adrp x8, .LCPI1_0
+; CHECK-NEXT:    ldr q0, [x8, :lo12:.LCPI1_0]
+; CHECK-NEXT:  .LBB1_4:
+; CHECK-NEXT:    ldrb w8, [sp, #79]
+; CHECK-NEXT:    mov v1.16b, v0.16b
+; CHECK-NEXT:    cmp w8, #0
+; CHECK-NEXT:    b.ne .LBB1_6
+; CHECK-NEXT:  // %bb.5:
+; CHECK-NEXT:    ldr q1, [sp] // 16-byte Folded Reload
+; CHECK-NEXT:  .LBB1_6:
+; CHECK-NEXT:    ldrb w8, [sp, #63]
+; CHECK-NEXT:    cmp w8, #0
+; CHECK-NEXT:    b.ne .LBB1_8
+; CHECK-NEXT:  // %bb.7:
+; CHECK-NEXT:    ldr q1, [sp, #16] // 16-byte Folded Reload
+; CHECK-NEXT:  .LBB1_8:
+; CHECK-NEXT:    adrp x8, .LCPI1_1
+; CHECK-NEXT:    str q0, [sp, #32] // 16-byte Folded Spill
+; CHECK-NEXT:    str q1, [sp, #16] // 16-byte Folded Spill
+; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI1_1]
+; CHECK-NEXT:    ldr q0, [sp, #32] // 16-byte Folded Reload
+; CHECK-NEXT:    bl __eqtf2
+; CHECK-NEXT:    ldr q0, [sp, #32] // 16-byte Folded Reload
+; CHECK-NEXT:    cmp w0, #0
+; CHECK-NEXT:    b.ne .LBB1_10
+; CHECK-NEXT:  // %bb.9:
+; CHECK-NEXT:    ldr q0, [sp, #16] // 16-byte Folded Reload
+; CHECK-NEXT:  .LBB1_10:
+; CHECK-NEXT:    ldr x30, [sp, #80] // 8-byte Folded Reload
+; CHECK-NEXT:    add sp, sp, #96
+; CHECK-NEXT:    ret
+  %res = call fp128 @llvm.maximum.f128(fp128 %x, fp128 %y)
+  ret fp128 %res
+}
diff --git a/llvm/test/CodeGen/ARM/fp-maximum-legalization.ll b/llvm/test/CodeGen/ARM/fp-maximum-legalization.ll
new file mode 100644
index 0000000000000..a3ab144356e16
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/fp-maximum-legalization.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=armv7 | FileCheck %s
+
+define double @maximum_double(double %x, double %y) nounwind {
+; CHECK-LABEL: maximum_double:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    sub sp, sp, #16
+; CHECK-NEXT:    vmov d17, r2, r3
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    vmov d16, r0, r1
+; CHECK-NEXT:    mov r3, #0
+; CHECK-NEXT:    vcmp.f64 d16, d17
+; CHECK-NEXT:    mov r0, #0
+; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
+; CHECK-NEXT:    vstr d16, [sp, #8]
+; CHECK-NEXT:    vstr d17, [sp]
+; CHECK-NEXT:    ldrb r1, [sp, #15]
+; CHECK-NEXT:    vmov.f64 d19, d17
+; CHECK-NEXT:    clz r1, r1
+; CHECK-NEXT:    vldr d18, .LCPI0_0
+; CHECK-NEXT:    movwvs r2, #1
+; CHECK-NEXT:    movwgt r3, #1
+; CHECK-NEXT:    cmp r3, #0
+; CHECK-NEXT:    vmovne.f64 d19, d16
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    ldrb r2, [sp, #7]
+; CHECK-NEXT:    vmovne.f64 d19, d18
+; CHECK-NEXT:    lsrs r1, r1, #5
+; CHECK-NEXT:    clz r1, r2
+; CHECK-NEXT:    vcmp.f64 d19, #0
+; CHECK-NEXT:    vmov.f64 d18, d19
+; CHECK-NEXT:    vmovne.f64 d18, d16
+; CHECK-NEXT:    lsrs r1, r1, #5
+; CHECK-NEXT:    vmovne.f64 d18, d17
+; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
+; CHECK-NEXT:    movweq r0, #1
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    vmovne.f64 d19, d18
+; CHECK-NEXT:    vmov r0, r1, d19
+; CHECK-NEXT:    add sp, sp, #16
+; CHECK-NEXT:    bx lr
+; CHECK-NEXT:    .p2align 3
+; CHECK-NEXT:  @ %bb.1:
+; CHECK-NEXT:  .LCPI0_0:
+; CHECK-NEXT:    .long 0 @ double NaN
+; CHECK-NEXT:    .long 2146959360
+  %res = call double @llvm.maximum(double %x, double %y)
+  ret double %res
+}
diff --git a/llvm/test/CodeGen/X86/fminimum-fmaximum.ll b/llvm/test/CodeGen/X86/fminimum-fmaximum.ll
index 989aabc9e87bd..80e3a017a44e3 100644
--- a/llvm/test/CodeGen/X86/fminimum-fmaximum.ll
+++ b/llvm/test/CodeGen/X86/fminimum-fmaximum.ll
@@ -2649,3 +2649,180 @@ define <4 x bfloat> @test_fmaximum_v4bf16(<4 x bfloat> %x, <4 x bfloat> %y) {
   %r = call <4 x bfloat> @llvm.maximum.v4bf16(<4 x bfloat> %x, <4 x bfloat> %y)
   ret <4 x bfloat> %r
 }
+
+define fp128 @maximum_fp128(fp128 %x, fp128 %y) nounwind {
+; SSE2-LABEL: maximum_fp128:
+; SSE2:       # %bb.0:
+; SSE2-NEXT:    subq $88, %rsp
+; SSE2-NEXT:    movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; SSE2-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; SSE2-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
+; SSE2-NEXT:    movaps %xmm1, {{[0-9]+}}(%rsp)
+; SSE2-NEXT:    callq __gttf2 at PLT
+; SSE2-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; SSE2-NEXT:    testl %eax, %eax
+; SSE2-NEXT:    movaps (%rsp), %xmm0 # 16-byte Reload
+; SSE2-NEXT:    jg .LBB35_2
+; SSE2-NEXT:  # %bb.1:
+; SSE2-NEXT:    movaps %xmm1, %xmm0
+; SSE2-NEXT:  .LBB35_2:
+; SSE2-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; SSE2-NEXT:    movaps (%rsp), %xmm0 # 16-byte Reload
+; SSE2-NEXT:    callq __unordtf2 at PLT
+; SSE2-NEXT:    testl %eax, %eax
+; SSE2-NEXT:    jne .LBB35_3
+; SSE2-NEXT:  # %bb.4:
+; SSE2-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; SSE2-NEXT:    jmp .LBB35_5
+; SSE2-NEXT:  .LBB35_3:
+; SSE2-NEXT:    movaps {{.*#+}} xmm0 = [NaN]
+; SSE2-NEXT:  .LBB35_5:
+; SSE2-NEXT:    cmpb $0, {{[0-9]+}}(%rsp)
+; SSE2-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; SSE2-NEXT:    je .LBB35_7
+; SSE2-NEXT:  # %bb.6:
+; SSE2-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; SSE2-NEXT:  .LBB35_7:
+; SSE2-NEXT:    cmpb $0, {{[0-9]+}}(%rsp)
+; SSE2-NEXT:    je .LBB35_9
+; SSE2-NEXT:  # %bb.8:
+; SSE2-NEXT:    movaps (%rsp), %xmm1 # 16-byte Reload
+; SSE2-NEXT:  .LBB35_9:
+; SSE2-NEXT:    movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; SSE2-NEXT:    xorps %xmm1, %xmm1
+; SSE2-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; SSE2-NEXT:    callq __eqtf2 at PLT
+; SSE2-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; SSE2-NEXT:    testl %eax, %eax
+; SSE2-NEXT:    je .LBB35_11
+; SSE2-NEXT:  # %bb.10:
+; SSE2-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; SSE2-NEXT:  .LBB35_11:
+; SSE2-NEXT:    addq $88, %rsp
+; SSE2-NEXT:    retq
+;
+; AVX-LABEL: maximum_fp128:
+; AVX:       # %bb.0:
+; AVX-NEXT:    subq $88, %rsp
+; AVX-NEXT:    vmovaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
+; AVX-NEXT:    vmovaps %xmm0, {{[0-9]+}}(%rsp)
+; AVX-NEXT:    vmovaps %xmm1, {{[0-9]+}}(%rsp)
+; AVX-NEXT:    callq __gttf2 at PLT
+; AVX-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; AVX-NEXT:    testl %eax, %eax
+; AVX-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
+; AVX-NEXT:    jg .LBB35_2
+; AVX-NEXT:  # %bb.1:
+; AVX-NEXT:    vmovaps %xmm1, %xmm0
+; AVX-NEXT:  .LBB35_2:
+; AVX-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
+; AVX-NEXT:    callq __unordtf2 at PLT
+; AVX-NEXT:    testl %eax, %eax
+; AVX-NEXT:    jne .LBB35_3
+; AVX-NEXT:  # %bb.4:
+; AVX-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; AVX-NEXT:    jmp .LBB35_5
+; AVX-NEXT:  .LBB35_3:
+; AVX-NEXT:    vmovaps {{.*#+}} xmm0 = [NaN]
+; AVX-NEXT:  .LBB35_5:
+; AVX-NEXT:    cmpb $0, {{[0-9]+}}(%rsp)
+; AVX-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; AVX-NEXT:    je .LBB35_7
+; AVX-NEXT:  # %bb.6:
+; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
+; AVX-NEXT:  .LBB35_7:
+; AVX-NEXT:    cmpb $0, {{[0-9]+}}(%rsp)
+; AVX-NEXT:    je .LBB35_9
+; AVX-NEXT:  # %bb.8:
+; AVX-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
+; AVX-NEXT:  .LBB35_9:
+; AVX-NEXT:    vmovaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX-NEXT:    vxorps %xmm1, %xmm1, %xmm1
+; AVX-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX-NEXT:    callq __eqtf2 at PLT
+; AVX-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; AVX-NEXT:    testl %eax, %eax
+; AVX-NEXT:    je .LBB35_11
+; AVX-NEXT:  # %bb.10:
+; AVX-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; AVX-NEXT:  .LBB35_11:
+; AVX-NEXT:    addq $88, %rsp
+; AVX-NEXT:    retq
+;
+; AVX10_2-LABEL: maximum_fp128:
+; AVX10_2:       # %bb.0:
+; AVX10_2-NEXT:    subq $88, %rsp
+; AVX10_2-NEXT:    vmovaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX10_2-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
+; AVX10_2-NEXT:    vmovaps %xmm0, {{[0-9]+}}(%rsp)
+; AVX10_2-NEXT:    vmovaps %xmm1, {{[0-9]+}}(%rsp)
+; AVX10_2-NEXT:    callq __gttf2 at PLT
+; AVX10_2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; AVX10_2-NEXT:    testl %eax, %eax
+; AVX10_2-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
+; AVX10_2-NEXT:    jg .LBB35_2
+; AVX10_2-NEXT:  # %bb.1:
+; AVX10_2-NEXT:    vmovaps %xmm1, %xmm0
+; AVX10_2-NEXT:  .LBB35_2:
+; AVX10_2-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX10_2-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
+; AVX10_2-NEXT:    callq __unordtf2 at PLT
+; AVX10_2-NEXT:    testl %eax, %eax
+; AVX10_2-NEXT:    jne .LBB35_3
+; AVX10_2-NEXT:  # %bb.4:
+; AVX10_2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; AVX10_2-NEXT:    jmp .LBB35_5
+; AVX10_2-NEXT:  .LBB35_3:
+; AVX10_2-NEXT:    vmovaps {{.*#+}} xmm0 = [NaN]
+; AVX10_2-NEXT:  .LBB35_5:
+; AVX10_2-NEXT:    cmpb $0, {{[0-9]+}}(%rsp)
+; AVX10_2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; AVX10_2-NEXT:    je .LBB35_7
+; AVX10_2-NEXT:  # %bb.6:
+; AVX10_2-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
+; AVX10_2-NEXT:  .LBB35_7:
+; AVX10_2-NEXT:    cmpb $0, {{[0-9]+}}(%rsp)
+; AVX10_2-NEXT:    je .LBB35_9
+; AVX10_2-NEXT:  # %bb.8:
+; AVX10_2-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
+; AVX10_2-NEXT:  .LBB35_9:
+; AVX10_2-NEXT:    vmovaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX10_2-NEXT:    vxorps %xmm1, %xmm1, %xmm1
+; AVX10_2-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; AVX10_2-NEXT:    callq __eqtf2 at PLT
+; AVX10_2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; AVX10_2-NEXT:    testl %eax, %eax
+; AVX10_2-NEXT:    je .LBB35_11
+; AVX10_2-NEXT:  # %bb.10:
+; AVX10_2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; AVX10_2-NEXT:  .LBB35_11:
+; AVX10_2-NEXT:    addq $88, %rsp
+; AVX10_2-NEXT:    retq
+;
+; X86-LABEL: maximum_fp128:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %ebp
+; X86-NEXT:    movl %esp, %ebp
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    andl $-16, %esp
+; X86-NEXT:    subl $80, %esp
+; X86-NEXT:    movl 8(%ebp), %esi
+; X86-NEXT:    vmovups 12(%ebp), %ymm0
+; X86-NEXT:    vmovups %ymm0, {{[0-9]+}}(%esp)
+; X86-NEXT:    leal {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %eax, (%esp)
+; X86-NEXT:    vzeroupper
+; X86-NEXT:    calll fmaximuml
+; X86-NEXT:    subl $4, %esp
+; X86-NEXT:    vmovaps {{[0-9]+}}(%esp), %xmm0
+; X86-NEXT:    vmovaps %xmm0, (%esi)
+; X86-NEXT:    movl %esi, %eax
+; X86-NEXT:    leal -4(%ebp), %esp
+; X86-NEXT:    popl %esi
+; X86-NEXT:    popl %ebp
+; X86-NEXT:    retl $4
+  %res = call fp128 @llvm.maximum.f128(fp128 %x, fp128 %y)
+  ret fp128 %res
+}

>From babd3392d586f7e5859abc697a953be0a9376e24 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 30 May 2025 17:52:15 +0200
Subject: [PATCH 5/5] Add i686 test

---
 .../CodeGen/X86/fminimum-fmaximum-i686.ll     | 530 ++++++++++++++++++
 1 file changed, 530 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/fminimum-fmaximum-i686.ll

diff --git a/llvm/test/CodeGen/X86/fminimum-fmaximum-i686.ll b/llvm/test/CodeGen/X86/fminimum-fmaximum-i686.ll
new file mode 100644
index 0000000000000..dea455a692420
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fminimum-fmaximum-i686.ll
@@ -0,0 +1,530 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s
+
+define half @maximum_half(half %x, half %y) nounwind {
+; CHECK-LABEL: maximum_half:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushl %esi
+; CHECK-NEXT:    subl $16, %esp
+; CHECK-NEXT:    movzwl {{[0-9]+}}(%esp), %esi
+; CHECK-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; CHECK-NEXT:    movl %eax, (%esp)
+; CHECK-NEXT:    calll __extendhfsf2
+; CHECK-NEXT:    fsts {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
+; CHECK-NEXT:    movl %esi, (%esp)
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    calll __extendhfsf2
+; CHECK-NEXT:    flds {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fsts {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:    ja .LBB0_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:    flds {{\.?LCPI[0-9]+_[0-9]+}}
+; CHECK-NEXT:    jp .LBB0_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB0_4:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    je .LBB0_6
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB0_6:
+; CHECK-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    je .LBB0_8
+; CHECK-NEXT:  # %bb.7:
+; CHECK-NEXT:    fstp %st(2)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:  .LBB0_8:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    jne .LBB0_9
+; CHECK-NEXT:  # %bb.10:
+; CHECK-NEXT:    jp .LBB0_13
+; CHECK-NEXT:  # %bb.11:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    jmp .LBB0_12
+; CHECK-NEXT:  .LBB0_9:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:  .LBB0_12:
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB0_13:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fstps (%esp)
+; CHECK-NEXT:    calll __truncsfhf2
+; CHECK-NEXT:    addl $16, %esp
+; CHECK-NEXT:    popl %esi
+; CHECK-NEXT:    retl
+  %res = call half @llvm.maximum.f16(half %x, half %y)
+  ret half %res
+}
+
+define float @maximum_float(float %x, float %y) nounwind {
+; CHECK-LABEL: maximum_float:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl $8, %esp
+; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
+; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fsts (%esp)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fsts {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:    ja .LBB1_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:  .LBB1_2:
+; CHECK-NEXT:    flds {{\.?LCPI[0-9]+_[0-9]+}}
+; CHECK-NEXT:    jp .LBB1_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB1_4:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    cmpl $0, (%esp)
+; CHECK-NEXT:    je .LBB1_6
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB1_6:
+; CHECK-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    je .LBB1_8
+; CHECK-NEXT:  # %bb.7:
+; CHECK-NEXT:    fstp %st(2)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:  .LBB1_8:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    jne .LBB1_9
+; CHECK-NEXT:  # %bb.10:
+; CHECK-NEXT:    jp .LBB1_13
+; CHECK-NEXT:  # %bb.11:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    jmp .LBB1_12
+; CHECK-NEXT:  .LBB1_9:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:  .LBB1_12:
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB1_13:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    addl $8, %esp
+; CHECK-NEXT:    retl
+  %res = call float @llvm.maximum.f32(float %x, float %y)
+  ret float %res
+}
+
+define double @maximum_double(double %x, double %y) nounwind {
+; CHECK-LABEL: maximum_double:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushl %ebp
+; CHECK-NEXT:    movl %esp, %ebp
+; CHECK-NEXT:    andl $-8, %esp
+; CHECK-NEXT:    subl $16, %esp
+; CHECK-NEXT:    fldl 16(%ebp)
+; CHECK-NEXT:    fldl 8(%ebp)
+; CHECK-NEXT:    fstl {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fstl (%esp)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:    ja .LBB2_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:  .LBB2_2:
+; CHECK-NEXT:    flds {{\.?LCPI[0-9]+_[0-9]+}}
+; CHECK-NEXT:    jp .LBB2_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB2_4:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    je .LBB2_6
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB2_6:
+; CHECK-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    je .LBB2_8
+; CHECK-NEXT:  # %bb.7:
+; CHECK-NEXT:    fstp %st(2)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:  .LBB2_8:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    jne .LBB2_9
+; CHECK-NEXT:  # %bb.10:
+; CHECK-NEXT:    jp .LBB2_13
+; CHECK-NEXT:  # %bb.11:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    jmp .LBB2_12
+; CHECK-NEXT:  .LBB2_9:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:  .LBB2_12:
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:  .LBB2_13:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    movl %ebp, %esp
+; CHECK-NEXT:    popl %ebp
+; CHECK-NEXT:    retl
+  %res = call double @llvm.maximum.f64(double %x, double %y)
+  ret double %res
+}
+
+define fp128 @maximum_fp128(fp128 %x, fp128 %y) nounwind {
+; CHECK-LABEL: maximum_fp128:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushl %ebp
+; CHECK-NEXT:    movl %esp, %ebp
+; CHECK-NEXT:    pushl %edi
+; CHECK-NEXT:    pushl %esi
+; CHECK-NEXT:    andl $-16, %esp
+; CHECK-NEXT:    subl $16, %esp
+; CHECK-NEXT:    movl 8(%ebp), %esi
+; CHECK-NEXT:    movl %esp, %eax
+; CHECK-NEXT:    pushl 40(%ebp)
+; CHECK-NEXT:    pushl 36(%ebp)
+; CHECK-NEXT:    pushl 32(%ebp)
+; CHECK-NEXT:    pushl 28(%ebp)
+; CHECK-NEXT:    pushl 24(%ebp)
+; CHECK-NEXT:    pushl 20(%ebp)
+; CHECK-NEXT:    pushl 16(%ebp)
+; CHECK-NEXT:    pushl 12(%ebp)
+; CHECK-NEXT:    pushl %eax
+; CHECK-NEXT:    calll fmaximuml
+; CHECK-NEXT:    addl $32, %esp
+; CHECK-NEXT:    movl (%esp), %eax
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %edi
+; CHECK-NEXT:    movl %edi, 12(%esi)
+; CHECK-NEXT:    movl %edx, 8(%esi)
+; CHECK-NEXT:    movl %ecx, 4(%esi)
+; CHECK-NEXT:    movl %eax, (%esi)
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    leal -8(%ebp), %esp
+; CHECK-NEXT:    popl %esi
+; CHECK-NEXT:    popl %edi
+; CHECK-NEXT:    popl %ebp
+; CHECK-NEXT:    retl $4
+  %res = call fp128 @llvm.maximum.f128(fp128 %x, fp128 %y)
+  ret fp128 %res
+}
+
+define half @minimum_half(half %x, half %y) nounwind {
+; CHECK-LABEL: minimum_half:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushl %esi
+; CHECK-NEXT:    subl $16, %esp
+; CHECK-NEXT:    movzwl {{[0-9]+}}(%esp), %esi
+; CHECK-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; CHECK-NEXT:    movl %eax, (%esp)
+; CHECK-NEXT:    calll __extendhfsf2
+; CHECK-NEXT:    fsts {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
+; CHECK-NEXT:    movl %esi, (%esp)
+; CHECK-NEXT:    fstps {{[0-9]+}}(%esp)
+; CHECK-NEXT:    calll __extendhfsf2
+; CHECK-NEXT:    flds {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fsts {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:    ja .LBB4_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:  .LBB4_2:
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    flds {{\.?LCPI[0-9]+_[0-9]+}}
+; CHECK-NEXT:    jp .LBB4_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(3)
+; CHECK-NEXT:  .LBB4_4:
+; CHECK-NEXT:    fstp %st(3)
+; CHECK-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    jne .LBB4_6
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:  .LBB4_6:
+; CHECK-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    jne .LBB4_8
+; CHECK-NEXT:  # %bb.7:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:  .LBB4_8:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:    fucom %st(2)
+; CHECK-NEXT:    fstp %st(2)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    jne .LBB4_9
+; CHECK-NEXT:  # %bb.10:
+; CHECK-NEXT:    jp .LBB4_13
+; CHECK-NEXT:  # %bb.11:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    jmp .LBB4_12
+; CHECK-NEXT:  .LBB4_9:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:  .LBB4_12:
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:  .LBB4_13:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fstps (%esp)
+; CHECK-NEXT:    calll __truncsfhf2
+; CHECK-NEXT:    addl $16, %esp
+; CHECK-NEXT:    popl %esi
+; CHECK-NEXT:    retl
+  %res = call half @llvm.minimum.f16(half %x, half %y)
+  ret half %res
+}
+
+define float @minimum_float(float %x, float %y) nounwind {
+; CHECK-LABEL: minimum_float:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subl $8, %esp
+; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
+; CHECK-NEXT:    flds {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fsts (%esp)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fsts {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:    ja .LBB5_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:  .LBB5_2:
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    flds {{\.?LCPI[0-9]+_[0-9]+}}
+; CHECK-NEXT:    jp .LBB5_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(3)
+; CHECK-NEXT:  .LBB5_4:
+; CHECK-NEXT:    fstp %st(3)
+; CHECK-NEXT:    cmpl $0, (%esp)
+; CHECK-NEXT:    jne .LBB5_6
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:  .LBB5_6:
+; CHECK-NEXT:    cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    jne .LBB5_8
+; CHECK-NEXT:  # %bb.7:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:  .LBB5_8:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:    fucom %st(2)
+; CHECK-NEXT:    fstp %st(2)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    jne .LBB5_9
+; CHECK-NEXT:  # %bb.10:
+; CHECK-NEXT:    jp .LBB5_13
+; CHECK-NEXT:  # %bb.11:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    jmp .LBB5_12
+; CHECK-NEXT:  .LBB5_9:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:  .LBB5_12:
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:  .LBB5_13:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    addl $8, %esp
+; CHECK-NEXT:    retl
+  %res = call float @llvm.minimum.f32(float %x, float %y)
+  ret float %res
+}
+
+define double @minimum_double(double %x, double %y) nounwind {
+; CHECK-LABEL: minimum_double:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushl %ebp
+; CHECK-NEXT:    movl %esp, %ebp
+; CHECK-NEXT:    andl $-8, %esp
+; CHECK-NEXT:    subl $16, %esp
+; CHECK-NEXT:    fldl 16(%ebp)
+; CHECK-NEXT:    fldl 8(%ebp)
+; CHECK-NEXT:    fstl {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fstl (%esp)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:    ja .LBB6_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(0)
+; CHECK-NEXT:  .LBB6_2:
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:    fucom %st(1)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    flds {{\.?LCPI[0-9]+_[0-9]+}}
+; CHECK-NEXT:    jp .LBB6_4
+; CHECK-NEXT:  # %bb.3:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(3)
+; CHECK-NEXT:  .LBB6_4:
+; CHECK-NEXT:    fstp %st(3)
+; CHECK-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    jne .LBB6_6
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fld %st(1)
+; CHECK-NEXT:  .LBB6_6:
+; CHECK-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    jne .LBB6_8
+; CHECK-NEXT:  # %bb.7:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:  .LBB6_8:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    fxch %st(2)
+; CHECK-NEXT:    fucom %st(2)
+; CHECK-NEXT:    fstp %st(2)
+; CHECK-NEXT:    fnstsw %ax
+; CHECK-NEXT:    # kill: def $ah killed $ah killed $ax
+; CHECK-NEXT:    sahf
+; CHECK-NEXT:    jne .LBB6_9
+; CHECK-NEXT:  # %bb.10:
+; CHECK-NEXT:    jp .LBB6_13
+; CHECK-NEXT:  # %bb.11:
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    jmp .LBB6_12
+; CHECK-NEXT:  .LBB6_9:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:  .LBB6_12:
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:  .LBB6_13:
+; CHECK-NEXT:    fstp %st(0)
+; CHECK-NEXT:    movl %ebp, %esp
+; CHECK-NEXT:    popl %ebp
+; CHECK-NEXT:    retl
+  %res = call double @llvm.minimum.f64(double %x, double %y)
+  ret double %res
+}
+
+define fp128 @minimum_fp128(fp128 %x, fp128 %y) nounwind {
+; CHECK-LABEL: minimum_fp128:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushl %ebp
+; CHECK-NEXT:    movl %esp, %ebp
+; CHECK-NEXT:    pushl %edi
+; CHECK-NEXT:    pushl %esi
+; CHECK-NEXT:    andl $-16, %esp
+; CHECK-NEXT:    subl $16, %esp
+; CHECK-NEXT:    movl 8(%ebp), %esi
+; CHECK-NEXT:    movl %esp, %eax
+; CHECK-NEXT:    pushl 40(%ebp)
+; CHECK-NEXT:    pushl 36(%ebp)
+; CHECK-NEXT:    pushl 32(%ebp)
+; CHECK-NEXT:    pushl 28(%ebp)
+; CHECK-NEXT:    pushl 24(%ebp)
+; CHECK-NEXT:    pushl 20(%ebp)
+; CHECK-NEXT:    pushl 16(%ebp)
+; CHECK-NEXT:    pushl 12(%ebp)
+; CHECK-NEXT:    pushl %eax
+; CHECK-NEXT:    calll fminimuml
+; CHECK-NEXT:    addl $32, %esp
+; CHECK-NEXT:    movl (%esp), %eax
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %edi
+; CHECK-NEXT:    movl %edi, 12(%esi)
+; CHECK-NEXT:    movl %edx, 8(%esi)
+; CHECK-NEXT:    movl %ecx, 4(%esi)
+; CHECK-NEXT:    movl %eax, (%esi)
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    leal -8(%ebp), %esp
+; CHECK-NEXT:    popl %esi
+; CHECK-NEXT:    popl %edi
+; CHECK-NEXT:    popl %ebp
+; CHECK-NEXT:    retl $4
+  %res = call fp128 @llvm.minimum.f128(fp128 %x, fp128 %y)
+  ret fp128 %res
+}



More information about the llvm-commits mailing list