xref: /llvm-project/llvm/test/Other/constant-fold-gep.ll (revision 10f315dc9c96ec2413881ab55a285e35d80def88)
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 - -passes='function(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 - -passes='function(instcombine),globalopt' -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 -passes='print<scalar-evolution>' < %s -disable-output 2>&1 | 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 ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -1)
22; PLAIN: @G1 = global ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -1)
23; PLAIN: @F8 = global ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -2)
24; PLAIN: @F1 = global ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -2)
25; PLAIN: @H8 = global ptr getelementptr (i8, ptr null, i32 -1)
26; PLAIN: @H1 = global ptr getelementptr (i1, ptr null, i32 -1)
27; OPT: @G8 = local_unnamed_addr global ptr null
28; OPT: @G1 = local_unnamed_addr global ptr null
29; OPT: @F8 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
30; OPT: @F1 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
31; OPT: @H8 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
32; OPT: @H1 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
33; TO: @G8 = local_unnamed_addr global ptr null
34; TO: @G1 = local_unnamed_addr global ptr null
35; TO: @F8 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
36; TO: @F1 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
37; TO: @H8 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
38; TO: @H1 = local_unnamed_addr global ptr inttoptr (i64 -1 to ptr)
39
40@G8 = global ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -1)
41@G1 = global ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -1)
42@F8 = global ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -2)
43@F1 = global ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -2)
44@H8 = global ptr getelementptr (i8, ptr inttoptr (i32 0 to ptr), i32 -1)
45@H1 = global ptr getelementptr (i1, ptr inttoptr (i32 0 to ptr), 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 (ptr getelementptr ({ [7 x double], [7 x double] }, ptr null, i64 11) to i64), i64 15)
52; PLAIN: @b = constant i64 ptrtoint (ptr getelementptr ({ i1, [13 x double] }, ptr null, i64 0, i32 1) to i64)
53; PLAIN: @c = constant i64 ptrtoint (ptr getelementptr ({ double, double, double, double }, ptr null, i64 0, i32 2) to i64)
54; PLAIN: @d = constant i64 ptrtoint (ptr getelementptr ([13 x double], ptr null, i64 0, i32 11) to i64)
55; PLAIN: @e = constant i64 ptrtoint (ptr getelementptr ({ double, float, double, double }, ptr null, i64 0, i32 2) to i64)
56; PLAIN: @f = constant i64 ptrtoint (ptr getelementptr ({ i1, <{ i16, i128 }> }, ptr null, i64 0, i32 1) to i64)
57; PLAIN: @g = constant i64 ptrtoint (ptr getelementptr ({ i1, { double, double } }, ptr null, i64 0, i32 1) to i64)
58; PLAIN: @h = constant i64 ptrtoint (ptr getelementptr (ptr, ptr null, i64 1) to i64)
59; PLAIN: @i = constant i64 ptrtoint (ptr getelementptr ({ i1, ptr }, ptr 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 (ptr getelementptr ({[7 x double], [7 x double]}, ptr null, i64 11) to i64), i64 5))
80@b = constant i64 ptrtoint (ptr getelementptr ({i1, [13 x double]}, ptr null, i64 0, i32 1) to i64)
81@c = constant i64 ptrtoint (ptr getelementptr ({double, double, double, double}, ptr null, i64 0, i32 2) to i64)
82@d = constant i64 ptrtoint (ptr getelementptr ([13 x double], ptr null, i64 0, i32 11) to i64)
83@e = constant i64 ptrtoint (ptr getelementptr ({double, float, double, double}, ptr null, i64 0, i32 2) to i64)
84@f = constant i64 ptrtoint (ptr getelementptr ({i1, <{ i16, i128 }>}, ptr null, i64 0, i32 1) to i64)
85@g = constant i64 ptrtoint (ptr getelementptr ({i1, {double, double}}, ptr null, i64 0, i32 1) to i64)
86@h = constant i64 ptrtoint (ptr getelementptr (ptr, ptr null, i64 1) to i64)
87@i = constant i64 ptrtoint (ptr getelementptr ({i1, ptr}, ptr 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 ptr getelementptr (i64, ptr null, i32 1)
92; PLAIN: @N = constant ptr getelementptr ({ i64, i64 }, ptr null, i32 0, i32 1)
93; PLAIN: @O = constant ptr getelementptr ([2 x i64], ptr null, i32 0, i32 1)
94; OPT: @M = local_unnamed_addr constant ptr inttoptr (i64 8 to ptr)
95; OPT: @N = local_unnamed_addr constant ptr inttoptr (i64 8 to ptr)
96; OPT: @O = local_unnamed_addr constant ptr inttoptr (i64 8 to ptr)
97; TO: @M = local_unnamed_addr constant ptr inttoptr (i64 8 to ptr)
98; TO: @N = local_unnamed_addr constant ptr inttoptr (i64 8 to ptr)
99; TO: @O = local_unnamed_addr constant ptr inttoptr (i64 8 to ptr)
100
101@M = constant ptr getelementptr (i64, ptr null, i32 1)
102@N = constant ptr getelementptr ({ i64, i64 }, ptr null, i32 0, i32 1)
103@O = constant ptr getelementptr ([2 x i64], ptr null, i32 0, i32 1)
104
105; Fold GEP of a GEP. Very simple cases are folded without targetdata.
106
107; PLAIN: @Y = global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 1), i64 1)
108; PLAIN: @Z = global ptr getelementptr inbounds (i32, ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 0), i64 1)
109; OPT: @Y = local_unnamed_addr global ptr getelementptr inbounds nuw (i8, ptr @ext, i64 48)
110; OPT: @Z = local_unnamed_addr global ptr getelementptr inbounds nuw (i8, ptr @ext, i64 12)
111; TO: @Y = local_unnamed_addr global ptr getelementptr inbounds nuw (i8, ptr @ext, i64 48)
112; TO: @Z = local_unnamed_addr global ptr getelementptr inbounds nuw (i8, ptr @ext, i64 12)
113
114@ext = external global [3 x { i32, i32 }]
115@Y = global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 1), i64 1)
116@Z = global ptr getelementptr inbounds (i32, ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @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 ptr @goo8() #0 {
122; PLAIN:   %t = bitcast ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -1) to ptr
123; PLAIN:   ret ptr %t
124; PLAIN: }
125; PLAIN: define ptr @goo1() #0 {
126; PLAIN:   %t = bitcast ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -1) to ptr
127; PLAIN:   ret ptr %t
128; PLAIN: }
129; PLAIN: define ptr @foo8() #0 {
130; PLAIN:   %t = bitcast ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -2) to ptr
131; PLAIN:   ret ptr %t
132; PLAIN: }
133; PLAIN: define ptr @foo1() #0 {
134; PLAIN:   %t = bitcast ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -2) to ptr
135; PLAIN:   ret ptr %t
136; PLAIN: }
137; PLAIN: define ptr @hoo8() #0 {
138; PLAIN:   %t = bitcast ptr getelementptr (i8, ptr null, i32 -1) to ptr
139; PLAIN:   ret ptr %t
140; PLAIN: }
141; PLAIN: define ptr @hoo1() #0 {
142; PLAIN:   %t = bitcast ptr getelementptr (i1, ptr null, i32 -1) to ptr
143; PLAIN:   ret ptr %t
144; PLAIN: }
145; OPT: define ptr @goo8() local_unnamed_addr #0 {
146; OPT:   ret ptr null
147; OPT: }
148; OPT: define ptr @goo1() local_unnamed_addr #0 {
149; OPT:   ret ptr null
150; OPT: }
151; OPT: define ptr @foo8() local_unnamed_addr #0 {
152; OPT:   ret ptr inttoptr (i64 -1 to ptr)
153; OPT: }
154; OPT: define ptr @foo1() local_unnamed_addr #0 {
155; OPT:   ret ptr inttoptr (i64 -1 to ptr)
156; OPT: }
157; OPT: define ptr @hoo8() local_unnamed_addr #0 {
158; OPT:   ret ptr inttoptr (i64 -1 to ptr)
159; OPT: }
160; OPT: define ptr @hoo1() local_unnamed_addr #0 {
161; OPT:   ret ptr inttoptr (i64 -1 to ptr)
162; OPT: }
163; TO: define ptr @goo8() local_unnamed_addr #0 {
164; TO:   ret ptr null
165; TO: }
166; TO: define ptr @goo1() local_unnamed_addr #0 {
167; TO:   ret ptr null
168; TO: }
169; TO: define ptr @foo8() local_unnamed_addr #0 {
170; TO:   ret ptr inttoptr (i64 -1 to ptr)
171; TO: }
172; TO: define ptr @foo1() local_unnamed_addr #0 {
173; TO:   ret ptr inttoptr (i64 -1 to ptr)
174; TO: }
175; TO: define ptr @hoo8() local_unnamed_addr #0 {
176; TO:   ret ptr inttoptr (i64 -1 to ptr)
177; TO: }
178; TO: define ptr @hoo1() local_unnamed_addr #0 {
179; TO:   ret ptr inttoptr (i64 -1 to ptr)
180; TO: }
181; SCEV: Classifying expressions for: @goo8
182; SCEV:   %t = bitcast ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -1) to ptr
183; SCEV:   -->  (-1 + inttoptr (i32 1 to ptr))
184; SCEV: Classifying expressions for: @goo1
185; SCEV:   %t = bitcast ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -1) to ptr
186; SCEV:   -->  (-1 + inttoptr (i32 1 to ptr))
187; SCEV: Classifying expressions for: @foo8
188; SCEV:   %t = bitcast ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -2) to ptr
189; SCEV:   -->  (-2 + inttoptr (i32 1 to ptr))
190; SCEV: Classifying expressions for: @foo1
191; SCEV:   %t = bitcast ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -2) to ptr
192; SCEV:   -->  (-2 + inttoptr (i32 1 to ptr))
193; SCEV: Classifying expressions for: @hoo8
194; SCEV:   -->  (-1 + null)<nuw><nsw> U: [-1,0) S: [-1,0)
195; SCEV: Classifying expressions for: @hoo1
196; SCEV:   -->  (-1 + null)<nuw><nsw> U: [-1,0) S: [-1,0)
197
198define ptr @goo8() nounwind {
199  %t = bitcast ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -1) to ptr
200  ret ptr %t
201}
202define ptr @goo1() nounwind {
203  %t = bitcast ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -1) to ptr
204  ret ptr %t
205}
206define ptr @foo8() nounwind {
207  %t = bitcast ptr getelementptr (i8, ptr inttoptr (i32 1 to ptr), i32 -2) to ptr
208  ret ptr %t
209}
210define ptr @foo1() nounwind {
211  %t = bitcast ptr getelementptr (i1, ptr inttoptr (i32 1 to ptr), i32 -2) to ptr
212  ret ptr %t
213}
214define ptr @hoo8() nounwind {
215  %t = bitcast ptr getelementptr (i8, ptr inttoptr (i32 0 to ptr), i32 -1) to ptr
216  ret ptr %t
217}
218define ptr @hoo1() nounwind {
219  %t = bitcast ptr getelementptr (i1, ptr inttoptr (i32 0 to ptr), i32 -1) to ptr
220  ret ptr %t
221}
222
223; PLAIN: define i64 @fa() #0 {
224; PLAIN:   %t = bitcast i64 mul (i64 ptrtoint (ptr getelementptr ({ [7 x double], [7 x double] }, ptr null, i64 11) to i64), i64 15) to i64
225; PLAIN:   ret i64 %t
226; PLAIN: }
227; PLAIN: define i64 @fb() #0 {
228; PLAIN:   %t = bitcast i64 ptrtoint (ptr getelementptr ({ i1, [13 x double] }, ptr 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 ptrtoint (ptr getelementptr ({ double, double, double, double }, ptr null, i64 0, i32 2) to i64) to i64
233; PLAIN:   ret i64 %t
234; PLAIN: }
235; PLAIN: define i64 @fd() #0 {
236; PLAIN:   %t = bitcast i64 ptrtoint (ptr getelementptr ([13 x double], ptr null, i64 0, i32 11) to i64) to i64
237; PLAIN:   ret i64 %t
238; PLAIN: }
239; PLAIN: define i64 @fe() #0 {
240; PLAIN:   %t = bitcast i64 ptrtoint (ptr getelementptr ({ double, float, double, double }, ptr 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 ptrtoint (ptr getelementptr ({ i1, <{ i16, i128 }> }, ptr null, i64 0, i32 1) to i64) to i64
245; PLAIN:   ret i64 %t
246; PLAIN: }
247; PLAIN: define i64 @fg() #0 {
248; PLAIN:   %t = bitcast i64 ptrtoint (ptr getelementptr ({ i1, { double, double } }, ptr 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 (ptr getelementptr (ptr, ptr 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 (ptr getelementptr ({ i1, ptr }, ptr 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-LABEL: Classifying expressions for: @fa
314; SCEV:   %t = bitcast i64 mul (i64 ptrtoint (ptr getelementptr ({ [7 x double], [7 x double] }, ptr null, i64 11) to i64), i64 15) to i64
315; SCEV:   -->  18480
316; SCEV-LABEL: Classifying expressions for: @fb
317; SCEV:  %t = bitcast i64 ptrtoint (ptr getelementptr ({ i1, [13 x double] }, ptr null, i64 0, i32 1) to i64) to i64
318; SCEV:   -->  8
319; SCEV-LABEL: Classifying expressions for: @fc
320; SCEV:  %t = bitcast i64 ptrtoint (ptr getelementptr ({ double, double, double, double }, ptr null, i64 0, i32 2) to i64) to i64
321; SCEV:   -->  16
322; SCEV-LABEL: Classifying expressions for: @fd
323; SCEV:   %t = bitcast i64 ptrtoint (ptr getelementptr ([13 x double], ptr null, i64 0, i32 11) to i64) to i64
324; SCEV:   -->  88
325; SCEV-LABEL: Classifying expressions for: @fe
326; SCEV:   %t = bitcast i64 ptrtoint (ptr getelementptr ({ double, float, double, double }, ptr null, i64 0, i32 2) to i64) to i64
327; SCEV:   -->  16
328; SCEV-LABEL: Classifying expressions for: @ff
329; SCEV:   %t = bitcast i64 ptrtoint (ptr getelementptr ({ i1, <{ i16, i128 }> }, ptr null, i64 0, i32 1) to i64) to i64
330; SCEV:   -->  1
331; SCEV-LABEL: Classifying expressions for: @fg
332; SCEV:   %t = bitcast i64 ptrtoint (ptr getelementptr ({ i1, { double, double } }, ptr null, i64 0, i32 1) to i64) to i64
333; SCEV:   -->  8
334; SCEV-LABEL: Classifying expressions for: @fh
335; SCEV:   %t = bitcast i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64) to i64
336; SCEV:   --> 8
337; SCEV-LABEL: Classifying expressions for: @fi
338; SCEV:   %t = bitcast i64 ptrtoint (ptr getelementptr ({ i1, ptr }, ptr null, i64 0, i32 1) to i64) to i64
339; SCEV:   --> 8
340
341define i64 @fa() nounwind {
342  %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint (ptr getelementptr ({[7 x double], [7 x double]}, ptr null, i64 11) to i64), i64 5)) to i64
343  ret i64 %t
344}
345define i64 @fb() nounwind {
346  %t = bitcast i64 ptrtoint (ptr getelementptr ({i1, [13 x double]}, ptr null, i64 0, i32 1) to i64) to i64
347  ret i64 %t
348}
349define i64 @fc() nounwind {
350  %t = bitcast i64 ptrtoint (ptr getelementptr ({double, double, double, double}, ptr null, i64 0, i32 2) to i64) to i64
351  ret i64 %t
352}
353define i64 @fd() nounwind {
354  %t = bitcast i64 ptrtoint (ptr getelementptr ([13 x double], ptr null, i64 0, i32 11) to i64) to i64
355  ret i64 %t
356}
357define i64 @fe() nounwind {
358  %t = bitcast i64 ptrtoint (ptr getelementptr ({double, float, double, double}, ptr null, i64 0, i32 2) to i64) to i64
359  ret i64 %t
360}
361define i64 @ff() nounwind {
362  %t = bitcast i64 ptrtoint (ptr getelementptr ({i1, <{ i16, i128 }>}, ptr null, i64 0, i32 1) to i64) to i64
363  ret i64 %t
364}
365define i64 @fg() nounwind {
366  %t = bitcast i64 ptrtoint (ptr getelementptr ({i1, {double, double}}, ptr null, i64 0, i32 1) to i64) to i64
367  ret i64 %t
368}
369define i64 @fh() nounwind {
370  %t = bitcast i64 ptrtoint (ptr getelementptr (ptr, ptr null, i32 1) to i64) to i64
371  ret i64 %t
372}
373define i64 @fi() nounwind {
374  %t = bitcast i64 ptrtoint (ptr getelementptr ({i1, ptr}, ptr null, i64 0, i32 1) to i64) to i64
375  ret i64 %t
376}
377
378; PLAIN: define ptr @fM() #0 {
379; PLAIN:   %t = bitcast ptr getelementptr (i64, ptr null, i32 1) to ptr
380; PLAIN:   ret ptr %t
381; PLAIN: }
382; PLAIN: define ptr @fN() #0 {
383; PLAIN:   %t = bitcast ptr getelementptr ({ i64, i64 }, ptr null, i32 0, i32 1) to ptr
384; PLAIN:   ret ptr %t
385; PLAIN: }
386; PLAIN: define ptr @fO() #0 {
387; PLAIN:   %t = bitcast ptr getelementptr ([2 x i64], ptr null, i32 0, i32 1) to ptr
388; PLAIN:   ret ptr %t
389; PLAIN: }
390; OPT: define ptr @fM() local_unnamed_addr #0 {
391; OPT:   ret ptr inttoptr (i64 8 to ptr)
392; OPT: }
393; OPT: define ptr @fN() local_unnamed_addr #0 {
394; OPT:   ret ptr inttoptr (i64 8 to ptr)
395; OPT: }
396; OPT: define ptr @fO() local_unnamed_addr #0 {
397; OPT:   ret ptr inttoptr (i64 8 to ptr)
398; OPT: }
399; TO: define ptr @fM() local_unnamed_addr #0 {
400; TO:   ret ptr inttoptr (i64 8 to ptr)
401; TO: }
402; TO: define ptr @fN() local_unnamed_addr #0 {
403; TO:   ret ptr inttoptr (i64 8 to ptr)
404; TO: }
405; TO: define ptr @fO() local_unnamed_addr #0 {
406; TO:   ret ptr inttoptr (i64 8 to ptr)
407; TO: }
408; SCEV: Classifying expressions for: @fM
409; SCEV:   %t = bitcast ptr getelementptr (i64, ptr null, i32 1) to ptr
410; SCEV:    --> (8 + null)<nuw><nsw> U: [8,9) S: [8,9)
411; SCEV: Classifying expressions for: @fN
412; SCEV:   %t = bitcast ptr getelementptr ({ i64, i64 }, ptr null, i32 0, i32 1) to ptr
413; SCEV:   --> (8 + null)<nuw><nsw> U: [8,9) S: [8,9)
414; SCEV: Classifying expressions for: @fO
415; SCEV:   %t = bitcast ptr getelementptr ([2 x i64], ptr null, i32 0, i32 1) to ptr
416; SCEV:   --> (8 + null)<nuw><nsw> U: [8,9) S: [8,9)
417
418define ptr @fM() nounwind {
419  %t = bitcast ptr getelementptr (i64, ptr null, i32 1) to ptr
420  ret ptr %t
421}
422define ptr @fN() nounwind {
423  %t = bitcast ptr getelementptr ({ i64, i64 }, ptr null, i32 0, i32 1) to ptr
424  ret ptr %t
425}
426define ptr @fO() nounwind {
427  %t = bitcast ptr getelementptr ([2 x i64], ptr null, i32 0, i32 1) to ptr
428  ret ptr %t
429}
430
431; PLAIN: define ptr @fZ() #0 {
432; PLAIN:   %t = bitcast ptr getelementptr inbounds (i32, ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 0), i64 1) to ptr
433; PLAIN:   ret ptr %t
434; PLAIN: }
435; OPT: define ptr @fZ() local_unnamed_addr #0 {
436; OPT:   ret ptr getelementptr inbounds nuw (i8, ptr @ext, i64 12)
437; OPT: }
438; TO: define ptr @fZ() local_unnamed_addr #0 {
439; TO:   ret ptr getelementptr inbounds nuw (i8, ptr @ext, i64 12)
440; TO: }
441; SCEV: Classifying expressions for: @fZ
442; SCEV:   %t = bitcast ptr getelementptr inbounds (i32, ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 0), i64 1) to ptr
443; SCEV:   -->  (12 + @ext)
444
445define ptr @fZ() nounwind {
446  %t = bitcast ptr getelementptr inbounds (i32, ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 0), i64 1) to ptr
447  ret ptr %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 ptr @different_addrspace() nounwind noinline {
456; OPT: different_addrspace
457  %p = getelementptr inbounds i8, ptr addrspacecast (ptr addrspace(12) @p12 to ptr),
458                                  i32 2
459  ret ptr %p
460; OPT: ret ptr getelementptr inbounds nuw (i8, ptr addrspacecast (ptr addrspace(12) @p12 to ptr), i64 2)
461}
462
463define ptr @same_addrspace() nounwind noinline {
464; OPT: same_addrspace
465  %p = getelementptr inbounds i8, ptr @p0, i32 2
466  ret ptr %p
467; OPT: ret ptr getelementptr inbounds nuw (i8, ptr @p0, 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
474define i1 @gv_gep_vs_gv() {
475  %cmp = icmp eq ptr @gv2, @gv1
476  ret i1 %cmp
477}
478; OPT: gv_gep_vs_gv
479; OPT: ret i1 false
480
481define i1 @gv_gep_vs_gv_gep() {
482  %cmp = icmp eq ptr @gv2, @gv3
483  ret i1 %cmp
484}
485; OPT: gv_gep_vs_gv_gep
486; OPT: ret i1 false
487
488; CHECK: attributes #0 = { nounwind }
489