1 ; "PLAIN" - No optimizations. This tests the target-independent
3 ; RUN: opt -S -o - < %s | FileCheck --check-prefix=PLAIN %s
5 ; "OPT" - Optimizations but no targetdata. This tests target-independent
6 ; folding in the optimizers.
7 ; RUN: opt -S -o - -instcombine -globalopt < %s | FileCheck --check-prefix=OPT %s
9 ; "TO" - Optimizations and targetdata. This tests target-dependent
10 ; folding in the optimizers.
11 ; RUN: opt -S -o - -instcombine -globalopt -default-data-layout="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" < %s | FileCheck --check-prefix=TO %s
13 ; "SCEV" - ScalarEvolution but no targetdata.
14 ; RUN: opt -analyze -scalar-evolution < %s | FileCheck --check-prefix=SCEV %s
16 ; ScalarEvolution with targetdata isn't interesting on these testcases
17 ; because ScalarEvolution doesn't attempt to duplicate all of instcombine's
18 ; and the constant folders' folding.
20 ; PLAIN: %0 = type { i1, double }
21 ; PLAIN: %1 = type { double, float, double, double }
22 ; PLAIN: %2 = type { i64, i64 }
23 ; OPT: %0 = type { i1, double }
24 ; OPT: %1 = type { double, float, double, double }
25 ; OPT: %2 = type { i64, i64 }
27 ; The automatic constant folder in opt does not have targetdata access, so
28 ; it can't fold gep arithmetic, in general. However, the constant folder run
29 ; from instcombine and global opt can use targetdata.
31 ; PLAIN: @G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1)
32 ; PLAIN: @G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1)
33 ; PLAIN: @F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2)
34 ; PLAIN: @F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2)
35 ; PLAIN: @H8 = global i8* getelementptr (i8* null, i32 -1)
36 ; PLAIN: @H1 = global i1* getelementptr (i1* null, i32 -1)
37 ; OPT: @G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1)
38 ; OPT: @G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1)
39 ; OPT: @F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2)
40 ; OPT: @F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2)
41 ; OPT: @H8 = global i8* getelementptr (i8* null, i32 -1)
42 ; OPT: @H1 = global i1* getelementptr (i1* null, i32 -1)
43 ; TO: @G8 = global i8* null
44 ; TO: @G1 = global i1* null
45 ; TO: @F8 = global i8* inttoptr (i64 -1 to i8*)
46 ; TO: @F1 = global i1* inttoptr (i64 -1 to i1*)
47 ; TO: @H8 = global i8* inttoptr (i64 -1 to i8*)
48 ; TO: @H1 = global i1* inttoptr (i64 -1 to i1*)
50 @G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1)
51 @G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1)
52 @F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2)
53 @F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2)
54 @H8 = global i8* getelementptr (i8* inttoptr (i32 0 to i8*), i32 -1)
55 @H1 = global i1* getelementptr (i1* inttoptr (i32 0 to i1*), i32 -1)
57 ; The target-independent folder should be able to do some clever
58 ; simplifications on sizeof, alignof, and offsetof expressions. The
59 ; target-dependent folder should fold these down to constants.
61 ; PLAIN: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310)
62 ; PLAIN: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
63 ; PLAIN: @c = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2)
64 ; PLAIN: @d = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11)
65 ; PLAIN: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64)
66 ; PLAIN: @f = constant i64 1
67 ; OPT: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310)
68 ; OPT: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
69 ; OPT: @c = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2)
70 ; OPT: @d = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11)
71 ; OPT: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64)
72 ; OPT: @f = constant i64 1
73 ; TO: @a = constant i64 18480
74 ; TO: @b = constant i64 8
75 ; TO: @c = constant i64 16
76 ; TO: @d = constant i64 88
77 ; TO: @e = constant i64 16
78 ; TO: @f = constant i64 1
80 @a = constant i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5))
81 @b = constant i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}* null, i64 0, i32 1) to i64)
82 @c = constant i64 ptrtoint (double* getelementptr ({double, double, double, double}* null, i64 0, i32 2) to i64)
83 @d = constant i64 ptrtoint (double* getelementptr ([13 x double]* null, i64 0, i32 11) to i64)
84 @e = constant i64 ptrtoint (double* getelementptr ({double, float, double, double}* null, i64 0, i32 2) to i64)
85 @f = constant i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64)
87 ; The target-dependent folder should cast GEP indices to integer-sized pointers.
89 ; PLAIN: @M = constant i64* getelementptr (i64* null, i32 1)
90 ; PLAIN: @N = constant i64* getelementptr (%2* null, i32 0, i32 1)
91 ; PLAIN: @O = constant i64* getelementptr ([2 x i64]* null, i32 0, i32 1)
92 ; OPT: @M = constant i64* getelementptr (i64* null, i32 1)
93 ; OPT: @N = constant i64* getelementptr (%2* null, i32 0, i32 1)
94 ; OPT: @O = constant i64* getelementptr ([2 x i64]* null, i32 0, i32 1)
95 ; TO: @M = constant i64* inttoptr (i64 8 to i64*)
96 ; TO: @N = constant i64* inttoptr (i64 8 to i64*)
97 ; TO: @O = constant i64* inttoptr (i64 8 to i64*)
99 @M = constant i64* getelementptr (i64 *null, i32 1)
100 @N = constant i64* getelementptr ({ i64, i64 } *null, i32 0, i32 1)
101 @O = constant i64* getelementptr ([2 x i64] *null, i32 0, i32 1)
103 ; Duplicate all of the above as function return values rather than
104 ; global initializers.
106 ; PLAIN: define i8* @goo8() nounwind {
107 ; PLAIN: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) to i8*
110 ; PLAIN: define i1* @goo1() nounwind {
111 ; PLAIN: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) to i1*
114 ; PLAIN: define i8* @foo8() nounwind {
115 ; PLAIN: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) to i8*
118 ; PLAIN: define i1* @foo1() nounwind {
119 ; PLAIN: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) to i1*
122 ; PLAIN: define i8* @hoo8() nounwind {
123 ; PLAIN: %t = bitcast i8* getelementptr (i8* null, i32 -1) to i8*
126 ; PLAIN: define i1* @hoo1() nounwind {
127 ; PLAIN: %t = bitcast i1* getelementptr (i1* null, i32 -1) to i1*
130 ; OPT: define i8* @goo8() nounwind {
131 ; OPT: ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1)
133 ; OPT: define i1* @goo1() nounwind {
134 ; OPT: ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1)
136 ; OPT: define i8* @foo8() nounwind {
137 ; OPT: ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2)
139 ; OPT: define i1* @foo1() nounwind {
140 ; OPT: ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2)
142 ; OPT: define i8* @hoo8() nounwind {
143 ; OPT: ret i8* getelementptr (i8* null, i32 -1)
145 ; OPT: define i1* @hoo1() nounwind {
146 ; OPT: ret i1* getelementptr (i1* null, i32 -1)
148 ; TO: define i8* @goo8() nounwind {
151 ; TO: define i1* @goo1() nounwind {
154 ; TO: define i8* @foo8() nounwind {
155 ; TO: ret i8* inttoptr (i64 -1 to i8*)
157 ; TO: define i1* @foo1() nounwind {
158 ; TO: ret i1* inttoptr (i64 -1 to i1*)
160 ; TO: define i8* @hoo8() nounwind {
161 ; TO: ret i8* inttoptr (i64 -1 to i8*)
163 ; TO: define i1* @hoo1() nounwind {
164 ; TO: ret i1* inttoptr (i64 -1 to i1*)
166 ; SCEV: Classifying expressions for: @goo8
167 ; SCEV: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) to i8*
168 ; SCEV: --> ((-1 * sizeof(i8)) + inttoptr (i32 1 to i8*))
169 ; SCEV: Classifying expressions for: @goo1
170 ; SCEV: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) to i1*
171 ; SCEV: --> ((-1 * sizeof(i1)) + inttoptr (i32 1 to i1*))
172 ; SCEV: Classifying expressions for: @foo8
173 ; SCEV: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) to i8*
174 ; SCEV: --> ((-2 * sizeof(i8)) + inttoptr (i32 1 to i8*))
175 ; SCEV: Classifying expressions for: @foo1
176 ; SCEV: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) to i1*
177 ; SCEV: --> ((-2 * sizeof(i1)) + inttoptr (i32 1 to i1*))
178 ; SCEV: Classifying expressions for: @hoo8
179 ; SCEV: --> (-1 * sizeof(i8))
180 ; SCEV: Classifying expressions for: @hoo1
181 ; SCEV: --> (-1 * sizeof(i1))
183 define i8* @goo8() nounwind {
184 %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) to i8*
187 define i1* @goo1() nounwind {
188 %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) to i1*
191 define i8* @foo8() nounwind {
192 %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) to i8*
195 define i1* @foo1() nounwind {
196 %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) to i1*
199 define i8* @hoo8() nounwind {
200 %t = bitcast i8* getelementptr (i8* inttoptr (i32 0 to i8*), i32 -1) to i8*
203 define i1* @hoo1() nounwind {
204 %t = bitcast i1* getelementptr (i1* inttoptr (i32 0 to i1*), i32 -1) to i1*
208 ; PLAIN: define i64 @fa() nounwind {
209 ; PLAIN: %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) to i64
212 ; PLAIN: define i64 @fb() nounwind {
213 ; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64
216 ; PLAIN: define i64 @fc() nounwind {
217 ; PLAIN: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) to i64
220 ; PLAIN: define i64 @fd() nounwind {
221 ; PLAIN: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) to i64
224 ; PLAIN: define i64 @fe() nounwind {
225 ; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) to i64
228 ; PLAIN: define i64 @ff() nounwind {
229 ; PLAIN: %t = bitcast i64 1 to i64
232 ; OPT: define i64 @fa() nounwind {
233 ; OPT: ret i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310)
235 ; OPT: define i64 @fb() nounwind {
236 ; OPT: ret i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64)
238 ; OPT: define i64 @fc() nounwind {
239 ; OPT: ret i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2)
241 ; OPT: define i64 @fd() nounwind {
242 ; OPT: ret i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11)
244 ; OPT: define i64 @fe() nounwind {
245 ; OPT: ret i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64)
247 ; OPT: define i64 @ff() nounwind {
250 ; TO: define i64 @fa() nounwind {
253 ; TO: define i64 @fb() nounwind {
256 ; TO: define i64 @fc() nounwind {
259 ; TO: define i64 @fd() nounwind {
262 ; TO: define i64 @fe() nounwind {
265 ; TO: define i64 @ff() nounwind {
268 ; SCEV: Classifying expressions for: @fa
269 ; SCEV: %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) to i64
270 ; SCEV: --> (2310 * sizeof(double))
271 ; SCEV: Classifying expressions for: @fb
272 ; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64
273 ; SCEV: --> alignof(double)
274 ; SCEV: Classifying expressions for: @fc
275 ; SCEV: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) to i64
276 ; SCEV: --> (2 * sizeof(double))
277 ; SCEV: Classifying expressions for: @fd
278 ; SCEV: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) to i64
279 ; SCEV: --> (11 * sizeof(double))
280 ; SCEV: Classifying expressions for: @fe
281 ; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) to i64
282 ; SCEV: --> offsetof({ double, float, double, double }, 2)
283 ; SCEV: Classifying expressions for: @ff
284 ; SCEV: %t = bitcast i64 1 to i64
287 define i64 @fa() nounwind {
288 %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) to i64
291 define i64 @fb() nounwind {
292 %t = bitcast i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}* null, i64 0, i32 1) to i64) to i64
295 define i64 @fc() nounwind {
296 %t = bitcast i64 ptrtoint (double* getelementptr ({double, double, double, double}* null, i64 0, i32 2) to i64) to i64
299 define i64 @fd() nounwind {
300 %t = bitcast i64 ptrtoint (double* getelementptr ([13 x double]* null, i64 0, i32 11) to i64) to i64
303 define i64 @fe() nounwind {
304 %t = bitcast i64 ptrtoint (double* getelementptr ({double, float, double, double}* null, i64 0, i32 2) to i64) to i64
307 define i64 @ff() nounwind {
308 %t = bitcast i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64) to i64
312 ; PLAIN: define i64* @fM() nounwind {
313 ; PLAIN: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64*
316 ; PLAIN: define i64* @fN() nounwind {
317 ; PLAIN: %t = bitcast i64* getelementptr (%2* null, i32 0, i32 1) to i64*
320 ; PLAIN: define i64* @fO() nounwind {
321 ; PLAIN: %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64*
324 ; OPT: define i64* @fM() nounwind {
325 ; OPT: ret i64* getelementptr (i64* null, i32 1)
327 ; OPT: define i64* @fN() nounwind {
328 ; OPT: ret i64* getelementptr (%2* null, i32 0, i32 1)
330 ; OPT: define i64* @fO() nounwind {
331 ; OPT: ret i64* getelementptr ([2 x i64]* null, i32 0, i32 1)
333 ; TO: define i64* @fM() nounwind {
334 ; TO: ret i64* inttoptr (i64 8 to i64*)
336 ; TO: define i64* @fN() nounwind {
337 ; TO: ret i64* inttoptr (i64 8 to i64*)
339 ; TO: define i64* @fO() nounwind {
340 ; TO: ret i64* inttoptr (i64 8 to i64*)
342 ; SCEV: Classifying expressions for: @fM
343 ; SCEV: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64*
344 ; SCEV: --> sizeof(i64)
345 ; SCEV: Classifying expressions for: @fN
346 ; SCEV: %t = bitcast i64* getelementptr (%2* null, i32 0, i32 1) to i64*
347 ; SCEV: --> sizeof(i64)
348 ; SCEV: Classifying expressions for: @fO
349 ; SCEV: %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64*
350 ; SCEV: --> sizeof(i64)
352 define i64* @fM() nounwind {
353 %t = bitcast i64* getelementptr (i64 *null, i32 1) to i64*
356 define i64* @fN() nounwind {
357 %t = bitcast i64* getelementptr ({ i64, i64 } *null, i32 0, i32 1) to i64*
360 define i64* @fO() nounwind {
361 %t = bitcast i64* getelementptr ([2 x i64] *null, i32 0, i32 1) to i64*