1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
5 %struct.T = type { i32, [10 x [20 x i8]] }
7 declare noalias ptr @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc"
9 define i8 @select_offsets_simplifiable_1(i1 %cnd1, i1 %cnd2) {
10 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_1
11 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) {
13 ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1)
14 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
15 ; CHECK-NEXT: store i8 23, ptr [[GEP23]], align 4
16 ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29
17 ; CHECK-NEXT: store i8 29, ptr [[GEP29]], align 4
18 ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7
19 ; CHECK-NEXT: store i8 7, ptr [[GEP7]], align 4
20 ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31
21 ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29
22 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7
23 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]]
24 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_SEL]], align 4
25 ; CHECK-NEXT: ret i8 [[I]]
28 %Bytes = call ptr @calloc(i64 1024, i64 1)
30 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
31 store i8 23, ptr %gep23, align 4
32 %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29
33 store i8 29, ptr %gep29, align 4
34 %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7
35 store i8 7, ptr %gep7, align 4
37 ;; This store is redundant, hence removed.
38 %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31
39 store i8 42, ptr %gep31, align 4
41 %sel0 = select i1 %cnd1, i64 23, i64 29
42 %sel1 = select i1 %cnd2, i64 %sel0, i64 7
43 %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1
44 %i = load i8, ptr %gep.sel, align 4
48 define i8 @select_offsets_simplifiable_2(i1 %cnd1, i1 %cnd2) {
49 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
50 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_2
51 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1:[0-9]+]] {
53 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
54 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
55 ; CHECK-NEXT: store i8 23, ptr [[GEP23]], align 4
56 ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29
57 ; CHECK-NEXT: store i8 29, ptr [[GEP29]], align 4
58 ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7
59 ; CHECK-NEXT: store i8 7, ptr [[GEP7]], align 4
60 ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31
61 ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 20, i64 26
62 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 4
63 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]]
64 ; CHECK-NEXT: [[GEP_PLUS:%.*]] = getelementptr inbounds i8, ptr [[GEP_SEL]], i64 3
65 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_PLUS]], align 4
66 ; CHECK-NEXT: ret i8 [[I]]
69 %Bytes = alloca [1024 x i8], align 16
71 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
72 store i8 23, ptr %gep23, align 4
73 %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29
74 store i8 29, ptr %gep29, align 4
75 %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7
76 store i8 7, ptr %gep7, align 4
78 ;; This store is redundant, hence removed.
79 %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31
80 store i8 42, ptr %gep31, align 4
82 ;; Adjust the offsets so that they match the stores after adding 3
83 %sel0 = select i1 %cnd1, i64 20, i64 26
84 %sel1 = select i1 %cnd2, i64 %sel0, i64 4
85 %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1
86 %gep.plus = getelementptr inbounds i8, ptr %gep.sel, i64 3
87 %i = load i8, ptr %gep.plus, align 4
91 define i8 @select_offsets_simplifiable_3(i1 %cnd1, i1 %cnd2) {
92 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
93 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_3
94 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] {
96 ; CHECK-NEXT: [[BUNDLE:%.*]] = alloca [[STRUCT_T:%.*]], align 64
97 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND1]], i64 1, i64 3
98 ; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CND2]], i64 5, i64 11
99 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [[STRUCT_T]], ptr [[BUNDLE]], i64 0, i32 1, i64 [[SEL1]], i64 [[SEL2]]
100 ; CHECK-NEXT: ret i8 100
103 %bundle = alloca %struct.T, align 64
104 %gep.fixed = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 1, i64 1
105 store i8 100, ptr %gep.fixed, align 4
106 %sel1 = select i1 %cnd1, i64 1, i64 3
107 %sel2 = select i1 %cnd2, i64 5, i64 11
108 %gep.sel = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 %sel1, i64 %sel2
109 store i8 42, ptr %gep.sel, align 4
110 %i = load i8, ptr %gep.fixed, align 4
114 ; Similar to select_offsets_not_simplifiable_3 but with uninitialized memory.
115 define i8 @select_offsets_simplifiable_4(i1 %cnd1, i1 %cnd2) {
116 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
117 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_simplifiable_4
118 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] {
120 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
121 ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29
122 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7
123 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]]
124 ; CHECK-NEXT: ret i8 100
127 %Bytes = alloca [1024 x i8], align 16
128 %sel0 = select i1 %cnd1, i64 23, i64 29
129 %sel1 = select i1 %cnd2, i64 %sel0, i64 7
130 %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1
131 store i8 100, ptr %gep.sel, align 4
132 %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29
133 %i = load i8, ptr %gep29, align 4
137 define i8 @select_offsets_not_simplifiable_1(i1 %cnd1, i1 %cnd2) {
138 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
139 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_1
140 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] {
142 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
143 ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29
144 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7
145 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
146 ; CHECK-NEXT: store i8 100, ptr [[GEP23]], align 4
147 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]]
148 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_SEL]], align 4
149 ; CHECK-NEXT: ret i8 [[I]]
152 %Bytes = alloca [1024 x i8], align 16
153 %sel0 = select i1 %cnd1, i64 23, i64 29
154 %sel1 = select i1 %cnd2, i64 %sel0, i64 7
155 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
156 store i8 100, ptr %gep23, align 4
157 %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1
158 %i = load i8, ptr %gep.sel, align 4
162 define i8 @select_offsets_not_simplifiable_2(i1 %cnd1, i1 %cnd2) {
163 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
164 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_2
165 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] {
167 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
168 ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29
169 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7
170 ; CHECK-NEXT: [[GEP32:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 32
171 ; CHECK-NEXT: store i8 100, ptr [[GEP32]], align 16
172 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]]
173 ; CHECK-NEXT: [[GEP_PLUS:%.*]] = getelementptr inbounds i8, ptr [[GEP_SEL]], i64 3
174 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_PLUS]], align 4
175 ; CHECK-NEXT: ret i8 [[I]]
178 %Bytes = alloca [1024 x i8], align 16
179 %sel0 = select i1 %cnd1, i64 23, i64 29
180 %sel1 = select i1 %cnd2, i64 %sel0, i64 7
181 %gep32 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 32
182 store i8 100, ptr %gep32, align 4
183 %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1
184 %gep.plus = getelementptr inbounds i8, ptr %gep.sel, i64 3
185 %i = load i8, ptr %gep.plus, align 4
189 define i8 @select_offsets_not_simplifiable_3(i1 %cnd1, i1 %cnd2) {
190 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_3
191 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) {
193 ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1)
194 ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29
195 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7
196 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]]
197 ; CHECK-NEXT: store i8 100, ptr [[GEP_SEL]], align 4
198 ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29
199 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP29]], align 4
200 ; CHECK-NEXT: ret i8 [[I]]
203 %Bytes = call ptr @calloc(i64 1024, i64 1)
204 %sel0 = select i1 %cnd1, i64 23, i64 29
205 %sel1 = select i1 %cnd2, i64 %sel0, i64 7
206 %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1
207 store i8 100, ptr %gep.sel, align 4
208 %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29
209 %i = load i8, ptr %gep29, align 4
213 define i8 @select_offsets_not_simplifiable_4(i1 %cnd1, i1 %cnd2) {
214 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_4
215 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) {
217 ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1)
218 ; CHECK-NEXT: [[SEL0:%.*]] = select i1 [[CND1]], i64 23, i64 29
219 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND2]], i64 [[SEL0]], i64 7
220 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[SEL1]]
221 ; CHECK-NEXT: [[GEP_PLUS:%.*]] = getelementptr inbounds i8, ptr [[GEP_SEL]], i64 3
222 ; CHECK-NEXT: store i8 100, ptr [[GEP_PLUS]], align 4
223 ; CHECK-NEXT: [[GEP32:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 32
224 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP32]], align 4
225 ; CHECK-NEXT: ret i8 [[I]]
228 %Bytes = call ptr @calloc(i64 1024, i64 1)
229 %sel0 = select i1 %cnd1, i64 23, i64 29
230 %sel1 = select i1 %cnd2, i64 %sel0, i64 7
231 %gep.sel = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %sel1
232 %gep.plus = getelementptr inbounds i8, ptr %gep.sel, i64 3
233 store i8 100, ptr %gep.plus, align 4
234 %gep32 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 32
235 %i = load i8, ptr %gep32, align 4
239 define i8 @select_offsets_not_simplifiable_5(i1 %cnd1, i1 %cnd2) {
240 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
241 ; CHECK-LABEL: define {{[^@]+}}@select_offsets_not_simplifiable_5
242 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] {
244 ; CHECK-NEXT: [[BUNDLE:%.*]] = alloca [[STRUCT_T:%.*]], align 64
245 ; CHECK-NEXT: [[GEP_FIXED:%.*]] = getelementptr inbounds [[STRUCT_T]], ptr [[BUNDLE]], i64 0, i32 1, i64 3, i64 5
246 ; CHECK-NEXT: store i8 100, ptr [[GEP_FIXED]], align 4
247 ; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CND1]], i64 1, i64 3
248 ; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CND2]], i64 5, i64 11
249 ; CHECK-NEXT: [[GEP_SEL:%.*]] = getelementptr inbounds [[STRUCT_T]], ptr [[BUNDLE]], i64 0, i32 1, i64 [[SEL1]], i64 [[SEL2]]
250 ; CHECK-NEXT: store i8 42, ptr [[GEP_SEL]], align 4
251 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP_FIXED]], align 4
252 ; CHECK-NEXT: ret i8 [[I]]
255 %bundle = alloca %struct.T, align 64
256 %gep.fixed = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 3, i64 5
257 store i8 100, ptr %gep.fixed, align 4
258 %sel1 = select i1 %cnd1, i64 1, i64 3
259 %sel2 = select i1 %cnd2, i64 5, i64 11
260 %gep.sel = getelementptr inbounds %struct.T, ptr %bundle, i64 0, i32 1, i64 %sel1, i64 %sel2
262 ;; This store prevents the constant 100 from being propagated to ret
263 store i8 42, ptr %gep.sel, align 4
265 %i = load i8, ptr %gep.fixed, align 4
269 define i8 @select_gep_simplifiable_1(i1 %cnd1, i1 %cnd2) {
270 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
271 ; CHECK-LABEL: define {{[^@]+}}@select_gep_simplifiable_1
272 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR2:[0-9]+]] {
274 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
275 ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7
276 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
277 ; CHECK-NEXT: [[SEL_PTR:%.*]] = select i1 [[CND1]], ptr [[GEP7]], ptr [[GEP23]]
278 ; CHECK-NEXT: store i8 42, ptr [[SEL_PTR]], align 4
279 ; CHECK-NEXT: ret i8 21
282 %Bytes = alloca [1024 x i8], align 16
283 %gep3 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 3
284 store i8 21, ptr %gep3, align 4
285 %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7
286 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
287 %sel.ptr = select i1 %cnd1, ptr %gep7, ptr %gep23
288 store i8 42, ptr %sel.ptr, align 4
289 %i = load i8, ptr %gep3, align 4
293 define i8 @select_gep_not_simplifiable_1(i1 %cnd1, i1 %cnd2) {
294 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
295 ; CHECK-LABEL: define {{[^@]+}}@select_gep_not_simplifiable_1
296 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR3:[0-9]+]] {
298 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
299 ; CHECK-NEXT: [[GEP7:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 7
300 ; CHECK-NEXT: store i8 1, ptr [[GEP7]], align 4
301 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
302 ; CHECK-NEXT: [[SEL_PTR:%.*]] = select i1 [[CND1]], ptr [[GEP7]], ptr [[GEP23]]
303 ; CHECK-NEXT: store i8 42, ptr [[SEL_PTR]], align 4
304 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP7]], align 4
305 ; CHECK-NEXT: ret i8 [[I]]
308 %Bytes = alloca [1024 x i8], align 16
309 %gep7 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 7
310 store i8 1, ptr %gep7, align 4
311 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
312 %sel.ptr = select i1 %cnd1, ptr %gep7, ptr %gep23
313 store i8 42, ptr %sel.ptr, align 4
314 %i = load i8, ptr %gep7, align 4
318 ; FIXME: The whole function is just "ret i8 21".
320 define i8 @phi_gep_simplifiable_1(i1 %cnd1, i1 %cnd2) {
321 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
322 ; CHECK-LABEL: define {{[^@]+}}@phi_gep_simplifiable_1
323 ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR3]] {
325 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
326 ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]]
328 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
329 ; CHECK-NEXT: store i8 21, ptr [[GEP23]], align 4
330 ; CHECK-NEXT: br label [[JOIN:%.*]]
332 ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31
333 ; CHECK-NEXT: store i8 21, ptr [[GEP31]], align 4
334 ; CHECK-NEXT: br label [[JOIN]]
336 ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ]
337 ; CHECK-NEXT: [[GEP29:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 29
338 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[PHI_PTR]], align 4
339 ; CHECK-NEXT: ret i8 [[I]]
342 %Bytes = alloca [1024 x i8], align 16
343 br i1 %cnd1, label %then, label %else
346 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
347 store i8 21, ptr %gep23, align 4
351 %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31
352 store i8 21, ptr %gep31, align 4
356 %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else]
357 ;; This store is eliminated
358 %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29
359 store i8 42, ptr %gep29, align 4
360 %i = load i8, ptr %phi.ptr, align 4
364 ; FIXME: The whole function is just "ret i8 42".
366 define i8 @phi_gep_simplifiable_2(i1 %cnd1, i1 %cnd2) {
367 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
368 ; CHECK-LABEL: define {{[^@]+}}@phi_gep_simplifiable_2
369 ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR2]] {
371 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
372 ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]]
374 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
375 ; CHECK-NEXT: br label [[JOIN:%.*]]
377 ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31
378 ; CHECK-NEXT: br label [[JOIN]]
380 ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ]
381 ; CHECK-NEXT: store i8 21, ptr [[PHI_PTR]], align 4
382 ; CHECK-NEXT: ret i8 42
385 %Bytes = alloca [1024 x i8], align 16
386 %gep29 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 29
387 ;; This store is propagated to the load.
388 store i8 42, ptr %gep29, align 4
389 br i1 %cnd1, label %then, label %else
392 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
396 %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31
400 %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else]
401 store i8 21, ptr %phi.ptr, align 4
402 ;; Replaced with the constant, and both store/load are eliminated.
403 %i = load i8, ptr %gep29, align 4
407 define i8 @phi_gep_not_simplifiable_1(i1 %cnd1, i1 %cnd2) {
408 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
409 ; CHECK-LABEL: define {{[^@]+}}@phi_gep_not_simplifiable_1
410 ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR3]] {
412 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
413 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
414 ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]]
416 ; CHECK-NEXT: br label [[JOIN:%.*]]
418 ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31
419 ; CHECK-NEXT: br label [[JOIN]]
421 ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ]
422 ; CHECK-NEXT: store i8 42, ptr [[GEP23]], align 4
423 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[PHI_PTR]], align 4
424 ; CHECK-NEXT: ret i8 [[I]]
427 %Bytes = alloca [1024 x i8], align 16
428 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
429 br i1 %cnd1, label %then, label %else
435 %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31
439 %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else]
440 ;; This store cannot be eliminated
441 store i8 42, ptr %gep23, align 4
442 %i = load i8, ptr %phi.ptr, align 4
446 define i8 @phi_gep_not_simplifiable_2(i1 %cnd1, i1 %cnd2) {
447 ; CHECK-LABEL: define {{[^@]+}}@phi_gep_not_simplifiable_2
448 ; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) {
450 ; CHECK-NEXT: [[BYTES:%.*]] = call ptr @calloc(i64 noundef 1024, i64 noundef 1)
451 ; CHECK-NEXT: [[GEP23:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 23
452 ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]]
454 ; CHECK-NEXT: br label [[JOIN:%.*]]
456 ; CHECK-NEXT: [[GEP31:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 31
457 ; CHECK-NEXT: br label [[JOIN]]
459 ; CHECK-NEXT: [[PHI_PTR:%.*]] = phi ptr [ [[GEP23]], [[THEN]] ], [ [[GEP31]], [[ELSE]] ]
460 ; CHECK-NEXT: store i8 21, ptr [[PHI_PTR]], align 4
461 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[GEP23]], align 4
462 ; CHECK-NEXT: ret i8 [[I]]
465 %Bytes = call ptr @calloc(i64 1024, i64 1)
466 %gep23 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 23
467 br i1 %cnd1, label %then, label %else
473 %gep31 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 31
477 %phi.ptr = phi ptr [%gep23, %then], [%gep31, %else]
478 store i8 21, ptr %phi.ptr, align 4
479 %i = load i8, ptr %gep23, align 4
483 define i8 @phi_offsets(i1 %cnd1, i1 %cnd2) {
484 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
485 ; CHECK-LABEL: define {{[^@]+}}@phi_offsets
486 ; CHECK-SAME: (i1 noundef [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR1]] {
488 ; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
489 ; CHECK-NEXT: br i1 [[CND1]], label [[THEN:%.*]], label [[ELSE:%.*]]
491 ; CHECK-NEXT: br label [[JOIN:%.*]]
493 ; CHECK-NEXT: br label [[JOIN]]
495 ; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 3, [[THEN]] ], [ 11, [[ELSE]] ]
496 ; CHECK-NEXT: [[GEP_PHI:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[PHI]]
497 ; CHECK-NEXT: ret i8 100
500 %Bytes = alloca [1024 x i8], align 16
501 store i8 100, ptr %Bytes, align 4
502 br i1 %cnd1, label %then, label %else
511 %phi = phi i64 [ 3, %then ], [ 11, %else ]
512 %gep.phi = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %phi
513 store i8 42, ptr %gep.phi, align 4
514 %i = load i8, ptr %Bytes, align 4
519 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" }
520 ; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
521 ; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
522 ; CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn }
524 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: