1; RUN: llc -march=amdgcn -mcpu=tahiti -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
2; RUN: llc -march=amdgcn -mcpu=hawaii -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
3; RUN: llc -march=amdgcn -mcpu=fiji -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
4; RUN: llc -march=r600 -mcpu=redwood < %s | FileCheck -check-prefix=R600 -check-prefix=FUNC %s
5
6; These tests check that fdiv is expanded correctly and also test that the
7; scheduler is scheduling the RECIP_IEEE and MUL_IEEE instructions in separate
8; instruction groups.
9
10; These test check that fdiv using unsafe_fp_math, coarse fp div, and IEEE754 fp div.
11
12; FUNC-LABEL: {{^}}fdiv_f32:
13; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[2].W
14; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[2].Z, PS
15
16; GCN: v_div_scale_f32 [[NUM_SCALE:v[0-9]+]]
17; GCN-DAG: v_div_scale_f32 [[DEN_SCALE:v[0-9]+]]
18; GCN-DAG: v_rcp_f32_e32 [[NUM_RCP:v[0-9]+]], [[NUM_SCALE]]
19
20; GCN: s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 3
21; GCN: v_fma_f32 [[A:v[0-9]+]], -[[NUM_SCALE]], [[NUM_RCP]], 1.0
22; GCN: v_fma_f32 [[B:v[0-9]+]], [[A]], [[NUM_RCP]], [[NUM_RCP]]
23; GCN: v_mul_f32_e32 [[C:v[0-9]+]], [[B]], [[DEN_SCALE]]
24; GCN: v_fma_f32 [[D:v[0-9]+]], -[[NUM_SCALE]], [[C]], [[DEN_SCALE]]
25; GCN: v_fma_f32 [[E:v[0-9]+]], [[D]], [[B]], [[C]]
26; GCN: v_fma_f32 [[F:v[0-9]+]], -[[NUM_SCALE]], [[E]], [[DEN_SCALE]]
27; GCN: s_setreg_imm32_b32 hwreg(HW_REG_MODE, 4, 2), 0
28; GCN: v_div_fmas_f32 [[FMAS:v[0-9]+]], [[F]], [[B]], [[E]]
29; GCN: v_div_fixup_f32 v{{[0-9]+}}, [[FMAS]],
30define void @fdiv_f32(float addrspace(1)* %out, float %a, float %b) #0 {
31entry:
32  %fdiv = fdiv float %a, %b
33  store float %fdiv, float addrspace(1)* %out
34  ret void
35}
36
37; FUNC-LABEL: {{^}}fdiv_f32_denormals:
38; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[2].W
39; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[2].Z, PS
40
41; GCN: v_div_scale_f32 [[NUM_SCALE:v[0-9]+]]
42; GCN-DAG: v_div_scale_f32 [[DEN_SCALE:v[0-9]+]]
43; GCN-DAG: v_rcp_f32_e32 [[NUM_RCP:v[0-9]+]], [[NUM_SCALE]]
44
45; GCN-NOT: s_setreg
46; GCN: v_fma_f32 [[A:v[0-9]+]], -[[NUM_SCALE]], [[NUM_RCP]], 1.0
47; GCN: v_fma_f32 [[B:v[0-9]+]], [[A]], [[NUM_RCP]], [[NUM_RCP]]
48; GCN: v_mul_f32_e32 [[C:v[0-9]+]], [[B]], [[DEN_SCALE]]
49; GCN: v_fma_f32 [[D:v[0-9]+]], -[[NUM_SCALE]], [[C]], [[DEN_SCALE]]
50; GCN: v_fma_f32 [[E:v[0-9]+]], [[D]], [[B]], [[C]]
51; GCN: v_fma_f32 [[F:v[0-9]+]], -[[NUM_SCALE]], [[E]], [[DEN_SCALE]]
52; GCN-NOT: s_setreg
53; GCN: v_div_fmas_f32 [[FMAS:v[0-9]+]], [[F]], [[B]], [[E]]
54; GCN: v_div_fixup_f32 v{{[0-9]+}}, [[FMAS]],
55define void @fdiv_f32_denormals(float addrspace(1)* %out, float %a, float %b) #2 {
56entry:
57  %fdiv = fdiv float %a, %b
58  store float %fdiv, float addrspace(1)* %out
59  ret void
60}
61
62; FUNC-LABEL: {{^}}fdiv_25ulp_f32:
63; GCN: v_cndmask_b32
64; GCN: v_mul_f32
65; GCN: v_rcp_f32
66; GCN: v_mul_f32
67; GCN: v_mul_f32
68define void @fdiv_25ulp_f32(float addrspace(1)* %out, float %a, float %b) #0 {
69entry:
70  %fdiv = fdiv float %a, %b, !fpmath !0
71  store float %fdiv, float addrspace(1)* %out
72  ret void
73}
74
75; Use correct fdiv
76; FUNC-LABEL: {{^}}fdiv_25ulp_denormals_f32:
77; GCN: v_fma_f32
78; GCN: v_div_fmas_f32
79; GCN: v_div_fixup_f32
80define void @fdiv_25ulp_denormals_f32(float addrspace(1)* %out, float %a, float %b) #2 {
81entry:
82  %fdiv = fdiv float %a, %b, !fpmath !0
83  store float %fdiv, float addrspace(1)* %out
84  ret void
85}
86
87; FUNC-LABEL: {{^}}fdiv_fast_denormals_f32:
88; GCN: v_rcp_f32_e32 [[RCP:v[0-9]+]], s{{[0-9]+}}
89; GCN: v_mul_f32_e32 [[RESULT:v[0-9]+]], s{{[0-9]+}}, [[RCP]]
90; GCN-NOT: [[RESULT]]
91; GCN: buffer_store_dword [[RESULT]]
92define void @fdiv_fast_denormals_f32(float addrspace(1)* %out, float %a, float %b) #2 {
93entry:
94  %fdiv = fdiv fast float %a, %b
95  store float %fdiv, float addrspace(1)* %out
96  ret void
97}
98
99; FUNC-LABEL: {{^}}fdiv_f32_fast_math:
100; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[2].W
101; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[2].Z, PS
102
103; GCN: v_rcp_f32_e32 [[RCP:v[0-9]+]], s{{[0-9]+}}
104; GCN: v_mul_f32_e32 [[RESULT:v[0-9]+]], s{{[0-9]+}}, [[RCP]]
105; GCN-NOT: [[RESULT]]
106; GCN: buffer_store_dword [[RESULT]]
107define void @fdiv_f32_fast_math(float addrspace(1)* %out, float %a, float %b) #0 {
108entry:
109  %fdiv = fdiv fast float %a, %b
110  store float %fdiv, float addrspace(1)* %out
111  ret void
112}
113
114; FUNC-LABEL: {{^}}fdiv_f32_arcp_math:
115; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[2].W
116; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[2].Z, PS
117
118; GCN: v_rcp_f32_e32 [[RCP:v[0-9]+]], s{{[0-9]+}}
119; GCN: v_mul_f32_e32 [[RESULT:v[0-9]+]], s{{[0-9]+}}, [[RCP]]
120; GCN-NOT: [[RESULT]]
121; GCN: buffer_store_dword [[RESULT]]
122define void @fdiv_f32_arcp_math(float addrspace(1)* %out, float %a, float %b) #0 {
123entry:
124  %fdiv = fdiv arcp float %a, %b
125  store float %fdiv, float addrspace(1)* %out
126  ret void
127}
128
129; FUNC-LABEL: {{^}}fdiv_v2f32:
130; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[3].Z
131; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[3].Y
132; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[3].X, PS
133; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[2].W, PS
134
135; GCN: v_div_scale_f32
136; GCN: v_div_scale_f32
137; GCN: v_div_scale_f32
138; GCN: v_div_scale_f32
139define void @fdiv_v2f32(<2 x float> addrspace(1)* %out, <2 x float> %a, <2 x float> %b) #0 {
140entry:
141  %fdiv = fdiv <2 x float> %a, %b
142  store <2 x float> %fdiv, <2 x float> addrspace(1)* %out
143  ret void
144}
145
146; FUNC-LABEL: {{^}}fdiv_ulp25_v2f32:
147; GCN: v_cmp_gt_f32
148; GCN: v_cmp_gt_f32
149define void @fdiv_ulp25_v2f32(<2 x float> addrspace(1)* %out, <2 x float> %a, <2 x float> %b) #0 {
150entry:
151  %fdiv = fdiv arcp <2 x float> %a, %b, !fpmath !0
152  store <2 x float> %fdiv, <2 x float> addrspace(1)* %out
153  ret void
154}
155
156; FUNC-LABEL: {{^}}fdiv_v2f32_fast_math:
157; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[3].Z
158; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[3].Y
159; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[3].X, PS
160; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[2].W, PS
161
162; GCN: v_rcp_f32
163; GCN: v_rcp_f32
164define void @fdiv_v2f32_fast_math(<2 x float> addrspace(1)* %out, <2 x float> %a, <2 x float> %b) #0 {
165entry:
166  %fdiv = fdiv fast <2 x float> %a, %b
167  store <2 x float> %fdiv, <2 x float> addrspace(1)* %out
168  ret void
169}
170
171; FUNC-LABEL: {{^}}fdiv_v2f32_arcp_math:
172; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[3].Z
173; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW]}}, KC0[3].Y
174; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[3].X, PS
175; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW]}}, KC0[2].W, PS
176
177; GCN: v_rcp_f32
178; GCN: v_rcp_f32
179define void @fdiv_v2f32_arcp_math(<2 x float> addrspace(1)* %out, <2 x float> %a, <2 x float> %b) #0 {
180entry:
181  %fdiv = fdiv arcp <2 x float> %a, %b
182  store <2 x float> %fdiv, <2 x float> addrspace(1)* %out
183  ret void
184}
185
186; FUNC-LABEL: {{^}}fdiv_v4f32:
187; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
188; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
189; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
190; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
191; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
192; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
193; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
194; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
195
196; GCN: v_div_fixup_f32
197; GCN: v_div_fixup_f32
198; GCN: v_div_fixup_f32
199; GCN: v_div_fixup_f32
200define void @fdiv_v4f32(<4 x float> addrspace(1)* %out, <4 x float> addrspace(1)* %in) #0 {
201  %b_ptr = getelementptr <4 x float>, <4 x float> addrspace(1)* %in, i32 1
202  %a = load <4 x float>, <4 x float> addrspace(1) * %in
203  %b = load <4 x float>, <4 x float> addrspace(1) * %b_ptr
204  %result = fdiv <4 x float> %a, %b
205  store <4 x float> %result, <4 x float> addrspace(1)* %out
206  ret void
207}
208
209; FUNC-LABEL: {{^}}fdiv_v4f32_fast_math:
210; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
211; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
212; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
213; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
214; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
215; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
216; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
217; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
218
219; GCN: v_rcp_f32
220; GCN: v_rcp_f32
221; GCN: v_rcp_f32
222; GCN: v_rcp_f32
223define void @fdiv_v4f32_fast_math(<4 x float> addrspace(1)* %out, <4 x float> addrspace(1)* %in) #0 {
224  %b_ptr = getelementptr <4 x float>, <4 x float> addrspace(1)* %in, i32 1
225  %a = load <4 x float>, <4 x float> addrspace(1) * %in
226  %b = load <4 x float>, <4 x float> addrspace(1) * %b_ptr
227  %result = fdiv fast <4 x float> %a, %b
228  store <4 x float> %result, <4 x float> addrspace(1)* %out
229  ret void
230}
231
232; FUNC-LABEL: {{^}}fdiv_v4f32_arcp_math:
233; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
234; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
235; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
236; R600-DAG: RECIP_IEEE * T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}
237; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
238; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
239; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
240; R600-DAG: MUL_IEEE {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}}, PS
241
242; GCN: v_rcp_f32
243; GCN: v_rcp_f32
244; GCN: v_rcp_f32
245; GCN: v_rcp_f32
246define void @fdiv_v4f32_arcp_math(<4 x float> addrspace(1)* %out, <4 x float> addrspace(1)* %in) #0 {
247  %b_ptr = getelementptr <4 x float>, <4 x float> addrspace(1)* %in, i32 1
248  %a = load <4 x float>, <4 x float> addrspace(1) * %in
249  %b = load <4 x float>, <4 x float> addrspace(1) * %b_ptr
250  %result = fdiv arcp <4 x float> %a, %b
251  store <4 x float> %result, <4 x float> addrspace(1)* %out
252  ret void
253}
254
255attributes #0 = { nounwind "enable-unsafe-fp-math"="false" "target-features"="-fp32-denormals" }
256attributes #1 = { nounwind "enable-unsafe-fp-math"="true" "target-features"="-fp32-denormals" }
257attributes #2 = { nounwind "enable-unsafe-fp-math"="false" "target-features"="+fp32-denormals" }
258
259!0 = !{float 2.500000e+00}
260