[llvm] [AMDGPU] Fix lowerFCOPYSIGN dropping the sign bit when narrowing the sign operand (PR #203492)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 12 03:11:04 PDT 2026
https://github.com/aobolensk created https://github.com/llvm/llvm-project/pull/203492
TRUNCATE of the v2i32-bitcast sign kept the low 16 bits of each lane but dropped f32 sign bit at bit 3
Shift right by 16 first so the sign bit lands in the f16 sign position
>From 90a9ba644cb96f737ce1c169ee23099e1f4ec2af Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 12 Jun 2026 12:08:59 +0200
Subject: [PATCH] [AMDGPU] Fix lowerFCOPYSIGN dropping the sign bit when
narrowing the sign operand
TRUNCATE of the v2i32-bitcast sign kept the low 16 bits of each lane but dropped f32 sign bit at bit 3
Shift right by 16 first so the sign bit lands in the f16 sign position
---
llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 8 +-
llvm/test/CodeGen/AMDGPU/fcopysign.bf16.ll | 110 +++++++++++----------
llvm/test/CodeGen/AMDGPU/fcopysign.f16.ll | 94 +++++++++---------
3 files changed, 112 insertions(+), 100 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index eb3b869990cdd..b2e96b26282b5 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8873,11 +8873,15 @@ SDValue SITargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
return Op;
// fcopysign v2f16:mag, v2f32:sign ->
- // fcopysign v2f16:mag, bitcast (trunc (bitcast sign to v2i32) to v2i16)
+ // fcopysign v2f16:mag,
+ // bitcast (trunc (srl (bitcast sign to v2i32), 16) to v2i16)
SDLoc SL(Op);
SDValue SignAsInt32 = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Sign);
- SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignAsInt32);
+ SDValue ShiftAmt = DAG.getConstant(16, SL, MVT::v2i32);
+ SDValue SignShifted =
+ DAG.getNode(ISD::SRL, SL, MVT::v2i32, SignAsInt32, ShiftAmt);
+ SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignShifted);
SDValue SignAsHalf16 = DAG.getNode(ISD::BITCAST, SL, MagVT, SignAsInt16);
diff --git a/llvm/test/CodeGen/AMDGPU/fcopysign.bf16.ll b/llvm/test/CodeGen/AMDGPU/fcopysign.bf16.ll
index 3f6750546618f..b0fc2d07b5404 100644
--- a/llvm/test/CodeGen/AMDGPU/fcopysign.bf16.ll
+++ b/llvm/test/CodeGen/AMDGPU/fcopysign.bf16.ll
@@ -3911,9 +3911,8 @@ define <2 x bfloat> @v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64(<2 x bfloat> %m
; GFX8-LABEL: v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX8: ; %bb.0:
; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX8-NEXT: v_lshlrev_b32_e32 v1, 16, v4
-; GFX8-NEXT: v_and_b32_e32 v2, 0x8000, v2
-; GFX8-NEXT: v_or_b32_e32 v1, v2, v1
+; GFX8-NEXT: s_mov_b32 s4, 0x3020706
+; GFX8-NEXT: v_perm_b32 v1, v2, v4, s4
; GFX8-NEXT: s_mov_b32 s4, 0x7fff7fff
; GFX8-NEXT: v_bfi_b32 v0, s4, v0, v1
; GFX8-NEXT: s_setpc_b64 s[30:31]
@@ -3921,7 +3920,7 @@ define <2 x bfloat> @v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64(<2 x bfloat> %m
; GFX9-LABEL: v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT: s_mov_b32 s4, 0x5040100
+; GFX9-NEXT: s_mov_b32 s4, 0x7060302
; GFX9-NEXT: v_perm_b32 v1, v4, v2, s4
; GFX9-NEXT: s_mov_b32 s4, 0x7fff7fff
; GFX9-NEXT: v_bfi_b32 v0, s4, v0, v1
@@ -3930,22 +3929,22 @@ define <2 x bfloat> @v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64(<2 x bfloat> %m
; GFX10-LABEL: v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX10-NEXT: v_perm_b32 v1, v4, v2, 0x5040100
+; GFX10-NEXT: v_perm_b32 v1, v4, v2, 0x7060302
; GFX10-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v1
; GFX10-NEXT: s_setpc_b64 s[30:31]
;
; GFX11TRUE16-LABEL: v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX11TRUE16: ; %bb.0:
; GFX11TRUE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11TRUE16-NEXT: v_mov_b16_e32 v2.h, v4.l
+; GFX11TRUE16-NEXT: v_mov_b16_e32 v4.l, v2.h
; GFX11TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; GFX11TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v2
+; GFX11TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v4
; GFX11TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11FAKE16-LABEL: v_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX11FAKE16: ; %bb.0:
; GFX11FAKE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11FAKE16-NEXT: v_perm_b32 v1, v4, v2, 0x5040100
+; GFX11FAKE16-NEXT: v_perm_b32 v1, v4, v2, 0x7060302
; GFX11FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
; GFX11FAKE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v1
; GFX11FAKE16-NEXT: s_setpc_b64 s[30:31]
@@ -4802,19 +4801,20 @@ define amdgpu_ps i32 @s_copysign_out_v2bf16_mag_v2bf16_sign_v2f64(<2 x bfloat> i
;
; GFX8-LABEL: s_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX8: ; %bb.0:
-; GFX8-NEXT: s_lshl_b32 s1, s4, 16
-; GFX8-NEXT: s_and_b32 s2, s2, 0x8000
-; GFX8-NEXT: s_or_b32 s1, s2, s1
-; GFX8-NEXT: s_mov_b32 s2, 0x7fff7fff
+; GFX8-NEXT: s_lshr_b32 s3, s4, 16
+; GFX8-NEXT: s_lshr_b64 s[2:3], s[2:3], 16
+; GFX8-NEXT: s_mov_b32 s1, 0x7fff7fff
; GFX8-NEXT: v_mov_b32_e32 v0, s0
-; GFX8-NEXT: v_mov_b32_e32 v1, s1
-; GFX8-NEXT: v_bfi_b32 v0, s2, v0, v1
+; GFX8-NEXT: v_mov_b32_e32 v1, s2
+; GFX8-NEXT: v_bfi_b32 v0, s1, v0, v1
; GFX8-NEXT: v_readfirstlane_b32 s0, v0
; GFX8-NEXT: ; return to shader part epilog
;
; GFX9-LABEL: s_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX9: ; %bb.0:
-; GFX9-NEXT: s_pack_ll_b32_b16 s1, s2, s4
+; GFX9-NEXT: s_lshr_b32 s1, s4, 16
+; GFX9-NEXT: s_lshr_b32 s2, s2, 16
+; GFX9-NEXT: s_pack_ll_b32_b16 s1, s2, s1
; GFX9-NEXT: s_mov_b32 s2, 0x7fff7fff
; GFX9-NEXT: v_mov_b32_e32 v0, s0
; GFX9-NEXT: v_mov_b32_e32 v1, s1
@@ -4824,7 +4824,9 @@ define amdgpu_ps i32 @s_copysign_out_v2bf16_mag_v2bf16_sign_v2f64(<2 x bfloat> i
;
; GFX10-LABEL: s_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX10: ; %bb.0:
-; GFX10-NEXT: s_pack_ll_b32_b16 s1, s2, s4
+; GFX10-NEXT: s_lshr_b32 s1, s4, 16
+; GFX10-NEXT: s_lshr_b32 s2, s2, 16
+; GFX10-NEXT: s_pack_ll_b32_b16 s1, s2, s1
; GFX10-NEXT: v_mov_b32_e32 v0, s1
; GFX10-NEXT: v_bfi_b32 v0, 0x7fff7fff, s0, v0
; GFX10-NEXT: v_readfirstlane_b32 s0, v0
@@ -4832,11 +4834,13 @@ define amdgpu_ps i32 @s_copysign_out_v2bf16_mag_v2bf16_sign_v2f64(<2 x bfloat> i
;
; GFX11-LABEL: s_copysign_out_v2bf16_mag_v2bf16_sign_v2f64:
; GFX11: ; %bb.0:
-; GFX11-NEXT: s_pack_ll_b32_b16 s1, s2, s4
-; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT: s_lshr_b32 s1, s4, 16
+; GFX11-NEXT: s_lshr_b32 s2, s2, 16
+; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
+; GFX11-NEXT: s_pack_ll_b32_b16 s1, s2, s1
; GFX11-NEXT: v_mov_b32_e32 v0, s1
+; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
; GFX11-NEXT: v_bfi_b32 v0, 0x7fff7fff, s0, v0
-; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1)
; GFX11-NEXT: v_readfirstlane_b32 s0, v0
; GFX11-NEXT: ; return to shader part epilog
%sign.trunc = fptrunc <2 x double> %sign to <2 x bfloat>
@@ -7152,21 +7156,18 @@ define <4 x bfloat> @v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64(<4 x bfloat> %m
; GFX8-LABEL: v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64:
; GFX8: ; %bb.0:
; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX8-NEXT: v_lshlrev_b32_e32 v2, 16, v5
-; GFX8-NEXT: v_and_b32_e32 v3, 0x8000, v3
-; GFX8-NEXT: v_or_b32_e32 v2, v3, v2
-; GFX8-NEXT: s_mov_b32 s4, 0x7fff7fff
-; GFX8-NEXT: v_bfi_b32 v0, s4, v0, v2
-; GFX8-NEXT: v_lshlrev_b32_e32 v2, 16, v9
-; GFX8-NEXT: v_and_b32_e32 v3, 0x8000, v7
-; GFX8-NEXT: v_or_b32_e32 v2, v3, v2
-; GFX8-NEXT: v_bfi_b32 v1, s4, v1, v2
+; GFX8-NEXT: s_mov_b32 s4, 0x3020706
+; GFX8-NEXT: v_perm_b32 v2, v3, v5, s4
+; GFX8-NEXT: s_mov_b32 s5, 0x7fff7fff
+; GFX8-NEXT: v_bfi_b32 v0, s5, v0, v2
+; GFX8-NEXT: v_perm_b32 v2, v7, v9, s4
+; GFX8-NEXT: v_bfi_b32 v1, s5, v1, v2
; GFX8-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-LABEL: v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT: s_mov_b32 s4, 0x5040100
+; GFX9-NEXT: s_mov_b32 s4, 0x7060302
; GFX9-NEXT: v_perm_b32 v2, v5, v3, s4
; GFX9-NEXT: s_mov_b32 s5, 0x7fff7fff
; GFX9-NEXT: v_bfi_b32 v0, s5, v0, v2
@@ -7177,8 +7178,8 @@ define <4 x bfloat> @v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64(<4 x bfloat> %m
; GFX10-LABEL: v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX10-NEXT: v_perm_b32 v2, v5, v3, 0x5040100
-; GFX10-NEXT: v_perm_b32 v3, v9, v7, 0x5040100
+; GFX10-NEXT: v_perm_b32 v2, v5, v3, 0x7060302
+; GFX10-NEXT: v_perm_b32 v3, v9, v7, 0x7060302
; GFX10-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v2
; GFX10-NEXT: v_bfi_b32 v1, 0x7fff7fff, v1, v3
; GFX10-NEXT: s_setpc_b64 s[30:31]
@@ -7186,18 +7187,18 @@ define <4 x bfloat> @v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64(<4 x bfloat> %m
; GFX11TRUE16-LABEL: v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64:
; GFX11TRUE16: ; %bb.0:
; GFX11TRUE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11TRUE16-NEXT: v_mov_b16_e32 v3.h, v5.l
-; GFX11TRUE16-NEXT: v_mov_b16_e32 v7.h, v9.l
+; GFX11TRUE16-NEXT: v_mov_b16_e32 v5.l, v3.h
+; GFX11TRUE16-NEXT: v_mov_b16_e32 v9.l, v7.h
; GFX11TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
-; GFX11TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v3
-; GFX11TRUE16-NEXT: v_bfi_b32 v1, 0x7fff7fff, v1, v7
+; GFX11TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v5
+; GFX11TRUE16-NEXT: v_bfi_b32 v1, 0x7fff7fff, v1, v9
; GFX11TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11FAKE16-LABEL: v_copysign_out_v4bf16_mag_v4bf16_sign_v4f64:
; GFX11FAKE16: ; %bb.0:
; GFX11FAKE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11FAKE16-NEXT: v_perm_b32 v2, v5, v3, 0x5040100
-; GFX11FAKE16-NEXT: v_perm_b32 v3, v9, v7, 0x5040100
+; GFX11FAKE16-NEXT: v_perm_b32 v2, v5, v3, 0x7060302
+; GFX11FAKE16-NEXT: v_perm_b32 v3, v9, v7, 0x7060302
; GFX11FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
; GFX11FAKE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v2
; GFX11FAKE16-NEXT: v_bfi_b32 v1, 0x7fff7fff, v1, v3
@@ -7934,9 +7935,9 @@ define amdgpu_ps i32 @s_copysign_v2bf16_0_v2f64(<2 x double> inreg %sign) {
;
; GFX8-LABEL: s_copysign_v2bf16_0_v2f64:
; GFX8: ; %bb.0:
-; GFX8-NEXT: s_lshl_b32 s0, s3, 16
-; GFX8-NEXT: s_and_b32 s1, s1, 0x8000
-; GFX8-NEXT: s_or_b32 s0, s1, s0
+; GFX8-NEXT: s_mov_b32 s0, s1
+; GFX8-NEXT: s_lshr_b32 s1, s3, 16
+; GFX8-NEXT: s_lshr_b64 s[0:1], s[0:1], 16
; GFX8-NEXT: s_mov_b32 s1, 0x7fff7fff
; GFX8-NEXT: v_mov_b32_e32 v0, s0
; GFX8-NEXT: v_bfi_b32 v0, s1, 0, v0
@@ -7945,20 +7946,26 @@ define amdgpu_ps i32 @s_copysign_v2bf16_0_v2f64(<2 x double> inreg %sign) {
;
; GFX9-LABEL: s_copysign_v2bf16_0_v2f64:
; GFX9: ; %bb.0:
-; GFX9-NEXT: s_pack_ll_b32_b16 s0, s1, s3
+; GFX9-NEXT: s_lshr_b32 s0, s3, 16
+; GFX9-NEXT: s_lshr_b32 s1, s1, 16
+; GFX9-NEXT: s_pack_ll_b32_b16 s0, s1, s0
; GFX9-NEXT: s_and_b32 s0, 0x80008000, s0
; GFX9-NEXT: ; return to shader part epilog
;
; GFX10-LABEL: s_copysign_v2bf16_0_v2f64:
; GFX10: ; %bb.0:
-; GFX10-NEXT: s_pack_ll_b32_b16 s0, s1, s3
+; GFX10-NEXT: s_lshr_b32 s0, s3, 16
+; GFX10-NEXT: s_lshr_b32 s1, s1, 16
+; GFX10-NEXT: s_pack_ll_b32_b16 s0, s1, s0
; GFX10-NEXT: s_and_b32 s0, 0x80008000, s0
; GFX10-NEXT: ; return to shader part epilog
;
; GFX11-LABEL: s_copysign_v2bf16_0_v2f64:
; GFX11: ; %bb.0:
-; GFX11-NEXT: s_pack_ll_b32_b16 s0, s1, s3
-; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1)
+; GFX11-NEXT: s_lshr_b32 s0, s3, 16
+; GFX11-NEXT: s_lshr_b32 s1, s1, 16
+; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
+; GFX11-NEXT: s_pack_ll_b32_b16 s0, s1, s0
; GFX11-NEXT: s_and_b32 s0, 0x80008000, s0
; GFX11-NEXT: ; return to shader part epilog
%sign.trunc = fptrunc <2 x double> %sign to <2 x bfloat>
@@ -7989,9 +7996,8 @@ define <2 x bfloat> @v_copysign_v2bf16_0_v2bf64(<2 x double> %sign) {
; GFX8-LABEL: v_copysign_v2bf16_0_v2bf64:
; GFX8: ; %bb.0:
; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX8-NEXT: v_lshlrev_b32_e32 v0, 16, v3
-; GFX8-NEXT: v_and_b32_e32 v1, 0x8000, v1
-; GFX8-NEXT: v_or_b32_e32 v0, v1, v0
+; GFX8-NEXT: s_mov_b32 s4, 0x3020706
+; GFX8-NEXT: v_perm_b32 v0, v1, v3, s4
; GFX8-NEXT: s_mov_b32 s4, 0x7fff7fff
; GFX8-NEXT: v_bfi_b32 v0, s4, 0, v0
; GFX8-NEXT: s_setpc_b64 s[30:31]
@@ -7999,7 +8005,7 @@ define <2 x bfloat> @v_copysign_v2bf16_0_v2bf64(<2 x double> %sign) {
; GFX9-LABEL: v_copysign_v2bf16_0_v2bf64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT: s_mov_b32 s4, 0x5040100
+; GFX9-NEXT: s_mov_b32 s4, 0x7060302
; GFX9-NEXT: v_perm_b32 v0, v3, v1, s4
; GFX9-NEXT: v_and_b32_e32 v0, 0x80008000, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
@@ -8007,22 +8013,22 @@ define <2 x bfloat> @v_copysign_v2bf16_0_v2bf64(<2 x double> %sign) {
; GFX10-LABEL: v_copysign_v2bf16_0_v2bf64:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX10-NEXT: v_perm_b32 v0, v3, v1, 0x5040100
+; GFX10-NEXT: v_perm_b32 v0, v3, v1, 0x7060302
; GFX10-NEXT: v_and_b32_e32 v0, 0x80008000, v0
; GFX10-NEXT: s_setpc_b64 s[30:31]
;
; GFX11TRUE16-LABEL: v_copysign_v2bf16_0_v2bf64:
; GFX11TRUE16: ; %bb.0:
; GFX11TRUE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11TRUE16-NEXT: v_mov_b16_e32 v1.h, v3.l
+; GFX11TRUE16-NEXT: v_mov_b16_e32 v3.l, v1.h
; GFX11TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; GFX11TRUE16-NEXT: v_and_b32_e32 v0, 0x80008000, v1
+; GFX11TRUE16-NEXT: v_and_b32_e32 v0, 0x80008000, v3
; GFX11TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11FAKE16-LABEL: v_copysign_v2bf16_0_v2bf64:
; GFX11FAKE16: ; %bb.0:
; GFX11FAKE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11FAKE16-NEXT: v_perm_b32 v0, v3, v1, 0x5040100
+; GFX11FAKE16-NEXT: v_perm_b32 v0, v3, v1, 0x7060302
; GFX11FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
; GFX11FAKE16-NEXT: v_and_b32_e32 v0, 0x80008000, v0
; GFX11FAKE16-NEXT: s_setpc_b64 s[30:31]
diff --git a/llvm/test/CodeGen/AMDGPU/fcopysign.f16.ll b/llvm/test/CodeGen/AMDGPU/fcopysign.f16.ll
index 0ae807783a151..3dace636df09b 100644
--- a/llvm/test/CodeGen/AMDGPU/fcopysign.f16.ll
+++ b/llvm/test/CodeGen/AMDGPU/fcopysign.f16.ll
@@ -3456,9 +3456,8 @@ define <2 x half> @v_copysign_out_v2f16_mag_v2f16_sign_v2f64(<2 x half> %mag, <2
; VI-LABEL: v_copysign_out_v2f16_mag_v2f16_sign_v2f64:
; VI: ; %bb.0:
; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_lshlrev_b32_e32 v1, 16, v4
-; VI-NEXT: v_and_b32_e32 v2, 0x8000, v2
-; VI-NEXT: v_or_b32_e32 v1, v2, v1
+; VI-NEXT: s_mov_b32 s4, 0x3020706
+; VI-NEXT: v_perm_b32 v1, v2, v4, s4
; VI-NEXT: s_mov_b32 s4, 0x7fff7fff
; VI-NEXT: v_bfi_b32 v0, s4, v0, v1
; VI-NEXT: s_setpc_b64 s[30:31]
@@ -3466,7 +3465,7 @@ define <2 x half> @v_copysign_out_v2f16_mag_v2f16_sign_v2f64(<2 x half> %mag, <2
; GFX9-LABEL: v_copysign_out_v2f16_mag_v2f16_sign_v2f64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT: s_mov_b32 s4, 0x5040100
+; GFX9-NEXT: s_mov_b32 s4, 0x7060302
; GFX9-NEXT: v_perm_b32 v1, v4, v2, s4
; GFX9-NEXT: s_mov_b32 s4, 0x7fff7fff
; GFX9-NEXT: v_bfi_b32 v0, s4, v0, v1
@@ -3475,15 +3474,15 @@ define <2 x half> @v_copysign_out_v2f16_mag_v2f16_sign_v2f64(<2 x half> %mag, <2
; GFX11-TRUE16-LABEL: v_copysign_out_v2f16_mag_v2f16_sign_v2f64:
; GFX11-TRUE16: ; %bb.0:
; GFX11-TRUE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-TRUE16-NEXT: v_mov_b16_e32 v2.h, v4.l
+; GFX11-TRUE16-NEXT: v_mov_b16_e32 v4.l, v2.h
; GFX11-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; GFX11-TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v2
+; GFX11-TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v4
; GFX11-TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11-FAKE16-LABEL: v_copysign_out_v2f16_mag_v2f16_sign_v2f64:
; GFX11-FAKE16: ; %bb.0:
; GFX11-FAKE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-FAKE16-NEXT: v_perm_b32 v1, v4, v2, 0x5040100
+; GFX11-FAKE16-NEXT: v_perm_b32 v1, v4, v2, 0x7060302
; GFX11-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
; GFX11-FAKE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v1
; GFX11-FAKE16-NEXT: s_setpc_b64 s[30:31]
@@ -4226,19 +4225,20 @@ define amdgpu_ps i32 @s_copysign_out_v2f16_mag_v2f16_sign_v2f64(<2 x half> inreg
;
; VI-LABEL: s_copysign_out_v2f16_mag_v2f16_sign_v2f64:
; VI: ; %bb.0:
-; VI-NEXT: s_lshl_b32 s1, s4, 16
-; VI-NEXT: s_and_b32 s2, s2, 0x8000
-; VI-NEXT: s_or_b32 s1, s2, s1
-; VI-NEXT: s_mov_b32 s2, 0x7fff7fff
+; VI-NEXT: s_lshr_b32 s3, s4, 16
+; VI-NEXT: s_lshr_b64 s[2:3], s[2:3], 16
+; VI-NEXT: s_mov_b32 s1, 0x7fff7fff
; VI-NEXT: v_mov_b32_e32 v0, s0
-; VI-NEXT: v_mov_b32_e32 v1, s1
-; VI-NEXT: v_bfi_b32 v0, s2, v0, v1
+; VI-NEXT: v_mov_b32_e32 v1, s2
+; VI-NEXT: v_bfi_b32 v0, s1, v0, v1
; VI-NEXT: v_readfirstlane_b32 s0, v0
; VI-NEXT: ; return to shader part epilog
;
; GFX9-LABEL: s_copysign_out_v2f16_mag_v2f16_sign_v2f64:
; GFX9: ; %bb.0:
-; GFX9-NEXT: s_pack_ll_b32_b16 s1, s2, s4
+; GFX9-NEXT: s_lshr_b32 s1, s4, 16
+; GFX9-NEXT: s_lshr_b32 s2, s2, 16
+; GFX9-NEXT: s_pack_ll_b32_b16 s1, s2, s1
; GFX9-NEXT: s_mov_b32 s2, 0x7fff7fff
; GFX9-NEXT: v_mov_b32_e32 v0, s0
; GFX9-NEXT: v_mov_b32_e32 v1, s1
@@ -4248,11 +4248,13 @@ define amdgpu_ps i32 @s_copysign_out_v2f16_mag_v2f16_sign_v2f64(<2 x half> inreg
;
; GFX11-LABEL: s_copysign_out_v2f16_mag_v2f16_sign_v2f64:
; GFX11: ; %bb.0:
-; GFX11-NEXT: s_pack_ll_b32_b16 s1, s2, s4
-; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-NEXT: s_lshr_b32 s1, s4, 16
+; GFX11-NEXT: s_lshr_b32 s2, s2, 16
+; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
+; GFX11-NEXT: s_pack_ll_b32_b16 s1, s2, s1
; GFX11-NEXT: v_mov_b32_e32 v0, s1
+; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
; GFX11-NEXT: v_bfi_b32 v0, 0x7fff7fff, s0, v0
-; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1)
; GFX11-NEXT: v_readfirstlane_b32 s0, v0
; GFX11-NEXT: ; return to shader part epilog
%sign.trunc = fptrunc <2 x double> %sign to <2 x half>
@@ -6576,21 +6578,18 @@ define <4 x half> @v_copysign_out_v4f16_mag_v4f16_sign_v4f64(<4 x half> %mag, <4
; VI-LABEL: v_copysign_out_v4f16_mag_v4f16_sign_v4f64:
; VI: ; %bb.0:
; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_lshlrev_b32_e32 v2, 16, v5
-; VI-NEXT: v_and_b32_e32 v3, 0x8000, v3
-; VI-NEXT: v_or_b32_e32 v2, v3, v2
-; VI-NEXT: s_mov_b32 s4, 0x7fff7fff
-; VI-NEXT: v_bfi_b32 v0, s4, v0, v2
-; VI-NEXT: v_lshlrev_b32_e32 v2, 16, v9
-; VI-NEXT: v_and_b32_e32 v3, 0x8000, v7
-; VI-NEXT: v_or_b32_e32 v2, v3, v2
-; VI-NEXT: v_bfi_b32 v1, s4, v1, v2
+; VI-NEXT: s_mov_b32 s4, 0x3020706
+; VI-NEXT: v_perm_b32 v2, v3, v5, s4
+; VI-NEXT: s_mov_b32 s5, 0x7fff7fff
+; VI-NEXT: v_bfi_b32 v0, s5, v0, v2
+; VI-NEXT: v_perm_b32 v2, v7, v9, s4
+; VI-NEXT: v_bfi_b32 v1, s5, v1, v2
; VI-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-LABEL: v_copysign_out_v4f16_mag_v4f16_sign_v4f64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT: s_mov_b32 s4, 0x5040100
+; GFX9-NEXT: s_mov_b32 s4, 0x7060302
; GFX9-NEXT: v_perm_b32 v2, v5, v3, s4
; GFX9-NEXT: s_mov_b32 s5, 0x7fff7fff
; GFX9-NEXT: v_bfi_b32 v0, s5, v0, v2
@@ -6601,18 +6600,18 @@ define <4 x half> @v_copysign_out_v4f16_mag_v4f16_sign_v4f64(<4 x half> %mag, <4
; GFX11-TRUE16-LABEL: v_copysign_out_v4f16_mag_v4f16_sign_v4f64:
; GFX11-TRUE16: ; %bb.0:
; GFX11-TRUE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-TRUE16-NEXT: v_mov_b16_e32 v3.h, v5.l
-; GFX11-TRUE16-NEXT: v_mov_b16_e32 v7.h, v9.l
+; GFX11-TRUE16-NEXT: v_mov_b16_e32 v5.l, v3.h
+; GFX11-TRUE16-NEXT: v_mov_b16_e32 v9.l, v7.h
; GFX11-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
-; GFX11-TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v3
-; GFX11-TRUE16-NEXT: v_bfi_b32 v1, 0x7fff7fff, v1, v7
+; GFX11-TRUE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v5
+; GFX11-TRUE16-NEXT: v_bfi_b32 v1, 0x7fff7fff, v1, v9
; GFX11-TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11-FAKE16-LABEL: v_copysign_out_v4f16_mag_v4f16_sign_v4f64:
; GFX11-FAKE16: ; %bb.0:
; GFX11-FAKE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-FAKE16-NEXT: v_perm_b32 v2, v5, v3, 0x5040100
-; GFX11-FAKE16-NEXT: v_perm_b32 v3, v9, v7, 0x5040100
+; GFX11-FAKE16-NEXT: v_perm_b32 v2, v5, v3, 0x7060302
+; GFX11-FAKE16-NEXT: v_perm_b32 v3, v9, v7, 0x7060302
; GFX11-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
; GFX11-FAKE16-NEXT: v_bfi_b32 v0, 0x7fff7fff, v0, v2
; GFX11-FAKE16-NEXT: v_bfi_b32 v1, 0x7fff7fff, v1, v3
@@ -7218,9 +7217,9 @@ define amdgpu_ps i32 @s_copysign_v2f16_0_v2f64(<2 x double> inreg %sign) {
;
; VI-LABEL: s_copysign_v2f16_0_v2f64:
; VI: ; %bb.0:
-; VI-NEXT: s_lshl_b32 s0, s3, 16
-; VI-NEXT: s_and_b32 s1, s1, 0x8000
-; VI-NEXT: s_or_b32 s0, s1, s0
+; VI-NEXT: s_mov_b32 s0, s1
+; VI-NEXT: s_lshr_b32 s1, s3, 16
+; VI-NEXT: s_lshr_b64 s[0:1], s[0:1], 16
; VI-NEXT: s_mov_b32 s1, 0x7fff7fff
; VI-NEXT: v_mov_b32_e32 v0, s0
; VI-NEXT: v_bfi_b32 v0, s1, 0, v0
@@ -7229,14 +7228,18 @@ define amdgpu_ps i32 @s_copysign_v2f16_0_v2f64(<2 x double> inreg %sign) {
;
; GFX9-LABEL: s_copysign_v2f16_0_v2f64:
; GFX9: ; %bb.0:
-; GFX9-NEXT: s_pack_ll_b32_b16 s0, s1, s3
+; GFX9-NEXT: s_lshr_b32 s0, s3, 16
+; GFX9-NEXT: s_lshr_b32 s1, s1, 16
+; GFX9-NEXT: s_pack_ll_b32_b16 s0, s1, s0
; GFX9-NEXT: s_and_b32 s0, 0x80008000, s0
; GFX9-NEXT: ; return to shader part epilog
;
; GFX11-LABEL: s_copysign_v2f16_0_v2f64:
; GFX11: ; %bb.0:
-; GFX11-NEXT: s_pack_ll_b32_b16 s0, s1, s3
-; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1)
+; GFX11-NEXT: s_lshr_b32 s0, s3, 16
+; GFX11-NEXT: s_lshr_b32 s1, s1, 16
+; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
+; GFX11-NEXT: s_pack_ll_b32_b16 s0, s1, s0
; GFX11-NEXT: s_and_b32 s0, 0x80008000, s0
; GFX11-NEXT: ; return to shader part epilog
%sign.trunc = fptrunc <2 x double> %sign to <2 x half>
@@ -7258,9 +7261,8 @@ define <2 x half> @v_copysign_v2f16_0_v2bf64(<2 x double> %sign) {
; VI-LABEL: v_copysign_v2f16_0_v2bf64:
; VI: ; %bb.0:
; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_lshlrev_b32_e32 v0, 16, v3
-; VI-NEXT: v_and_b32_e32 v1, 0x8000, v1
-; VI-NEXT: v_or_b32_e32 v0, v1, v0
+; VI-NEXT: s_mov_b32 s4, 0x3020706
+; VI-NEXT: v_perm_b32 v0, v1, v3, s4
; VI-NEXT: s_mov_b32 s4, 0x7fff7fff
; VI-NEXT: v_bfi_b32 v0, s4, 0, v0
; VI-NEXT: s_setpc_b64 s[30:31]
@@ -7268,7 +7270,7 @@ define <2 x half> @v_copysign_v2f16_0_v2bf64(<2 x double> %sign) {
; GFX9-LABEL: v_copysign_v2f16_0_v2bf64:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT: s_mov_b32 s4, 0x5040100
+; GFX9-NEXT: s_mov_b32 s4, 0x7060302
; GFX9-NEXT: v_perm_b32 v0, v3, v1, s4
; GFX9-NEXT: v_and_b32_e32 v0, 0x80008000, v0
; GFX9-NEXT: s_setpc_b64 s[30:31]
@@ -7276,15 +7278,15 @@ define <2 x half> @v_copysign_v2f16_0_v2bf64(<2 x double> %sign) {
; GFX11-TRUE16-LABEL: v_copysign_v2f16_0_v2bf64:
; GFX11-TRUE16: ; %bb.0:
; GFX11-TRUE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-TRUE16-NEXT: v_mov_b16_e32 v1.h, v3.l
+; GFX11-TRUE16-NEXT: v_mov_b16_e32 v3.l, v1.h
; GFX11-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; GFX11-TRUE16-NEXT: v_and_b32_e32 v0, 0x80008000, v1
+; GFX11-TRUE16-NEXT: v_and_b32_e32 v0, 0x80008000, v3
; GFX11-TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11-FAKE16-LABEL: v_copysign_v2f16_0_v2bf64:
; GFX11-FAKE16: ; %bb.0:
; GFX11-FAKE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-FAKE16-NEXT: v_perm_b32 v0, v3, v1, 0x5040100
+; GFX11-FAKE16-NEXT: v_perm_b32 v0, v3, v1, 0x7060302
; GFX11-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
; GFX11-FAKE16-NEXT: v_and_b32_e32 v0, 0x80008000, v0
; GFX11-FAKE16-NEXT: s_setpc_b64 s[30:31]
More information about the llvm-commits
mailing list