1 ; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-optree -polly-codegen -analyze < %s | FileCheck %s -match-full-lines
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.
10 ; for (int j = 0; j < n; j += 1) {
13 ; double val2 = val1 + val1;
20 define void @func1(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B, double* noalias nonnull %C) {
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
30 %A_idx = getelementptr inbounds double, double* %A, i32 %j
31 %val1 = load double, double* %A_idx
32 %val2 = fadd double %val1, %val1
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
43 %j.inc = add nuw nsw i32 %j, 1
55 ; CHECK: Instructions copied: 1
56 ; CHECK: Known loads forwarded: 3
57 ; CHECK: Operand trees forwarded: 2
58 ; CHECK: Statements with forwarded operand trees: 1
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
71 ; CHECK-NEXT: %val2 = fadd double %val1, %val1
73 ; CHECK-NEXT: Stmt_bodyB
74 ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
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
83 ; CHECK-NEXT: %val1 = load double, double* %A_idx
84 ; CHECK-NEXT: %val2 = fadd double %val1, %val1
85 ; CHECK-NEXT: %val1 = load double, double* %A_idx
86 ; CHECK-NEXT: store double %val1, double* %B_idx
87 ; CHECK-NEXT: store double %val2, double* %C_idx
92 define void @func2(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B, double* noalias nonnull %C) {
97 %j = phi i32 [0, %entry], [%j.inc, %inc]
98 %j.cmp = icmp slt i32 %j, %n
99 br i1 %j.cmp, label %bodyA, label %exit
102 %A_idx = getelementptr inbounds double, double* %A, i32 %j
103 %val1 = load double, double* %A_idx
104 %val2 = fadd double %val1, %val1
108 %B_idx = getelementptr inbounds double, double* %B, i32 %j
109 store double %val2, double* %B_idx
110 %C_idx = getelementptr inbounds double, double* %C, i32 %j
111 store double %val1, double* %C_idx
115 %j.inc = add nuw nsw i32 %j, 1
126 ; CHECK: Statistics {
127 ; CHECK: Instructions copied: 1
128 ; CHECK: Known loads forwarded: 3
129 ; CHECK: Operand trees forwarded: 2
130 ; CHECK: Statements with forwarded operand trees: 1
133 ; CHECK: After statements {
134 ; CHECK-NEXT: Stmt_bodyA
135 ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
136 ; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] -> MemRef_A[i0] };
137 ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
138 ; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] -> MemRef_val2[] };
139 ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
140 ; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] -> MemRef_val1[] };
141 ; CHECK-NEXT: Instructions {
142 ; CHECK-NEXT: %val1 = load double, double* %A_idx
143 ; CHECK-NEXT: %val2 = fadd double %val1, %val1
145 ; CHECK-NEXT: Stmt_bodyB
146 ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
148 ; CHECK-NEXT: new: [n] -> { Stmt_bodyB[i0] -> MemRef_A[i0] };
149 ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
150 ; CHECK-NEXT: [n] -> { Stmt_bodyB[i0] -> MemRef_B[i0] };
151 ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
152 ; CHECK-NEXT: [n] -> { Stmt_bodyB[i0] -> MemRef_C[i0] };
153 ; CHECK-NEXT: Instructions {
154 ; CHECK-NEXT: %val1 = load double, double* %A_idx
155 ; CHECK-NEXT: %val1 = load double, double* %A_idx
156 ; CHECK-NEXT: %val1 = load double, double* %A_idx
157 ; CHECK-NEXT: %val2 = fadd double %val1, %val1
158 ; CHECK-NEXT: store double %val2, double* %B_idx
159 ; CHECK-NEXT: store double %val1, double* %C_idx