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