xref: /llvm-project/llvm/test/CodeGen/ARM/dsp-loop-indexing.ll (revision eecb99c5f66c8491766628a2925587e20f3b1dbd)
1; RUN: llc -mtriple=thumbv7em -mattr=+fp-armv8 %s -o - | \
2; RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEFAULT
3
4; RUN: llc -mtriple=thumbv8m.main -mattr=+fp-armv8,+dsp %s -o - | \
5; RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEFAULT
6
7; -lsr-backedge-indexing=false
8
9; RUN: llc -mtriple=thumbv8m.main -mattr=+fp-armv8,+dsp -lsr-preferred-addressing-mode=postindexed %s -o - | \
10; RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=DISABLED
11
12; RUN: llc -mtriple=thumbv8 %s -o - | \
13; RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=DISABLED
14
15; RUN: llc -mtriple=thumbv8m.main -mattr=+fp-armv8,+dsp -lsr-complexity-limit=2147483647 %s -o - | \
16; RUN:     FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-COMPLEX
17
18; CHECK-LABEL: test_qadd_2
19; CHECK: @ %loop
20
21; CHECK-DEFAULT: ldr{{.*}}, #4]
22; CHECK-DEFAULT: ldr{{.*}}, #4]
23; CHECK-DEFAULT: str{{.*}}, #4]
24; CHECK-DEFAULT: ldr{{.*}}, #8]!
25; CHECK-DEAFULT: ldr{{.*}}, #8]!
26; CHECK-DEFAULT: str{{.*}}, #8]!
27
28; CHECK-COMPLEX: ldr{{.*}}, #8]!
29; CHECK-COMPLEX: ldr{{.*}}, #8]!
30; CHECK-COMPLEX: str{{.*}}, #8]!
31; CHECK-COMPLEX: ldr{{.*}}, #4]
32; CHECK-COMPLEX: ldr{{.*}}, #4]
33; CHECK-COMPLEX: str{{.*}}, #4]
34
35; DISABLED-NOT: ldr{{.*}}]!
36; DISABLED-NOT: str{{.*}}]!
37
38define void @test_qadd_2(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
39entry:
40  br label %loop
41
42loop:
43  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
44  %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ]
45  %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1
46  %a.1 = load i32, ptr %gep.a.1
47  %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1
48  %b.1 = load i32, ptr %gep.b.1
49  %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1)
50  %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1
51  store i32 %qadd.1, ptr %addr.1
52  %idx.2 = or disjoint i32 %idx.1, 1
53  %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2
54  %a.2 = load i32, ptr %gep.a.2
55  %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2
56  %b.2 = load i32, ptr %gep.b.2
57  %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2)
58  %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2
59  store i32 %qadd.2, ptr %addr.2
60  %i.next = add nsw nuw i32 %i, -2
61  %idx.next = add nsw nuw i32 %idx.1, 2
62  %cmp = icmp ult i32 %i.next, %N
63  br i1 %cmp, label %loop, label %exit
64
65exit:
66  ret void
67}
68
69; CHECK-LABEL: test_qadd_2_backwards
70; TODO: Indexes should be generated.
71
72; CHECK: @ %loop
73
74; CHECK-DEFAULT: ldr{{.*}},
75; CHECK-DEFAULT: ldr{{.*}},
76; CHECK-DEFAULT: str{{.*}},
77; CHECK-DEFAULT: ldr{{.*}}, #-4]
78; CHECK-DEFAULT: ldr{{.*}}, #-4]
79; CHECK-DEFAULT: sub{{.*}}, #8
80; CHECK-DEFAULT: str{{.*}}, #-4]
81; CHECK-DEFAULT: sub{{.*}}, #8
82
83; CHECK-COMPLEX: ldr{{.*}} lsl #2]
84; CHECK-COMPLEX: ldr{{.*}} lsl #2]
85; CHECK-COMPLEX: str{{.*}} lsl #2]
86; CHECK-COMPLEX: ldr{{.*}} lsl #2]
87; CHECK-COMPLEX: ldr{{.*}} lsl #2]
88; CHECK-COMPLEX: str{{.*}} lsl #2]
89
90; DISABLED-NOT: ldr{{.*}}]!
91; DISABLED-NOT: str{{.*}}]!
92
93define void @test_qadd_2_backwards(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
94entry:
95  br label %loop
96
97loop:
98  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
99  %idx.1 = phi i32 [ %N, %entry ], [ %idx.next, %loop ]
100  %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1
101  %a.1 = load i32, ptr %gep.a.1
102  %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1
103  %b.1 = load i32, ptr %gep.b.1
104  %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1)
105  %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1
106  store i32 %qadd.1, ptr %addr.1
107  %idx.2 = sub nsw nuw i32 %idx.1, 1
108  %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2
109  %a.2 = load i32, ptr %gep.a.2
110  %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2
111  %b.2 = load i32, ptr %gep.b.2
112  %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2)
113  %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2
114  store i32 %qadd.2, ptr %addr.2
115  %i.next = add nsw nuw i32 %i, -2
116  %idx.next = sub nsw nuw i32 %idx.1, 2
117  %cmp = icmp ult i32 %i.next, %N
118  br i1 %cmp, label %loop, label %exit
119
120exit:
121  ret void
122}
123
124; CHECK-LABEL: test_qadd_3
125; CHECK: @ %loop
126
127; CHECK-DEFAULT: ldr{{.*}}, #8]
128; CHECK-DEFAULT: ldr{{.*}}, #8]
129; CHECK-DEFAULT: str{{.*}}, #8]
130; CHECK-DEFAULT: ldr{{.*}}, #12]!
131; CHECK-DEFAULT: ldr{{.*}}, #12]!
132; CHECK-DEFAULT: str{{.*}}, #12]!
133
134; CHECK-COMPLEX: ldr{{.*}}, #12]!
135; CHECK-COMPLEX: ldr{{.*}}, #12]!
136; CHECK-COMPLEX: str{{.*}}, #12]!
137; CHECK-COMPLEX: ldr{{.*}}, #4]
138; CHECK-COMPLEX: ldr{{.*}}, #4]
139; CHECK-COMPLEX: str{{.*}}, #4]
140; CHECK-COMPLEX: ldr{{.*}}, #8]
141; CHECK-COMPLEX: ldr{{.*}}, #8]
142; CHECK-COMPLEX: str{{.*}}, #8]
143
144; DISABLED-NOT: ldr{{.*}}]!
145; DISABLED-NOT: str{{.*}}]!
146
147define void @test_qadd_3(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
148entry:
149  br label %loop
150
151loop:
152  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
153  %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ]
154  %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1
155  %a.1 = load i32, ptr %gep.a.1
156  %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1
157  %b.1 = load i32, ptr %gep.b.1
158  %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1)
159  %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1
160  store i32 %qadd.1, ptr %addr.1
161  %idx.2 = add nuw nsw i32 %idx.1, 1
162  %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2
163  %a.2 = load i32, ptr %gep.a.2
164  %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2
165  %b.2 = load i32, ptr %gep.b.2
166  %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2)
167  %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2
168  store i32 %qadd.2, ptr %addr.2
169  %idx.3 = add nuw nsw i32 %idx.1, 2
170  %gep.a.3 = getelementptr inbounds i32, ptr %a.array, i32 %idx.3
171  %a.3 = load i32, ptr %gep.a.3
172  %gep.b.3 = getelementptr inbounds i32, ptr %b.array, i32 %idx.3
173  %b.3 = load i32, ptr %gep.b.3
174  %qadd.3 = call i32 @llvm.arm.qadd(i32 %a.3, i32 %b.3)
175  %addr.3 = getelementptr inbounds i32, ptr %out.array, i32 %idx.3
176  store i32 %qadd.3, ptr %addr.3
177  %i.next = add nsw nuw i32 %i, -3
178  %idx.next = add nsw nuw i32 %idx.1, 3
179  %cmp = icmp ult i32 %i.next, %N
180  br i1 %cmp, label %loop, label %exit
181
182exit:
183  ret void
184}
185
186; CHECK-LABEL: test_qadd_4
187; CHECK: @ %loop
188
189; TODO: pre-inc store
190
191; CHECK-DEFAULT: ldr{{.*}}, #4]
192; CHECK-DEFAULT: ldr{{.*}}, #4]
193; CHECK-DEFAULT: str{{.*}}, #4]
194; CHECK-DEFAULT: ldr{{.*}}, #8]
195; CHECK-DEFAULT: ldr{{.*}}, #8]
196; CHECK-DEFAULT: str{{.*}}, #8]
197; CHECK-DEFAULT: ldr{{.*}}, #12]
198; CHECK-DEFAULT: ldr{{.*}}, #12]
199; CHECK-DEFAULT: str{{.*}}, #12]
200
201; CHECK-COMPLEX: ldr{{.*}}, #16]!
202; CHECK-COMPLEX: ldr{{.*}}, #16]!
203; CHECK-COMPLEX: str{{.*}}, #16]!
204; CHECK-COMPLEX: ldr{{.*}}, #4]
205; CHECK-COMPLEX: ldr{{.*}}, #4]
206; CHECK-COMPLEX: str{{.*}}, #4]
207; CHECK-COMPLEX: ldr{{.*}}, #8]
208; CHECK-COMPLEX: ldr{{.*}}, #8]
209; CHECK-COMPLEX: str{{.*}}, #8]
210; CHECK-COMPLEX: ldr{{.*}}, #12]
211; CHECK-COMPLEX: ldr{{.*}}, #12]
212; CHECK-COMPLEX: str{{.*}}, #12]
213
214; DISABLED-NOT: ldr{{.*}}]!
215; DISABLED-NOT: str{{.*}}]!
216
217define void @test_qadd_4(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
218entry:
219  br label %loop
220
221loop:
222  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
223  %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ]
224  %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1
225  %a.1 = load i32, ptr %gep.a.1
226  %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1
227  %b.1 = load i32, ptr %gep.b.1
228  %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1)
229  %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1
230  store i32 %qadd.1, ptr %addr.1
231  %idx.2 = or disjoint i32 %idx.1, 1
232  %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2
233  %a.2 = load i32, ptr %gep.a.2
234  %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2
235  %b.2 = load i32, ptr %gep.b.2
236  %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2)
237  %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2
238  store i32 %qadd.2, ptr %addr.2
239  %idx.3 = or disjoint i32 %idx.1, 2
240  %gep.a.3 = getelementptr inbounds i32, ptr %a.array, i32 %idx.3
241  %a.3 = load i32, ptr %gep.a.3
242  %gep.b.3 = getelementptr inbounds i32, ptr %b.array, i32 %idx.3
243  %b.3 = load i32, ptr %gep.b.3
244  %qadd.3 = call i32 @llvm.arm.qadd(i32 %a.3, i32 %b.3)
245  %addr.3 = getelementptr inbounds i32, ptr %out.array, i32 %idx.3
246  store i32 %qadd.3, ptr %addr.3
247  %idx.4 = or disjoint i32 %idx.1, 3
248  %gep.a.4 = getelementptr inbounds i32, ptr %a.array, i32 %idx.4
249  %a.4 = load i32, ptr %gep.a.4
250  %gep.b.4 = getelementptr inbounds i32, ptr %b.array, i32 %idx.4
251  %b.4 = load i32, ptr %gep.b.4
252  %qadd.4 = call i32 @llvm.arm.qadd(i32 %a.4, i32 %b.4)
253  %addr.4 = getelementptr inbounds i32, ptr %out.array, i32 %idx.4
254  store i32 %qadd.4, ptr %addr.4
255  %i.next = add nsw nuw i32 %i, -4
256  %idx.next = add nsw nuw i32 %idx.1, 4
257  %cmp = icmp ult i32 %i.next, %N
258  br i1 %cmp, label %loop, label %exit
259
260exit:
261  ret void
262}
263
264; CHECK-LABEL: test_qadd16_2
265; CHECK: @ %loop
266; TODO: pre-inc store.
267
268; CHECK-DEFAULT: ldr{{.*}}, #4]
269; CHECK-DEFAULT: ldr{{.*}}, #4]
270; CHECK-DEFAULT: str{{.*}}, #8]
271; CHECK-DEFAULT: ldr{{.*}}, #8]!
272; CHECK-DEFAULT: ldr{{.*}}, #8]!
273; CHECK-DEFAULT: str{{.*}}, #16]!
274
275; CHECK-COMPLEX: ldr{{.*}}, #8]!
276; CHECK-COMPLEX: ldr{{.*}}, #8]!
277; CHECK-COMPLEX: str{{.*}}, #16]!
278; CHECK-COMPLEX: ldr{{.*}}, #4]
279; CHECK-COMPLEX: ldr{{.*}}, #4]
280; CHECK-COMPLEX: str{{.*}}, #8]
281
282; DISABLED-NOT: ldr{{.*}}]!
283; DISABLED-NOT: str{{.*}}]!
284
285define void @test_qadd16_2(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
286entry:
287  br label %loop
288
289loop:
290  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
291  %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ]
292  %gep.a.1 = getelementptr inbounds i16, ptr %a.array, i32 %idx.1
293  %a.1 = load i32, ptr %gep.a.1
294  %gep.b.1 = getelementptr inbounds i16, ptr %b.array, i32 %idx.1
295  %b.1 = load i32, ptr %gep.b.1
296  %qadd.1 = call i32 @llvm.arm.qadd16(i32 %a.1, i32 %b.1)
297  %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1
298  store i32 %qadd.1, ptr %addr.1
299  %idx.2 = add nsw nuw i32 %idx.1, 2
300  %gep.a.2 = getelementptr inbounds i16, ptr %a.array, i32 %idx.2
301  %a.2 = load i32, ptr %gep.a.2
302  %gep.b.2 = getelementptr inbounds i16, ptr %b.array, i32 %idx.2
303  %b.2 = load i32, ptr %gep.b.2
304  %qadd.2 = call i32 @llvm.arm.qadd16(i32 %a.2, i32 %b.2)
305  %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2
306  store i32 %qadd.2, ptr %addr.2
307  %i.next = add nsw nuw i32 %i, -2
308  %idx.next = add nsw nuw i32 %idx.1, 4
309  %cmp = icmp ult i32 %i.next, %N
310  br i1 %cmp, label %loop, label %exit
311
312exit:
313  ret void
314}
315
316declare i32 @llvm.arm.qadd(i32, i32)
317declare i32 @llvm.arm.qadd16(i32, i32)
318