1; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree -polly-codegen -analyze < %s | FileCheck %s -match-full-lines
2;
3; %val1 is used three times: Twice by its own operand tree of %val2 and once
4; more by the store in %bodyB.
5; Verify that we can handle multiple uses by the same instruction and uses
6; in multiple statements as well.
7; The result processing may depend on the order in which the values are used,
8; hence we check both orderings.
9;
10; for (int j = 0; j < n; j += 1) {
11; bodyA:
12;   double val1 = A[j];
13;   double val2 = val1 + val1;
14;
15; bodyB:
16;   B[j] = val1;
17;   C[j] = val2;
18; }
19;
20define void @func1(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B, double* noalias nonnull %C) {
21entry:
22  br label %for
23
24for:
25  %j = phi i32 [0, %entry], [%j.inc, %inc]
26  %j.cmp = icmp slt i32 %j, %n
27  br i1 %j.cmp, label %bodyA, label %exit
28
29    bodyA:
30      %A_idx = getelementptr inbounds double, double* %A, i32 %j
31      %val1 = load double, double* %A_idx
32      %val2 = fadd double %val1, %val1
33      br label %bodyB
34
35    bodyB:
36      %B_idx = getelementptr inbounds double, double* %B, i32 %j
37      store double %val1, double* %B_idx
38      %C_idx = getelementptr inbounds double, double* %C, i32 %j
39      store double %val2, double* %C_idx
40      br label %inc
41
42inc:
43  %j.inc = add nuw nsw i32 %j, 1
44  br label %for
45
46exit:
47  br label %return
48
49return:
50  ret void
51}
52
53
54; CHECK: Statistics {
55; CHECK:     Instructions copied: 1
56; CHECK:     Known loads forwarded: 2
57; CHECK:     Operand trees forwarded: 2
58; CHECK:     Statements with forwarded operand trees: 1
59; CHECK: }
60
61; CHECK:      After statements {
62; CHECK-NEXT:     Stmt_bodyA
63; CHECK-NEXT:             ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
64; CHECK-NEXT:                 [n] -> { Stmt_bodyA[i0] -> MemRef_A[i0] };
65; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
66; CHECK-NEXT:                 [n] -> { Stmt_bodyA[i0] -> MemRef_val1[] };
67; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
68; CHECK-NEXT:                 [n] -> { Stmt_bodyA[i0] -> MemRef_val2[] };
69; CHECK-NEXT:             Instructions {
70; CHECK-NEXT:                   %val1 = load double, double* %A_idx, align 8
71; CHECK-NEXT:                   %val2 = fadd double %val1, %val1
72; CHECK-NEXT:             }
73; CHECK-NEXT:     Stmt_bodyB
74; CHECK-NEXT:             ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
75; CHECK-NEXT:                 ;
76; CHECK-NEXT:            new: [n] -> { Stmt_bodyB[i0] -> MemRef_A[i0] };
77; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
78; CHECK-NEXT:                 [n] -> { Stmt_bodyB[i0] -> MemRef_B[i0] };
79; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
80; CHECK-NEXT:                 [n] -> { Stmt_bodyB[i0] -> MemRef_C[i0] };
81; CHECK-NEXT:             Instructions {
82; CHECK-NEXT:                   %val1 = load double, double* %A_idx, align 8
83; CHECK-NEXT:                   %val2 = fadd double %val1, %val1
84; CHECK-NEXT:                   %val1 = load double, double* %A_idx, align 8
85; CHECK-NEXT:                   store double %val1, double* %B_idx, align 8
86; CHECK-NEXT:                   store double %val2, double* %C_idx, align 8
87; CHECK-NEXT:             }
88; CHECK-NEXT: }
89
90
91define void @func2(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B, double* noalias nonnull %C) {
92entry:
93  br label %for
94
95for:
96  %j = phi i32 [0, %entry], [%j.inc, %inc]
97  %j.cmp = icmp slt i32 %j, %n
98  br i1 %j.cmp, label %bodyA, label %exit
99
100    bodyA:
101      %A_idx = getelementptr inbounds double, double* %A, i32 %j
102      %val1 = load double, double* %A_idx
103      %val2 = fadd double %val1, %val1
104      br label %bodyB
105
106    bodyB:
107      %B_idx = getelementptr inbounds double, double* %B, i32 %j
108      store double %val2, double* %B_idx
109      %C_idx = getelementptr inbounds double, double* %C, i32 %j
110      store double %val1, double* %C_idx
111      br label %inc
112
113inc:
114  %j.inc = add nuw nsw i32 %j, 1
115  br label %for
116
117exit:
118  br label %return
119
120return:
121  ret void
122}
123
124
125; CHECK: Statistics {
126; CHECK:     Instructions copied: 1
127; CHECK:     Known loads forwarded: 2
128; CHECK:     Operand trees forwarded: 2
129; CHECK:     Statements with forwarded operand trees: 1
130; CHECK: }
131
132; CHECK:      After statements {
133; CHECK-NEXT:     Stmt_bodyA
134; CHECK-NEXT:             ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
135; CHECK-NEXT:                 [n] -> { Stmt_bodyA[i0] -> MemRef_A[i0] };
136; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
137; CHECK-NEXT:                 [n] -> { Stmt_bodyA[i0] -> MemRef_val2[] };
138; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
139; CHECK-NEXT:                 [n] -> { Stmt_bodyA[i0] -> MemRef_val1[] };
140; CHECK-NEXT:             Instructions {
141; CHECK-NEXT:                   %val1 = load double, double* %A_idx, align 8
142; CHECK-NEXT:                   %val2 = fadd double %val1, %val1
143; CHECK-NEXT:             }
144; CHECK-NEXT:     Stmt_bodyB
145; CHECK-NEXT:             ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
146; CHECK-NEXT:                 ;
147; CHECK-NEXT:            new: [n] -> { Stmt_bodyB[i0] -> MemRef_A[i0] };
148; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
149; CHECK-NEXT:                 [n] -> { Stmt_bodyB[i0] -> MemRef_B[i0] };
150; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
151; CHECK-NEXT:                 [n] -> { Stmt_bodyB[i0] -> MemRef_C[i0] };
152; CHECK-NEXT:             Instructions {
153; CHECK-NEXT:                   %val1 = load double, double* %A_idx, align 8
154; CHECK-NEXT:                   %val1 = load double, double* %A_idx, align 8
155; CHECK-NEXT:                   %val2 = fadd double %val1, %val1
156; CHECK-NEXT:                   store double %val2, double* %B_idx, align 8
157; CHECK-NEXT:                   store double %val1, double* %C_idx, align 8
158; CHECK-NEXT:             }
159; CHECK-NEXT: }
160