Fix Polly
[polly-mirror.git] / test / ForwardOpTree / forward_load_tripleuse.ll
blobed2f4d38d775b702208cff972ad760664659a574
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) {
11 ; bodyA:
12 ;   double val1 = A[j];
13 ;   double val2 = val1 + val1;
15 ; bodyB:
16 ;   B[j] = val1;
17 ;   C[j] = val2;
18 ; }
20 define void @func1(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B, double* noalias nonnull %C) {
21 entry:
22   br label %for
24 for:
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
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
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
42 inc:
43   %j.inc = add nuw nsw i32 %j, 1
44   br label %for
46 exit:
47   br label %return
49 return:
50   ret void
54 ; CHECK: Statistics {
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
59 ; CHECK: }
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
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
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
88 ; CHECK-NEXT:             }
89 ; CHECK-NEXT: }
92 define void @func2(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B, double* noalias nonnull %C) {
93 entry:
94   br label %for
96 for:
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
101     bodyA:
102       %A_idx = getelementptr inbounds double, double* %A, i32 %j
103       %val1 = load double, double* %A_idx
104       %val2 = fadd double %val1, %val1
105       br label %bodyB
107     bodyB:
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
112       br label %inc
114 inc:
115   %j.inc = add nuw nsw i32 %j, 1
116   br label %for
118 exit:
119   br label %return
121 return:
122   ret void
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
131 ; CHECK: }
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
144 ; CHECK-NEXT:             }
145 ; CHECK-NEXT:     Stmt_bodyB
146 ; CHECK-NEXT:             ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
147 ; CHECK-NEXT:                 ;
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
160 ; CHECK-NEXT:             }
161 ; CHECK-NEXT: }