1; RUN: opt %loadPolly -basic-aa -polly-scops -analyze < %s | FileCheck %s
2; RUN: opt %loadPolly -basic-aa -polly-function-scops -analyze < %s | FileCheck %s
3
4; ModuleID = 'scalar_to_array.ll'
5target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
6
7@A = common global [1024 x float] zeroinitializer, align 8
8
9; Terminating loops without side-effects will be optimzied away, hence
10; detecting a scop would be pointless.
11; CHECK-NOT: Function: empty
12; Function Attrs: nounwind
13define i32 @empty() #0 {
14entry:
15  fence seq_cst
16  br label %for.cond
17
18for.cond:                                         ; preds = %for.inc, %entry
19  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
20  %exitcond = icmp ne i64 %indvar, 1024
21  br i1 %exitcond, label %for.body, label %return
22
23for.body:                                         ; preds = %for.cond
24  br label %for.inc
25
26for.inc:                                          ; preds = %for.body
27  %indvar.next = add i64 %indvar, 1
28  br label %for.cond
29
30return:                                           ; preds = %for.cond
31  fence seq_cst
32  ret i32 0
33}
34
35; CHECK-LABEL: Function: array_access
36; Function Attrs: nounwind
37define i32 @array_access() #0 {
38entry:
39  fence seq_cst
40  br label %for.cond
41
42for.cond:                                         ; preds = %for.inc, %entry
43  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
44  %exitcond = icmp ne i64 %indvar, 1024
45  br i1 %exitcond, label %for.body, label %return
46
47for.body:                                         ; preds = %for.cond
48  %arrayidx = getelementptr [1024 x float], [1024 x float]* @A, i64 0, i64 %indvar
49  %float = uitofp i64 %indvar to float
50  store float %float, float* %arrayidx
51  br label %for.inc
52; CHECK:     Stmt_for_body
53; CHECK-NOT:     ReadAccess
54; CHECK:         MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
55; CHECK-NEXT:        { Stmt_for_body[i0] -> MemRef_A[i0] };
56
57for.inc:                                          ; preds = %for.body
58  %indvar.next = add i64 %indvar, 1
59  br label %for.cond
60
61return:                                           ; preds = %for.cond
62  fence seq_cst
63  ret i32 0
64}
65
66; Function Attrs: nounwind
67; CHECK-LABEL: Function: intra_scop_dep
68define i32 @intra_scop_dep() #0 {
69entry:
70  fence seq_cst
71  br label %for.cond
72
73for.cond:                                         ; preds = %for.inc, %entry
74  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
75  %exitcond = icmp ne i64 %indvar, 1024
76  br i1 %exitcond, label %for.body.a, label %return
77
78for.body.a:                                       ; preds = %for.cond
79  %arrayidx = getelementptr [1024 x float], [1024 x float]* @A, i64 0, i64 %indvar
80  %scalar = load float, float* %arrayidx
81  br label %for.body.b
82; CHECK:      Stmt_for_body_a
83; CHECK:          ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
84; CHECK-NEXT:         { Stmt_for_body_a[i0] -> MemRef_A[i0] };
85; CHECK:          MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
86; CHECK-NEXT:         { Stmt_for_body_a[i0] -> MemRef_scalar[] };
87
88for.body.b:                                       ; preds = %for.body.a
89  %arrayidx2 = getelementptr [1024 x float], [1024 x float]* @A, i64 0, i64 %indvar
90  %float = uitofp i64 %indvar to float
91  %sum = fadd float %scalar, %float
92  store float %sum, float* %arrayidx2
93  br label %for.inc
94; CHECK:      Stmt_for_body_b
95; CHECK:          ReadAccess :=       [Reduction Type: NONE] [Scalar: 1]
96; CHECK-NEXT:          { Stmt_for_body_b[i0] -> MemRef_scalar[] };
97; CHECK:          MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
98; CHECK-NEXT:         { Stmt_for_body_b[i0] -> MemRef_A[i0] };
99
100for.inc:                                          ; preds = %for.body.b
101  %indvar.next = add i64 %indvar, 1
102  br label %for.cond
103
104return:                                           ; preds = %for.cond
105  fence seq_cst
106  ret i32 0
107}
108
109; It is not possible to have a scop which accesses a scalar element that is
110; a global variable. All global variables are pointers containing possibly
111; a single element. Hence they do not need to be handled anyways.
112; Please note that this is still required when scalar to array rewritting is
113; disabled.
114
115; CHECK-LABEL: Function: use_after_scop
116; Function Attrs: nounwind
117define i32 @use_after_scop() #0 {
118entry:
119  %scalar.s2a = alloca float
120  fence seq_cst
121  br label %for.head
122
123for.head:                                         ; preds = %for.inc, %entry
124  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
125  br label %for.body
126
127for.body:                                         ; preds = %for.head
128  %arrayidx = getelementptr [1024 x float], [1024 x float]* @A, i64 0, i64 %indvar
129  %scalar = load float, float* %arrayidx
130  store float %scalar, float* %scalar.s2a
131; Escaped uses are still required to be rewritten to stack variable.
132; CHECK:      Stmt_for_body
133; CHECK:          ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
134; CHECK-NEXT:         { Stmt_for_body[i0] -> MemRef_A[i0] };
135; CHECK:          MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
136; CHECK-NEXT:         { Stmt_for_body[i0] -> MemRef_scalar_s2a[0] };
137  br label %for.inc
138
139for.inc:                                          ; preds = %for.body
140  %indvar.next = add i64 %indvar, 1
141  %exitcond = icmp ne i64 %indvar.next, 1024
142  br i1 %exitcond, label %for.head, label %for.after
143
144for.after:                                        ; preds = %for.inc
145  %scalar.loadoutside = load float, float* %scalar.s2a
146  fence seq_cst
147  %return_value = fptosi float %scalar.loadoutside to i32
148  br label %return
149
150return:                                           ; preds = %for.after
151  ret i32 %return_value
152}
153
154; We currently do not transform scalar references, that have only read accesses
155; in the scop. There are two reasons for this:
156;
157;  o We don't introduce additional memory references which may yield to compile
158;    time overhead.
159;  o For integer values, such a translation may block the use of scalar
160;    evolution on those values.
161;
162; CHECK-LABEL: Function: before_scop
163; Function Attrs: nounwind
164define i32 @before_scop() #0 {
165entry:
166  br label %preheader
167
168preheader:                                        ; preds = %entry
169  %scalar = fadd float 4.000000e+00, 5.000000e+00
170  fence seq_cst
171  br label %for.cond
172
173for.cond:                                         ; preds = %for.inc, %preheader
174  %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %preheader ]
175  %exitcond = icmp ne i64 %indvar, 1024
176  br i1 %exitcond, label %for.body, label %return
177
178for.body:                                         ; preds = %for.cond
179  %arrayidx = getelementptr [1024 x float], [1024 x float]* @A, i64 0, i64 %indvar
180  store float %scalar, float* %arrayidx
181  br label %for.inc
182; CHECK:      Stmt_for_body
183; CHECK:          MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
184; CHECK-NEXT:         { Stmt_for_body[i0] -> MemRef_A[i0] };
185
186for.inc:                                          ; preds = %for.body
187  %indvar.next = add i64 %indvar, 1
188  br label %for.cond
189
190return:                                           ; preds = %for.cond
191  fence seq_cst
192  ret i32 0
193}
194
195attributes #0 = { nounwind }
196