1 ; RUN: llc -mtriple=thumbv7em -mattr=+fp-armv8 %s -o - | \
2 ; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEFAULT
4 ; RUN: llc -mtriple=thumbv8m.main -mattr=+fp-armv8,+dsp %s -o - | \
5 ; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEFAULT
7 ; -lsr-backedge-indexing=false
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
12 ; RUN: llc -mtriple=thumbv8 %s -o - | \
13 ; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=DISABLED
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
18 ; CHECK-LABEL: test_qadd_2
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]!
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]
35 ; DISABLED-NOT: ldr{{.*}}]!
36 ; DISABLED-NOT: str{{.*}}]!
38 define void @test_qadd_2(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
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 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
69 ; CHECK-LABEL: test_qadd_2_backwards
70 ; TODO: Indexes should be generated.
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
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]
90 ; DISABLED-NOT: ldr{{.*}}]!
91 ; DISABLED-NOT: str{{.*}}]!
93 define void @test_qadd_2_backwards(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
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
124 ; CHECK-LABEL: test_qadd_3
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]!
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]
144 ; DISABLED-NOT: ldr{{.*}}]!
145 ; DISABLED-NOT: str{{.*}}]!
147 define void @test_qadd_3(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
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
186 ; CHECK-LABEL: test_qadd_4
189 ; TODO: pre-inc store
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]
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]
214 ; DISABLED-NOT: ldr{{.*}}]!
215 ; DISABLED-NOT: str{{.*}}]!
217 define void @test_qadd_4(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
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 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 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 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
264 ; CHECK-LABEL: test_qadd16_2
266 ; TODO: pre-inc store.
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]!
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]
282 ; DISABLED-NOT: ldr{{.*}}]!
283 ; DISABLED-NOT: str{{.*}}]!
285 define void @test_qadd16_2(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) {
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
316 declare i32 @llvm.arm.qadd(i32, i32)
317 declare i32 @llvm.arm.qadd16(i32, i32)