1 ; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-print-optree -polly-codegen -disable-output < %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, ptr noalias nonnull %A, ptr noalias nonnull %B, ptr 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, ptr %A, i32 %j
31 %val1 = load double, ptr %A_idx
32 %val2 = fadd double %val1, %val1
36 %B_idx = getelementptr inbounds double, ptr %B, i32 %j
37 store double %val1, ptr %B_idx
38 %C_idx = getelementptr inbounds double, ptr %C, i32 %j
39 store double %val2, ptr %C_idx
43 %j.inc = add nuw nsw i32 %j, 1
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
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, ptr %A_idx, align 8
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, ptr %A_idx, align 8
83 ; CHECK-NEXT: %val2 = fadd double %val1, %val1
84 ; CHECK-NEXT: %val1 = load double, ptr %A_idx, align 8
85 ; CHECK-NEXT: store double %val1, ptr %B_idx, align 8
86 ; CHECK-NEXT: store double %val2, ptr %C_idx, align 8
91 define void @func2(i32 %n, ptr noalias nonnull %A, ptr noalias nonnull %B, ptr noalias nonnull %C) {
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
101 %A_idx = getelementptr inbounds double, ptr %A, i32 %j
102 %val1 = load double, ptr %A_idx
103 %val2 = fadd double %val1, %val1
107 %B_idx = getelementptr inbounds double, ptr %B, i32 %j
108 store double %val2, ptr %B_idx
109 %C_idx = getelementptr inbounds double, ptr %C, i32 %j
110 store double %val1, ptr %C_idx
114 %j.inc = add nuw nsw i32 %j, 1
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
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, ptr %A_idx, align 8
142 ; CHECK-NEXT: %val2 = fadd double %val1, %val1
144 ; CHECK-NEXT: Stmt_bodyB
145 ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
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, ptr %A_idx, align 8
154 ; CHECK-NEXT: %val1 = load double, ptr %A_idx, align 8
155 ; CHECK-NEXT: %val2 = fadd double %val1, %val1
156 ; CHECK-NEXT: store double %val2, ptr %B_idx, align 8
157 ; CHECK-NEXT: store double %val1, ptr %C_idx, align 8