xref: /llvm-project/llvm/test/Transforms/CorrelatedValuePropagation/phi-common-val.ll (revision df9c00beea5be08fc47aaea58eae333fc6cbef33)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
3
4define ptr @simplify_phi_common_value_op0(ptr %ptr, ptr %b) {
5; CHECK-LABEL: @simplify_phi_common_value_op0(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq ptr [[PTR:%.*]], null
8; CHECK-NEXT:    br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]]
9; CHECK:       else:
10; CHECK-NEXT:    [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4
11; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[LB]], 1
12; CHECK-NEXT:    store i32 [[ADD]], ptr [[B]], align 4
13; CHECK-NEXT:    br label [[RETURN]]
14; CHECK:       return:
15; CHECK-NEXT:    ret ptr [[PTR]]
16;
17entry:
18  %isnull = icmp eq ptr %ptr, null
19  br i1 %isnull, label %return, label %else
20
21else:
22  %lb = load i32, ptr %b
23  %add = add nsw i32 %lb, 1
24  store i32 %add, ptr %b
25  br label %return
26
27return:
28  %r = phi ptr [ %ptr, %else ], [ null, %entry ]
29  ret ptr %r
30}
31
32define ptr @simplify_phi_common_value_op1(ptr %ptr, ptr %b) {
33; CHECK-LABEL: @simplify_phi_common_value_op1(
34; CHECK-NEXT:  entry:
35; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq ptr [[PTR:%.*]], null
36; CHECK-NEXT:    br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]]
37; CHECK:       else:
38; CHECK-NEXT:    [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4
39; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LB]], 1
40; CHECK-NEXT:    store i32 [[ADD]], ptr [[B]], align 4
41; CHECK-NEXT:    br label [[RETURN]]
42; CHECK:       return:
43; CHECK-NEXT:    ret ptr [[PTR]]
44;
45entry:
46  %isnull = icmp eq ptr %ptr, null
47  br i1 %isnull, label %return, label %else
48
49else:
50  %lb = load i32, ptr %b
51  %add = add i32 %lb, 1
52  store i32 %add, ptr %b
53  br label %return
54
55return:
56  %r = phi ptr [ null, %entry], [ %ptr, %else ]
57  ret ptr %r
58}
59
60define i8 @simplify_phi_multiple_constants(i8 %x, ptr %b) {
61; CHECK-LABEL: @simplify_phi_multiple_constants(
62; CHECK-NEXT:  entry:
63; CHECK-NEXT:    [[IS0:%.*]] = icmp eq i8 [[X:%.*]], 0
64; CHECK-NEXT:    br i1 [[IS0]], label [[RETURN:%.*]], label [[ELSE1:%.*]]
65; CHECK:       else1:
66; CHECK-NEXT:    [[IS42:%.*]] = icmp eq i8 [[X]], 42
67; CHECK-NEXT:    br i1 [[IS42]], label [[RETURN]], label [[ELSE2:%.*]]
68; CHECK:       else2:
69; CHECK-NEXT:    [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4
70; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LB]], 1
71; CHECK-NEXT:    store i32 [[ADD]], ptr [[B]], align 4
72; CHECK-NEXT:    br label [[RETURN]]
73; CHECK:       return:
74; CHECK-NEXT:    ret i8 [[X]]
75;
76entry:
77  %is0 = icmp eq i8 %x, 0
78  br i1 %is0, label %return, label %else1
79
80else1:
81  %is42 = icmp eq i8 %x, 42
82  br i1 %is42, label %return, label %else2
83
84else2:
85  %lb = load i32, ptr %b
86  %add = add i32 %lb, 1
87  store i32 %add, ptr %b
88  br label %return
89
90return:
91  %r = phi i8 [ 0, %entry], [ %x, %else2 ], [ 42, %else1 ]
92  ret i8 %r
93}
94
95define ptr @simplify_phi_common_value_from_instruction(ptr %ptr_op, ptr %b, i32 %i) {
96; CHECK-LABEL: @simplify_phi_common_value_from_instruction(
97; CHECK-NEXT:  entry:
98; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[PTR_OP:%.*]], i32 [[I:%.*]]
99; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq ptr [[PTR]], null
100; CHECK-NEXT:    br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]]
101; CHECK:       else:
102; CHECK-NEXT:    [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4
103; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[LB]], 1
104; CHECK-NEXT:    store i32 [[ADD]], ptr [[B]], align 4
105; CHECK-NEXT:    br label [[RETURN]]
106; CHECK:       return:
107; CHECK-NEXT:    ret ptr [[PTR]]
108;
109entry:
110  %ptr = getelementptr i8, ptr %ptr_op, i32 %i
111  %isnull = icmp eq ptr %ptr, null
112  br i1 %isnull, label %return, label %else
113
114else:
115  %lb = load i32, ptr %b
116  %add = add nsw i32 %lb, 1
117  store i32 %add, ptr %b
118  br label %return
119
120return:
121  %r = phi ptr [ %ptr, %else ], [ null, %entry ]
122  ret ptr %r
123}
124
125; The sub has 'nsw', so it is not safe to propagate that value along
126; the bb2 edge because that would propagate poison to the return.
127; FIXME: In this particular case, it would be possible to perform the
128; transform if we drop nowrap flags from the sub.
129
130define i32 @PR43802(i32 %arg) {
131; CHECK-LABEL: @PR43802(
132; CHECK-NEXT:  entry:
133; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[ARG:%.*]]
134; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[ARG]], -2147483648
135; CHECK-NEXT:    br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]]
136; CHECK:       bb2:
137; CHECK-NEXT:    br label [[BB3]]
138; CHECK:       bb3:
139; CHECK-NEXT:    [[R:%.*]] = phi i32 [ -2147483648, [[BB2]] ], [ [[SUB]], [[ENTRY:%.*]] ]
140; CHECK-NEXT:    ret i32 [[R]]
141;
142entry:
143  %sub = sub nsw i32 0, %arg
144  %cmp = icmp eq i32 %arg, -2147483648
145  br i1 %cmp, label %bb2, label %bb3
146
147bb2:
148  br label %bb3
149
150bb3:
151  %r = phi i32 [ -2147483648, %bb2 ], [ %sub, %entry ]
152  ret i32 %r
153}
154
155; Same as previous test case, but without nowrap flags.
156define i32 @PR43802_without_nowrap(i32 %arg) {
157; CHECK-LABEL: @PR43802_without_nowrap(
158; CHECK-NEXT:  entry:
159; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 0, [[ARG:%.*]]
160; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[ARG]], -2147483648
161; CHECK-NEXT:    br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]]
162; CHECK:       bb2:
163; CHECK-NEXT:    br label [[BB3]]
164; CHECK:       bb3:
165; CHECK-NEXT:    [[SUB:%.*]] = phi i32 [ -2147483648, [[BB2]] ], [ [[SUB1]], [[ENTRY:%.*]] ]
166; CHECK-NEXT:    ret i32 [[SUB]]
167;
168entry:
169  %sub = sub i32 0, %arg
170  %cmp = icmp eq i32 %arg, -2147483648
171  br i1 %cmp, label %bb2, label %bb3
172
173bb2:
174  br label %bb3
175
176bb3:
177  %r = phi i32 [ -2147483648, %bb2 ], [ %sub, %entry ]
178  ret i32 %r
179}
180
181; Similar to the previous case, we know that %y is always poison on the
182; entry -> join1 edge, and thus always zero or poison on the join1 -> join2
183; edge. We need to make sure that we don't replace zero with "zero or poison".
184
185define i8 @pr50399(i8 %x) {
186; CHECK-LABEL: @pr50399(
187; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -100
188; CHECK-NEXT:    [[Y:%.*]] = add nsw i8 [[X]], -100
189; CHECK-NEXT:    br i1 [[CMP]], label [[JOIN1:%.*]], label [[ELSE:%.*]]
190; CHECK:       else:
191; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[Y]], 0
192; CHECK-NEXT:    br i1 [[CMP2]], label [[JOIN1]], label [[ELSE2:%.*]]
193; CHECK:       join1:
194; CHECK-NEXT:    br label [[JOIN2:%.*]]
195; CHECK:       else2:
196; CHECK-NEXT:    br label [[JOIN2]]
197; CHECK:       join2:
198; CHECK-NEXT:    [[PHI:%.*]] = phi i8 [ 0, [[JOIN1]] ], [ [[Y]], [[ELSE2]] ]
199; CHECK-NEXT:    ret i8 [[PHI]]
200;
201  %cmp = icmp slt i8 %x, -100
202  %y = add nsw i8 %x, -100
203  br i1 %cmp, label %join1, label %else
204
205else:                                               ; preds = %cond.end9
206  %cmp2 = icmp eq i8 %y, 0
207  br i1 %cmp2, label %join1, label %else2
208
209join1:
210  br label %join2
211
212else2:                                         ; preds = %bb
213  br label %join2
214
215join2:
216  %phi = phi i8 [ 0, %join1 ], [ %y, %else2 ]
217  ret i8 %phi
218}
219