xref: /llvm-project/llvm/test/CodeGen/AMDGPU/prevent-fmul-hoist-ir.ll (revision 211bcf67aadb1175af382f55403ae759177281c7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -S -passes='simplifycfg<hoist-common-insts>' -mtriple=amdgcn-- --fp-contract=fast -mcpu=gfx1030 < %s | FileCheck -check-prefix=GFX -check-prefix=FP-CONTRACT-FAST %s
3; RUN: opt -S -passes='simplifycfg<hoist-common-insts>' -mtriple=amdgcn-- --fp-contract=off --enable-unsafe-fp-math -mcpu=gfx1030 < %s | FileCheck -check-prefix=GFX -check-prefix=UNSAFE-FP-MATH %s
4; RUN: opt -S -passes='simplifycfg<hoist-common-insts>' -mtriple=amdgcn-- --fp-contract=off -mcpu=gfx1030 < %s | FileCheck -check-prefix=GFX -check-prefix=NO-UNSAFE-FP-MATH %s
5
6define double @is_profitable_f64_contract(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
7; GFX-LABEL: define double @is_profitable_f64_contract(
8; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0:[0-9]+]] {
9; GFX-NEXT:  [[ENTRY:.*:]]
10; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
11; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
12; GFX-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
13; GFX-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
14; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
15; GFX:       [[COMMON_RET:.*]]:
16; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
17; GFX-NEXT:    ret double [[COMMON_RET_OP]]
18; GFX:       [[IF_THEN]]:
19; GFX-NEXT:    [[MUL:%.*]] = fmul contract double [[X]], [[A_1]]
20; GFX-NEXT:    [[ADD]] = fadd contract double 1.000000e+00, [[MUL]]
21; GFX-NEXT:    br label %[[COMMON_RET]]
22; GFX:       [[IF_ELSE]]:
23; GFX-NEXT:    [[MUL1:%.*]] = fmul contract double [[X]], [[A_1]]
24; GFX-NEXT:    [[SUB]] = fsub contract double [[MUL1]], [[Y]]
25; GFX-NEXT:    br label %[[COMMON_RET]]
26;
27entry:
28  %y = load double, ptr %ptr_y, align 8
29  %cmp = fcmp oeq double %y, 0.000000e+00
30  %x = load double, ptr %ptr_x, align 8
31  br i1 %cmp, label %if.then, label %if.else
32
33if.then:                                          ; preds = %entry
34  %a_1 = load double, ptr %ptr_a, align 8
35  %mul = fmul contract double %x, %a_1
36  %add = fadd contract double 1.000000e+00, %mul
37  ret double %add
38
39if.else:                                          ; preds = %entry
40  %a_2 = load double, ptr %ptr_a, align 8
41  %mul1 = fmul contract double %x, %a_2
42  %sub = fsub contract double %mul1, %y
43  ret double %sub
44}
45
46define double @is_profitable_f64_modifiers(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
47; GFX-LABEL: define double @is_profitable_f64_modifiers(
48; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
49; GFX-NEXT:  [[ENTRY:.*:]]
50; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
51; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
52; GFX-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
53; GFX-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
54; GFX-NEXT:    [[MUL:%.*]] = fmul contract double [[X]], [[A_1]]
55; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
56; GFX:       [[COMMON_RET:.*]]:
57; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
58; GFX-NEXT:    ret double [[COMMON_RET_OP]]
59; GFX:       [[IF_THEN]]:
60; GFX-NEXT:    [[FNEG:%.*]] = fneg double [[MUL]]
61; GFX-NEXT:    [[ADD]] = fadd contract double 1.000000e+00, [[FNEG]]
62; GFX-NEXT:    br label %[[COMMON_RET]]
63; GFX:       [[IF_ELSE]]:
64; GFX-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[MUL]])
65; GFX-NEXT:    [[SUB]] = fsub contract double [[FABS]], [[Y]]
66; GFX-NEXT:    br label %[[COMMON_RET]]
67;
68entry:
69  %y = load double, ptr %ptr_y, align 8
70  %cmp = fcmp oeq double %y, 0.000000e+00
71  %x = load double, ptr %ptr_x, align 8
72  br i1 %cmp, label %if.then, label %if.else
73
74if.then:                                          ; preds = %entry
75  %a_1 = load double, ptr %ptr_a, align 8
76  %mul = fmul contract double %x, %a_1
77  %fneg = fneg double %mul
78  %add = fadd contract double 1.000000e+00, %fneg
79  ret double %add
80
81if.else:                                          ; preds = %entry
82  %a_2 = load double, ptr %ptr_a, align 8
83  %mul1 = fmul contract double %x, %a_2
84  %fabs = call double @llvm.fabs.f64(double %mul1)
85  %sub = fsub contract double %fabs, %y
86  ret double %sub
87}
88
89define float @is_profitable_f32(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
90; GFX-LABEL: define float @is_profitable_f32(
91; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
92; GFX-NEXT:  [[ENTRY:.*:]]
93; GFX-NEXT:    [[Y:%.*]] = load float, ptr [[PTR_Y]], align 8
94; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq float [[Y]], 0.000000e+00
95; GFX-NEXT:    [[X:%.*]] = load float, ptr [[PTR_X]], align 8
96; GFX-NEXT:    [[A_1:%.*]] = load float, ptr [[PTR_A]], align 8
97; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
98; GFX:       [[COMMON_RET:.*]]:
99; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi float [ [[MUL:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
100; GFX-NEXT:    ret float [[COMMON_RET_OP]]
101; GFX:       [[IF_THEN]]:
102; GFX-NEXT:    [[MUL]] = fmul contract float [[X]], [[A_1]]
103; GFX-NEXT:    [[ADD:%.*]] = fadd contract float 1.000000e+00, [[MUL]]
104; GFX-NEXT:    br label %[[COMMON_RET]]
105; GFX:       [[IF_ELSE]]:
106; GFX-NEXT:    [[MUL1:%.*]] = fmul contract float [[X]], [[A_1]]
107; GFX-NEXT:    [[SUB]] = fsub contract float [[MUL1]], [[Y]]
108; GFX-NEXT:    br label %[[COMMON_RET]]
109;
110entry:
111  %y = load float, ptr %ptr_y, align 8
112  %cmp = fcmp oeq float %y, 0.000000e+00
113  %x = load float, ptr %ptr_x, align 8
114  br i1 %cmp, label %if.then, label %if.else
115
116if.then:                                          ; preds = %entry
117  %a_1 = load float, ptr %ptr_a, align 8
118  %mul = fmul contract float %x, %a_1
119  %add = fadd contract float 1.000000e+00, %mul
120  ret float %mul
121
122if.else:                                          ; preds = %entry
123  %a_2 = load float, ptr %ptr_a, align 8
124  %mul1 = fmul contract float %x, %a_2
125  %sub = fsub contract float %mul1, %y
126  ret float %sub
127}
128
129define half @is_profitable_f16_preserve(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
130; GFX-LABEL: define half @is_profitable_f16_preserve(
131; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
132; GFX-NEXT:  [[ENTRY:.*:]]
133; GFX-NEXT:    [[Y:%.*]] = load half, ptr [[PTR_Y]], align 8
134; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq half [[Y]], 0xH0000
135; GFX-NEXT:    [[X:%.*]] = load half, ptr [[PTR_X]], align 8
136; GFX-NEXT:    [[A_1:%.*]] = load half, ptr [[PTR_A]], align 8
137; GFX-NEXT:    [[MUL:%.*]] = fmul contract half [[X]], [[A_1]]
138; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
139; GFX:       [[COMMON_RET:.*]]:
140; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi half [ [[MUL]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
141; GFX-NEXT:    ret half [[COMMON_RET_OP]]
142; GFX:       [[IF_THEN]]:
143; GFX-NEXT:    [[ADD:%.*]] = fadd contract half [[Y]], [[MUL]]
144; GFX-NEXT:    br label %[[COMMON_RET]]
145; GFX:       [[IF_ELSE]]:
146; GFX-NEXT:    [[SUB]] = fsub contract half [[MUL]], [[Y]]
147; GFX-NEXT:    br label %[[COMMON_RET]]
148;
149entry:
150  %y = load half, ptr %ptr_y, align 8
151  %cmp = fcmp oeq half %y, 0.000000e+00
152  %x = load half, ptr %ptr_x, align 8
153  br i1 %cmp, label %if.then, label %if.else
154
155if.then:                                          ; preds = %entry
156  %a_1 = load half, ptr %ptr_a, align 8
157  %mul = fmul contract half %x, %a_1
158  %add = fadd contract half %y, %mul
159  ret half %mul
160
161if.else:                                          ; preds = %entry
162  %a_2 = load half, ptr %ptr_a, align 8
163  %mul1 = fmul contract half %x, %a_2
164  %sub = fsub contract half %mul1, %y
165  ret half %sub
166}
167
168define half @is_profitable_f16_ieee(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #1 {
169; GFX-LABEL: define half @is_profitable_f16_ieee(
170; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR1:[0-9]+]] {
171; GFX-NEXT:  [[ENTRY:.*:]]
172; GFX-NEXT:    [[Y:%.*]] = load half, ptr [[PTR_Y]], align 8
173; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq half [[Y]], 0xH0000
174; GFX-NEXT:    [[X:%.*]] = load half, ptr [[PTR_X]], align 8
175; GFX-NEXT:    [[A_1:%.*]] = load half, ptr [[PTR_A]], align 8
176; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
177; GFX:       [[COMMON_RET:.*]]:
178; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi half [ [[MUL:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
179; GFX-NEXT:    ret half [[COMMON_RET_OP]]
180; GFX:       [[IF_THEN]]:
181; GFX-NEXT:    [[MUL]] = fmul contract half [[X]], [[A_1]]
182; GFX-NEXT:    [[ADD:%.*]] = fadd contract half [[Y]], [[MUL]]
183; GFX-NEXT:    br label %[[COMMON_RET]]
184; GFX:       [[IF_ELSE]]:
185; GFX-NEXT:    [[MUL1:%.*]] = fmul contract half [[X]], [[A_1]]
186; GFX-NEXT:    [[SUB]] = fsub contract half [[MUL1]], [[Y]]
187; GFX-NEXT:    br label %[[COMMON_RET]]
188;
189entry:
190  %y = load half, ptr %ptr_y, align 8
191  %cmp = fcmp oeq half %y, 0.000000e+00
192  %x = load half, ptr %ptr_x, align 8
193  br i1 %cmp, label %if.then, label %if.else
194
195if.then:                                          ; preds = %entry
196  %a_1 = load half, ptr %ptr_a, align 8
197  %mul = fmul contract half %x, %a_1
198  %add = fadd contract half %y, %mul
199  ret half %mul
200
201if.else:                                          ; preds = %entry
202  %a_2 = load half, ptr %ptr_a, align 8
203  %mul1 = fmul contract half %x, %a_2
204  %sub = fsub contract half %mul1, %y
205  ret half %sub
206}
207
208define bfloat @is_profitable_bfloat_preserve(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
209; GFX-LABEL: define bfloat @is_profitable_bfloat_preserve(
210; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
211; GFX-NEXT:  [[ENTRY:.*:]]
212; GFX-NEXT:    [[Y:%.*]] = load bfloat, ptr [[PTR_Y]], align 8
213; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq bfloat [[Y]], 0xR0000
214; GFX-NEXT:    [[X:%.*]] = load bfloat, ptr [[PTR_X]], align 8
215; GFX-NEXT:    [[A_1:%.*]] = load bfloat, ptr [[PTR_A]], align 8
216; GFX-NEXT:    [[MUL:%.*]] = fmul contract bfloat [[X]], [[A_1]]
217; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
218; GFX:       [[COMMON_RET:.*]]:
219; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi bfloat [ [[MUL]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
220; GFX-NEXT:    ret bfloat [[COMMON_RET_OP]]
221; GFX:       [[IF_THEN]]:
222; GFX-NEXT:    [[ADD:%.*]] = fadd contract bfloat 0xR3F80, [[MUL]]
223; GFX-NEXT:    br label %[[COMMON_RET]]
224; GFX:       [[IF_ELSE]]:
225; GFX-NEXT:    [[SUB]] = fsub contract bfloat [[MUL]], [[Y]]
226; GFX-NEXT:    br label %[[COMMON_RET]]
227;
228entry:
229  %y = load bfloat, ptr %ptr_y, align 8
230  %cmp = fcmp oeq bfloat %y, 0.000000e+00
231  %x = load bfloat, ptr %ptr_x, align 8
232  br i1 %cmp, label %if.then, label %if.else
233
234if.then:                                          ; preds = %entry
235  %a_1 = load bfloat, ptr %ptr_a, align 8
236  %mul = fmul contract bfloat %x, %a_1
237  %add = fadd contract bfloat 1.000000e+00, %mul
238  ret bfloat %mul
239
240if.else:                                          ; preds = %entry
241  %a_2 = load bfloat, ptr %ptr_a, align 8
242  %mul1 = fmul contract bfloat %x, %a_2
243  %sub = fsub contract bfloat %mul1, %y
244  ret bfloat %sub
245}
246
247define bfloat @is_profitable_bfloat_ieee(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #1 {
248; GFX-LABEL: define bfloat @is_profitable_bfloat_ieee(
249; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR1]] {
250; GFX-NEXT:  [[ENTRY:.*:]]
251; GFX-NEXT:    [[Y:%.*]] = load bfloat, ptr [[PTR_Y]], align 8
252; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq bfloat [[Y]], 0xR0000
253; GFX-NEXT:    [[X:%.*]] = load bfloat, ptr [[PTR_X]], align 8
254; GFX-NEXT:    [[A_1:%.*]] = load bfloat, ptr [[PTR_A]], align 8
255; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
256; GFX:       [[COMMON_RET:.*]]:
257; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi bfloat [ [[MUL:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
258; GFX-NEXT:    ret bfloat [[COMMON_RET_OP]]
259; GFX:       [[IF_THEN]]:
260; GFX-NEXT:    [[MUL]] = fmul contract bfloat [[X]], [[A_1]]
261; GFX-NEXT:    [[ADD:%.*]] = fadd contract bfloat 0xR3F80, [[MUL]]
262; GFX-NEXT:    br label %[[COMMON_RET]]
263; GFX:       [[IF_ELSE]]:
264; GFX-NEXT:    [[MUL1:%.*]] = fmul contract bfloat [[X]], [[A_1]]
265; GFX-NEXT:    [[SUB]] = fsub contract bfloat [[MUL1]], [[Y]]
266; GFX-NEXT:    br label %[[COMMON_RET]]
267;
268entry:
269  %y = load bfloat, ptr %ptr_y, align 8
270  %cmp = fcmp oeq bfloat %y, 0.000000e+00
271  %x = load bfloat, ptr %ptr_x, align 8
272  br i1 %cmp, label %if.then, label %if.else
273
274if.then:                                          ; preds = %entry
275  %a_1 = load bfloat, ptr %ptr_a, align 8
276  %mul = fmul contract bfloat %x, %a_1
277  %add = fadd contract bfloat 1.000000e+00, %mul
278  ret bfloat %mul
279
280if.else:                                          ; preds = %entry
281  %a_2 = load bfloat, ptr %ptr_a, align 8
282  %mul1 = fmul contract bfloat %x, %a_2
283  %sub = fsub contract bfloat %mul1, %y
284  ret bfloat %sub
285}
286
287define double @is_profitable_constant(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #1 {
288; GFX-LABEL: define double @is_profitable_constant(
289; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR1]] {
290; GFX-NEXT:  [[ENTRY:.*:]]
291; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
292; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
293; GFX-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
294; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
295; GFX:       [[COMMON_RET:.*]]:
296; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
297; GFX-NEXT:    ret double [[COMMON_RET_OP]]
298; GFX:       [[IF_THEN]]:
299; GFX-NEXT:    [[MUL:%.*]] = fmul contract double 2.000000e+00, [[X]]
300; GFX-NEXT:    [[ADD]] = fadd contract double 1.000000e+00, [[MUL]]
301; GFX-NEXT:    br label %[[COMMON_RET]]
302; GFX:       [[IF_ELSE]]:
303; GFX-NEXT:    [[MUL1:%.*]] = fmul contract double 3.000000e+00, [[X]]
304; GFX-NEXT:    [[SUB]] = fsub contract double [[MUL1]], [[Y]]
305; GFX-NEXT:    br label %[[COMMON_RET]]
306;
307entry:
308  %y = load double, ptr %ptr_y, align 8
309  %cmp = fcmp oeq double %y, 0.000000e+00
310  %x = load double, ptr %ptr_x, align 8
311  br i1 %cmp, label %if.then, label %if.else
312
313if.then:                                          ; preds = %entry
314  %mul = fmul contract double 2.000000e+00, %x
315  %add = fadd contract double 1.000000e+00, %mul
316  ret double %add
317
318if.else:                                          ; preds = %entry
319  %mul1 = fmul contract double 3.000000e+00, %x
320  %sub = fsub contract double %mul1, %y
321  ret double %sub
322}
323
324@v1_ptr = external addrspace(3) global ptr
325@v2_ptr = external addrspace(3) global ptr
326
327define <8 x half> @is_profitable_vector(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) {
328; GFX-LABEL: define <8 x half> @is_profitable_vector(
329; GFX-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR2:[0-9]+]] {
330; GFX-NEXT:  [[ENTRY:.*:]]
331; GFX-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
332; GFX-NEXT:    [[X:%.*]] = load <8 x half>, ptr [[PTR_X]], align 8
333; GFX-NEXT:    [[V1:%.*]] = load <8 x half>, ptr addrspace(3) @v1_ptr, align 16
334; GFX-NEXT:    [[V2:%.*]] = load <8 x half>, ptr addrspace(3) @v2_ptr, align 16
335; GFX-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
336; GFX-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
337; GFX:       [[COMMON_RET:.*]]:
338; GFX-NEXT:    [[COMMON_RET_OP:%.*]] = phi <8 x half> [ [[ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
339; GFX-NEXT:    ret <8 x half> [[COMMON_RET_OP]]
340; GFX:       [[IF_THEN]]:
341; GFX-NEXT:    [[MUL:%.*]] = fmul contract <8 x half> [[V1]], [[X]]
342; GFX-NEXT:    [[ADD]] = fadd contract <8 x half> [[V2]], [[MUL]]
343; GFX-NEXT:    br label %[[COMMON_RET]]
344; GFX:       [[IF_ELSE]]:
345; GFX-NEXT:    [[MUL1:%.*]] = fmul contract <8 x half> [[V1]], [[X]]
346; GFX-NEXT:    [[SUB]] = fsub contract <8 x half> [[MUL1]], [[V2]]
347; GFX-NEXT:    br label %[[COMMON_RET]]
348;
349entry:
350  %y = load double, ptr %ptr_y, align 8
351  %x = load <8 x half>, ptr %ptr_x, align 8
352  %v1 = load <8 x half>, ptr addrspace(3) @v1_ptr
353  %v2 = load <8 x half>, ptr addrspace(3) @v2_ptr
354  %cmp = fcmp oeq double %y, 0.000000e+00
355  br i1 %cmp, label %if.then, label %if.else
356
357if.then:                                          ; preds = %entry
358  %mul = fmul contract <8 x half> %v1, %x
359  %add = fadd contract <8 x half> %v2, %mul
360  ret <8 x half> %add
361
362if.else:                                          ; preds = %entry
363  %mul1 = fmul contract <8 x half> %v1, %x
364  %sub = fsub contract <8 x half> %mul1, %v2
365  ret <8 x half> %sub
366}
367
368define double @is_profitable_f64_nocontract(ptr dereferenceable(8) %ptr_x, ptr dereferenceable(8) %ptr_y, ptr dereferenceable(8) %ptr_a) #0 {
369; FP-CONTRACT-FAST-LABEL: define double @is_profitable_f64_nocontract(
370; FP-CONTRACT-FAST-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
371; FP-CONTRACT-FAST-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
372; FP-CONTRACT-FAST-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
373; FP-CONTRACT-FAST-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
374; FP-CONTRACT-FAST-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
375; FP-CONTRACT-FAST-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
376; FP-CONTRACT-FAST:       [[COMMON_RET:.*]]:
377; FP-CONTRACT-FAST-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[PTR_ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
378; FP-CONTRACT-FAST-NEXT:    ret double [[COMMON_RET_OP]]
379; FP-CONTRACT-FAST:       [[IF_THEN]]:
380; FP-CONTRACT-FAST-NEXT:    [[MUL:%.*]] = fmul double [[X]], [[A_1]]
381; FP-CONTRACT-FAST-NEXT:    [[PTR_ADD]] = fadd double 1.000000e+00, [[MUL]]
382; FP-CONTRACT-FAST-NEXT:    br label %[[COMMON_RET]]
383; FP-CONTRACT-FAST:       [[IF_ELSE]]:
384; FP-CONTRACT-FAST-NEXT:    [[MUL1:%.*]] = fmul double [[X]], [[A_1]]
385; FP-CONTRACT-FAST-NEXT:    [[SUB]] = fsub double [[MUL1]], [[Y]]
386; FP-CONTRACT-FAST-NEXT:    br label %[[COMMON_RET]]
387;
388; UNSAFE-FP-MATH-LABEL: define double @is_profitable_f64_nocontract(
389; UNSAFE-FP-MATH-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
390; UNSAFE-FP-MATH-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
391; UNSAFE-FP-MATH-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
392; UNSAFE-FP-MATH-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
393; UNSAFE-FP-MATH-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
394; UNSAFE-FP-MATH-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
395; UNSAFE-FP-MATH:       [[COMMON_RET:.*]]:
396; UNSAFE-FP-MATH-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[PTR_ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
397; UNSAFE-FP-MATH-NEXT:    ret double [[COMMON_RET_OP]]
398; UNSAFE-FP-MATH:       [[IF_THEN]]:
399; UNSAFE-FP-MATH-NEXT:    [[MUL:%.*]] = fmul double [[X]], [[A_1]]
400; UNSAFE-FP-MATH-NEXT:    [[PTR_ADD]] = fadd double 1.000000e+00, [[MUL]]
401; UNSAFE-FP-MATH-NEXT:    br label %[[COMMON_RET]]
402; UNSAFE-FP-MATH:       [[IF_ELSE]]:
403; UNSAFE-FP-MATH-NEXT:    [[MUL1:%.*]] = fmul double [[X]], [[A_1]]
404; UNSAFE-FP-MATH-NEXT:    [[SUB]] = fsub double [[MUL1]], [[Y]]
405; UNSAFE-FP-MATH-NEXT:    br label %[[COMMON_RET]]
406;
407; NO-UNSAFE-FP-MATH-LABEL: define double @is_profitable_f64_nocontract(
408; NO-UNSAFE-FP-MATH-SAME: ptr dereferenceable(8) [[PTR_X:%.*]], ptr dereferenceable(8) [[PTR_Y:%.*]], ptr dereferenceable(8) [[PTR_A:%.*]]) #[[ATTR0]] {
409; NO-UNSAFE-FP-MATH-NEXT:    [[Y:%.*]] = load double, ptr [[PTR_Y]], align 8
410; NO-UNSAFE-FP-MATH-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
411; NO-UNSAFE-FP-MATH-NEXT:    [[X:%.*]] = load double, ptr [[PTR_X]], align 8
412; NO-UNSAFE-FP-MATH-NEXT:    [[A_1:%.*]] = load double, ptr [[PTR_A]], align 8
413; NO-UNSAFE-FP-MATH-NEXT:    [[MUL:%.*]] = fmul double [[X]], [[A_1]]
414; NO-UNSAFE-FP-MATH-NEXT:    br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
415; NO-UNSAFE-FP-MATH:       [[COMMON_RET:.*]]:
416; NO-UNSAFE-FP-MATH-NEXT:    [[COMMON_RET_OP:%.*]] = phi double [ [[PTR_ADD:%.*]], %[[IF_THEN]] ], [ [[SUB:%.*]], %[[IF_ELSE]] ]
417; NO-UNSAFE-FP-MATH-NEXT:    ret double [[COMMON_RET_OP]]
418; NO-UNSAFE-FP-MATH:       [[IF_THEN]]:
419; NO-UNSAFE-FP-MATH-NEXT:    [[PTR_ADD]] = fadd double 1.000000e+00, [[MUL]]
420; NO-UNSAFE-FP-MATH-NEXT:    br label %[[COMMON_RET]]
421; NO-UNSAFE-FP-MATH:       [[IF_ELSE]]:
422; NO-UNSAFE-FP-MATH-NEXT:    [[SUB]] = fsub double [[MUL]], [[Y]]
423; NO-UNSAFE-FP-MATH-NEXT:    br label %[[COMMON_RET]]
424;
425  %y = load double, ptr %ptr_y, align 8
426  %cmp = fcmp oeq double %y, 0.000000e+00
427  %x = load double, ptr %ptr_x, align 8
428  br i1 %cmp, label %if.then, label %if.else
429
430if.then:                                          ; preds = %entry
431  %a_1 = load double, ptr %ptr_a, align 8
432  %mul = fmul double %x, %a_1
433  %ptr_add = fadd double 1.000000e+00, %mul
434  ret double %ptr_add
435
436if.else:                                          ; preds = %entry
437  %a_2 = load double, ptr %ptr_a, align 8
438  %mul1 = fmul double %x, %a_2
439  %sub = fsub double %mul1, %y
440  ret double %sub
441}
442
443attributes #0 = { nounwind "denormal-fp-math"="preserve-sign,preserve-sign" }
444attributes #1 = { nounwind "denormal-fp-math"="ieee,ieee" }
445