• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; "PLAIN" - No optimizations. This tests the default target layout
2; constant folder.
3; RUN: opt -S -o - < %s | FileCheck --check-prefix=PLAIN %s
4
5; "OPT" - Optimizations but no targetdata. This tests default target layout
6; folding in the optimizers.
7; RUN: opt -S -o - -instcombine -globalopt < %s | FileCheck --check-prefix=OPT %s
8
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
12
13; "SCEV" - ScalarEvolution with default target layout
14; RUN: opt -analyze -scalar-evolution < %s | FileCheck --check-prefix=SCEV %s
15
16
17; The automatic constant folder in opt does not have targetdata access, so
18; it can't fold gep arithmetic, in general. However, the constant folder run
19; from instcombine and global opt can use targetdata.
20
21; PLAIN: @G8 = global i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -1)
22; PLAIN: @G1 = global i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -1)
23; PLAIN: @F8 = global i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -2)
24; PLAIN: @F1 = global i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -2)
25; PLAIN: @H8 = global i8* getelementptr (i8, i8* null, i32 -1)
26; PLAIN: @H1 = global i1* getelementptr (i1, i1* null, i32 -1)
27; OPT: @G8 = local_unnamed_addr global i8* null
28; OPT: @G1 = local_unnamed_addr global i1* null
29; OPT: @F8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*)
30; OPT: @F1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*)
31; OPT: @H8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*)
32; OPT: @H1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*)
33; TO: @G8 = local_unnamed_addr global i8* null
34; TO: @G1 = local_unnamed_addr global i1* null
35; TO: @F8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*)
36; TO: @F1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*)
37; TO: @H8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*)
38; TO: @H1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*)
39
40@G8 = global i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -1)
41@G1 = global i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -1)
42@F8 = global i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -2)
43@F1 = global i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -2)
44@H8 = global i8* getelementptr (i8, i8* inttoptr (i32 0 to i8*), i32 -1)
45@H1 = global i1* getelementptr (i1, i1* inttoptr (i32 0 to i1*), i32 -1)
46
47; The target-independent folder should be able to do some clever
48; simplifications on sizeof, alignof, and offsetof expressions. The
49; target-dependent folder should fold these down to constants.
50
51; PLAIN: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2310)
52; PLAIN: @b = constant i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64)
53; PLAIN: @c = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2)
54; PLAIN: @d = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 11)
55; PLAIN: @e = constant i64 ptrtoint (double* getelementptr ({ double, float, double, double }, { double, float, double, double }* null, i64 0, i32 2) to i64)
56; PLAIN: @f = constant i64 1
57; PLAIN: @g = constant i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64)
58; PLAIN: @h = constant i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64)
59; PLAIN: @i = constant i64 ptrtoint (i1** getelementptr ({ i1, i1* }, { i1, i1* }* null, i64 0, i32 1) to i64)
60; OPT: @a = local_unnamed_addr constant i64 18480
61; OPT: @b = local_unnamed_addr constant i64 8
62; OPT: @c = local_unnamed_addr constant i64 16
63; OPT: @d = local_unnamed_addr constant i64 88
64; OPT: @e = local_unnamed_addr constant i64 16
65; OPT: @f = local_unnamed_addr constant i64 1
66; OPT: @g = local_unnamed_addr constant i64 8
67; OPT: @h = local_unnamed_addr constant i64 8
68; OPT: @i = local_unnamed_addr constant i64 8
69; TO: @a = local_unnamed_addr constant i64 18480
70; TO: @b = local_unnamed_addr constant i64 8
71; TO: @c = local_unnamed_addr constant i64 16
72; TO: @d = local_unnamed_addr constant i64 88
73; TO: @e = local_unnamed_addr constant i64 16
74; TO: @f = local_unnamed_addr constant i64 1
75; TO: @g = local_unnamed_addr constant i64 8
76; TO: @h = local_unnamed_addr constant i64 8
77; TO: @i = local_unnamed_addr constant i64 8
78
79@a = constant i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}, {[7 x double], [7 x double]}* null, i64 11) to i64), i64 5))
80@b = constant i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}, {i1, [13 x double]}* null, i64 0, i32 1) to i64)
81@c = constant i64 ptrtoint (double* getelementptr ({double, double, double, double}, {double, double, double, double}* null, i64 0, i32 2) to i64)
82@d = constant i64 ptrtoint (double* getelementptr ([13 x double], [13 x double]* null, i64 0, i32 11) to i64)
83@e = constant i64 ptrtoint (double* getelementptr ({double, float, double, double}, {double, float, double, double}* null, i64 0, i32 2) to i64)
84@f = constant i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}, {i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64)
85@g = constant i64 ptrtoint ({double, double}* getelementptr ({i1, {double, double}}, {i1, {double, double}}* null, i64 0, i32 1) to i64)
86@h = constant i64 ptrtoint (double** getelementptr (double*, double** null, i64 1) to i64)
87@i = constant i64 ptrtoint (double** getelementptr ({i1, double*}, {i1, double*}* null, i64 0, i32 1) to i64)
88
89; The target-dependent folder should cast GEP indices to integer-sized pointers.
90
91; PLAIN: @M = constant i64* getelementptr (i64, i64* null, i32 1)
92; PLAIN: @N = constant i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1)
93; PLAIN: @O = constant i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1)
94; OPT: @M = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*)
95; OPT: @N = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*)
96; OPT: @O = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*)
97; TO: @M = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*)
98; TO: @N = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*)
99; TO: @O = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*)
100
101@M = constant i64* getelementptr (i64, i64* null, i32 1)
102@N = constant i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1)
103@O = constant i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1)
104
105; Fold GEP of a GEP. Very simple cases are folded without targetdata.
106
107; PLAIN: @Y = global [3 x { i32, i32 }]* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2)
108; PLAIN: @Z = global i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1)
109; OPT: @Y = local_unnamed_addr global [3 x { i32, i32 }]* getelementptr ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2)
110; OPT: @Z = local_unnamed_addr global i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1)
111; TO: @Y = local_unnamed_addr global [3 x { i32, i32 }]* getelementptr ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2)
112; TO: @Z = local_unnamed_addr global i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1)
113
114@ext = external global [3 x { i32, i32 }]
115@Y = global [3 x { i32, i32 }]* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 1), i64 1)
116@Z = global i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1)
117
118; Duplicate all of the above as function return values rather than
119; global initializers.
120
121; PLAIN: define i8* @goo8() #0 {
122; PLAIN:   %t = bitcast i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -1) to i8*
123; PLAIN:   ret i8* %t
124; PLAIN: }
125; PLAIN: define i1* @goo1() #0 {
126; PLAIN:   %t = bitcast i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -1) to i1*
127; PLAIN:   ret i1* %t
128; PLAIN: }
129; PLAIN: define i8* @foo8() #0 {
130; PLAIN:   %t = bitcast i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -2) to i8*
131; PLAIN:   ret i8* %t
132; PLAIN: }
133; PLAIN: define i1* @foo1() #0 {
134; PLAIN:   %t = bitcast i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -2) to i1*
135; PLAIN:   ret i1* %t
136; PLAIN: }
137; PLAIN: define i8* @hoo8() #0 {
138; PLAIN:   %t = bitcast i8* getelementptr (i8, i8* null, i32 -1) to i8*
139; PLAIN:   ret i8* %t
140; PLAIN: }
141; PLAIN: define i1* @hoo1() #0 {
142; PLAIN:   %t = bitcast i1* getelementptr (i1, i1* null, i32 -1) to i1*
143; PLAIN:   ret i1* %t
144; PLAIN: }
145; OPT: define i8* @goo8() local_unnamed_addr #0 {
146; OPT:   ret i8* null
147; OPT: }
148; OPT: define i1* @goo1() local_unnamed_addr #0 {
149; OPT:   ret i1* null
150; OPT: }
151; OPT: define i8* @foo8() local_unnamed_addr #0 {
152; OPT:   ret i8* inttoptr (i64 -1 to i8*)
153; OPT: }
154; OPT: define i1* @foo1() local_unnamed_addr #0 {
155; OPT:   ret i1* inttoptr (i64 -1 to i1*)
156; OPT: }
157; OPT: define i8* @hoo8() local_unnamed_addr #0 {
158; OPT:   ret i8* inttoptr (i64 -1 to i8*)
159; OPT: }
160; OPT: define i1* @hoo1() local_unnamed_addr #0 {
161; OPT:   ret i1* inttoptr (i64 -1 to i1*)
162; OPT: }
163; TO: define i8* @goo8() local_unnamed_addr #0 {
164; TO:   ret i8* null
165; TO: }
166; TO: define i1* @goo1() local_unnamed_addr #0 {
167; TO:   ret i1* null
168; TO: }
169; TO: define i8* @foo8() local_unnamed_addr #0 {
170; TO:   ret i8* inttoptr (i64 -1 to i8*)
171; TO: }
172; TO: define i1* @foo1() local_unnamed_addr #0 {
173; TO:   ret i1* inttoptr (i64 -1 to i1*)
174; TO: }
175; TO: define i8* @hoo8() local_unnamed_addr #0 {
176; TO:   ret i8* inttoptr (i64 -1 to i8*)
177; TO: }
178; TO: define i1* @hoo1() local_unnamed_addr #0 {
179; TO:   ret i1* inttoptr (i64 -1 to i1*)
180; TO: }
181; SCEV: Classifying expressions for: @goo8
182; SCEV:   %t = bitcast i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -1) to i8*
183; SCEV:   -->  (-1 + inttoptr (i32 1 to i8*))
184; SCEV: Classifying expressions for: @goo1
185; SCEV:   %t = bitcast i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -1) to i1*
186; SCEV:   -->  (-1 + inttoptr (i32 1 to i1*))
187; SCEV: Classifying expressions for: @foo8
188; SCEV:   %t = bitcast i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -2) to i8*
189; SCEV:   -->  (-2 + inttoptr (i32 1 to i8*))
190; SCEV: Classifying expressions for: @foo1
191; SCEV:   %t = bitcast i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -2) to i1*
192; SCEV:   -->  (-2 + inttoptr (i32 1 to i1*))
193; SCEV: Classifying expressions for: @hoo8
194; SCEV:   -->  -1
195; SCEV: Classifying expressions for: @hoo1
196; SCEV:   -->  -1
197
198define i8* @goo8() nounwind {
199  %t = bitcast i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -1) to i8*
200  ret i8* %t
201}
202define i1* @goo1() nounwind {
203  %t = bitcast i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -1) to i1*
204  ret i1* %t
205}
206define i8* @foo8() nounwind {
207  %t = bitcast i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -2) to i8*
208  ret i8* %t
209}
210define i1* @foo1() nounwind {
211  %t = bitcast i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -2) to i1*
212  ret i1* %t
213}
214define i8* @hoo8() nounwind {
215  %t = bitcast i8* getelementptr (i8, i8* inttoptr (i32 0 to i8*), i32 -1) to i8*
216  ret i8* %t
217}
218define i1* @hoo1() nounwind {
219  %t = bitcast i1* getelementptr (i1, i1* inttoptr (i32 0 to i1*), i32 -1) to i1*
220  ret i1* %t
221}
222
223; PLAIN: define i64 @fa() #0 {
224; PLAIN:   %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2310) to i64
225; PLAIN:   ret i64 %t
226; PLAIN: }
227; PLAIN: define i64 @fb() #0 {
228; PLAIN:   %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64) to i64
229; PLAIN:   ret i64 %t
230; PLAIN: }
231; PLAIN: define i64 @fc() #0 {
232; PLAIN:   %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2) to i64
233; PLAIN:   ret i64 %t
234; PLAIN: }
235; PLAIN: define i64 @fd() #0 {
236; PLAIN:   %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 11) to i64
237; PLAIN:   ret i64 %t
238; PLAIN: }
239; PLAIN: define i64 @fe() #0 {
240; PLAIN:   %t = bitcast i64 ptrtoint (double* getelementptr ({ double, float, double, double }, { double, float, double, double }* null, i64 0, i32 2) to i64) to i64
241; PLAIN:   ret i64 %t
242; PLAIN: }
243; PLAIN: define i64 @ff() #0 {
244; PLAIN:   %t = bitcast i64 1 to i64
245; PLAIN:   ret i64 %t
246; PLAIN: }
247; PLAIN: define i64 @fg() #0 {
248; PLAIN:   %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64) to i64
249; PLAIN:   ret i64 %t
250; PLAIN: }
251; PLAIN: define i64 @fh() #0 {
252; PLAIN:   %t = bitcast i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64) to i64
253; PLAIN:   ret i64 %t
254; PLAIN: }
255; PLAIN: define i64 @fi() #0 {
256; PLAIN:   %t = bitcast i64 ptrtoint (i1** getelementptr ({ i1, i1* }, { i1, i1* }* null, i64 0, i32 1) to i64) to i64
257; PLAIN:   ret i64 %t
258; PLAIN: }
259; OPT: define i64 @fa() local_unnamed_addr #0 {
260; OPT:   ret i64 18480
261; OPT: }
262; OPT: define i64 @fb() local_unnamed_addr #0 {
263; OPT:   ret i64 8
264; OPT: }
265; OPT: define i64 @fc() local_unnamed_addr #0 {
266; OPT:   ret i64 16
267; OPT: }
268; OPT: define i64 @fd() local_unnamed_addr #0 {
269; OPT:   ret i64 88
270; OPT: }
271; OPT: define i64 @fe() local_unnamed_addr #0 {
272; OPT:   ret i64 16
273; OPT: }
274; OPT: define i64 @ff() local_unnamed_addr #0 {
275; OPT:   ret i64 1
276; OPT: }
277; OPT: define i64 @fg() local_unnamed_addr #0 {
278; OPT:   ret i64 8
279; OPT: }
280; OPT: define i64 @fh() local_unnamed_addr #0 {
281; OPT:   ret i64 8
282; OPT: }
283; OPT: define i64 @fi() local_unnamed_addr #0 {
284; OPT:   ret i64 8
285; OPT: }
286; TO: define i64 @fa() local_unnamed_addr #0 {
287; TO:   ret i64 18480
288; TO: }
289; TO: define i64 @fb() local_unnamed_addr #0 {
290; TO:   ret i64 8
291; TO: }
292; TO: define i64 @fc() local_unnamed_addr #0 {
293; TO:   ret i64 16
294; TO: }
295; TO: define i64 @fd() local_unnamed_addr #0 {
296; TO:   ret i64 88
297; TO: }
298; TO: define i64 @fe() local_unnamed_addr #0 {
299; TO:   ret i64 16
300; TO: }
301; TO: define i64 @ff() local_unnamed_addr #0 {
302; TO:   ret i64 1
303; TO: }
304; TO: define i64 @fg() local_unnamed_addr #0 {
305; TO:   ret i64 8
306; TO: }
307; TO: define i64 @fh() local_unnamed_addr #0 {
308; TO:   ret i64 8
309; TO: }
310; TO: define i64 @fi() local_unnamed_addr #0 {
311; TO:   ret i64 8
312; TO: }
313; SCEV: Classifying expressions for: @fa
314; SCEV:   %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2310) to i64
315; SCEV:   -->  (2310 * sizeof(double))
316; SCEV: Classifying expressions for: @fb
317; SCEV:   %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64) to i64
318; SCEV:   -->  alignof(double)
319; SCEV: Classifying expressions for: @fc
320; SCEV:   %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2) to i64
321; SCEV:   -->  (2 * sizeof(double))
322; SCEV: Classifying expressions for: @fd
323; SCEV:   %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 11) to i64
324; SCEV:   -->  (11 * sizeof(double))
325; SCEV: Classifying expressions for: @fe
326; SCEV:   %t = bitcast i64 ptrtoint (double* getelementptr ({ double, float, double, double }, { double, float, double, double }* null, i64 0, i32 2) to i64) to i64
327; SCEV:   -->  offsetof({ double, float, double, double }, 2)
328; SCEV: Classifying expressions for: @ff
329; SCEV:   %t = bitcast i64 1 to i64
330; SCEV:   -->  1
331; SCEV: Classifying expressions for: @fg
332; SCEV:   %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64) to i64
333; SCEV:   -->  alignof(double)
334; SCEV: Classifying expressions for: @fh
335; SCEV:   %t = bitcast i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64) to i64
336; SCEV:   -->  sizeof(i1*)
337; SCEV: Classifying expressions for: @fi
338; SCEV:   %t = bitcast i64 ptrtoint (i1** getelementptr ({ i1, i1* }, { i1, i1* }* null, i64 0, i32 1) to i64) to i64
339; SCEV:   -->  alignof(i1*)
340
341define i64 @fa() nounwind {
342  %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}, {[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) to i64
343  ret i64 %t
344}
345define i64 @fb() nounwind {
346  %t = bitcast i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}, {i1, [13 x double]}* null, i64 0, i32 1) to i64) to i64
347  ret i64 %t
348}
349define i64 @fc() nounwind {
350  %t = bitcast i64 ptrtoint (double* getelementptr ({double, double, double, double}, {double, double, double, double}* null, i64 0, i32 2) to i64) to i64
351  ret i64 %t
352}
353define i64 @fd() nounwind {
354  %t = bitcast i64 ptrtoint (double* getelementptr ([13 x double], [13 x double]* null, i64 0, i32 11) to i64) to i64
355  ret i64 %t
356}
357define i64 @fe() nounwind {
358  %t = bitcast i64 ptrtoint (double* getelementptr ({double, float, double, double}, {double, float, double, double}* null, i64 0, i32 2) to i64) to i64
359  ret i64 %t
360}
361define i64 @ff() nounwind {
362  %t = bitcast i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}, {i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64) to i64
363  ret i64 %t
364}
365define i64 @fg() nounwind {
366  %t = bitcast i64 ptrtoint ({double, double}* getelementptr ({i1, {double, double}}, {i1, {double, double}}* null, i64 0, i32 1) to i64) to i64
367  ret i64 %t
368}
369define i64 @fh() nounwind {
370  %t = bitcast i64 ptrtoint (double** getelementptr (double*, double** null, i32 1) to i64) to i64
371  ret i64 %t
372}
373define i64 @fi() nounwind {
374  %t = bitcast i64 ptrtoint (double** getelementptr ({i1, double*}, {i1, double*}* null, i64 0, i32 1) to i64) to i64
375  ret i64 %t
376}
377
378; PLAIN: define i64* @fM() #0 {
379; PLAIN:   %t = bitcast i64* getelementptr (i64, i64* null, i32 1) to i64*
380; PLAIN:   ret i64* %t
381; PLAIN: }
382; PLAIN: define i64* @fN() #0 {
383; PLAIN:   %t = bitcast i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1) to i64*
384; PLAIN:   ret i64* %t
385; PLAIN: }
386; PLAIN: define i64* @fO() #0 {
387; PLAIN:   %t = bitcast i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1) to i64*
388; PLAIN:   ret i64* %t
389; PLAIN: }
390; OPT: define i64* @fM() local_unnamed_addr #0 {
391; OPT:   ret i64* inttoptr (i64 8 to i64*)
392; OPT: }
393; OPT: define i64* @fN() local_unnamed_addr #0 {
394; OPT:   ret i64* inttoptr (i64 8 to i64*)
395; OPT: }
396; OPT: define i64* @fO() local_unnamed_addr #0 {
397; OPT:   ret i64* inttoptr (i64 8 to i64*)
398; OPT: }
399; TO: define i64* @fM() local_unnamed_addr #0 {
400; TO:   ret i64* inttoptr (i64 8 to i64*)
401; TO: }
402; TO: define i64* @fN() local_unnamed_addr #0 {
403; TO:   ret i64* inttoptr (i64 8 to i64*)
404; TO: }
405; TO: define i64* @fO() local_unnamed_addr #0 {
406; TO:   ret i64* inttoptr (i64 8 to i64*)
407; TO: }
408; SCEV: Classifying expressions for: @fM
409; SCEV:   %t = bitcast i64* getelementptr (i64, i64* null, i32 1) to i64*
410; SCEV:   -->  8
411; SCEV: Classifying expressions for: @fN
412; SCEV:   %t = bitcast i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1) to i64*
413; SCEV:   -->  8
414; SCEV: Classifying expressions for: @fO
415; SCEV:   %t = bitcast i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1) to i64*
416; SCEV:   -->  8
417
418define i64* @fM() nounwind {
419  %t = bitcast i64* getelementptr (i64, i64* null, i32 1) to i64*
420  ret i64* %t
421}
422define i64* @fN() nounwind {
423  %t = bitcast i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1) to i64*
424  ret i64* %t
425}
426define i64* @fO() nounwind {
427  %t = bitcast i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1) to i64*
428  ret i64* %t
429}
430
431; PLAIN: define i32* @fZ() #0 {
432; PLAIN:   %t = bitcast i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) to i32*
433; PLAIN:   ret i32* %t
434; PLAIN: }
435; OPT: define i32* @fZ() local_unnamed_addr #0 {
436; OPT:   ret i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1)
437; OPT: }
438; TO: define i32* @fZ() local_unnamed_addr #0 {
439; TO:   ret i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1)
440; TO: }
441; SCEV: Classifying expressions for: @fZ
442; SCEV:   %t = bitcast i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) to i32*
443; SCEV:   -->  (12 + @ext)
444
445define i32* @fZ() nounwind {
446  %t = bitcast i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) to i32*
447  ret i32* %t
448}
449
450; PR15262 - Check GEP folding with casts between address spaces.
451
452@p0 = global [4 x i8] zeroinitializer, align 1
453@p12 = addrspace(12) global [4 x i8] zeroinitializer, align 1
454
455define i8* @different_addrspace() nounwind noinline {
456; OPT: different_addrspace
457  %p = getelementptr inbounds i8, i8* addrspacecast ([4 x i8] addrspace(12)* @p12 to i8*),
458                                  i32 2
459  ret i8* %p
460; OPT: ret i8* getelementptr ([4 x i8], [4 x i8]* addrspacecast ([4 x i8] addrspace(12)* @p12 to [4 x i8]*), i64 0, i64 2)
461}
462
463define i8* @same_addrspace() nounwind noinline {
464; OPT: same_addrspace
465  %p = getelementptr inbounds i8, i8* bitcast ([4 x i8] * @p0 to i8*), i32 2
466  ret i8* %p
467; OPT: ret i8* getelementptr inbounds ([4 x i8], [4 x i8]* @p0, i64 0, i64 2)
468}
469
470@gv1 = internal global i32 1
471@gv2 = internal global [1 x i32] [ i32 2 ]
472@gv3 = internal global [1 x i32] [ i32 2 ]
473
474; Handled by TI-independent constant folder
475define i1 @gv_gep_vs_gv() {
476  ret i1 icmp eq (i32* getelementptr inbounds ([1 x i32], [1 x i32]* @gv2, i32 0, i32 0), i32* @gv1)
477}
478; PLAIN: gv_gep_vs_gv
479; PLAIN: ret i1 false
480
481define i1 @gv_gep_vs_gv_gep() {
482  ret i1 icmp eq (i32* getelementptr inbounds ([1 x i32], [1 x i32]* @gv2, i32 0, i32 0), i32* getelementptr inbounds ([1 x i32], [1 x i32]* @gv3, i32 0, i32 0))
483}
484; PLAIN: gv_gep_vs_gv_gep
485; PLAIN: ret i1 false
486
487; CHECK: attributes #0 = { nounwind }
488