• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -basicaa -gvn -enable-load-pre -S | FileCheck %s
2target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
3
4define i32 @test1(i32* %p, i1 %C) {
5; CHECK-LABEL: @test1(
6block1:
7	br i1 %C, label %block2, label %block3
8
9block2:
10 br label %block4
11; CHECK: block2:
12; CHECK-NEXT: load i32, i32* %p
13
14block3:
15  store i32 0, i32* %p
16  br label %block4
17
18block4:
19  %PRE = load i32, i32* %p
20  ret i32 %PRE
21; CHECK: block4:
22; CHECK-NEXT: phi i32
23; CHECK-NEXT: ret i32
24}
25
26; This is a simple phi translation case.
27define i32 @test2(i32* %p, i32* %q, i1 %C) {
28; CHECK-LABEL: @test2(
29block1:
30	br i1 %C, label %block2, label %block3
31
32block2:
33 br label %block4
34; CHECK: block2:
35; CHECK-NEXT: load i32, i32* %q
36
37block3:
38  store i32 0, i32* %p
39  br label %block4
40
41block4:
42  %P2 = phi i32* [%p, %block3], [%q, %block2]
43  %PRE = load i32, i32* %P2
44  ret i32 %PRE
45; CHECK: block4:
46; CHECK-NEXT: phi i32 [
47; CHECK-NOT: load
48; CHECK: ret i32
49}
50
51; This is a PRE case that requires phi translation through a GEP.
52define i32 @test3(i32* %p, i32* %q, i32** %Hack, i1 %C) {
53; CHECK-LABEL: @test3(
54block1:
55  %B = getelementptr i32, i32* %q, i32 1
56  store i32* %B, i32** %Hack
57	br i1 %C, label %block2, label %block3
58
59block2:
60 br label %block4
61; CHECK: block2:
62; CHECK-NEXT: load i32, i32* %B
63
64block3:
65  %A = getelementptr i32, i32* %p, i32 1
66  store i32 0, i32* %A
67  br label %block4
68
69block4:
70  %P2 = phi i32* [%p, %block3], [%q, %block2]
71  %P3 = getelementptr i32, i32* %P2, i32 1
72  %PRE = load i32, i32* %P3
73  ret i32 %PRE
74; CHECK: block4:
75; CHECK-NEXT: phi i32 [
76; CHECK-NOT: load
77; CHECK: ret i32
78}
79
80;; Here the loaded address is available, but the computation is in 'block3'
81;; which does not dominate 'block2'.
82define i32 @test4(i32* %p, i32* %q, i32** %Hack, i1 %C) {
83; CHECK-LABEL: @test4(
84block1:
85	br i1 %C, label %block2, label %block3
86
87block2:
88 br label %block4
89; CHECK: block2:
90; CHECK:   load i32, i32*
91; CHECK:   br label %block4
92
93block3:
94  %B = getelementptr i32, i32* %q, i32 1
95  store i32* %B, i32** %Hack
96
97  %A = getelementptr i32, i32* %p, i32 1
98  store i32 0, i32* %A
99  br label %block4
100
101block4:
102  %P2 = phi i32* [%p, %block3], [%q, %block2]
103  %P3 = getelementptr i32, i32* %P2, i32 1
104  %PRE = load i32, i32* %P3
105  ret i32 %PRE
106; CHECK: block4:
107; CHECK-NEXT: phi i32 [
108; CHECK-NOT: load
109; CHECK: ret i32
110}
111
112;void test5(int N, double *G) {
113;  int j;
114;  for (j = 0; j < N - 1; j++)
115;    G[j] = G[j] + G[j+1];
116;}
117
118define void @test5(i32 %N, double* nocapture %G) nounwind ssp {
119; CHECK-LABEL: @test5(
120entry:
121  %0 = add i32 %N, -1
122  %1 = icmp sgt i32 %0, 0
123  br i1 %1, label %bb.nph, label %return
124
125bb.nph:
126  %tmp = zext i32 %0 to i64
127  br label %bb
128
129; CHECK: bb.nph:
130; CHECK: load double, double*
131; CHECK: br label %bb
132
133bb:
134  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ]
135  %tmp6 = add i64 %indvar, 1
136  %scevgep = getelementptr double, double* %G, i64 %tmp6
137  %scevgep7 = getelementptr double, double* %G, i64 %indvar
138  %2 = load double, double* %scevgep7, align 8
139  %3 = load double, double* %scevgep, align 8
140  %4 = fadd double %2, %3
141  store double %4, double* %scevgep7, align 8
142  %exitcond = icmp eq i64 %tmp6, %tmp
143  br i1 %exitcond, label %return, label %bb
144
145; Should only be one load in the loop.
146; CHECK: bb:
147; CHECK: load double, double*
148; CHECK-NOT: load double, double*
149; CHECK: br i1 %exitcond
150
151return:
152  ret void
153}
154
155;void test6(int N, double *G) {
156;  int j;
157;  for (j = 0; j < N - 1; j++)
158;    G[j+1] = G[j] + G[j+1];
159;}
160
161define void @test6(i32 %N, double* nocapture %G) nounwind ssp {
162; CHECK-LABEL: @test6(
163entry:
164  %0 = add i32 %N, -1
165  %1 = icmp sgt i32 %0, 0
166  br i1 %1, label %bb.nph, label %return
167
168bb.nph:
169  %tmp = zext i32 %0 to i64
170  br label %bb
171
172; CHECK: bb.nph:
173; CHECK: load double, double*
174; CHECK: br label %bb
175
176bb:
177  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ]
178  %tmp6 = add i64 %indvar, 1
179  %scevgep = getelementptr double, double* %G, i64 %tmp6
180  %scevgep7 = getelementptr double, double* %G, i64 %indvar
181  %2 = load double, double* %scevgep7, align 8
182  %3 = load double, double* %scevgep, align 8
183  %4 = fadd double %2, %3
184  store double %4, double* %scevgep, align 8
185  %exitcond = icmp eq i64 %tmp6, %tmp
186  br i1 %exitcond, label %return, label %bb
187
188; Should only be one load in the loop.
189; CHECK: bb:
190; CHECK: load double, double*
191; CHECK-NOT: load double, double*
192; CHECK: br i1 %exitcond
193
194return:
195  ret void
196}
197
198;void test7(int N, double* G) {
199;  long j;
200;  G[1] = 1;
201;  for (j = 1; j < N - 1; j++)
202;      G[j+1] = G[j] + G[j+1];
203;}
204
205; This requires phi translation of the adds.
206define void @test7(i32 %N, double* nocapture %G) nounwind ssp {
207entry:
208  %0 = getelementptr inbounds double, double* %G, i64 1
209  store double 1.000000e+00, double* %0, align 8
210  %1 = add i32 %N, -1
211  %2 = icmp sgt i32 %1, 1
212  br i1 %2, label %bb.nph, label %return
213
214bb.nph:
215  %tmp = sext i32 %1 to i64
216  %tmp7 = add i64 %tmp, -1
217  br label %bb
218
219bb:
220  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ]
221  %tmp8 = add i64 %indvar, 2
222  %scevgep = getelementptr double, double* %G, i64 %tmp8
223  %tmp9 = add i64 %indvar, 1
224  %scevgep10 = getelementptr double, double* %G, i64 %tmp9
225  %3 = load double, double* %scevgep10, align 8
226  %4 = load double, double* %scevgep, align 8
227  %5 = fadd double %3, %4
228  store double %5, double* %scevgep, align 8
229  %exitcond = icmp eq i64 %tmp9, %tmp7
230  br i1 %exitcond, label %return, label %bb
231
232; Should only be one load in the loop.
233; CHECK: bb:
234; CHECK: load double, double*
235; CHECK-NOT: load double, double*
236; CHECK: br i1 %exitcond
237
238return:
239  ret void
240}
241
242;; Here the loaded address isn't available in 'block2' at all, requiring a new
243;; GEP to be inserted into it.
244define i32 @test8(i32* %p, i32* %q, i32** %Hack, i1 %C) {
245; CHECK-LABEL: @test8(
246block1:
247	br i1 %C, label %block2, label %block3
248
249block2:
250 br label %block4
251; CHECK: block2:
252; CHECK:   load i32, i32*
253; CHECK:   br label %block4
254
255block3:
256  %A = getelementptr i32, i32* %p, i32 1
257  store i32 0, i32* %A
258  br label %block4
259
260block4:
261  %P2 = phi i32* [%p, %block3], [%q, %block2]
262  %P3 = getelementptr i32, i32* %P2, i32 1
263  %PRE = load i32, i32* %P3
264  ret i32 %PRE
265; CHECK: block4:
266; CHECK-NEXT: phi i32 [
267; CHECK-NOT: load
268; CHECK: ret i32
269}
270
271;void test9(int N, double* G) {
272;  long j;
273;  for (j = 1; j < N - 1; j++)
274;      G[j+1] = G[j] + G[j+1];
275;}
276
277; This requires phi translation of the adds.
278define void @test9(i32 %N, double* nocapture %G) nounwind ssp {
279entry:
280  add i32 0, 0
281  %1 = add i32 %N, -1
282  %2 = icmp sgt i32 %1, 1
283  br i1 %2, label %bb.nph, label %return
284
285bb.nph:
286  %tmp = sext i32 %1 to i64
287  %tmp7 = add i64 %tmp, -1
288  br label %bb
289
290; CHECK: bb.nph:
291; CHECK:   load double, double*
292; CHECK:   br label %bb
293
294bb:
295  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ]
296  %tmp8 = add i64 %indvar, 2
297  %scevgep = getelementptr double, double* %G, i64 %tmp8
298  %tmp9 = add i64 %indvar, 1
299  %scevgep10 = getelementptr double, double* %G, i64 %tmp9
300  %3 = load double, double* %scevgep10, align 8
301  %4 = load double, double* %scevgep, align 8
302  %5 = fadd double %3, %4
303  store double %5, double* %scevgep, align 8
304  %exitcond = icmp eq i64 %tmp9, %tmp7
305  br i1 %exitcond, label %return, label %bb
306
307; Should only be one load in the loop.
308; CHECK: bb:
309; CHECK: load double, double*
310; CHECK-NOT: load double, double*
311; CHECK: br i1 %exitcond
312
313return:
314  ret void
315}
316
317;void test10(int N, double* G) {
318;  long j;
319;  for (j = 1; j < N - 1; j++)
320;      G[j] = G[j] + G[j+1] + G[j-1];
321;}
322
323; PR5501
324define void @test10(i32 %N, double* nocapture %G) nounwind ssp {
325entry:
326  %0 = add i32 %N, -1
327  %1 = icmp sgt i32 %0, 1
328  br i1 %1, label %bb.nph, label %return
329
330bb.nph:
331  %tmp = sext i32 %0 to i64
332  %tmp8 = add i64 %tmp, -1
333  br label %bb
334; CHECK: bb.nph:
335; CHECK:   load double, double*
336; CHECK:   load double, double*
337; CHECK:   br label %bb
338
339
340bb:
341  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp11, %bb ]
342  %scevgep = getelementptr double, double* %G, i64 %indvar
343  %tmp9 = add i64 %indvar, 2
344  %scevgep10 = getelementptr double, double* %G, i64 %tmp9
345  %tmp11 = add i64 %indvar, 1
346  %scevgep12 = getelementptr double, double* %G, i64 %tmp11
347  %2 = load double, double* %scevgep12, align 8
348  %3 = load double, double* %scevgep10, align 8
349  %4 = fadd double %2, %3
350  %5 = load double, double* %scevgep, align 8
351  %6 = fadd double %4, %5
352  store double %6, double* %scevgep12, align 8
353  %exitcond = icmp eq i64 %tmp11, %tmp8
354  br i1 %exitcond, label %return, label %bb
355
356; Should only be one load in the loop.
357; CHECK: bb:
358; CHECK: load double, double*
359; CHECK-NOT: load double, double*
360; CHECK: br i1 %exitcond
361
362return:
363  ret void
364}
365
366; Test critical edge splitting.
367define i32 @test11(i32* %p, i1 %C, i32 %N) {
368; CHECK-LABEL: @test11(
369block1:
370        br i1 %C, label %block2, label %block3
371
372block2:
373 %cond = icmp sgt i32 %N, 1
374 br i1 %cond, label %block4, label %block5
375; CHECK: load i32, i32* %p
376; CHECK-NEXT: br label %block4
377
378block3:
379  store i32 0, i32* %p
380  br label %block4
381
382block4:
383  %PRE = load i32, i32* %p
384  br label %block5
385
386block5:
387  %ret = phi i32 [ 0, %block2 ], [ %PRE, %block4 ]
388  ret i32 %ret
389; CHECK: block4:
390; CHECK-NEXT: phi i32
391}
392
393declare void @f()
394declare void @g(i32)
395declare i32 @__CxxFrameHandler3(...)
396
397; Test that loads aren't PRE'd into EH pads.
398define void @test12(i32* %p) personality i32 (...)* @__CxxFrameHandler3 {
399; CHECK-LABEL: @test12(
400block1:
401  invoke void @f()
402          to label %block2 unwind label %catch.dispatch
403
404block2:
405  invoke void @f()
406          to label %block3 unwind label %cleanup
407
408block3:
409  ret void
410
411catch.dispatch:
412  %cs1 = catchswitch within none [label %catch] unwind label %cleanup2
413
414catch:
415  %c = catchpad within %cs1 []
416  catchret from %c to label %block2
417
418cleanup:
419  %c1 = cleanuppad within none []
420  store i32 0, i32* %p
421  cleanupret from %c1 unwind label %cleanup2
422
423; CHECK: cleanup2:
424; CHECK-NOT: phi
425; CHECK-NEXT: %c2 = cleanuppad within none []
426; CHECK-NEXT: %NOTPRE = load i32, i32* %p
427cleanup2:
428  %c2 = cleanuppad within none []
429  %NOTPRE = load i32, i32* %p
430  call void @g(i32 %NOTPRE)
431  cleanupret from %c2 unwind to caller
432}
433