Home | History | Annotate | Download | only in CodeGen
      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)
     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)
     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)
     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)
     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)
     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)
     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)
     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)
     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)
     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
     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)
     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)
     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)
    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)
    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)
    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
    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
    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
    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)
    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)
    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)
    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)
    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)
    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)
    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
    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]]
    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]]
    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)
    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
    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
    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
    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)
    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)
    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)
    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)
    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]])
    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
    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
    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
    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
    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
    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
    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
    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
    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]]])
    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]]])
    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]]])
    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 %{{.*}})
    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 %{{.*}})
    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 %{{.*}})
    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