1; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI -check-prefix=SIVI %s
2; RUN: llc -march=amdgcn -mcpu=fiji -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=GFX89 -check-prefix=VI -check-prefix=SIVI %s
3; RUN: llc -march=amdgcn -mcpu=gfx901 -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=GFX89 -check-prefix=GFX9 %s
4
5; GCN-LABEL: {{^}}fsub_f16:
6; GCN: buffer_load_ushort v[[A_F16:[0-9]+]]
7; GCN: buffer_load_ushort v[[B_F16:[0-9]+]]
8; SI:  v_cvt_f32_f16_e32 v[[A_F32:[0-9]+]], v[[A_F16]]
9; SI:  v_cvt_f32_f16_e32 v[[B_F32:[0-9]+]], v[[B_F16]]
10; SI:  v_subrev_f32_e32 v[[R_F32:[0-9]+]], v[[B_F32]], v[[A_F32]]
11; SI:  v_cvt_f16_f32_e32 v[[R_F16:[0-9]+]], v[[R_F32]]
12; GFX89:  v_subrev_f16_e32 v[[R_F16:[0-9]+]], v[[B_F16]], v[[A_F16]]
13; GCN: buffer_store_short v[[R_F16]]
14; GCN: s_endpgm
15define void @fsub_f16(
16    half addrspace(1)* %r,
17    half addrspace(1)* %a,
18    half addrspace(1)* %b) {
19entry:
20  %a.val = load half, half addrspace(1)* %a
21  %b.val = load half, half addrspace(1)* %b
22  %r.val = fsub half %a.val, %b.val
23  store half %r.val, half addrspace(1)* %r
24  ret void
25}
26
27; GCN-LABEL: {{^}}fsub_f16_imm_a:
28; GCN: buffer_load_ushort v[[B_F16:[0-9]+]]
29; SI:  v_cvt_f32_f16_e32 v[[B_F32:[0-9]+]], v[[B_F16]]
30; SI:  v_sub_f32_e32 v[[R_F32:[0-9]+]], 1.0, v[[B_F32]]
31; SI:  v_cvt_f16_f32_e32 v[[R_F16:[0-9]+]], v[[R_F32]]
32; GFX89:  v_sub_f16_e32 v[[R_F16:[0-9]+]], 1.0, v[[B_F16]]
33; GCN: buffer_store_short v[[R_F16]]
34; GCN: s_endpgm
35define void @fsub_f16_imm_a(
36    half addrspace(1)* %r,
37    half addrspace(1)* %b) {
38entry:
39  %b.val = load half, half addrspace(1)* %b
40  %r.val = fsub half 1.0, %b.val
41  store half %r.val, half addrspace(1)* %r
42  ret void
43}
44
45; GCN-LABEL: {{^}}fsub_f16_imm_b:
46; GCN: buffer_load_ushort v[[A_F16:[0-9]+]]
47; SI:  v_cvt_f32_f16_e32 v[[A_F32:[0-9]+]], v[[A_F16]]
48; SI:  v_add_f32_e32 v[[R_F32:[0-9]+]], -2.0, v[[A_F32]]
49; SI:  v_cvt_f16_f32_e32 v[[R_F16:[0-9]+]], v[[R_F32]]
50; GFX89:  v_add_f16_e32 v[[R_F16:[0-9]+]], -2.0, v[[A_F16]]
51; GCN: buffer_store_short v[[R_F16]]
52; GCN: s_endpgm
53define void @fsub_f16_imm_b(
54    half addrspace(1)* %r,
55    half addrspace(1)* %a) {
56entry:
57  %a.val = load half, half addrspace(1)* %a
58  %r.val = fsub half %a.val, 2.0
59  store half %r.val, half addrspace(1)* %r
60  ret void
61}
62
63; GCN-LABEL: {{^}}fsub_v2f16:
64; GCN: buffer_load_dword v[[A_V2_F16:[0-9]+]]
65; GCN: buffer_load_dword v[[B_V2_F16:[0-9]+]]
66; SIVI-DAG: v_lshrrev_b32_e32 v[[A_F16_1:[0-9]+]], 16, v[[A_V2_F16]]
67; SIVI-DAG: v_lshrrev_b32_e32 v[[B_F16_1:[0-9]+]], 16, v[[B_V2_F16]]
68
69; SI:  v_cvt_f32_f16_e32 v[[A_F32_0:[0-9]+]], v[[A_V2_F16]]
70; SI:  v_cvt_f32_f16_e32 v[[B_F32_0:[0-9]+]], v[[B_V2_F16]]
71; SI:  v_cvt_f32_f16_e32 v[[A_F32_1:[0-9]+]], v[[A_F16_1]]
72; SI:  v_cvt_f32_f16_e32 v[[B_F32_1:[0-9]+]], v[[B_F16_1]]
73; SI:  v_subrev_f32_e32 v[[R_F32_0:[0-9]+]], v[[B_F32_0]], v[[A_F32_0]]
74; SI:  v_cvt_f16_f32_e32 v[[R_F16_0:[0-9]+]], v[[R_F32_0]]
75; SI:  v_subrev_f32_e32 v[[R_F32_1:[0-9]+]], v[[B_F32_1]], v[[A_F32_1]]
76; SI:  v_cvt_f16_f32_e32 v[[R_F16_1:[0-9]+]], v[[R_F32_1]]
77
78; VI-DAG: v_subrev_f16_e32 v[[R_F16_0:[0-9]+]], v[[B_V2_F16]], v[[A_V2_F16]]
79; VI: v_subrev_f16_e32 v[[R_F16_1:[0-9]+]], v[[B_F16_1]], v[[A_F16_1]]
80
81; SIVI: v_and_b32_e32 v[[R_F16_LO:[0-9]+]], 0xffff, v[[R_F16_0]]
82; SIVI: v_lshlrev_b32_e32 v[[R_F16_HI:[0-9]+]], 16, v[[R_F16_1]]
83; SIVI: v_or_b32_e32 v[[R_V2_F16:[0-9]+]], v[[R_F16_HI]], v[[R_F16_LO]]
84
85; GFX9: v_pk_add_f16 v[[R_V2_F16:[0-9]+]], v[[A_V2_F16]], v[[B_V2_F16]] neg_lo:[0,1] neg_hi:[0,1]
86
87; GCN: buffer_store_dword v[[R_V2_F16]]
88; GCN: s_endpgm
89define void @fsub_v2f16(
90    <2 x half> addrspace(1)* %r,
91    <2 x half> addrspace(1)* %a,
92    <2 x half> addrspace(1)* %b) {
93entry:
94  %a.val = load <2 x half>, <2 x half> addrspace(1)* %a
95  %b.val = load <2 x half>, <2 x half> addrspace(1)* %b
96  %r.val = fsub <2 x half> %a.val, %b.val
97  store <2 x half> %r.val, <2 x half> addrspace(1)* %r
98  ret void
99}
100
101; GCN-LABEL: {{^}}fsub_v2f16_imm_a:
102; GCN: buffer_load_dword v[[B_V2_F16:[0-9]+]]
103; SI:  v_cvt_f32_f16_e32 v[[B_F32_0:[0-9]+]], v[[B_V2_F16]]
104; SIVI: v_lshrrev_b32_e32 v[[B_F16_1:[0-9]+]], 16, v[[B_V2_F16]]
105
106; SI:  v_cvt_f32_f16_e32 v[[B_F32_1:[0-9]+]], v[[B_F16_1]]
107; SI:  v_sub_f32_e32 v[[R_F32_0:[0-9]+]], 1.0, v[[B_F32_0]]
108; SI:  v_cvt_f16_f32_e32 v[[R_F16_0:[0-9]+]], v[[R_F32_0]]
109; SI:  v_sub_f32_e32 v[[R_F32_1:[0-9]+]], 2.0, v[[B_F32_1]]
110; SI:  v_cvt_f16_f32_e32 v[[R_F16_1:[0-9]+]], v[[R_F32_1]]
111
112; VI:  v_sub_f16_e32 v[[R_F16_0:[0-9]+]], 1.0, v[[B_V2_F16]]
113; VI:  v_sub_f16_e32 v[[R_F16_1:[0-9]+]], 2.0, v[[B_F16_1]]
114
115; SIVI: v_and_b32_e32 v[[R_F16_LO:[0-9]+]], 0xffff, v[[R_F16_0]]
116; SIVI: v_lshlrev_b32_e32 v[[R_F16_HI:[0-9]+]], 16, v[[R_F16_1]]
117; SIVI: v_or_b32_e32 v[[R_V2_F16:[0-9]+]], v[[R_F16_HI]], v[[R_F16_LO]]
118
119; GFX9: s_mov_b32 [[K:s[0-9]+]], 0x40003c00
120; GFX9: v_pk_add_f16 v[[R_V2_F16:[0-9]+]], [[K]], v[[B_V2_F16]] neg_lo:[0,1] neg_hi:[0,1]
121
122; GCN: buffer_store_dword v[[R_V2_F16]]
123; GCN: s_endpgm
124define void @fsub_v2f16_imm_a(
125    <2 x half> addrspace(1)* %r,
126    <2 x half> addrspace(1)* %b) {
127entry:
128  %b.val = load <2 x half>, <2 x half> addrspace(1)* %b
129  %r.val = fsub <2 x half> <half 1.0, half 2.0>, %b.val
130  store <2 x half> %r.val, <2 x half> addrspace(1)* %r
131  ret void
132}
133
134; GCN-LABEL: {{^}}fsub_v2f16_imm_b:
135; GCN: buffer_load_dword v[[A_V2_F16:[0-9]+]]
136; SI:  v_cvt_f32_f16_e32 v[[A_F32_0:[0-9]+]], v[[A_V2_F16]]
137; SIVI: v_lshrrev_b32_e32 v[[A_F16_1:[0-9]+]], 16, v[[A_V2_F16]]
138
139; SI:  v_cvt_f32_f16_e32 v[[A_F32_1:[0-9]+]], v[[A_F16_1]]
140; SI:  v_add_f32_e32 v[[R_F32_0:[0-9]+]], -2.0, v[[A_F32_0]]
141; SI:  v_cvt_f16_f32_e32 v[[R_F16_0:[0-9]+]], v[[R_F32_0]]
142; SI:  v_add_f32_e32 v[[R_F32_1:[0-9]+]], -1.0, v[[A_F32_1]]
143; SI:  v_cvt_f16_f32_e32 v[[R_F16_1:[0-9]+]], v[[R_F32_1]]
144; VI:  v_add_f16_e32 v[[R_F16_0:[0-9]+]], -2.0, v[[A_V2_F16]]
145; VI:  v_add_f16_e32 v[[R_F16_1:[0-9]+]], -1.0, v[[A_F16_1]]
146
147; SIVI: v_and_b32_e32 v[[R_F16_LO:[0-9]+]], 0xffff, v[[R_F16_0]]
148; SIVI: v_lshlrev_b32_e32 v[[R_F16_HI:[0-9]+]], 16, v[[R_F16_1]]
149; SIVI: v_or_b32_e32 v[[R_V2_F16:[0-9]+]], v[[R_F16_HI]], v[[R_F16_LO]]
150
151; GFX9: s_mov_b32 [[K:s[0-9]+]], 0xbc00c000
152; GFX9: v_pk_add_f16 v[[R_V2_F16:[0-9]+]], [[K]], v[[A_V2_F16]]{{$}}
153
154; GCN: buffer_store_dword v[[R_V2_F16]]
155; GCN: s_endpgm
156define void @fsub_v2f16_imm_b(
157    <2 x half> addrspace(1)* %r,
158    <2 x half> addrspace(1)* %a) {
159entry:
160  %a.val = load <2 x half>, <2 x half> addrspace(1)* %a
161  %r.val = fsub <2 x half> %a.val, <half 2.0, half 1.0>
162  store <2 x half> %r.val, <2 x half> addrspace(1)* %r
163  ret void
164}
165