xref: /llvm-project/llvm/test/Transforms/InstCombine/AMDGPU/rcp-contract-rsq.ll (revision 61c8af67924b02c8f2cf871439c24650a0207f29)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=instcombine -S < %s | FileCheck %s
3
4declare half @llvm.amdgcn.sqrt.f16(half)
5declare float @llvm.amdgcn.sqrt.f32(float)
6declare double @llvm.amdgcn.sqrt.f64(double)
7
8declare half @llvm.amdgcn.rcp.f16(half)
9declare float @llvm.amdgcn.rcp.f32(float)
10declare double @llvm.amdgcn.rcp.f64(double)
11
12declare half @llvm.amdgcn.rsq.f16(half)
13declare float @llvm.amdgcn.rsq.f32(float)
14declare double @llvm.amdgcn.rsq.f64(double)
15
16
17declare half @llvm.sqrt.f16(half)
18declare float @llvm.sqrt.f32(float)
19declare double @llvm.sqrt.f64(double)
20
21; Should allow precision increasing contraction to rsq call
22define float @amdgcn_rcp_amdgcn_sqrt_f32_contract(float %x) {
23; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_contract
24; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1:[0-9]+]] {
25; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]])
26; CHECK-NEXT:    ret float [[RSQ]]
27;
28  %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x)
29  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
30  ret float %rsq
31}
32
33; contract required on both calls
34define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract0(float %x) {
35; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract0
36; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
37; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.amdgcn.sqrt.f32(float [[X]])
38; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
39; CHECK-NEXT:    ret float [[RSQ]]
40;
41  %sqrt = call float @llvm.amdgcn.sqrt.f32(float %x)
42  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
43  ret float %rsq
44}
45
46; contract required on both calls
47define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract1(float %x) {
48; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract1
49; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
50; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.amdgcn.sqrt.f32(float [[X]])
51; CHECK-NEXT:    [[RSQ:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT]])
52; CHECK-NEXT:    ret float [[RSQ]]
53;
54  %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x)
55  %rsq = call float @llvm.amdgcn.rcp.f32(float %sqrt)
56  ret float %rsq
57}
58
59; Reject from multiple uses of sqrt
60define float @amdgcn_rcp_amdgcn_sqrt_f32_contract_multi_use(float %x, ptr %ptr) {
61; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_contract_multi_use
62; CHECK-SAME: (float [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] {
63; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.amdgcn.sqrt.f32(float [[X]])
64; CHECK-NEXT:    store float [[SQRT]], ptr [[PTR]], align 4
65; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
66; CHECK-NEXT:    ret float [[RSQ]]
67;
68  %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x)
69  store float %sqrt, ptr %ptr
70  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
71  ret float %rsq
72}
73
74; Test flags are or'd together
75define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract(float %x) {
76; CHECK-LABEL: define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract
77; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
78; CHECK-NEXT:    [[RSQ:%.*]] = call nnan ninf contract float @llvm.amdgcn.rsq.f32(float [[X]])
79; CHECK-NEXT:    ret float [[RSQ]]
80;
81  %sqrt = call nnan contract float @llvm.amdgcn.sqrt.f32(float %x)
82  %rsq = call ninf contract float @llvm.amdgcn.rcp.f32(float %sqrt)
83  ret float %rsq
84}
85
86; Should allow precision increasing contraction to rsq call
87define half @amdgcn_rcp_amdgcn_sqrt_f16_contract(half %x) {
88; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_contract
89; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
90; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rsq.f16(half [[X]])
91; CHECK-NEXT:    ret half [[RSQ]]
92;
93  %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x)
94  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
95  ret half %rsq
96}
97
98; contract required on both calls
99define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0(half %x) {
100; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0
101; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
102; CHECK-NEXT:    [[SQRT:%.*]] = call half @llvm.sqrt.f16(half [[X]])
103; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]])
104; CHECK-NEXT:    ret half [[RSQ]]
105;
106  %sqrt = call half @llvm.amdgcn.sqrt.f16(half %x)
107  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
108  ret half %rsq
109}
110
111; contract required on both calls
112define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1(half %x) {
113; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1
114; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
115; CHECK-NEXT:    [[SQRT:%.*]] = call contract half @llvm.sqrt.f16(half [[X]])
116; CHECK-NEXT:    [[RSQ:%.*]] = call half @llvm.amdgcn.rcp.f16(half [[SQRT]])
117; CHECK-NEXT:    ret half [[RSQ]]
118;
119  %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x)
120  %rsq = call half @llvm.amdgcn.rcp.f16(half %sqrt)
121  ret half %rsq
122}
123
124; Reject from multiple uses of sqrt
125define half @amdgcn_rcp_amdgcn_sqrt_f16_contract_multi_use(half %x, ptr %ptr) {
126; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_contract_multi_use
127; CHECK-SAME: (half [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] {
128; CHECK-NEXT:    [[SQRT:%.*]] = call contract half @llvm.sqrt.f16(half [[X]])
129; CHECK-NEXT:    store half [[SQRT]], ptr [[PTR]], align 2
130; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]])
131; CHECK-NEXT:    ret half [[RSQ]]
132;
133  %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x)
134  store half %sqrt, ptr %ptr
135  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
136  ret half %rsq
137}
138
139; Test flags are or'd together
140define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract(half %x) {
141; CHECK-LABEL: define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract
142; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
143; CHECK-NEXT:    [[RSQ:%.*]] = call nnan ninf contract half @llvm.amdgcn.rsq.f16(half [[X]])
144; CHECK-NEXT:    ret half [[RSQ]]
145;
146  %sqrt = call nnan contract half @llvm.amdgcn.sqrt.f16(half %x)
147  %rsq = call ninf contract half @llvm.amdgcn.rcp.f16(half %sqrt)
148  ret half %rsq
149}
150
151; Should allow precision increasing contraction to rsq call
152define double @amdgcn_rcp_amdgcn_sqrt_f64_contract(double %x) {
153; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_contract
154; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
155; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rsq.f64(double [[X]])
156; CHECK-NEXT:    ret double [[RSQ]]
157;
158  %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x)
159  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
160  ret double %rsq
161}
162
163; contract required on both calls
164define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0(double %x) {
165; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0
166; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
167; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.amdgcn.sqrt.f64(double [[X]])
168; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
169; CHECK-NEXT:    ret double [[RSQ]]
170;
171  %sqrt = call double @llvm.amdgcn.sqrt.f64(double %x)
172  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
173  ret double %rsq
174}
175
176; contract required on both calls
177define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1(double %x) {
178; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1
179; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
180; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.amdgcn.sqrt.f64(double [[X]])
181; CHECK-NEXT:    [[RSQ:%.*]] = call double @llvm.amdgcn.rcp.f64(double [[SQRT]])
182; CHECK-NEXT:    ret double [[RSQ]]
183;
184  %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x)
185  %rsq = call double @llvm.amdgcn.rcp.f64(double %sqrt)
186  ret double %rsq
187}
188
189; Reject from multiple uses of sqrt
190define double @amdgcn_rcp_amdgcn_sqrt_f64_contract_multi_use(double %x, ptr %ptr) {
191; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_contract_multi_use
192; CHECK-SAME: (double [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] {
193; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.amdgcn.sqrt.f64(double [[X]])
194; CHECK-NEXT:    store double [[SQRT]], ptr [[PTR]], align 8
195; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
196; CHECK-NEXT:    ret double [[RSQ]]
197;
198  %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x)
199  store double %sqrt, ptr %ptr
200  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
201  ret double %rsq
202}
203
204; Test flags are or'd together
205define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract(double %x) {
206; CHECK-LABEL: define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract
207; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
208; CHECK-NEXT:    [[RSQ:%.*]] = call nnan ninf contract double @llvm.amdgcn.rsq.f64(double [[X]])
209; CHECK-NEXT:    ret double [[RSQ]]
210;
211  %sqrt = call nnan contract double @llvm.amdgcn.sqrt.f64(double %x)
212  %rsq = call ninf contract double @llvm.amdgcn.rcp.f64(double %sqrt)
213  ret double %rsq
214}
215
216; Do not contract with regular sqrt
217define float @amdgcn_rcp_sqrt_f32_contract(float %x) {
218; CHECK-LABEL: define float @amdgcn_rcp_sqrt_f32_contract
219; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
220; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]])
221; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
222; CHECK-NEXT:    ret float [[RSQ]]
223;
224  %sqrt = call contract float @llvm.sqrt.f32(float %x)
225  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
226  ret float %rsq
227}
228
229; Do contract with regular sqrt for f16
230define half @amdgcn_rcp_sqrt_f16_contract(half %x) {
231; CHECK-LABEL: define half @amdgcn_rcp_sqrt_f16_contract
232; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
233; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rsq.f16(half [[X]])
234; CHECK-NEXT:    ret half [[RSQ]]
235;
236  %sqrt = call contract half @llvm.sqrt.f16(half %x)
237  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
238  ret half %rsq
239}
240
241; Do not contract with regular sqrt
242define double @amdgcn_rcp_sqrt_f64_contract(double %x) {
243; CHECK-LABEL: define double @amdgcn_rcp_sqrt_f64_contract
244; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
245; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]])
246; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
247; CHECK-NEXT:    ret double [[RSQ]]
248;
249  %sqrt = call contract double @llvm.sqrt.f64(double %x)
250  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
251  ret double %rsq
252}
253
254define float @amdgcn_rcp_afn_sqrt_f32_contract(float %x) {
255; CHECK-LABEL: define float @amdgcn_rcp_afn_sqrt_f32_contract
256; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
257; CHECK-NEXT:    [[RSQ:%.*]] = call contract afn float @llvm.amdgcn.rsq.f32(float [[X]])
258; CHECK-NEXT:    ret float [[RSQ]]
259;
260  %sqrt = call afn contract float @llvm.sqrt.f32(float %x)
261  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
262  ret float %rsq
263}
264
265define float @amdgcn_rcp_fpmath3_sqrt_f32_contract(float %x) {
266; CHECK-LABEL: define float @amdgcn_rcp_fpmath3_sqrt_f32_contract
267; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
268; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]])
269; CHECK-NEXT:    ret float [[RSQ]]
270;
271  %sqrt = call contract float @llvm.sqrt.f32(float %x), !fpmath !0
272  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
273  ret float %rsq
274}
275
276define float @amdgcn_rcp_fpmath1_sqrt_f32_contract(float %x) {
277; CHECK-LABEL: define float @amdgcn_rcp_fpmath1_sqrt_f32_contract
278; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
279; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]])
280; CHECK-NEXT:    ret float [[RSQ]]
281;
282  %sqrt = call contract float @llvm.sqrt.f32(float %x), !fpmath !1
283  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
284  ret float %rsq
285}
286
287; Ignore f64 sqrt
288define double @amdgcn_rcp_afn_sqrt_f64_contract(double %x) {
289; CHECK-LABEL: define double @amdgcn_rcp_afn_sqrt_f64_contract
290; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
291; CHECK-NEXT:    [[SQRT:%.*]] = call contract afn double @llvm.sqrt.f64(double [[X]])
292; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
293; CHECK-NEXT:    ret double [[RSQ]]
294;
295  %sqrt = call afn contract double @llvm.sqrt.f64(double %x)
296  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
297  ret double %rsq
298}
299
300; Ignore f64 sqrt
301define double @amdgcn_rcp_fpmath3_sqrt_f64_contract(double %x) {
302; CHECK-LABEL: define double @amdgcn_rcp_fpmath3_sqrt_f64_contract
303; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
304; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath !0
305; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
306; CHECK-NEXT:    ret double [[RSQ]]
307;
308  %sqrt = call contract double @llvm.sqrt.f64(double %x), !fpmath !0
309  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
310  ret double %rsq
311}
312
313; Ignore f64 sqrt
314define double @amdgcn_rcp_fpmath1_sqrt_f64_contract(double %x) {
315; CHECK-LABEL: define double @amdgcn_rcp_fpmath1_sqrt_f64_contract
316; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
317; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath !1
318; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
319; CHECK-NEXT:    ret double [[RSQ]]
320;
321  %sqrt = call contract double @llvm.sqrt.f64(double %x), !fpmath !1
322  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
323  ret double %rsq
324}
325
326!0 = !{float 3.0}
327!1 = !{float 1.0}
328