[llvm] [SDAG] Fix fmaximum legalization errors (PR #142170)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri May 30 08:33:27 PDT 2025
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/142170
FMAXIMUM is currently legalized via IS_FPCLASS for the signed zero handling. This is problematic, because it assumes the equivalent integer type is legal. Many targets have legal fp128, but illegal i128, so this results in legalization failures.
Fix this by replacing IS_FPCLASS with checking the bitcast to integer instead. In that case it is sufficient to use any legal integer type, as we're just interested in the sign bit. This can be obtained via a stack temporary cast. There is existing FloatSignAsInt functionality used for legalization of FABS and similar we can use for this purpose.
(Happy to land the FloatSignAsInt helper move separately if the general direction here seems ok.)
>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/4] 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/4] 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/4] 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/4] 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
+}
More information about the llvm-commits
mailing list