xref: /llvm-project/llvm/test/Transforms/InstCombine/fsqrtdiv-transform.ll (revision 3b3590aa59f6ba35c746c01c0692621494b62cab)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S -passes='instcombine<no-verify-fixpoint>' < %s | FileCheck %s
3
4@x = global double 0.000000e+00
5@r1 = global double 0.000000e+00
6@r2 = global double 0.000000e+00
7@r3 = global double 0.000000e+00
8@v = global [2 x double] zeroinitializer
9@v1 = global [2 x double] zeroinitializer
10@v2 = global [2 x double] zeroinitializer
11
12; div/mul/div1 in the same block.
13define void @bb_constraint_case1(double %a) {
14; CHECK-LABEL: define void @bb_constraint_case1(
15; CHECK-SAME: double [[A:%.*]]) {
16; CHECK-NEXT:  entry:
17; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]])
18; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]]
19; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[SQRT1]]
20; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
21; CHECK-NEXT:    store double [[TMP0]], ptr @r1, align 8
22; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
23; CHECK-NEXT:    ret void
24;
25entry:
26  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
27  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
28  store double %div, ptr @x
29  %mul = fmul reassoc double %div, %div
30  store double %mul, ptr @r1
31  %div1 = fdiv reassoc double %a, %sqrt
32  store double %div1, ptr @r2
33  ret void
34}
35
36; div/mul in one block and div1 in other block with conditional guard.
37define void @bb_constraint_case2(double %a, i32 %d) {
38; CHECK-LABEL: define void @bb_constraint_case2(
39; CHECK-SAME: double [[A:%.*]], i32 [[D:%.*]]) {
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]])
42; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]]
43; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[SQRT1]]
44; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
45; CHECK-NEXT:    store double [[TMP0]], ptr @r1, align 8
46; CHECK-NEXT:    [[D_NOT:%.*]] = icmp eq i32 [[D]], 0
47; CHECK-NEXT:    br i1 [[D_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
48; CHECK:       if.then:
49; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
50; CHECK-NEXT:    br label [[IF_END]]
51; CHECK:       if.end:
52; CHECK-NEXT:    ret void
53;
54entry:
55  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
56  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
57  store double %div, ptr @x
58  %mul = fmul reassoc double %div, %div
59  store double %mul, ptr @r1
60  %d.not = icmp eq i32 %d, 0
61  br i1 %d.not, label %if.end, label %if.then
62
63if.then:                                          ; preds = %entry
64  %div1 = fdiv reassoc double %a, %sqrt
65  store double %div1, ptr @r2
66  br label %if.end
67
68if.end:                                           ; preds = %if.then, %entry
69  ret void
70}
71
72; div in one block. mul/div1 in other block and conditionally guarded. Don't optimize.
73define void @bb_constraint_case3(double %a, i32 %d) {
74; CHECK-LABEL: define void @bb_constraint_case3(
75; CHECK-SAME: double [[A:%.*]], i32 [[D:%.*]]) {
76; CHECK-NEXT:  entry:
77; CHECK-NEXT:    [[SQRT:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
78; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf arcp double 1.000000e+00, [[SQRT]]
79; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
80; CHECK-NEXT:    [[D_NOT:%.*]] = icmp eq i32 [[D]], 0
81; CHECK-NEXT:    br i1 [[D_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
82; CHECK:       if.then:
83; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc double [[DIV]], [[DIV]]
84; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
85; CHECK-NEXT:    [[DIV1:%.*]] = fdiv reassoc double [[A]], [[SQRT]]
86; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
87; CHECK-NEXT:    br label [[IF_END]]
88; CHECK:       if.end:
89; CHECK-NEXT:    ret void
90;
91entry:
92  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
93  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
94  store double %div, ptr @x
95  %d.not = icmp eq i32 %d, 0
96  br i1 %d.not, label %if.end, label %if.then
97
98if.then:                                          ; preds = %entry
99  %mul = fmul reassoc double %div, %div
100  store double %mul, ptr @r1
101  %div1 = fdiv reassoc double %a, %sqrt
102  store double %div1, ptr @r2
103  br label %if.end
104
105if.end:                                           ; preds = %if.then, %entry
106  ret void
107}
108
109; div in one block. mul/div1 each in different block and conditionally guarded. Don't optimize.
110define void @bb_constraint_case4(double %a, i32 %c, i32 %d) {
111; CHECK-LABEL: define void @bb_constraint_case4(
112; CHECK-SAME: double [[A:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
113; CHECK-NEXT:  entry:
114; CHECK-NEXT:    [[SQRT:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
115; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf arcp double 1.000000e+00, [[SQRT]]
116; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
117; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq i32 [[C]], 0
118; CHECK-NEXT:    br i1 [[C_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
119; CHECK:       if.then:
120; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc double [[DIV]], [[DIV]]
121; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
122; CHECK-NEXT:    br label [[IF_END]]
123; CHECK:       if.end:
124; CHECK-NEXT:    [[D_NOT:%.*]] = icmp eq i32 [[D]], 0
125; CHECK-NEXT:    br i1 [[D_NOT]], label [[IF_END1:%.*]], label [[IF_THEN1:%.*]]
126; CHECK:       if.then1:
127; CHECK-NEXT:    [[DIV1:%.*]] = fdiv reassoc double [[A]], [[SQRT]]
128; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
129; CHECK-NEXT:    br label [[IF_END1]]
130; CHECK:       if.end1:
131; CHECK-NEXT:    ret void
132;
133entry:
134  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
135  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
136  store double %div, ptr @x
137  %c.not = icmp eq i32 %c, 0
138  br i1 %c.not, label %if.end, label %if.then
139
140if.then:                                          ; preds = %entry
141  %mul = fmul reassoc double %div, %div
142  store double %mul, ptr @r1
143  br label %if.end
144
145if.end:                                           ; preds = %if.then, %entry
146  %d.not = icmp eq i32 %d, 0
147  br i1 %d.not, label %if.end1, label %if.then1
148
149if.then1:                                         ; preds = %if.end
150  %div1 = fdiv reassoc double %a, %sqrt
151  store double %div1, ptr @r2
152  br label %if.end1
153
154if.end1:                                          ; preds = %if.then1, %if.end
155  ret void
156}
157
158; sqrt value comes from different blocks. Don't optimize.
159define void @bb_constraint_case5(double %a, i32 %c) {
160; CHECK-LABEL: define void @bb_constraint_case5(
161; CHECK-SAME: double [[A:%.*]], i32 [[C:%.*]]) {
162; CHECK-NEXT:  entry:
163; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq i32 [[C]], 0
164; CHECK-NEXT:    br i1 [[C_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
165; CHECK:       if.then:
166; CHECK-NEXT:    [[TMP0:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
167; CHECK-NEXT:    br label [[IF_END:%.*]]
168; CHECK:       if.else:
169; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[A]], 1.000000e+01
170; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[ADD]])
171; CHECK-NEXT:    br label [[IF_END]]
172; CHECK:       if.end:
173; CHECK-NEXT:    [[SQRT:%.*]] = phi double [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ]
174; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf arcp double 1.000000e+00, [[SQRT]]
175; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc double [[DIV]], [[DIV]]
176; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
177; CHECK-NEXT:    [[DIV1:%.*]] = fdiv reassoc double [[A]], [[SQRT]]
178; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
179; CHECK-NEXT:    ret void
180;
181entry:
182  %c.not = icmp eq i32 %c, 0
183  br i1 %c.not, label %if.else, label %if.then
184
185if.then:                                          ; preds = %entry
186  %0 = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
187  br label %if.end
188
189if.else:                                          ; preds = %entry
190  %add = fadd double %a, 1.000000e+01
191  %1 = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %add)
192  br label %if.end
193
194if.end:                                           ; preds = %if.else, %if.then
195  %sqrt = phi double[ %0, %if.then], [ %1, %if.else]
196  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
197  %mul = fmul reassoc double %div, %div
198  store double %mul, ptr @r1
199  %div1 = fdiv reassoc double %a, %sqrt
200  store double %div1, ptr @r2
201  ret void
202}
203
204; div in one block and conditionally guarded. mul/div1 in other block. Don't optimize.
205define void @bb_constraint_case6(double %a, i32 %d) {
206; CHECK-LABEL: define void @bb_constraint_case6(
207; CHECK-SAME: double [[A:%.*]], i32 [[D:%.*]]) {
208; CHECK-NEXT:  entry:
209; CHECK-NEXT:    [[SQRT:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
210; CHECK-NEXT:    [[D_NOT:%.*]] = icmp eq i32 [[D]], 0
211; CHECK-NEXT:    br i1 [[D_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
212; CHECK:       if.else:
213; CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr @x, align 8
214; CHECK-NEXT:    br label [[IF_END:%.*]]
215; CHECK:       if.then:
216; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc ninf arcp double 1.000000e+00, [[SQRT]]
217; CHECK-NEXT:    store double [[TMP1]], ptr @x, align 8
218; CHECK-NEXT:    br label [[IF_END]]
219; CHECK:       if.end:
220; CHECK-NEXT:    [[DIV:%.*]] = phi double [ [[TMP0]], [[IF_ELSE]] ], [ [[TMP1]], [[IF_THEN]] ]
221; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc double [[DIV]], [[DIV]]
222; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
223; CHECK-NEXT:    [[DIV1:%.*]] = fdiv reassoc double [[A]], [[SQRT]]
224; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
225; CHECK-NEXT:    ret void
226;
227entry:
228  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
229  %d.not = icmp eq i32 %d, 0
230  br i1 %d.not, label %if.else, label %if.then
231
232if.else:                                          ; preds = %entry
233  %1 = load double, ptr @x
234  br label %if.end
235
236if.then:                                          ; preds = %entry
237  %2 = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
238  store double %2, ptr @x
239  br label %if.end
240
241if.end:                                           ; preds = %if.else, %if.then
242  %div = phi double [ %1, %if.else ], [ %2, %if.then ]
243  %mul = fmul reassoc double %div, %div
244  store double %mul, ptr @r1
245  %div1 = fdiv reassoc double %a, %sqrt
246  store double %div1, ptr @r2
247  ret void
248}
249
250; value for mul comes from different blocks. Don't optimize.
251define void @bb_constraint_case7(double %a, i32 %c, i32 %d) {
252; CHECK-LABEL: define void @bb_constraint_case7(
253; CHECK-SAME: double [[A:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
254; CHECK-NEXT:  entry:
255; CHECK-NEXT:    [[SQRT:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
256; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf arcp double 1.000000e+00, [[SQRT]]
257; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
258; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq i32 [[C]], 0
259; CHECK-NEXT:    br i1 [[C_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
260; CHECK:       if.then:
261; CHECK-NEXT:    [[TMP0:%.*]] = fdiv double 3.000000e+00, [[A]]
262; CHECK-NEXT:    br label [[IF_END:%.*]]
263; CHECK:       if.else:
264; CHECK-NEXT:    [[D_NOT:%.*]] = icmp eq i32 [[D]], 0
265; CHECK-NEXT:    br i1 [[D_NOT]], label [[IF_ELSE1:%.*]], label [[IF_THEN1:%.*]]
266; CHECK:       if.then1:
267; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double 2.000000e+00, [[A]]
268; CHECK-NEXT:    br label [[IF_END]]
269; CHECK:       if.else1:
270; CHECK-NEXT:    [[TMP2:%.*]] = fmul reassoc double [[DIV]], [[DIV]]
271; CHECK-NEXT:    br label [[IF_END]]
272; CHECK:       if.end:
273; CHECK-NEXT:    [[MUL:%.*]] = phi double [ [[TMP1]], [[IF_THEN1]] ], [ [[TMP2]], [[IF_ELSE1]] ], [ [[TMP0]], [[IF_THEN]] ]
274; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
275; CHECK-NEXT:    [[DIV1:%.*]] = fdiv reassoc double [[A]], [[SQRT]]
276; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
277; CHECK-NEXT:    ret void
278;
279entry:
280  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
281  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
282  store double %div, ptr @x
283  %c.not = icmp eq i32 %c, 0
284  br i1 %c.not, label %if.else, label %if.then
285
286if.then:                                          ; preds = %entry
287  %1 = fdiv double 3.000000e+00, %a
288  br label %if.end
289
290if.else:                                          ; preds = %entry
291  %d.not = icmp eq i32 %d, 0
292  br i1 %d.not, label %if.else1, label %if.then1
293
294if.then1:                                         ; preds = %if.else
295  %2 = fdiv double 2.000000e+00, %a
296  br label %if.end
297
298if.else1:                                         ; preds = %if.else
299  %3 = fmul reassoc double %div, %div
300  br label %if.end
301
302if.end:                                           ; preds = %if.then1, %if.else1, %if.then
303  %mul = phi double [ %2, %if.then1 ], [ %3, %if.else1 ], [ %1, %if.then ]
304  store double %mul, ptr @r1
305  %div1 = fdiv reassoc double %a, %sqrt
306  store double %div1, ptr @r2
307  ret void
308}
309
310; value of mul  comes from two different blocks(as shown by select ins).
311define void @bb_constraint_case8(double %a, i32 %c) {
312; CHECK-LABEL: define void @bb_constraint_case8(
313; CHECK-SAME: double [[A:%.*]], i32 [[C:%.*]]) {
314; CHECK-NEXT:  entry:
315; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]])
316; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]]
317; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[SQRT1]]
318; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
319; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq i32 [[C]], 0
320; CHECK-NEXT:    [[TMP1:%.*]] = fmul double [[A]], [[A]]
321; CHECK-NEXT:    [[MUL:%.*]] = select i1 [[C_NOT]], double [[TMP1]], double [[TMP0]]
322; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
323; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
324; CHECK-NEXT:    ret void
325;
326entry:
327  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
328  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
329  store double %div, ptr @x
330  %c.not = icmp eq i32 %c, 0
331  %1 = fmul double %a, %a
332  %2 = fmul reassoc double %div, %div
333  %mul = select i1 %c.not, double %1, double %2
334  store double %mul, ptr @r1
335  %div1 = fdiv reassoc double %a, %sqrt
336  store double %div1, ptr @r2
337  ret void
338}
339
340; multiple instances of multiply ops to optimize. Optimize all.
341define void @mutiple_multiply_instances(double %a, i32 %c) {
342; CHECK-LABEL: define void @mutiple_multiply_instances(
343; CHECK-SAME: double [[A:%.*]], i32 [[C:%.*]]) {
344; CHECK-NEXT:  entry:
345; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]])
346; CHECK-NEXT:    [[TMP1:%.*]] = fdiv reassoc double 1.000000e+00, [[A]]
347; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP1]], [[SQRT1]]
348; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
349; CHECK-NEXT:    [[C_NOT:%.*]] = icmp eq i32 [[C]], 0
350; CHECK-NEXT:    [[TMP2:%.*]] = fmul double [[A]], [[A]]
351; CHECK-NEXT:    [[TMP3:%.*]] = fmul double [[A]], [[A]]
352; CHECK-NEXT:    [[MUL1:%.*]] = select i1 [[C_NOT]], double [[TMP2]], double [[TMP1]]
353; CHECK-NEXT:    [[MUL2:%.*]] = select i1 [[C_NOT]], double [[TMP1]], double [[TMP3]]
354; CHECK-NEXT:    store double [[MUL1]], ptr @r1, align 8
355; CHECK-NEXT:    store double [[MUL2]], ptr @r3, align 8
356; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
357; CHECK-NEXT:    ret void
358;
359entry:
360  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
361  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
362  store double %div, ptr @x
363  %c.not = icmp eq i32 %c, 0
364  %1 = fmul double %a, %a
365  %2 = fmul double %a, %a
366  %3 = fmul reassoc double %div, %div
367  %4 = fmul reassoc double %div, %div
368  %mul1 = select i1 %c.not, double %1, double %3
369  %mul2 = select i1 %c.not, double %4, double %2
370  store double %mul1, ptr @r1
371  store double %mul2, ptr @r3
372  %div1 = fdiv reassoc double %a, %sqrt
373  store double %div1, ptr @r2
374  ret void
375}
376
377; missing flags for optimization.
378define void @missing_arcp_flag_on_div(double %a) {
379; CHECK-LABEL: define void @missing_arcp_flag_on_div(
380; CHECK-SAME: double [[A:%.*]]) {
381; CHECK-NEXT:  entry:
382; CHECK-NEXT:    [[SQRT:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
383; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf double 1.000000e+00, [[SQRT]]
384; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
385; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc double [[DIV]], [[DIV]]
386; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
387; CHECK-NEXT:    [[DIV1:%.*]] = fdiv reassoc double [[A]], [[SQRT]]
388; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
389; CHECK-NEXT:    ret void
390;
391entry:
392  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
393  %div = fdiv reassoc ninf double 1.000000e+00, %sqrt
394  store double %div, ptr @x
395  %mul = fmul reassoc double %div, %div
396  store double %mul, ptr @r1
397  %div1 = fdiv reassoc double %a, %sqrt
398  store double %div1, ptr @r2
399  ret void
400}
401
402; missing flags for optimization.
403define void @missing_reassoc_flag_on_mul(double %a) {
404; CHECK-LABEL: define void @missing_reassoc_flag_on_mul(
405; CHECK-SAME: double [[A:%.*]]) {
406; CHECK-NEXT:  entry:
407; CHECK-NEXT:    [[SQRT:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
408; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf arcp double 1.000000e+00, [[SQRT]]
409; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
410; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[DIV]], [[DIV]]
411; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
412; CHECK-NEXT:    [[DIV1:%.*]] = fdiv reassoc double [[A]], [[SQRT]]
413; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
414; CHECK-NEXT:    ret void
415;
416entry:
417  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
418  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
419  store double %div, ptr @x
420  %mul = fmul double %div, %div
421  store double %mul, ptr @r1
422  %div1 = fdiv reassoc double %a, %sqrt
423  store double %div1, ptr @r2
424  ret void
425}
426
427; missing flags for optimization.
428define void @missing_reassoc_flag_on_div1(double %a) {
429; CHECK-LABEL: define void @missing_reassoc_flag_on_div1(
430; CHECK-SAME: double [[A:%.*]]) {
431; CHECK-NEXT:  entry:
432; CHECK-NEXT:    [[SQRT:%.*]] = call reassoc nnan ninf nsz double @llvm.sqrt.f64(double [[A]])
433; CHECK-NEXT:    [[DIV:%.*]] = fdiv reassoc ninf arcp double 1.000000e+00, [[SQRT]]
434; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
435; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc double [[DIV]], [[DIV]]
436; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
437; CHECK-NEXT:    [[DIV1:%.*]] = fdiv double [[A]], [[SQRT]]
438; CHECK-NEXT:    store double [[DIV1]], ptr @r2, align 8
439; CHECK-NEXT:    ret void
440;
441entry:
442  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
443  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
444  store double %div, ptr @x
445  %mul = fmul reassoc double %div, %div
446  store double %mul, ptr @r1
447  %div1 = fdiv double %a, %sqrt
448  store double %div1, ptr @r2
449  ret void
450}
451
452; div = -1/sqrt(a)
453define void @negative_fdiv_val(double %a) {
454; CHECK-LABEL: define void @negative_fdiv_val(
455; CHECK-SAME: double [[A:%.*]]) {
456; CHECK-NEXT:  entry:
457; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]])
458; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]]
459; CHECK-NEXT:    [[TMP1:%.*]] = fneg reassoc double [[SQRT1]]
460; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[TMP1]]
461; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
462; CHECK-NEXT:    store double [[TMP0]], ptr @r1, align 8
463; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
464; CHECK-NEXT:    ret void
465;
466entry:
467  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
468  %div = fdiv reassoc arcp ninf double -1.000000e+00, %sqrt
469  store double %div, ptr @x
470  %mul = fmul reassoc double %div, %div
471  store double %mul, ptr @r1
472  %div1 = fdiv reassoc double %a, %sqrt
473  store double %div1, ptr @r2
474  ret void
475}
476
477define void @fpmath_metadata_on_div1(double %a) {
478; CHECK-LABEL: define void @fpmath_metadata_on_div1(
479; CHECK-SAME: double [[A:%.*]]) {
480; CHECK-NEXT:  entry:
481; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]]), !fpmath [[META0:![0-9]+]]
482; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]]
483; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[SQRT1]]
484; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
485; CHECK-NEXT:    store double [[TMP0]], ptr @r1, align 8
486; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
487; CHECK-NEXT:    ret void
488;
489entry:
490  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
491  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
492  store double %div, ptr @x
493  %mul = fmul reassoc double %div, %div
494  store double %mul, ptr @r1
495  %div1 = fdiv reassoc double %a, %sqrt, !fpmath !3
496  store double %div1, ptr @r2
497  ret void
498}
499
500define void @fpmath_metadata_on_mul(double %a) {
501; CHECK-LABEL: define void @fpmath_metadata_on_mul(
502; CHECK-SAME: double [[A:%.*]]) {
503; CHECK-NEXT:  entry:
504; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]])
505; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]], !fpmath [[META1:![0-9]+]]
506; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[SQRT1]]
507; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
508; CHECK-NEXT:    store double [[TMP0]], ptr @r1, align 8
509; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
510; CHECK-NEXT:    ret void
511;
512entry:
513  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
514  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt
515  store double %div, ptr @x
516  %mul = fmul reassoc double %div, %div, !fpmath !2
517  store double %mul, ptr @r1
518  %div1 = fdiv reassoc double %a, %sqrt
519  store double %div1, ptr @r2
520  ret void
521}
522
523; FIXME: DIV in the result should get the fpmath metadata from %div.
524define void @fpmath_metadata_on_div(double %a) {
525; CHECK-LABEL: define void @fpmath_metadata_on_div(
526; CHECK-SAME: double [[A:%.*]]) {
527; CHECK-NEXT:  entry:
528; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]])
529; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]]
530; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[SQRT1]], !fpmath [[META2:![0-9]+]]
531; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
532; CHECK-NEXT:    store double [[TMP0]], ptr @r1, align 8
533; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
534; CHECK-NEXT:    ret void
535;
536entry:
537  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a)
538  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt, !fpmath !1
539  store double %div, ptr @x
540  %mul = fmul reassoc double %div, %div
541  store double %mul, ptr @r1
542  %div1 = fdiv reassoc double %a, %sqrt
543  store double %div1, ptr @r2
544  ret void
545}
546
547define void @fpmath_metadata_on_all(double %a) {
548; CHECK-LABEL: define void @fpmath_metadata_on_all(
549; CHECK-SAME: double [[A:%.*]]) {
550; CHECK-NEXT:  entry:
551; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc double @llvm.sqrt.f64(double [[A]]), !fpmath [[META0]]
552; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc double 1.000000e+00, [[A]], !fpmath [[META1]]
553; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc double [[TMP0]], [[SQRT1]], !fpmath [[META2]]
554; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
555; CHECK-NEXT:    store double [[TMP0]], ptr @r1, align 8
556; CHECK-NEXT:    store double [[SQRT1]], ptr @r2, align 8
557; CHECK-NEXT:    ret void
558;
559entry:
560  %sqrt = call reassoc nnan nsz ninf double @llvm.sqrt.f64(double %a), !fpmath !0
561  %div = fdiv reassoc arcp ninf double 1.000000e+00, %sqrt, !fpmath !1
562  store double %div, ptr @x
563  %mul = fmul reassoc double %div, %div, !fpmath !2
564  store double %mul, ptr @r1
565  %div1 = fdiv reassoc double %a, %sqrt, !fpmath !3
566  store double %div1, ptr @r2
567  ret void
568}
569
570define void @vector_input(<2 x double> %a) {
571; CHECK-LABEL: define void @vector_input(
572; CHECK-SAME: <2 x double> [[A:%.*]]) {
573; CHECK-NEXT:  entry:
574; CHECK-NEXT:    [[SQRT1:%.*]] = call reassoc <2 x double> @llvm.sqrt.v2f64(<2 x double> [[A]])
575; CHECK-NEXT:    [[TMP0:%.*]] = fdiv reassoc <2 x double> splat (double 1.000000e+00), [[A]]
576; CHECK-NEXT:    [[DIV:%.*]] = fmul reassoc <2 x double> [[TMP0]], [[SQRT1]]
577; CHECK-NEXT:    store <2 x double> [[DIV]], ptr @v, align 16
578; CHECK-NEXT:    store <2 x double> [[TMP0]], ptr @v1, align 16
579; CHECK-NEXT:    store <2 x double> [[SQRT1]], ptr @v2, align 16
580; CHECK-NEXT:    ret void
581;
582entry:
583  %sqrt = call reassoc nnan nsz ninf <2 x double> @llvm.sqrt.v2f64(<2 x double> %a)
584  %div = fdiv reassoc arcp ninf <2 x double><double 1.000000e+00, double 1.000000e+00>, %sqrt
585  store <2 x double> %div, ptr @v
586  %mul = fmul reassoc <2 x double> %div, %div
587  store <2 x double> %mul, ptr @v1
588  %div1 = fdiv reassoc <2 x double> %a, %sqrt
589  store <2 x double> %div1, ptr @v2
590  ret void
591}
592
593define void @strict_fp_metadata(double %a) {
594; CHECK-LABEL: define void @strict_fp_metadata(
595; CHECK-SAME: double [[A:%.*]]) {
596; CHECK-NEXT:  entry:
597; CHECK-NEXT:    [[CONV:%.*]] = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 1, metadata !"round.dynamic", metadata !"fpexcept.strict")
598; CHECK-NEXT:    [[CALL:%.*]] = call double @llvm.sqrt.f64(double noundef [[A]])
599; CHECK-NEXT:    [[DIV:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[CONV]], double [[CALL]], metadata !"round.dynamic", metadata !"fpexcept.strict")
600; CHECK-NEXT:    store double [[DIV]], ptr @x, align 8
601; CHECK-NEXT:    [[MUL:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[DIV]], double [[DIV]], metadata !"round.dynamic", metadata !"fpexcept.strict")
602; CHECK-NEXT:    store double [[MUL]], ptr @r1, align 8
603; CHECK-NEXT:    [[DIV2:%.*]] = call double @llvm.experimental.constrained.fdiv.f64(double [[A]], double [[CALL]], metadata !"round.dynamic", metadata !"fpexcept.strict")
604; CHECK-NEXT:    store double [[DIV2]], ptr @r2, align 8
605; CHECK-NEXT:    ret void
606;
607entry:
608  %conv = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 1, metadata !"round.dynamic", metadata !"fpexcept.strict")
609  %call = call double @llvm.sqrt.f64(double noundef %a)
610  %div = call double @llvm.experimental.constrained.fdiv.f64(double %conv, double %call, metadata !"round.dynamic", metadata !"fpexcept.strict")
611  store double %div, ptr @x
612  %mul = call double @llvm.experimental.constrained.fmul.f64(double %div, double %div, metadata !"round.dynamic", metadata !"fpexcept.strict")
613  store double %mul, ptr @r1
614  %div2 = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %call, metadata !"round.dynamic", metadata !"fpexcept.strict")
615  store double %div2, ptr @r2
616  ret void
617}
618
619declare double @llvm.experimental.constrained.sitofp.f64.i32(i32, metadata, metadata)
620declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata)
621declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata)
622declare double @llvm.sqrt.f64(double)
623declare <2 x double> @llvm.sqrt.v2f64(<2 x double>)
624
625!0 = !{float 2.5}
626!1 = !{float 3.5}
627!2 = !{float 4.5}
628!3 = !{float 5.5}
629; CHECK: [[META0]] = !{float 5.500000e+00}
630; CHECK: [[META1]] = !{float 4.500000e+00}
631; CHECK: [[META2]] = !{float 3.500000e+00}
632