1; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI %s
2; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s
3; RUN: llc -march=amdgcn -mcpu=gfx901 -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s
4
5declare half @llvm.copysign.f16(half, half)
6declare float @llvm.copysign.f32(float, float)
7declare double @llvm.copysign.f64(double, double)
8declare <2 x half> @llvm.copysign.v2f16(<2 x half>, <2 x half>)
9declare <3 x half> @llvm.copysign.v3f16(<3 x half>, <3 x half>)
10declare <4 x half> @llvm.copysign.v4f16(<4 x half>, <4 x half>)
11
12; GCN-LABEL: {{^}}test_copysign_f16:
13; SI: buffer_load_ushort v[[MAG:[0-9]+]]
14; SI: buffer_load_ushort v[[SIGN:[0-9]+]]
15; SI: s_brev_b32 s[[CONST:[0-9]+]], -2
16; SI: v_cvt_f32_f16_e32 v[[MAG_F32:[0-9]+]], v[[MAG]]
17; SI: v_cvt_f32_f16_e32 v[[SIGN_F32:[0-9]+]], v[[SIGN]]
18; SI: v_bfi_b32 v[[OUT_F32:[0-9]+]], s[[CONST]], v[[MAG_F32]], v[[SIGN_F32]]
19; SI: v_cvt_f16_f32_e32 v[[OUT:[0-9]+]], v[[OUT_F32]]
20; VI: buffer_load_ushort v[[SIGN:[0-9]+]]
21; VI: buffer_load_ushort v[[MAG:[0-9]+]]
22; VI: s_movk_i32 s[[CONST:[0-9]+]], 0x7fff
23; VI: v_bfi_b32 v[[OUT:[0-9]+]], s[[CONST]], v[[MAG]], v[[SIGN]]
24; GCN: buffer_store_short v[[OUT]]
25; GCN: s_endpgm
26define void @test_copysign_f16(
27  half addrspace(1)* %arg_out,
28  half addrspace(1)* %arg_mag,
29  half addrspace(1)* %arg_sign) {
30entry:
31  %mag = load half, half addrspace(1)* %arg_mag
32  %sign = load half, half addrspace(1)* %arg_sign
33  %out = call half @llvm.copysign.f16(half %mag, half %sign)
34  store half %out, half addrspace(1)* %arg_out
35  ret void
36}
37
38; GCN-LABEL: {{^}}test_copysign_out_f32_mag_f16_sign_f32:
39; GCN-DAG: buffer_load_ushort v[[MAG:[0-9]+]]
40; GCN-DAG: buffer_load_dword v[[SIGN:[0-9]+]]
41; GCN-DAG: s_brev_b32 s[[CONST:[0-9]+]], -2
42; GCN-DAG: v_cvt_f32_f16_e32 v[[MAG_EXT:[0-9]+]], v[[MAG]]
43; GCN: v_bfi_b32 v[[OUT:[0-9]+]], s[[CONST]], v[[MAG_EXT]], v[[SIGN]]
44; GCN: buffer_store_dword v[[OUT]]
45; GCN: s_endpgm
46define void @test_copysign_out_f32_mag_f16_sign_f32(
47  float addrspace(1)* %arg_out,
48  half addrspace(1)* %arg_mag,
49  float addrspace(1)* %arg_sign) {
50entry:
51  %mag = load half, half addrspace(1)* %arg_mag
52  %mag.ext = fpext half %mag to float
53  %sign = load float, float addrspace(1)* %arg_sign
54  %out = call float @llvm.copysign.f32(float %mag.ext, float %sign)
55  store float %out, float addrspace(1)* %arg_out
56  ret void
57}
58
59; GCN-LABEL: {{^}}test_copysign_out_f64_mag_f16_sign_f64:
60; GCN-DAG: buffer_load_ushort v[[MAG:[0-9]+]]
61; GCN-DAG: buffer_load_dwordx2 v{{\[}}[[SIGN_LO:[0-9]+]]:[[SIGN_HI:[0-9]+]]{{\]}}
62; GCN-DAG: s_brev_b32 s[[CONST:[0-9]+]], -2
63; GCN-DAG: v_cvt_f32_f16_e32 v[[MAG_EXT:[0-9]+]], v[[MAG]]
64; GCN-DAG: v_cvt_f64_f32_e32 v{{\[}}[[MAG_EXT_LO:[0-9]+]]:[[MAG_EXT_HI:[0-9]+]]{{\]}}, v[[MAG_EXT]]
65; GCN: v_bfi_b32 v[[OUT_HI:[0-9]+]], s[[CONST]], v[[MAG_EXT_HI]], v[[SIGN_HI]]
66; GCN: buffer_store_dwordx2 v{{\[}}[[MAG_EXT_LO]]:[[OUT_HI]]{{\]}}
67; GCN: s_endpgm
68define void @test_copysign_out_f64_mag_f16_sign_f64(
69  double addrspace(1)* %arg_out,
70  half addrspace(1)* %arg_mag,
71  double addrspace(1)* %arg_sign) {
72entry:
73  %mag = load half, half addrspace(1)* %arg_mag
74  %mag.ext = fpext half %mag to double
75  %sign = load double, double addrspace(1)* %arg_sign
76  %out = call double @llvm.copysign.f64(double %mag.ext, double %sign)
77  store double %out, double addrspace(1)* %arg_out
78  ret void
79}
80
81; GCN-LABEL: {{^}}test_copysign_out_f32_mag_f32_sign_f16:
82; GCN-DAG: buffer_load_dword v[[MAG:[0-9]+]]
83; GCN-DAG: buffer_load_ushort v[[SIGN:[0-9]+]]
84; GCN-DAG: s_brev_b32 s[[CONST:[0-9]+]], -2
85; SI-DAG: v_cvt_f32_f16_e32 v[[SIGN_F32:[0-9]+]], v[[SIGN]]
86; SI: v_bfi_b32 v[[OUT:[0-9]+]], s[[CONST]], v[[MAG]], v[[SIGN_F32]]
87; VI-DAG: v_lshlrev_b32_e32 v[[SIGN_SHIFT:[0-9]+]], 16, v[[SIGN]]
88; VI: v_bfi_b32 v[[OUT:[0-9]+]], s[[CONST]], v[[MAG]], v[[SIGN_SHIFT]]
89; GCN: buffer_store_dword v[[OUT]]
90; GCN: s_endpgm
91define void @test_copysign_out_f32_mag_f32_sign_f16(
92  float addrspace(1)* %arg_out,
93  float addrspace(1)* %arg_mag,
94  half addrspace(1)* %arg_sign) {
95entry:
96  %mag = load float, float addrspace(1)* %arg_mag
97  %sign = load half, half addrspace(1)* %arg_sign
98  %sign.ext = fpext half %sign to float
99  %out = call float @llvm.copysign.f32(float %mag, float %sign.ext)
100  store float %out, float addrspace(1)* %arg_out
101  ret void
102}
103
104; GCN-LABEL: {{^}}test_copysign_out_f64_mag_f64_sign_f16:
105; GCN-DAG: buffer_load_dwordx2 v{{\[}}[[MAG_LO:[0-9]+]]:[[MAG_HI:[0-9]+]]{{\]}}
106; GCN-DAG: buffer_load_ushort v[[SIGN:[0-9]+]]
107; GCN-DAG: s_brev_b32 s[[CONST:[0-9]+]], -2
108; SI-DAG: v_cvt_f32_f16_e32 v[[SIGN_F32:[0-9]+]], v[[SIGN]]
109; SI: v_bfi_b32 v[[OUT_HI:[0-9]+]], s[[CONST]], v[[MAG_HI]], v[[SIGN_F32]]
110; VI-DAG: v_lshlrev_b32_e32 v[[SIGN_SHIFT:[0-9]+]], 16, v[[SIGN]]
111; VI: v_bfi_b32 v[[OUT_HI:[0-9]+]], s[[CONST]], v[[MAG_HI]], v[[SIGN_SHIFT]]
112; GCN: buffer_store_dwordx2 v{{\[}}[[MAG_LO]]:[[OUT_HI]]{{\]}}
113; GCN: s_endpgm
114define void @test_copysign_out_f64_mag_f64_sign_f16(
115  double addrspace(1)* %arg_out,
116  double addrspace(1)* %arg_mag,
117  half addrspace(1)* %arg_sign) {
118entry:
119  %mag = load double, double addrspace(1)* %arg_mag
120  %sign = load half, half addrspace(1)* %arg_sign
121  %sign.ext = fpext half %sign to double
122  %out = call double @llvm.copysign.f64(double %mag, double %sign.ext)
123  store double %out, double addrspace(1)* %arg_out
124  ret void
125}
126
127; GCN-LABEL: {{^}}test_copysign_out_f16_mag_f16_sign_f32:
128; GCN-DAG: buffer_load_ushort v[[MAG:[0-9]+]]
129; GCN-DAG: buffer_load_dword v[[SIGN:[0-9]+]]
130; SI-DAG: s_brev_b32 s[[CONST:[0-9]+]], -2
131; SI-DAG: v_cvt_f32_f16_e32 v[[MAG_F32:[0-9]+]], v[[MAG]]
132; SI: v_bfi_b32 v[[OUT_F32:[0-9]+]], s[[CONST]], v[[MAG_F32]], v[[SIGN]]
133; SI: v_cvt_f16_f32_e32 v[[OUT:[0-9]+]], v[[OUT_F32]]
134; VI-DAG: s_movk_i32 s[[CONST:[0-9]+]], 0x7fff
135; VI-DAG: v_lshrrev_b32_e32 v[[SIGN_SHIFT:[0-9]+]], 16, v[[SIGN]]
136; VI: v_bfi_b32 v[[OUT:[0-9]+]], s[[CONST]], v[[MAG]], v[[SIGN_SHIFT]]
137; GCN: buffer_store_short v[[OUT]]
138; GCN: s_endpgm
139define void @test_copysign_out_f16_mag_f16_sign_f32(
140  half addrspace(1)* %arg_out,
141  half addrspace(1)* %arg_mag,
142  float addrspace(1)* %arg_sign) {
143entry:
144  %mag = load half, half addrspace(1)* %arg_mag
145  %sign = load float, float addrspace(1)* %arg_sign
146  %sign.trunc = fptrunc float %sign to half
147  %out = call half @llvm.copysign.f16(half %mag, half %sign.trunc)
148  store half %out, half addrspace(1)* %arg_out
149  ret void
150}
151
152; GCN-LABEL: {{^}}test_copysign_out_f16_mag_f16_sign_f64:
153; GCN-DAG: buffer_load_ushort v[[MAG:[0-9]+]]
154; GCN-DAG: buffer_load_dwordx2 v{{\[}}[[SIGN_LO:[0-9]+]]:[[SIGN_HI:[0-9]+]]{{\]}}
155; SI-DAG: s_brev_b32 s[[CONST:[0-9]+]], -2
156; SI-DAG: v_cvt_f32_f16_e32 v[[MAG_F32:[0-9]+]], v[[MAG]]
157; SI: v_bfi_b32 v[[OUT_F32:[0-9]+]], s[[CONST]], v[[MAG_F32]], v[[SIGN_HI]]
158; SI: v_cvt_f16_f32_e32 v[[OUT:[0-9]+]], v[[OUT_F32]]
159; VI-DAG: s_movk_i32 s[[CONST:[0-9]+]], 0x7fff
160; VI-DAG: v_lshrrev_b32_e32 v[[SIGN_SHIFT:[0-9]+]], 16, v[[SIGN_HI]]
161; VI: v_bfi_b32 v[[OUT:[0-9]+]], s[[CONST]], v[[MAG]], v[[SIGN_SHIFT]]
162; GCN: buffer_store_short v[[OUT]]
163; GCN: s_endpgm
164define void @test_copysign_out_f16_mag_f16_sign_f64(
165  half addrspace(1)* %arg_out,
166  half addrspace(1)* %arg_mag,
167  double addrspace(1)* %arg_sign) {
168entry:
169  %mag = load half, half addrspace(1)* %arg_mag
170  %sign = load double, double addrspace(1)* %arg_sign
171  %sign.trunc = fptrunc double %sign to half
172  %out = call half @llvm.copysign.f16(half %mag, half %sign.trunc)
173  store half %out, half addrspace(1)* %arg_out
174  ret void
175}
176
177; GCN-LABEL: {{^}}test_copysign_out_f16_mag_f32_sign_f16:
178; GCN-DAG: buffer_load_dword v[[MAG:[0-9]+]]
179; GCN-DAG: buffer_load_ushort v[[SIGN:[0-9]+]]
180; SI-DAG: s_brev_b32 s[[CONST:[0-9]+]], -2
181; SI-DAG: v_cvt_f16_f32_e32 v[[MAG_TRUNC:[0-9]+]], v[[MAG]]
182; SI-DAG: v_cvt_f32_f16_e32 v[[SIGN_F32:[0-9]+]], v[[SIGN]]
183; SI-DAG: v_cvt_f32_f16_e32 v[[MAG_F32:[0-9]+]], v[[MAG_TRUNC]]
184; SI: v_bfi_b32 v[[OUT_F32:[0-9]+]], s[[CONST]], v[[MAG_F32]], v[[SIGN_F32]]
185; SI: v_cvt_f16_f32_e32 v[[OUT:[0-9]+]], v[[OUT_F32]]
186; VI-DAG: s_movk_i32 s[[CONST:[0-9]+]], 0x7fff
187; VI-DAG: v_cvt_f16_f32_e32 v[[MAG_TRUNC:[0-9]+]], v[[MAG]]
188; VI: v_bfi_b32 v[[OUT:[0-9]+]], s[[CONST]], v[[MAG_TRUNC]], v[[SIGN]]
189; GCN: buffer_store_short v[[OUT]]
190; GCN: s_endpgm
191define void @test_copysign_out_f16_mag_f32_sign_f16(
192  half addrspace(1)* %arg_out,
193  float addrspace(1)* %arg_mag,
194  half addrspace(1)* %arg_sign) {
195entry:
196  %mag = load float, float addrspace(1)* %arg_mag
197  %mag.trunc = fptrunc float %mag to half
198  %sign = load half, half addrspace(1)* %arg_sign
199  %out = call half @llvm.copysign.f16(half %mag.trunc, half %sign)
200  store half %out, half addrspace(1)* %arg_out
201  ret void
202}
203
204; GCN-LABEL: {{^}}test_copysign_out_f16_mag_f64_sign_f16:
205; GCN: v_bfi_b32
206; GCN: s_endpgm
207define void @test_copysign_out_f16_mag_f64_sign_f16(
208  half addrspace(1)* %arg_out,
209  double addrspace(1)* %arg_mag,
210  half addrspace(1)* %arg_sign) {
211entry:
212  %mag = load double, double addrspace(1)* %arg_mag
213  %mag.trunc = fptrunc double %mag to half
214  %sign = load half, half addrspace(1)* %arg_sign
215  %out = call half @llvm.copysign.f16(half %mag.trunc, half %sign)
216  store half %out, half addrspace(1)* %arg_out
217  ret void
218}
219
220; GCN-LABEL: {{^}}test_copysign_v2f16:
221; GCN: v_bfi_b32
222; GCN: v_bfi_b32
223; GCN: s_endpgm
224define void @test_copysign_v2f16(
225  <2 x half> addrspace(1)* %arg_out,
226  <2 x half> %arg_mag,
227  <2 x half> %arg_sign) {
228entry:
229  %out = call <2 x half> @llvm.copysign.v2f16(<2 x half> %arg_mag, <2 x half> %arg_sign)
230  store <2 x half> %out, <2 x half> addrspace(1)* %arg_out
231  ret void
232}
233
234; GCN-LABEL: {{^}}test_copysign_v3f16:
235; GCN: v_bfi_b32
236; GCN: v_bfi_b32
237; GCN: v_bfi_b32
238; GCN: s_endpgm
239define void @test_copysign_v3f16(
240  <3 x half> addrspace(1)* %arg_out,
241  <3 x half> %arg_mag,
242  <3 x half> %arg_sign) {
243entry:
244  %out = call <3 x half> @llvm.copysign.v3f16(<3 x half> %arg_mag, <3 x half> %arg_sign)
245  store <3 x half> %out, <3 x half> addrspace(1)* %arg_out
246  ret void
247}
248
249; GCN-LABEL: {{^}}test_copysign_v4f16:
250; GCN: v_bfi_b32
251; GCN: v_bfi_b32
252; GCN: v_bfi_b32
253; GCN: v_bfi_b32
254; GCN: s_endpgm
255define void @test_copysign_v4f16(
256  <4 x half> addrspace(1)* %arg_out,
257  <4 x half> %arg_mag,
258  <4 x half> %arg_sign) {
259entry:
260  %out = call <4 x half> @llvm.copysign.v4f16(<4 x half> %arg_mag, <4 x half> %arg_sign)
261  store <4 x half> %out, <4 x half> addrspace(1)* %arg_out
262  ret void
263}
264