blob: f9d88e891be9b7a69ee8e0dcd25467ecf34f8e38 [file] [log] [blame]
Adam Nemete2b885c2015-04-23 20:09:20 +00001; RUN: opt -basicaa -loop-accesses -analyze < %s | FileCheck %s
Sean Silva284b0322016-07-07 01:01:53 +00002; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output < %s 2>&1 | FileCheck %s
Adam Nemete2b885c2015-04-23 20:09:20 +00003
4; This loop:
5;
6; int **A;
7; for (i)
8; for (j) {
9; A[i][j] = A[i-1][j] * B[j]
10; B[j+1] = 2 // backward dep between this and the previous
11; }
12;
13; is transformed by Load-PRE to stash away A[i] for the next iteration of the
14; outer loop:
15;
16; Curr = A[0]; // Prev_0
17; for (i: 1..N) {
18; Prev = Curr; // Prev = PHI (Prev_0, Curr)
19; Curr = A[i];
20; for (j: 0..N) {
21; Curr[j] = Prev[j] * B[j]
22; B[j+1] = 2 // backward dep between this and the previous
23; }
24; }
25;
26; Since A[i] and A[i-1] are likely to be independent, getUnderlyingObjects
27; should not assume that Curr and Prev share the same underlying object.
28;
29; If it did we would try to dependence-analyze Curr and Prev and the analysis
30; would fail with non-constant distance.
31;
32; To illustrate one of the negative consequences of this, if the loop has a
33; backward dependence we won't detect this but instead fully fall back on
34; memchecks (that is what LAA does after encountering a case of non-constant
35; distance).
36
37target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
38target triple = "x86_64-apple-macosx10.10.0"
39
40; CHECK: for_j.body:
Adam Nemete2b885c2015-04-23 20:09:20 +000041; CHECK-NEXT: Report: unsafe dependent memory operations in loop
Adam Nemeta2df7502015-11-03 21:39:52 +000042; CHECK-NEXT: Dependences:
Adam Nemete2b885c2015-04-23 20:09:20 +000043; CHECK-NEXT: Backward:
44; CHECK-NEXT: %loadB = load i8, i8* %gepB, align 1 ->
45; CHECK-NEXT: store i8 2, i8* %gepB_plus_one, align 1
46
47define void @f(i8** noalias %A, i8* noalias %B, i64 %N) {
48for_i.preheader:
49 %prev_0 = load i8*, i8** %A, align 8
50 br label %for_i.body
51
52for_i.body:
53 %i = phi i64 [1, %for_i.preheader], [%i.1, %for_j.end]
54 %prev = phi i8* [%prev_0, %for_i.preheader], [%curr, %for_j.end]
55 %gep = getelementptr inbounds i8*, i8** %A, i64 %i
56 %curr = load i8*, i8** %gep, align 8
57 br label %for_j.preheader
58
59for_j.preheader:
60 br label %for_j.body
61
62for_j.body:
63 %j = phi i64 [0, %for_j.preheader], [%j.1, %for_j.body]
64
65 %gepPrev = getelementptr inbounds i8, i8* %prev, i64 %j
66 %gepCurr = getelementptr inbounds i8, i8* %curr, i64 %j
67 %gepB = getelementptr inbounds i8, i8* %B, i64 %j
68
69 %loadPrev = load i8, i8* %gepPrev, align 1
70 %loadB = load i8, i8* %gepB, align 1
71
72 %mul = mul i8 %loadPrev, %loadB
73
74 store i8 %mul, i8* %gepCurr, align 1
75
76 %gepB_plus_one = getelementptr inbounds i8, i8* %gepB, i64 1
77 store i8 2, i8* %gepB_plus_one, align 1
78
79 %j.1 = add nuw i64 %j, 1
80 %exitcondj = icmp eq i64 %j.1, %N
81 br i1 %exitcondj, label %for_j.end, label %for_j.body
82
83for_j.end:
84
85 %i.1 = add nuw i64 %i, 1
86 %exitcond = icmp eq i64 %i.1, %N
87 br i1 %exitcond, label %for_i.end, label %for_i.body
88
89for_i.end:
90 ret void
91}