• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -ffreestanding -triple armv8-eabi -target-cpu cortex-a57 -O -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch32
2 // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +neon -target-feature +crc -target-feature +crypto -O -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch64
3 
4 #include <arm_acle.h>
5 
6 /* 8 SYNCHRONIZATION, BARRIER AND HINT INTRINSICS */
7 /* 8.3 Memory Barriers */
8 // ARM-LABEL: test_dmb
9 // AArch32: call void @llvm.arm.dmb(i32 1)
10 // AArch64: call void @llvm.aarch64.dmb(i32 1)
test_dmb(void)11 void test_dmb(void) {
12   __dmb(1);
13 }
14 
15 // ARM-LABEL: test_dsb
16 // AArch32: call void @llvm.arm.dsb(i32 2)
17 // AArch64: call void @llvm.aarch64.dsb(i32 2)
test_dsb(void)18 void test_dsb(void) {
19   __dsb(2);
20 }
21 
22 // ARM-LABEL: test_isb
23 // AArch32: call void @llvm.arm.isb(i32 3)
24 // AArch64: call void @llvm.aarch64.isb(i32 3)
test_isb(void)25 void test_isb(void) {
26   __isb(3);
27 }
28 
29 /* 8.4 Hints */
30 // ARM-LABEL: test_yield
31 // AArch32: call void @llvm.arm.hint(i32 1)
32 // AArch64: call void @llvm.aarch64.hint(i32 1)
test_yield(void)33 void test_yield(void) {
34   __yield();
35 }
36 
37 // ARM-LABEL: test_wfe
38 // AArch32: call void @llvm.arm.hint(i32 2)
39 // AArch64: call void @llvm.aarch64.hint(i32 2)
test_wfe(void)40 void test_wfe(void) {
41   __wfe();
42 }
43 
44 // ARM-LABEL: test_wfi
45 // AArch32: call void @llvm.arm.hint(i32 3)
46 // AArch64: call void @llvm.aarch64.hint(i32 3)
test_wfi(void)47 void test_wfi(void) {
48   __wfi();
49 }
50 
51 // ARM-LABEL: test_sev
52 // AArch32: call void @llvm.arm.hint(i32 4)
53 // AArch64: call void @llvm.aarch64.hint(i32 4)
test_sev(void)54 void test_sev(void) {
55   __sev();
56 }
57 
58 // ARM-LABEL: test_sevl
59 // AArch32: call void @llvm.arm.hint(i32 5)
60 // AArch64: call void @llvm.aarch64.hint(i32 5)
test_sevl(void)61 void test_sevl(void) {
62   __sevl();
63 }
64 
65 #if __ARM_32BIT_STATE
66 // AArch32-LABEL: test_dbg
67 // AArch32: call void @llvm.arm.dbg(i32 0)
test_dbg(void)68 void test_dbg(void) {
69   __dbg(0);
70 }
71 #endif
72 
73 /* 8.5 Swap */
74 // ARM-LABEL: test_swp
75 // AArch32: call i32 @llvm.arm.ldrex
76 // AArch32: call i32 @llvm.arm.strex
77 // AArch64: call i64 @llvm.aarch64.ldxr
78 // AArch64: call i32 @llvm.aarch64.stxr
test_swp(uint32_t x,volatile void * p)79 uint32_t test_swp(uint32_t x, volatile void *p) {
80   __swp(x, p);
81 }
82 
83 /* 8.6 Memory prefetch intrinsics */
84 /* 8.6.1 Data prefetch */
85 // ARM-LABEL: test_pld
86 // ARM: call void @llvm.prefetch(i8* null, i32 0, i32 3, i32 1)
test_pld()87 void test_pld() {
88   __pld(0);
89 }
90 
91 // ARM-LABEL: test_pldx
92 // AArch32: call void @llvm.prefetch(i8* null, i32 1, i32 3, i32 1)
93 // AArch64: call void @llvm.prefetch(i8* null, i32 1, i32 1, i32 1)
test_pldx()94 void test_pldx() {
95   __pldx(1, 2, 0, 0);
96 }
97 
98 /* 8.6.2 Instruction prefetch */
99 // ARM-LABEL: test_pli
100 // ARM: call void @llvm.prefetch(i8* null, i32 0, i32 3, i32 0)
test_pli()101 void test_pli() {
102   __pli(0);
103 }
104 
105 // ARM-LABEL: test_plix
106 // AArch32: call void @llvm.prefetch(i8* null, i32 0, i32 3, i32 0)
107 // AArch64: call void @llvm.prefetch(i8* null, i32 0, i32 1, i32 0)
test_plix()108 void test_plix() {
109   __plix(2, 0, 0);
110 }
111 
112 /* 8.7 NOP */
113 // ARM-LABEL: test_nop
114 // AArch32: call void @llvm.arm.hint(i32 0)
115 // AArch64: call void @llvm.aarch64.hint(i32 0)
test_nop(void)116 void test_nop(void) {
117   __nop();
118 }
119 
120 /* 9 DATA-PROCESSING INTRINSICS */
121 /* 9.2 Miscellaneous data-processing intrinsics */
122 // ARM-LABEL: test_ror
123 // ARM: lshr
124 // ARM: sub
125 // ARM: shl
126 // ARM: or
test_ror(uint32_t x,uint32_t y)127 uint32_t test_ror(uint32_t x, uint32_t y) {
128   return __ror(x, y);
129 }
130 
131 // ARM-LABEL: test_rorl
132 // ARM: lshr
133 // ARM: sub
134 // ARM: shl
135 // ARM: or
test_rorl(unsigned long x,uint32_t y)136 unsigned long test_rorl(unsigned long x, uint32_t y) {
137   return __rorl(x, y);
138 }
139 
140 // ARM-LABEL: test_rorll
141 // ARM: lshr
142 // ARM: sub
143 // ARM: shl
144 // ARM: or
test_rorll(uint64_t x,uint32_t y)145 uint64_t test_rorll(uint64_t x, uint32_t y) {
146   return __rorll(x, y);
147 }
148 
149 // ARM-LABEL: test_clz
150 // ARM: call i32 @llvm.ctlz.i32(i32 %t, i1 false)
test_clz(uint32_t t)151 uint32_t test_clz(uint32_t t) {
152   return __clz(t);
153 }
154 
155 // ARM-LABEL: test_clzl
156 // AArch32: call i32 @llvm.ctlz.i32(i32 %t, i1 false)
157 // AArch64: call i64 @llvm.ctlz.i64(i64 %t, i1 false)
test_clzl(long t)158 long test_clzl(long t) {
159   return __clzl(t);
160 }
161 
162 // ARM-LABEL: test_clzll
163 // ARM: call i64 @llvm.ctlz.i64(i64 %t, i1 false)
test_clzll(uint64_t t)164 uint64_t test_clzll(uint64_t t) {
165   return __clzll(t);
166 }
167 
168 // ARM-LABEL: test_rev
169 // ARM: call i32 @llvm.bswap.i32(i32 %t)
test_rev(uint32_t t)170 uint32_t test_rev(uint32_t t) {
171   return __rev(t);
172 }
173 
174 // ARM-LABEL: test_revl
175 // AArch32: call i32 @llvm.bswap.i32(i32 %t)
176 // AArch64: call i64 @llvm.bswap.i64(i64 %t)
test_revl(long t)177 long test_revl(long t) {
178   return __revl(t);
179 }
180 
181 // ARM-LABEL: test_revll
182 // ARM: call i64 @llvm.bswap.i64(i64 %t)
test_revll(uint64_t t)183 uint64_t test_revll(uint64_t t) {
184   return __revll(t);
185 }
186 
187 // ARM-LABEL: test_rev16
188 // ARM: llvm.bswap
189 // ARM: lshr {{.*}}, 16
190 // ARM: shl {{.*}}, 16
191 // ARM: or
test_rev16(uint32_t t)192 uint32_t test_rev16(uint32_t t) {
193   return __rev16(t);
194 }
195 
196 // ARM-LABEL: test_rev16l
197 // AArch32: llvm.bswap
198 // AArch32: lshr {{.*}}, 16
199 // AArch32: shl {{.*}}, 16
200 // AArch32: or
201 // AArch64: [[T1:%.*]] = lshr i64 [[IN:%.*]], 32
202 // AArch64: [[T2:%.*]] = trunc i64 [[T1]] to i32
203 // AArch64: [[T3:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T2]])
204 // AArch64: [[T4:%.*]] = lshr i32 [[T3]], 16
205 // AArch64: [[T5:%.*]] = shl i32 [[T3]], 16
206 // AArch64: [[T6:%.*]] = or i32 [[T5]], [[T4]]
207 // AArch64: [[T7:%.*]] = zext i32 [[T6]] to i64
208 // AArch64: [[T8:%.*]] = shl nuw i64 [[T7]], 32
209 // AArch64: [[T9:%.*]] = trunc i64 [[IN]] to i32
210 // AArch64: [[T10:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T9]])
211 // AArch64: [[T11:%.*]] = lshr i32 [[T10]], 16
212 // AArch64: [[T12:%.*]] = shl i32 [[T10]], 16
213 // AArch64: [[T13:%.*]] = or i32 [[T12]], [[T11]]
214 // AArch64: [[T14:%.*]] = zext i32 [[T13]] to i64
215 // AArch64: [[T15:%.*]] = or i64 [[T8]], [[T14]]
test_rev16l(long t)216 long test_rev16l(long t) {
217   return __rev16l(t);
218 }
219 
220 // ARM-LABEL: test_rev16ll
221 // ARM: [[T1:%.*]] = lshr i64 [[IN:%.*]], 32
222 // ARM: [[T2:%.*]] = trunc i64 [[T1]] to i32
223 // ARM: [[T3:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T2]])
224 // ARM: [[T4:%.*]] = lshr i32 [[T3]], 16
225 // ARM: [[T5:%.*]] = shl i32 [[T3]], 16
226 // ARM: [[T6:%.*]] = or i32 [[T5]], [[T4]]
227 // ARM: [[T7:%.*]] = zext i32 [[T6]] to i64
228 // ARM: [[T8:%.*]] = shl nuw i64 [[T7]], 32
229 // ARM: [[T9:%.*]] = trunc i64 [[IN]] to i32
230 // ARM: [[T10:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T9]])
231 // ARM: [[T11:%.*]] = lshr i32 [[T10]], 16
232 // ARM: [[T12:%.*]] = shl i32 [[T10]], 16
233 // ARM: [[T13:%.*]] = or i32 [[T12]], [[T11]]
234 // ARM: [[T14:%.*]] = zext i32 [[T13]] to i64
235 // ARM: [[T15:%.*]] = or i64 [[T8]], [[T14]]
test_rev16ll(uint64_t t)236 uint64_t test_rev16ll(uint64_t t) {
237   return __rev16ll(t);
238 }
239 
240 // ARM-LABEL: test_revsh
241 // ARM: call i16 @llvm.bswap.i16(i16 %t)
test_revsh(int16_t t)242 int16_t test_revsh(int16_t t) {
243   return __revsh(t);
244 }
245 
246 // ARM-LABEL: test_rbit
247 // AArch32: call i32 @llvm.arm.rbit
248 // AArch64: call i32 @llvm.aarch64.rbit.i32
test_rbit(uint32_t t)249 uint32_t test_rbit(uint32_t t) {
250   return __rbit(t);
251 }
252 
253 // ARM-LABEL: test_rbitl
254 // AArch32: call i32 @llvm.arm.rbit
255 // AArch64: call i64 @llvm.aarch64.rbit.i64
test_rbitl(long t)256 long test_rbitl(long t) {
257   return __rbitl(t);
258 }
259 
260 // ARM-LABEL: test_rbitll
261 // AArch32: call i32 @llvm.arm.rbit
262 // AArch32: call i32 @llvm.arm.rbit
263 // AArch64: call i64 @llvm.aarch64.rbit.i64
test_rbitll(uint64_t t)264 uint64_t test_rbitll(uint64_t t) {
265   return __rbitll(t);
266 }
267 
268 /* 9.4 Saturating intrinsics */
269 #ifdef __ARM_32BIT_STATE
270 
271 /* 9.4.1 Width-specified saturation intrinsics */
272 // AArch32-LABEL: test_ssat
273 // AArch32: call i32 @llvm.arm.ssat(i32 %t, i32 1)
test_ssat(int32_t t)274 int32_t test_ssat(int32_t t) {
275   return __ssat(t, 1);
276 }
277 
278 // AArch32-LABEL: test_usat
279 // AArch32: call i32 @llvm.arm.usat(i32 %t, i32 2)
test_usat(int32_t t)280 int32_t test_usat(int32_t t) {
281   return __usat(t, 2);
282 }
283 
284 /* 9.4.2 Saturating addition and subtraction intrinsics */
285 // AArch32-LABEL: test_qadd
286 // AArch32: call i32 @llvm.arm.qadd(i32 %a, i32 %b)
test_qadd(int32_t a,int32_t b)287 int32_t test_qadd(int32_t a, int32_t b) {
288   return __qadd(a, b);
289 }
290 
291 // AArch32-LABEL: test_qsub
292 // AArch32: call i32 @llvm.arm.qsub(i32 %a, i32 %b)
test_qsub(int32_t a,int32_t b)293 int32_t test_qsub(int32_t a, int32_t b) {
294   return __qsub(a, b);
295 }
296 
297 extern int32_t f();
298 // AArch32-LABEL: test_qdbl
299 // AArch32: [[VAR:%[a-z0-9]+]] = {{.*}} call {{.*}} @f
300 // AArch32-NOT: call {{.*}} @f
301 // AArch32: call i32 @llvm.arm.qadd(i32 [[VAR]], i32 [[VAR]])
test_qdbl()302 int32_t test_qdbl() {
303   return __qdbl(f());
304 }
305 #endif
306 
307 /* 9.7 CRC32 intrinsics */
308 // ARM-LABEL: test_crc32b
309 // AArch32: call i32 @llvm.arm.crc32b
310 // AArch64: call i32 @llvm.aarch64.crc32b
test_crc32b(uint32_t a,uint8_t b)311 uint32_t test_crc32b(uint32_t a, uint8_t b) {
312   return __crc32b(a, b);
313 }
314 
315 // ARM-LABEL: test_crc32h
316 // AArch32: call i32 @llvm.arm.crc32h
317 // AArch64: call i32 @llvm.aarch64.crc32h
test_crc32h(uint32_t a,uint16_t b)318 uint32_t test_crc32h(uint32_t a, uint16_t b) {
319   return __crc32h(a, b);
320 }
321 
322 // ARM-LABEL: test_crc32w
323 // AArch32: call i32 @llvm.arm.crc32w
324 // AArch64: call i32 @llvm.aarch64.crc32w
test_crc32w(uint32_t a,uint32_t b)325 uint32_t test_crc32w(uint32_t a, uint32_t b) {
326   return __crc32w(a, b);
327 }
328 
329 // ARM-LABEL: test_crc32d
330 // AArch32: call i32 @llvm.arm.crc32w
331 // AArch32: call i32 @llvm.arm.crc32w
332 // AArch64: call i32 @llvm.aarch64.crc32x
test_crc32d(uint32_t a,uint64_t b)333 uint32_t test_crc32d(uint32_t a, uint64_t b) {
334   return __crc32d(a, b);
335 }
336 
337 // ARM-LABEL: test_crc32cb
338 // AArch32: call i32 @llvm.arm.crc32cb
339 // AArch64: call i32 @llvm.aarch64.crc32cb
test_crc32cb(uint32_t a,uint8_t b)340 uint32_t test_crc32cb(uint32_t a, uint8_t b) {
341   return __crc32cb(a, b);
342 }
343 
344 // ARM-LABEL: test_crc32ch
345 // AArch32: call i32 @llvm.arm.crc32ch
346 // AArch64: call i32 @llvm.aarch64.crc32ch
test_crc32ch(uint32_t a,uint16_t b)347 uint32_t test_crc32ch(uint32_t a, uint16_t b) {
348   return __crc32ch(a, b);
349 }
350 
351 // ARM-LABEL: test_crc32cw
352 // AArch32: call i32 @llvm.arm.crc32cw
353 // AArch64: call i32 @llvm.aarch64.crc32cw
test_crc32cw(uint32_t a,uint32_t b)354 uint32_t test_crc32cw(uint32_t a, uint32_t b) {
355   return __crc32cw(a, b);
356 }
357 
358 // ARM-LABEL: test_crc32cd
359 // AArch32: call i32 @llvm.arm.crc32cw
360 // AArch32: call i32 @llvm.arm.crc32cw
361 // AArch64: call i32 @llvm.aarch64.crc32cx
test_crc32cd(uint32_t a,uint64_t b)362 uint32_t test_crc32cd(uint32_t a, uint64_t b) {
363   return __crc32cd(a, b);
364 }
365 
366 /* 10.1 Special register intrinsics */
367 // ARM-LABEL: test_rsr
368 // AArch64: call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]])
369 // AArch32: call i32 @llvm.read_register.i32(metadata ![[M2:[0-9]]])
test_rsr()370 uint32_t test_rsr() {
371 #ifdef __ARM_32BIT_STATE
372   return __arm_rsr("cp1:2:c3:c4:5");
373 #else
374   return __arm_rsr("1:2:3:4:5");
375 #endif
376 }
377 
378 // ARM-LABEL: test_rsr64
379 // AArch64: call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]])
380 // AArch32: call i64 @llvm.read_register.i64(metadata ![[M3:[0-9]]])
test_rsr64()381 uint64_t test_rsr64() {
382 #ifdef __ARM_32BIT_STATE
383   return __arm_rsr64("cp1:2:c3");
384 #else
385   return __arm_rsr64("1:2:3:4:5");
386 #endif
387 }
388 
389 // ARM-LABEL: test_rsrp
390 // AArch64: call i64 @llvm.read_register.i64(metadata ![[M1:[0-9]]])
391 // AArch32: call i32 @llvm.read_register.i32(metadata ![[M4:[0-9]]])
test_rsrp()392 void *test_rsrp() {
393   return __arm_rsrp("sysreg");
394 }
395 
396 // ARM-LABEL: test_wsr
397 // AArch64: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 %{{.*}})
398 // AArch32: call void @llvm.write_register.i32(metadata ![[M2:[0-9]]], i32 %{{.*}})
test_wsr(uint32_t v)399 void test_wsr(uint32_t v) {
400 #ifdef __ARM_32BIT_STATE
401   __arm_wsr("cp1:2:c3:c4:5", v);
402 #else
403   __arm_wsr("1:2:3:4:5", v);
404 #endif
405 }
406 
407 // ARM-LABEL: test_wsr64
408 // AArch64: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 %{{.*}})
409 // AArch32: call void @llvm.write_register.i64(metadata ![[M3:[0-9]]], i64 %{{.*}})
test_wsr64(uint64_t v)410 void test_wsr64(uint64_t v) {
411 #ifdef __ARM_32BIT_STATE
412   __arm_wsr64("cp1:2:c3", v);
413 #else
414   __arm_wsr64("1:2:3:4:5", v);
415 #endif
416 }
417 
418 // ARM-LABEL: test_wsrp
419 // AArch64: call void @llvm.write_register.i64(metadata ![[M1:[0-9]]], i64 %{{.*}})
420 // AArch32: call void @llvm.write_register.i32(metadata ![[M4:[0-9]]], i32 %{{.*}})
test_wsrp(void * v)421 void test_wsrp(void *v) {
422   __arm_wsrp("sysreg", v);
423 }
424 
425 // AArch32: ![[M2]] = !{!"cp1:2:c3:c4:5"}
426 // AArch32: ![[M3]] = !{!"cp1:2:c3"}
427 // AArch32: ![[M4]] = !{!"sysreg"}
428 
429 // AArch64: ![[M0]] = !{!"1:2:3:4:5"}
430 // AArch64: ![[M1]] = !{!"sysreg"}
431