xref: /llvm-project/llvm/test/Transforms/GVN/edge.ll (revision cd16b077bf4bc6d55e06c41fa0f6774ac05dcb56)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -passes=gvn -S < %s | FileCheck %s
3
4define i32 @f1(i32 %x) {
5; CHECK-LABEL: define i32 @f1(
6; CHECK-SAME: i32 [[X:%.*]]) {
7; CHECK-NEXT:  [[BB0:.*:]]
8; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X]], 0
9; CHECK-NEXT:    br i1 [[CMP]], label %[[BB2:.*]], label %[[BB1:.*]]
10; CHECK:       [[BB1]]:
11; CHECK-NEXT:    br label %[[BB2]]
12; CHECK:       [[BB2]]:
13; CHECK-NEXT:    ret i32 [[X]]
14;
15bb0:
16  %cmp = icmp eq i32 %x, 0
17  br i1 %cmp, label %bb2, label %bb1
18bb1:
19  br label %bb2
20bb2:
21  %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
22  %foo = add i32 %cond, %x
23  ret i32 %foo
24}
25
26define i32 @f2(i32 %x) {
27; CHECK-LABEL: define i32 @f2(
28; CHECK-SAME: i32 [[X:%.*]]) {
29; CHECK-NEXT:  [[BB0:.*:]]
30; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[X]], 0
31; CHECK-NEXT:    br i1 [[CMP]], label %[[BB1:.*]], label %[[BB2:.*]]
32; CHECK:       [[BB1]]:
33; CHECK-NEXT:    br label %[[BB2]]
34; CHECK:       [[BB2]]:
35; CHECK-NEXT:    ret i32 [[X]]
36;
37bb0:
38  %cmp = icmp ne i32 %x, 0
39  br i1 %cmp, label %bb1, label %bb2
40bb1:
41  br label %bb2
42bb2:
43  %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
44  %foo = add i32 %cond, %x
45  ret i32 %foo
46}
47
48define i32 @f3(i32 %x) {
49; CHECK-LABEL: define i32 @f3(
50; CHECK-SAME: i32 [[X:%.*]]) {
51; CHECK-NEXT:  [[BB0:.*:]]
52; CHECK-NEXT:    switch i32 [[X]], label %[[BB1:.*]] [
53; CHECK-NEXT:      i32 0, label %[[BB2:.*]]
54; CHECK-NEXT:    ]
55; CHECK:       [[BB1]]:
56; CHECK-NEXT:    br label %[[BB2]]
57; CHECK:       [[BB2]]:
58; CHECK-NEXT:    ret i32 [[X]]
59;
60bb0:
61  switch i32 %x, label %bb1 [ i32 0, label %bb2]
62bb1:
63  br label %bb2
64bb2:
65  %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
66  %foo = add i32 %cond, %x
67  ret i32 %foo
68}
69
70declare void @g(i1)
71define void @f4(ptr %x)  {
72; CHECK-LABEL: define void @f4(
73; CHECK-SAME: ptr [[X:%.*]]) {
74; CHECK-NEXT:  [[BB0:.*:]]
75; CHECK-NEXT:    [[Y:%.*]] = icmp eq ptr null, [[X]]
76; CHECK-NEXT:    br i1 [[Y]], label %[[BB2:.*]], label %[[BB1:.*]]
77; CHECK:       [[BB1]]:
78; CHECK-NEXT:    br label %[[BB2]]
79; CHECK:       [[BB2]]:
80; CHECK-NEXT:    call void @g(i1 [[Y]])
81; CHECK-NEXT:    ret void
82;
83bb0:
84  %y = icmp eq ptr null, %x
85  br i1 %y, label %bb2, label %bb1
86bb1:
87  br label %bb2
88bb2:
89  %zed = icmp eq ptr null, %x
90  call void @g(i1 %zed)
91  ret void
92}
93
94define double @fcmp_oeq_not_zero(double %x, double %y) {
95; CHECK-LABEL: define double @fcmp_oeq_not_zero(
96; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
97; CHECK-NEXT:  [[ENTRY:.*]]:
98; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 2.000000e+00
99; CHECK-NEXT:    br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]]
100; CHECK:       [[IF]]:
101; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00
102; CHECK-NEXT:    br label %[[RETURN]]
103; CHECK:       [[RETURN]]:
104; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ]
105; CHECK-NEXT:    ret double [[RETVAL]]
106;
107entry:
108  %cmp = fcmp oeq double %y, 2.0
109  br i1 %cmp, label %if, label %return
110
111if:
112  %div = fdiv double %x, %y
113  br label %return
114
115return:
116  %retval = phi double [ %div, %if ], [ %x, %entry ]
117  ret double %retval
118}
119
120define double @fcmp_une_not_zero(double %x, double %y) {
121; CHECK-LABEL: define double @fcmp_une_not_zero(
122; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
123; CHECK-NEXT:  [[ENTRY:.*]]:
124; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[Y]], 2.000000e+00
125; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]]
126; CHECK:       [[ELSE]]:
127; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00
128; CHECK-NEXT:    br label %[[RETURN]]
129; CHECK:       [[RETURN]]:
130; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ]
131; CHECK-NEXT:    ret double [[RETVAL]]
132;
133entry:
134  %cmp = fcmp une double %y, 2.0
135  br i1 %cmp, label %return, label %else
136
137else:
138  %div = fdiv double %x, %y
139  br label %return
140
141return:
142  %retval = phi double [ %div, %else ], [ %x, %entry ]
143  ret double %retval
144}
145
146define double @fcmp_one_possibly_nan(double %x, double %y) {
147; CHECK-LABEL: define double @fcmp_one_possibly_nan(
148; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
149; CHECK-NEXT:  [[ENTRY:.*]]:
150; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[Y]], 2.000000e+00
151; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]]
152; CHECK:       [[ELSE]]:
153; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], [[Y]]
154; CHECK-NEXT:    br label %[[RETURN]]
155; CHECK:       [[RETURN]]:
156; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ]
157; CHECK-NEXT:    ret double [[RETVAL]]
158;
159entry:
160  %cmp = fcmp one double %y, 2.0
161  br i1 %cmp, label %return, label %else
162
163else:
164  %div = fdiv double %x, %y
165  br label %return
166
167return:
168  %retval = phi double [ %div, %else ], [ %x, %entry ]
169  ret double %retval
170}
171
172define double @fcmp_one_not_zero_or_nan(double %x, double %y) {
173; CHECK-LABEL: define double @fcmp_one_not_zero_or_nan(
174; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
175; CHECK-NEXT:  [[ENTRY:.*]]:
176; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan one double [[Y]], 2.000000e+00
177; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]]
178; CHECK:       [[ELSE]]:
179; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00
180; CHECK-NEXT:    br label %[[RETURN]]
181; CHECK:       [[RETURN]]:
182; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ]
183; CHECK-NEXT:    ret double [[RETVAL]]
184;
185entry:
186  %cmp = fcmp nnan one double %y, 2.0
187  br i1 %cmp, label %return, label %else
188
189else:
190  %div = fdiv double %x, %y
191  br label %return
192
193return:
194  %retval = phi double [ %div, %else ], [ %x, %entry ]
195  ret double %retval
196}
197
198; PR22376 - We can't propagate zero constants because -0.0
199; compares equal to 0.0. If %y is -0.0 in this test case,
200; we would produce the wrong sign on the infinity return value.
201define double @fcmp_oeq_zero(double %x, double %y) {
202; CHECK-LABEL: define double @fcmp_oeq_zero(
203; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
204; CHECK-NEXT:  [[ENTRY:.*]]:
205; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00
206; CHECK-NEXT:    br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]]
207; CHECK:       [[IF]]:
208; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], [[Y]]
209; CHECK-NEXT:    br label %[[RETURN]]
210; CHECK:       [[RETURN]]:
211; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ]
212; CHECK-NEXT:    ret double [[RETVAL]]
213;
214entry:
215  %cmp = fcmp oeq double %y, 0.0
216  br i1 %cmp, label %if, label %return
217
218if:
219  %div = fdiv double %x, %y
220  br label %return
221
222return:
223  %retval = phi double [ %div, %if ], [ %x, %entry ]
224  ret double %retval
225}
226
227; Denormals may be flushed to zero in some cases by the backend.
228; Hence, treat denormals as 0.
229define float @fcmp_oeq_denormal(float %x, float %y) {
230; CHECK-LABEL: define float @fcmp_oeq_denormal(
231; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
232; CHECK-NEXT:  [[ENTRY:.*]]:
233; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[Y]], 0x3800000000000000
234; CHECK-NEXT:    br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]]
235; CHECK:       [[IF]]:
236; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[X]], [[Y]]
237; CHECK-NEXT:    br label %[[RETURN]]
238; CHECK:       [[RETURN]]:
239; CHECK-NEXT:    [[RETVAL:%.*]] = phi float [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ]
240; CHECK-NEXT:    ret float [[RETVAL]]
241;
242entry:
243  %cmp = fcmp oeq float %y, 0x3800000000000000
244  br i1 %cmp, label %if, label %return
245
246if:
247  %div = fdiv float %x, %y
248  br label %return
249
250return:
251  %retval = phi float [ %div, %if ], [ %x, %entry ]
252  ret float %retval
253}
254
255define double @fcmp_une_zero(double %x, double %y) {
256; CHECK-LABEL: define double @fcmp_une_zero(
257; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
258; CHECK-NEXT:  [[ENTRY:.*]]:
259; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[Y]], -0.000000e+00
260; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]]
261; CHECK:       [[ELSE]]:
262; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], [[Y]]
263; CHECK-NEXT:    br label %[[RETURN]]
264; CHECK:       [[RETURN]]:
265; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ]
266; CHECK-NEXT:    ret double [[RETVAL]]
267;
268entry:
269  %cmp = fcmp une double %y, -0.0
270  br i1 %cmp, label %return, label %else
271
272else:
273  %div = fdiv double %x, %y
274  br label %return
275
276return:
277  %retval = phi double [ %div, %else ], [ %x, %entry ]
278  ret double %retval
279}
280
281; We also cannot propagate a value if it's not a constant.
282; This is because the value could be 0.0, -0.0, or a denormal.
283
284define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) {
285; CHECK-LABEL: define double @fcmp_oeq_maybe_zero(
286; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) {
287; CHECK-NEXT:  [[ENTRY:.*]]:
288; CHECK-NEXT:    [[Z:%.*]] = fadd double [[Z1]], [[Z2]]
289; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y]], [[Z]]
290; CHECK-NEXT:    br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]]
291; CHECK:       [[IF]]:
292; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], [[Z]]
293; CHECK-NEXT:    br label %[[RETURN]]
294; CHECK:       [[RETURN]]:
295; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ]
296; CHECK-NEXT:    ret double [[RETVAL]]
297;
298entry:
299  %z = fadd double %z1, %z2
300  %cmp = fcmp oeq double %y, %z
301  br i1 %cmp, label %if, label %return
302
303if:
304  %div = fdiv double %x, %z
305  br label %return
306
307return:
308  %retval = phi double [ %div, %if ], [ %x, %entry ]
309  ret double %retval
310}
311
312define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) {
313; CHECK-LABEL: define double @fcmp_une_maybe_zero(
314; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) {
315; CHECK-NEXT:  [[ENTRY:.*]]:
316; CHECK-NEXT:    [[Z:%.*]] = fadd double [[Z1]], [[Z2]]
317; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[Y]], [[Z]]
318; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]]
319; CHECK:       [[ELSE]]:
320; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], [[Z]]
321; CHECK-NEXT:    br label %[[RETURN]]
322; CHECK:       [[RETURN]]:
323; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ]
324; CHECK-NEXT:    ret double [[RETVAL]]
325;
326entry:
327  %z = fadd double %z1, %z2
328  %cmp = fcmp une double %y, %z
329  br i1 %cmp, label %return, label %else
330
331else:
332  %div = fdiv double %x, %z
333  br label %return
334
335return:
336  %retval = phi double [ %div, %else ], [ %x, %entry ]
337  ret double %retval
338}
339
340
341define double @fcmp_ueq_possibly_nan(double %x, double %y) {
342; CHECK-LABEL: define double @fcmp_ueq_possibly_nan(
343; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
344; CHECK-NEXT:  [[ENTRY:.*]]:
345; CHECK-NEXT:    [[CMP:%.*]] = fcmp ueq double [[Y]], 2.000000e+00
346; CHECK-NEXT:    br i1 [[CMP]], label %[[DO_DIV:.*]], label %[[RETURN:.*]]
347; CHECK:       [[DO_DIV]]:
348; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], [[Y]]
349; CHECK-NEXT:    br label %[[RETURN]]
350; CHECK:       [[RETURN]]:
351; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[DO_DIV]] ], [ [[X]], %[[ENTRY]] ]
352; CHECK-NEXT:    ret double [[RETVAL]]
353;
354entry:
355  %cmp = fcmp ueq double %y, 2.0
356  br i1 %cmp, label %do_div, label %return
357
358do_div:
359  %div = fdiv double %x, %y
360  br label %return
361
362return:
363  %retval = phi double [ %div, %do_div ], [ %x, %entry ]
364  ret double %retval
365}
366
367define double @fcmp_ueq_not_zero_or_nan(double %x, double %y) {
368; CHECK-LABEL: define double @fcmp_ueq_not_zero_or_nan(
369; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
370; CHECK-NEXT:  [[ENTRY:.*]]:
371; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan ueq double [[Y]], 2.000000e+00
372; CHECK-NEXT:    br i1 [[CMP]], label %[[DO_DIV:.*]], label %[[RETURN:.*]]
373; CHECK:       [[DO_DIV]]:
374; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00
375; CHECK-NEXT:    br label %[[RETURN]]
376; CHECK:       [[RETURN]]:
377; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], %[[DO_DIV]] ], [ [[X]], %[[ENTRY]] ]
378; CHECK-NEXT:    ret double [[RETVAL]]
379;
380entry:
381  %cmp = fcmp nnan ueq double %y, 2.0
382  br i1 %cmp, label %do_div, label %return
383
384do_div:
385  %div = fdiv double %x, %y
386  br label %return
387
388return:
389  %retval = phi double [ %div, %do_div ], [ %x, %entry ]
390  ret double %retval
391}
392