1 // RUN: %clang_cc1 -ffreestanding -triple armv8-eabi -target-cpu cortex-a57 -O2 -fno-experimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch32 -check-prefix=ARM-LEGACY -check-prefix=AArch32-LEGACY 2 // RUN: %clang_cc1 -ffreestanding -triple armv8-eabi -target-cpu cortex-a57 -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch32 -check-prefix=ARM-NEWPM -check-prefix=AArch32-NEWPM 3 // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +neon -target-feature +crc -target-feature +crypto -O2 -fno-experimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch64 -check-prefix=ARM-LEGACY -check-prefix=AArch64-LEGACY 4 // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +neon -target-feature +crc -target-feature +crypto -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch64 -check-prefix=ARM-NEWPM -check-prefix=AArch64-NEWPM 5 // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +v8.3a -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=AArch64-v8_3 6 // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +v8.4a -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=AArch64-v8_3 7 // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +v8.5a -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=AArch64-v8_3 8 9 // REQUIRES: rewrite 10 11 #include <arm_acle.h> 12 13 /* 8 SYNCHRONIZATION, BARRIER AND HINT INTRINSICS */ 14 /* 8.3 Memory Barriers */ 15 // ARM-LABEL: test_dmb 16 // AArch32: call void @llvm.arm.dmb(i32 1) 17 // AArch64: call void @llvm.aarch64.dmb(i32 1) 18 void test_dmb(void) { 19 __dmb(1); 20 } 21 22 // ARM-LABEL: test_dsb 23 // AArch32: call void @llvm.arm.dsb(i32 2) 24 // AArch64: call void @llvm.aarch64.dsb(i32 2) 25 void test_dsb(void) { 26 __dsb(2); 27 } 28 29 // ARM-LABEL: test_isb 30 // AArch32: call void @llvm.arm.isb(i32 3) 31 // AArch64: call void @llvm.aarch64.isb(i32 3) 32 void test_isb(void) { 33 __isb(3); 34 } 35 36 /* 8.4 Hints */ 37 // ARM-LABEL: test_yield 38 // AArch32: call void @llvm.arm.hint(i32 1) 39 // AArch64: call void @llvm.aarch64.hint(i32 1) 40 void test_yield(void) { 41 __yield(); 42 } 43 44 // ARM-LABEL: test_wfe 45 // AArch32: call void @llvm.arm.hint(i32 2) 46 // AArch64: call void @llvm.aarch64.hint(i32 2) 47 void test_wfe(void) { 48 __wfe(); 49 } 50 51 // ARM-LABEL: test_wfi 52 // AArch32: call void @llvm.arm.hint(i32 3) 53 // AArch64: call void @llvm.aarch64.hint(i32 3) 54 void test_wfi(void) { 55 __wfi(); 56 } 57 58 // ARM-LABEL: test_sev 59 // AArch32: call void @llvm.arm.hint(i32 4) 60 // AArch64: call void @llvm.aarch64.hint(i32 4) 61 void test_sev(void) { 62 __sev(); 63 } 64 65 // ARM-LABEL: test_sevl 66 // AArch32: call void @llvm.arm.hint(i32 5) 67 // AArch64: call void @llvm.aarch64.hint(i32 5) 68 void test_sevl(void) { 69 __sevl(); 70 } 71 72 #if __ARM_32BIT_STATE 73 // AArch32-LABEL: test_dbg 74 // AArch32: call void @llvm.arm.dbg(i32 0) 75 void test_dbg(void) { 76 __dbg(0); 77 } 78 #endif 79 80 /* 8.5 Swap */ 81 // ARM-LABEL: test_swp 82 // AArch32: call i32 @llvm.arm.ldrex 83 // AArch32: call i32 @llvm.arm.strex 84 // AArch64: call i64 @llvm.aarch64.ldxr 85 // AArch64: call i32 @llvm.aarch64.stxr 86 void test_swp(uint32_t x, volatile void *p) { 87 __swp(x, p); 88 } 89 90 /* 8.6 Memory prefetch intrinsics */ 91 /* 8.6.1 Data prefetch */ 92 // ARM-LABEL: test_pld 93 // ARM: call void @llvm.prefetch.p0i8(i8* null, i32 0, i32 3, i32 1) 94 void test_pld() { 95 __pld(0); 96 } 97 98 // ARM-LABEL: test_pldx 99 // AArch32: call void @llvm.prefetch.p0i8(i8* null, i32 1, i32 3, i32 1) 100 // AArch64: call void @llvm.prefetch.p0i8(i8* null, i32 1, i32 1, i32 1) 101 void test_pldx() { 102 __pldx(1, 2, 0, 0); 103 } 104 105 /* 8.6.2 Instruction prefetch */ 106 // ARM-LABEL: test_pli 107 // ARM: call void @llvm.prefetch.p0i8(i8* null, i32 0, i32 3, i32 0) 108 void test_pli() { 109 __pli(0); 110 } 111 112 // ARM-LABEL: test_plix 113 // AArch32: call void @llvm.prefetch.p0i8(i8* null, i32 0, i32 3, i32 0) 114 // AArch64: call void @llvm.prefetch.p0i8(i8* null, i32 0, i32 1, i32 0) 115 void test_plix() { 116 __plix(2, 0, 0); 117 } 118 119 /* 8.7 NOP */ 120 // ARM-LABEL: test_nop 121 // AArch32: call void @llvm.arm.hint(i32 0) 122 // AArch64: call void @llvm.aarch64.hint(i32 0) 123 void test_nop(void) { 124 __nop(); 125 } 126 127 /* 9 DATA-PROCESSING INTRINSICS */ 128 129 /* 9.2 Miscellaneous data-processing intrinsics */ 130 // ARM-LABEL: test_ror 131 // ARM-LEGACY: lshr 132 // ARM-LEGACY: sub 133 // ARM-LEGACY: shl 134 // ARM-LEGACY: or 135 // ARM-NEWPM: call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %y) 136 uint32_t test_ror(uint32_t x, uint32_t y) { 137 return __ror(x, y); 138 } 139 140 // ARM-LABEL: test_rorl 141 // ARM-LEGACY: lshr 142 // ARM-LEGACY: sub 143 // ARM-LEGACY: shl 144 // ARM-LEGACY: or 145 // AArch32-NEWPM: call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %y) 146 unsigned long test_rorl(unsigned long x, uint32_t y) { 147 return __rorl(x, y); 148 } 149 150 // ARM-LABEL: test_rorll 151 // ARM: lshr 152 // ARM: sub 153 // ARM: shl 154 // ARM: or 155 uint64_t test_rorll(uint64_t x, uint32_t y) { 156 return __rorll(x, y); 157 } 158 159 // ARM-LABEL: test_clz 160 // ARM: call i32 @llvm.ctlz.i32(i32 %t, i1 false) 161 uint32_t test_clz(uint32_t t) { 162 return __clz(t); 163 } 164 165 // ARM-LABEL: test_clzl 166 // AArch32: call i32 @llvm.ctlz.i32(i32 %t, i1 false) 167 // AArch64: call i64 @llvm.ctlz.i64(i64 %t, i1 false) 168 long test_clzl(long t) { 169 return __clzl(t); 170 } 171 172 // ARM-LABEL: test_clzll 173 // ARM: call i64 @llvm.ctlz.i64(i64 %t, i1 false) 174 uint64_t test_clzll(uint64_t t) { 175 return __clzll(t); 176 } 177 178 // ARM-LABEL: test_rev 179 // ARM: call i32 @llvm.bswap.i32(i32 %t) 180 uint32_t test_rev(uint32_t t) { 181 return __rev(t); 182 } 183 184 // ARM-LABEL: test_revl 185 // AArch32: call i32 @llvm.bswap.i32(i32 %t) 186 // AArch64: call i64 @llvm.bswap.i64(i64 %t) 187 long test_revl(long t) { 188 return __revl(t); 189 } 190 191 // ARM-LABEL: test_revll 192 // ARM: call i64 @llvm.bswap.i64(i64 %t) 193 uint64_t test_revll(uint64_t t) { 194 return __revll(t); 195 } 196 197 // ARM-LABEL: test_rev16 198 // ARM: llvm.bswap 199 // ARM-LEGACY: lshr {{.*}}, 16 200 // ARM-LEGACY: shl {{.*}}, 16 201 // ARM-LEGACY: or 202 // ARM-NEWPM: call i32 @llvm.fshl.i32(i32 %0, i32 %0, i32 16) 203 uint32_t test_rev16(uint32_t t) { 204 return __rev16(t); 205 } 206 207 // ARM-LABEL: test_rev16l 208 // AArch32: llvm.bswap 209 // AArch32-LEGACY: lshr {{.*}}, 16 210 // AArch32-LEGACY: shl {{.*}}, 16 211 // AArch32-LEGACY: or 212 // AArch32-NEWPM: call i32 @llvm.fshl.i32(i32 %0, i32 %0, i32 16) 213 // AArch64: [[T1:%.*]] = lshr i64 [[IN:%.*]], 32 214 // AArch64: [[T2:%.*]] = trunc i64 [[T1]] to i32 215 // AArch64: [[T3:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T2]]) 216 // AArch64-LEGACY: [[T4:%.*]] = lshr i32 [[T3]], 16 217 // AArch64-LEGACY: [[T5:%.*]] = shl i32 [[T3]], 16 218 // AArch64-LEGACY: [[T6:%.*]] = or i32 [[T5]], [[T4]] 219 // AArch64-NEWPM: [[T6:%.*]] = tail call i32 @llvm.fshl.i32(i32 [[T3]], i32 [[T3]], i32 16) 220 // AArch64: [[T7:%.*]] = zext i32 [[T6]] to i64 221 // AArch64: [[T8:%.*]] = shl nuw i64 [[T7]], 32 222 // AArch64: [[T9:%.*]] = trunc i64 [[IN]] to i32 223 // AArch64: [[T10:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T9]]) 224 // AArch64-LEGACY: [[T11:%.*]] = lshr i32 [[T10]], 16 225 // AArch64-LEGACY: [[T12:%.*]] = shl i32 [[T10]], 16 226 // AArch64-LEGACY: [[T13:%.*]] = or i32 [[T12]], [[T11]] 227 // AArch64-NEWPM: [[T13:%.*]] = tail call i32 @llvm.fshl.i32(i32 [[T10]], i32 [[T10]], i32 16) 228 // AArch64: [[T14:%.*]] = zext i32 [[T13]] to i64 229 // AArch64: [[T15:%.*]] = or i64 [[T8]], [[T14]] 230 long test_rev16l(long t) { 231 return __rev16l(t); 232 } 233 234 // ARM-LABEL: test_rev16ll 235 // ARM: [[T1:%.*]] = lshr i64 [[IN:%.*]], 32 236 // ARM: [[T2:%.*]] = trunc i64 [[T1]] to i32 237 // ARM: [[T3:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T2]]) 238 // ARM-LEGACY: [[T4:%.*]] = lshr i32 [[T3]], 16 239 // ARM-LEGACY: [[T5:%.*]] = shl i32 [[T3]], 16 240 // ARM-LEGACY: [[T6:%.*]] = or i32 [[T5]], [[T4]] 241 // ARM-NEWPM: [[T6:%.*]] = tail call i32 @llvm.fshl.i32(i32 [[T3]], i32 [[T3]], i32 16) 242 // ARM: [[T7:%.*]] = zext i32 [[T6]] to i64 243 // ARM: [[T8:%.*]] = shl nuw i64 [[T7]], 32 244 // ARM: [[T9:%.*]] = trunc i64 [[IN]] to i32 245 // ARM: [[T10:%.*]] = tail call i32 @llvm.bswap.i32(i32 [[T9]]) 246 // ARM-LEGACY: [[T11:%.*]] = lshr i32 [[T10]], 16 247 // ARM-LEGACY: [[T12:%.*]] = shl i32 [[T10]], 16 248 // ARM-LEGACY: [[T13:%.*]] = or i32 [[T12]], [[T11]] 249 // ARM-NEWPM: [[T13:%.*]] = tail call i32 @llvm.fshl.i32(i32 [[T10]], i32 [[T10]], i32 16) 250 // ARM: [[T14:%.*]] = zext i32 [[T13]] to i64 251 // ARM: [[T15:%.*]] = or i64 [[T8]], [[T14]] 252 uint64_t test_rev16ll(uint64_t t) { 253 return __rev16ll(t); 254 } 255 256 // ARM-LABEL: test_revsh 257 // ARM: call i16 @llvm.bswap.i16(i16 %t) 258 int16_t test_revsh(int16_t t) { 259 return __revsh(t); 260 } 261 262 // ARM-LABEL: test_rbit 263 // AArch32: call i32 @llvm.bitreverse.i32 264 // AArch64: call i32 @llvm.bitreverse.i32 265 uint32_t test_rbit(uint32_t t) { 266 return __rbit(t); 267 } 268 269 // ARM-LABEL: test_rbitl 270 // AArch32: call i32 @llvm.bitreverse.i32 271 // AArch64: call i64 @llvm.bitreverse.i64 272 long test_rbitl(long t) { 273 return __rbitl(t); 274 } 275 276 // ARM-LABEL: test_rbitll 277 // AArch32: call i32 @llvm.bitreverse.i32 278 // AArch32: call i32 @llvm.bitreverse.i32 279 // AArch64: call i64 @llvm.bitreverse.i64 280 uint64_t test_rbitll(uint64_t t) { 281 return __rbitll(t); 282 } 283 284 /* 9.4 Saturating intrinsics */ 285 #ifdef __ARM_FEATURE_SAT 286 /* 9.4.1 Width-specified saturation intrinsics */ 287 // AArch32-LABEL: test_ssat 288 // AArch32: call i32 @llvm.arm.ssat(i32 %t, i32 1) 289 int32_t test_ssat(int32_t t) { 290 return __ssat(t, 1); 291 } 292 293 // AArch32-LABEL: test_usat 294 // AArch32: call i32 @llvm.arm.usat(i32 %t, i32 2) 295 uint32_t test_usat(int32_t t) { 296 return __usat(t, 2); 297 } 298 #endif 299 300 /* 9.4.2 Saturating addition and subtraction intrinsics */ 301 #ifdef __ARM_FEATURE_DSP 302 // AArch32-LABEL: test_qadd 303 // AArch32: call i32 @llvm.arm.qadd(i32 %a, i32 %b) 304 int32_t test_qadd(int32_t a, int32_t b) { 305 return __qadd(a, b); 306 } 307 308 // AArch32-LABEL: test_qsub 309 // AArch32: call i32 @llvm.arm.qsub(i32 %a, i32 %b) 310 int32_t test_qsub(int32_t a, int32_t b) { 311 return __qsub(a, b); 312 } 313 314 extern int32_t f(); 315 // AArch32-LABEL: test_qdbl 316 // AArch32: [[VAR:%[a-z0-9]+]] = {{.*}} call {{.*}} @f 317 // AArch32-NOT: call {{.*}} @f 318 // AArch32: call i32 @llvm.arm.qadd(i32 [[VAR]], i32 [[VAR]]) 319 int32_t test_qdbl() { 320 return __qdbl(f()); 321 } 322 #endif 323 324 /* 325 * 9.3 16-bit multiplications 326 */ 327 #if __ARM_FEATURE_DSP 328 // AArch32-LABEL: test_smulbb 329 // AArch32: call i32 @llvm.arm.smulbb 330 int32_t test_smulbb(int32_t a, int32_t b) { 331 return __smulbb(a, b); 332 } 333 // AArch32-LABEL: test_smulbt 334 // AArch32: call i32 @llvm.arm.smulbt 335 int32_t test_smulbt(int32_t a, int32_t b) { 336 return __smulbt(a, b); 337 } 338 // AArch32-LABEL: test_smultb 339 // AArch32: call i32 @llvm.arm.smultb 340 int32_t test_smultb(int32_t a, int32_t b) { 341 return __smultb(a, b); 342 } 343 // AArch32-LABEL: test_smultt 344 // AArch32: call i32 @llvm.arm.smultt 345 int32_t test_smultt(int32_t a, int32_t b) { 346 return __smultt(a, b); 347 } 348 // AArch32-LABEL: test_smulwb 349 // AArch32: call i32 @llvm.arm.smulwb 350 int32_t test_smulwb(int32_t a, int32_t b) { 351 return __smulwb(a, b); 352 } 353 // AArch32-LABEL: test_smulwt 354 // AArch32: call i32 @llvm.arm.smulwt 355 int32_t test_smulwt(int32_t a, int32_t b) { 356 return __smulwt(a, b); 357 } 358 #endif 359 360 /* 9.4.3 Accumultating multiplications */ 361 #if __ARM_FEATURE_DSP 362 // AArch32-LABEL: test_smlabb 363 // AArch32: call i32 @llvm.arm.smlabb(i32 %a, i32 %b, i32 %c) 364 int32_t test_smlabb(int32_t a, int32_t b, int32_t c) { 365 return __smlabb(a, b, c); 366 } 367 // AArch32-LABEL: test_smlabt 368 // AArch32: call i32 @llvm.arm.smlabt(i32 %a, i32 %b, i32 %c) 369 int32_t test_smlabt(int32_t a, int32_t b, int32_t c) { 370 return __smlabt(a, b, c); 371 } 372 // AArch32-LABEL: test_smlatb 373 // AArch32: call i32 @llvm.arm.smlatb(i32 %a, i32 %b, i32 %c) 374 int32_t test_smlatb(int32_t a, int32_t b, int32_t c) { 375 return __smlatb(a, b, c); 376 } 377 // AArch32-LABEL: test_smlatt 378 // AArch32: call i32 @llvm.arm.smlatt(i32 %a, i32 %b, i32 %c) 379 int32_t test_smlatt(int32_t a, int32_t b, int32_t c) { 380 return __smlatt(a, b, c); 381 } 382 // AArch32-LABEL: test_smlawb 383 // AArch32: call i32 @llvm.arm.smlawb(i32 %a, i32 %b, i32 %c) 384 int32_t test_smlawb(int32_t a, int32_t b, int32_t c) { 385 return __smlawb(a, b, c); 386 } 387 // AArch32-LABEL: test_smlawt 388 // AArch32: call i32 @llvm.arm.smlawt(i32 %a, i32 %b, i32 %c) 389 int32_t test_smlawt(int32_t a, int32_t b, int32_t c) { 390 return __smlawt(a, b, c); 391 } 392 #endif 393 394 /* 9.5.4 Parallel 16-bit saturation */ 395 #if __ARM_FEATURE_SIMD32 396 // AArch32-LABEL: test_ssat16 397 // AArch32: call i32 @llvm.arm.ssat16 398 int16x2_t test_ssat16(int16x2_t a) { 399 return __ssat16(a, 15); 400 } 401 // AArch32-LABEL: test_usat16 402 // AArch32: call i32 @llvm.arm.usat16 403 uint16x2_t test_usat16(int16x2_t a) { 404 return __usat16(a, 15); 405 } 406 #endif 407 408 /* 9.5.5 Packing and unpacking */ 409 #if __ARM_FEATURE_SIMD32 410 // AArch32-LABEL: test_sxtab16 411 // AArch32: call i32 @llvm.arm.sxtab16 412 int16x2_t test_sxtab16(int16x2_t a, int8x4_t b) { 413 return __sxtab16(a, b); 414 } 415 // AArch32-LABEL: test_sxtb16 416 // AArch32: call i32 @llvm.arm.sxtb16 417 int16x2_t test_sxtb16(int8x4_t a) { 418 return __sxtb16(a); 419 } 420 // AArch32-LABEL: test_uxtab16 421 // AArch32: call i32 @llvm.arm.uxtab16 422 int16x2_t test_uxtab16(int16x2_t a, int8x4_t b) { 423 return __uxtab16(a, b); 424 } 425 // AArch32-LABEL: test_uxtb16 426 // AArch32: call i32 @llvm.arm.uxtb16 427 int16x2_t test_uxtb16(int8x4_t a) { 428 return __uxtb16(a); 429 } 430 #endif 431 432 /* 9.5.6 Parallel selection */ 433 #if __ARM_FEATURE_SIMD32 434 // AArch32-LABEL: test_sel 435 // AArch32: call i32 @llvm.arm.sel 436 uint8x4_t test_sel(uint8x4_t a, uint8x4_t b) { 437 return __sel(a, b); 438 } 439 #endif 440 441 /* 9.5.7 Parallel 8-bit addition and subtraction */ 442 #if __ARM_FEATURE_SIMD32 443 // AArch32-LABEL: test_qadd8 444 // AArch32: call i32 @llvm.arm.qadd8 445 int16x2_t test_qadd8(int8x4_t a, int8x4_t b) { 446 return __qadd8(a, b); 447 } 448 // AArch32-LABEL: test_qsub8 449 // AArch32: call i32 @llvm.arm.qsub8 450 int8x4_t test_qsub8(int8x4_t a, int8x4_t b) { 451 return __qsub8(a, b); 452 } 453 // AArch32-LABEL: test_sadd8 454 // AArch32: call i32 @llvm.arm.sadd8 455 int8x4_t test_sadd8(int8x4_t a, int8x4_t b) { 456 return __sadd8(a, b); 457 } 458 // AArch32-LABEL: test_shadd8 459 // AArch32: call i32 @llvm.arm.shadd8 460 int8x4_t test_shadd8(int8x4_t a, int8x4_t b) { 461 return __shadd8(a, b); 462 } 463 // AArch32-LABEL: test_shsub8 464 // AArch32: call i32 @llvm.arm.shsub8 465 int8x4_t test_shsub8(int8x4_t a, int8x4_t b) { 466 return __shsub8(a, b); 467 } 468 // AArch32-LABEL: test_ssub8 469 // AArch32: call i32 @llvm.arm.ssub8 470 int8x4_t test_ssub8(int8x4_t a, int8x4_t b) { 471 return __ssub8(a, b); 472 } 473 // AArch32-LABEL: test_uadd8 474 // AArch32: call i32 @llvm.arm.uadd8 475 uint8x4_t test_uadd8(uint8x4_t a, uint8x4_t b) { 476 return __uadd8(a, b); 477 } 478 // AArch32-LABEL: test_uhadd8 479 // AArch32: call i32 @llvm.arm.uhadd8 480 uint8x4_t test_uhadd8(uint8x4_t a, uint8x4_t b) { 481 return __uhadd8(a, b); 482 } 483 // AArch32-LABEL: test_uhsub8 484 // AArch32: call i32 @llvm.arm.uhsub8 485 uint8x4_t test_uhsub8(uint8x4_t a, uint8x4_t b) { 486 return __uhsub8(a, b); 487 } 488 // AArch32-LABEL: test_uqadd8 489 // AArch32: call i32 @llvm.arm.uqadd8 490 uint8x4_t test_uqadd8(uint8x4_t a, uint8x4_t b) { 491 return __uqadd8(a, b); 492 } 493 // AArch32-LABEL: test_uqsub8 494 // AArch32: call i32 @llvm.arm.uqsub8 495 uint8x4_t test_uqsub8(uint8x4_t a, uint8x4_t b) { 496 return __uqsub8(a, b); 497 } 498 // AArch32-LABEL: test_usub8 499 // AArch32: call i32 @llvm.arm.usub8 500 uint8x4_t test_usub8(uint8x4_t a, uint8x4_t b) { 501 return __usub8(a, b); 502 } 503 #endif 504 505 /* 9.5.8 Sum of 8-bit absolute differences */ 506 #if __ARM_FEATURE_SIMD32 507 // AArch32-LABEL: test_usad8 508 // AArch32: call i32 @llvm.arm.usad8 509 uint32_t test_usad8(uint8x4_t a, uint8x4_t b) { 510 return __usad8(a, b); 511 } 512 // AArch32-LABEL: test_usada8 513 // AArch32: call i32 @llvm.arm.usada8 514 uint32_t test_usada8(uint8_t a, uint8_t b, uint8_t c) { 515 return __usada8(a, b, c); 516 } 517 #endif 518 519 /* 9.5.9 Parallel 16-bit addition and subtraction */ 520 #if __ARM_FEATURE_SIMD32 521 // AArch32-LABEL: test_qadd16 522 // AArch32: call i32 @llvm.arm.qadd16 523 int16x2_t test_qadd16(int16x2_t a, int16x2_t b) { 524 return __qadd16(a, b); 525 } 526 // AArch32-LABEL: test_qasx 527 // AArch32: call i32 @llvm.arm.qasx 528 int16x2_t test_qasx(int16x2_t a, int16x2_t b) { 529 return __qasx(a, b); 530 } 531 // AArch32-LABEL: test_qsax 532 // AArch32: call i32 @llvm.arm.qsax 533 int16x2_t test_qsax(int16x2_t a, int16x2_t b) { 534 return __qsax(a, b); 535 } 536 // AArch32-LABEL: test_qsub16 537 // AArch32: call i32 @llvm.arm.qsub16 538 int16x2_t test_qsub16(int16x2_t a, int16x2_t b) { 539 return __qsub16(a, b); 540 } 541 // AArch32-LABEL: test_sadd16 542 // AArch32: call i32 @llvm.arm.sadd16 543 int16x2_t test_sadd16(int16x2_t a, int16x2_t b) { 544 return __sadd16(a, b); 545 } 546 // AArch32-LABEL: test_sasx 547 // AArch32: call i32 @llvm.arm.sasx 548 int16x2_t test_sasx(int16x2_t a, int16x2_t b) { 549 return __sasx(a, b); 550 } 551 // AArch32-LABEL: test_shadd16 552 // AArch32: call i32 @llvm.arm.shadd16 553 int16x2_t test_shadd16(int16x2_t a, int16x2_t b) { 554 return __shadd16(a, b); 555 } 556 // AArch32-LABEL: test_shasx 557 // AArch32: call i32 @llvm.arm.shasx 558 int16x2_t test_shasx(int16x2_t a, int16x2_t b) { 559 return __shasx(a, b); 560 } 561 // AArch32-LABEL: test_shsax 562 // AArch32: call i32 @llvm.arm.shsax 563 int16x2_t test_shsax(int16x2_t a, int16x2_t b) { 564 return __shsax(a, b); 565 } 566 // AArch32-LABEL: test_shsub16 567 // AArch32: call i32 @llvm.arm.shsub16 568 int16x2_t test_shsub16(int16x2_t a, int16x2_t b) { 569 return __shsub16(a, b); 570 } 571 // AArch32-LABEL: test_ssax 572 // AArch32: call i32 @llvm.arm.ssax 573 int16x2_t test_ssax(int16x2_t a, int16x2_t b) { 574 return __ssax(a, b); 575 } 576 // AArch32-LABEL: test_ssub16 577 // AArch32: call i32 @llvm.arm.ssub16 578 int16x2_t test_ssub16(int16x2_t a, int16x2_t b) { 579 return __ssub16(a, b); 580 } 581 // AArch32-LABEL: test_uadd16 582 // AArch32: call i32 @llvm.arm.uadd16 583 uint16x2_t test_uadd16(uint16x2_t a, uint16x2_t b) { 584 return __uadd16(a, b); 585 } 586 // AArch32-LABEL: test_uasx 587 // AArch32: call i32 @llvm.arm.uasx 588 uint16x2_t test_uasx(uint16x2_t a, uint16x2_t b) { 589 return __uasx(a, b); 590 } 591 // AArch32-LABEL: test_uhadd16 592 // AArch32: call i32 @llvm.arm.uhadd16 593 uint16x2_t test_uhadd16(uint16x2_t a, uint16x2_t b) { 594 return __uhadd16(a, b); 595 } 596 // AArch32-LABEL: test_uhasx 597 // AArch32: call i32 @llvm.arm.uhasx 598 uint16x2_t test_uhasx(uint16x2_t a, uint16x2_t b) { 599 return __uhasx(a, b); 600 } 601 // AArch32-LABEL: test_uhsax 602 // AArch32: call i32 @llvm.arm.uhsax 603 uint16x2_t test_uhsax(uint16x2_t a, uint16x2_t b) { 604 return __uhsax(a, b); 605 } 606 // AArch32-LABEL: test_uhsub16 607 // AArch32: call i32 @llvm.arm.uhsub16 608 uint16x2_t test_uhsub16(uint16x2_t a, uint16x2_t b) { 609 return __uhsub16(a, b); 610 } 611 // AArch32-LABEL: test_uqadd16 612 // AArch32: call i32 @llvm.arm.uqadd16 613 uint16x2_t test_uqadd16(uint16x2_t a, uint16x2_t b) { 614 return __uqadd16(a, b); 615 } 616 // AArch32-LABEL: test_uqasx 617 // AArch32: call i32 @llvm.arm.uqasx 618 uint16x2_t test_uqasx(uint16x2_t a, uint16x2_t b) { 619 return __uqasx(a, b); 620 } 621 // AArch32-LABEL: test_uqsax 622 // AArch32: call i32 @llvm.arm.uqsax 623 uint16x2_t test_uqsax(uint16x2_t a, uint16x2_t b) { 624 return __uqsax(a, b); 625 } 626 // AArch32-LABEL: test_uqsub16 627 // AArch32: call i32 @llvm.arm.uqsub16 628 uint16x2_t test_uqsub16(uint16x2_t a, uint16x2_t b) { 629 return __uqsub16(a, b); 630 } 631 // AArch32-LABEL: test_usax 632 // AArch32: call i32 @llvm.arm.usax 633 uint16x2_t test_usax(uint16x2_t a, uint16x2_t b) { 634 return __usax(a, b); 635 } 636 // AArch32-LABEL: test_usub16 637 // AArch32: call i32 @llvm.arm.usub16 638 uint16x2_t test_usub16(uint16x2_t a, uint16x2_t b) { 639 return __usub16(a, b); 640 } 641 #endif 642 643 /* 9.5.10 Parallel 16-bit multiplications */ 644 #if __ARM_FEATURE_SIMD32 645 // AArch32-LABEL: test_smlad 646 // AArch32: call i32 @llvm.arm.smlad 647 int32_t test_smlad(int16x2_t a, int16x2_t b, int32_t c) { 648 return __smlad(a, b, c); 649 } 650 // AArch32-LABEL: test_smladx 651 // AArch32: call i32 @llvm.arm.smladx 652 int32_t test_smladx(int16x2_t a, int16x2_t b, int32_t c) { 653 return __smladx(a, b, c); 654 } 655 // AArch32-LABEL: test_smlald 656 // AArch32: call i64 @llvm.arm.smlald 657 int64_t test_smlald(int16x2_t a, int16x2_t b, int64_t c) { 658 return __smlald(a, b, c); 659 } 660 // AArch32-LABEL: test_smlaldx 661 // AArch32: call i64 @llvm.arm.smlaldx 662 int64_t test_smlaldx(int16x2_t a, int16x2_t b, int64_t c) { 663 return __smlaldx(a, b, c); 664 } 665 // AArch32-LABEL: test_smlsd 666 // AArch32: call i32 @llvm.arm.smlsd 667 int32_t test_smlsd(int16x2_t a, int16x2_t b, int32_t c) { 668 return __smlsd(a, b, c); 669 } 670 // AArch32-LABEL: test_smlsdx 671 // AArch32: call i32 @llvm.arm.smlsdx 672 int32_t test_smlsdx(int16x2_t a, int16x2_t b, int32_t c) { 673 return __smlsdx(a, b, c); 674 } 675 // AArch32-LABEL: test_smlsld 676 // AArch32: call i64 @llvm.arm.smlsld 677 int64_t test_smlsld(int16x2_t a, int16x2_t b, int64_t c) { 678 return __smlsld(a, b, c); 679 } 680 // AArch32-LABEL: test_smlsldx 681 // AArch32: call i64 @llvm.arm.smlsldx 682 int64_t test_smlsldx(int16x2_t a, int16x2_t b, int64_t c) { 683 return __smlsldx(a, b, c); 684 } 685 // AArch32-LABEL: test_smuad 686 // AArch32: call i32 @llvm.arm.smuad 687 int32_t test_smuad(int16x2_t a, int16x2_t b) { 688 return __smuad(a, b); 689 } 690 // AArch32-LABEL: test_smuadx 691 // AArch32: call i32 @llvm.arm.smuadx 692 int32_t test_smuadx(int16x2_t a, int16x2_t b) { 693 return __smuadx(a, b); 694 } 695 // AArch32-LABEL: test_smusd 696 // AArch32: call i32 @llvm.arm.smusd 697 int32_t test_smusd(int16x2_t a, int16x2_t b) { 698 return __smusd(a, b); 699 } 700 // AArch32-LABEL: test_smusdx 701 // AArch32: call i32 @llvm.arm.smusdx 702 int32_t test_smusdx(int16x2_t a, int16x2_t b) { 703 return __smusdx(a, b); 704 } 705 #endif 706 707 /* 9.7 CRC32 intrinsics */ 708 // ARM-LABEL: test_crc32b 709 // AArch32: call i32 @llvm.arm.crc32b 710 // AArch64: call i32 @llvm.aarch64.crc32b 711 uint32_t test_crc32b(uint32_t a, uint8_t b) { 712 return __crc32b(a, b); 713 } 714 715 // ARM-LABEL: test_crc32h 716 // AArch32: call i32 @llvm.arm.crc32h 717 // AArch64: call i32 @llvm.aarch64.crc32h 718 uint32_t test_crc32h(uint32_t a, uint16_t b) { 719 return __crc32h(a, b); 720 } 721 722 // ARM-LABEL: test_crc32w 723 // AArch32: call i32 @llvm.arm.crc32w 724 // AArch64: call i32 @llvm.aarch64.crc32w 725 uint32_t test_crc32w(uint32_t a, uint32_t b) { 726 return __crc32w(a, b); 727 } 728 729 // ARM-LABEL: test_crc32d 730 // AArch32: call i32 @llvm.arm.crc32w 731 // AArch32: call i32 @llvm.arm.crc32w 732 // AArch64: call i32 @llvm.aarch64.crc32x 733 uint32_t test_crc32d(uint32_t a, uint64_t b) { 734 return __crc32d(a, b); 735 } 736 737 // ARM-LABEL: test_crc32cb 738 // AArch32: call i32 @llvm.arm.crc32cb 739 // AArch64: call i32 @llvm.aarch64.crc32cb 740 uint32_t test_crc32cb(uint32_t a, uint8_t b) { 741 return __crc32cb(a, b); 742 } 743 744 // ARM-LABEL: test_crc32ch 745 // AArch32: call i32 @llvm.arm.crc32ch 746 // AArch64: call i32 @llvm.aarch64.crc32ch 747 uint32_t test_crc32ch(uint32_t a, uint16_t b) { 748 return __crc32ch(a, b); 749 } 750 751 // ARM-LABEL: test_crc32cw 752 // AArch32: call i32 @llvm.arm.crc32cw 753 // AArch64: call i32 @llvm.aarch64.crc32cw 754 uint32_t test_crc32cw(uint32_t a, uint32_t b) { 755 return __crc32cw(a, b); 756 } 757 758 // ARM-LABEL: test_crc32cd 759 // AArch32: call i32 @llvm.arm.crc32cw 760 // AArch32: call i32 @llvm.arm.crc32cw 761 // AArch64: call i32 @llvm.aarch64.crc32cx 762 uint32_t test_crc32cd(uint32_t a, uint64_t b) { 763 return __crc32cd(a, b); 764 } 765 766 /* 10.1 Special register intrinsics */ 767 // ARM-LABEL: test_rsr 768 // AArch64: call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]]) 769 // AArch32: call i32 @llvm.read_register.i32(metadata ![[M2:[0-9]]]) 770 uint32_t test_rsr() { 771 #ifdef __ARM_32BIT_STATE 772 return __arm_rsr("cp1:2:c3:c4:5"); 773 #else 774 return __arm_rsr("1:2:3:4:5"); 775 #endif 776 } 777 778 // ARM-LABEL: test_rsr64 779 // AArch64: call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]]) 780 // AArch32: call i64 @llvm.read_register.i64(metadata ![[M3:[0-9]]]) 781 uint64_t test_rsr64() { 782 #ifdef __ARM_32BIT_STATE 783 return __arm_rsr64("cp1:2:c3"); 784 #else 785 return __arm_rsr64("1:2:3:4:5"); 786 #endif 787 } 788 789 // ARM-LABEL: test_rsrp 790 // AArch64: call i64 @llvm.read_register.i64(metadata ![[M1:[0-9]]]) 791 // AArch32: call i32 @llvm.read_register.i32(metadata ![[M4:[0-9]]]) 792 void *test_rsrp() { 793 return __arm_rsrp("sysreg"); 794 } 795 796 // ARM-LABEL: test_wsr 797 // AArch64: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 %{{.*}}) 798 // AArch32: call void @llvm.write_register.i32(metadata ![[M2:[0-9]]], i32 %{{.*}}) 799 void test_wsr(uint32_t v) { 800 #ifdef __ARM_32BIT_STATE 801 __arm_wsr("cp1:2:c3:c4:5", v); 802 #else 803 __arm_wsr("1:2:3:4:5", v); 804 #endif 805 } 806 807 // ARM-LABEL: test_wsr64 808 // AArch64: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 %{{.*}}) 809 // AArch32: call void @llvm.write_register.i64(metadata ![[M3:[0-9]]], i64 %{{.*}}) 810 void test_wsr64(uint64_t v) { 811 #ifdef __ARM_32BIT_STATE 812 __arm_wsr64("cp1:2:c3", v); 813 #else 814 __arm_wsr64("1:2:3:4:5", v); 815 #endif 816 } 817 818 // ARM-LABEL: test_wsrp 819 // AArch64: call void @llvm.write_register.i64(metadata ![[M1:[0-9]]], i64 %{{.*}}) 820 // AArch32: call void @llvm.write_register.i32(metadata ![[M4:[0-9]]], i32 %{{.*}}) 821 void test_wsrp(void *v) { 822 __arm_wsrp("sysreg", v); 823 } 824 825 // AArch32: ![[M2]] = !{!"cp1:2:c3:c4:5"} 826 // AArch32: ![[M3]] = !{!"cp1:2:c3"} 827 // AArch32: ![[M4]] = !{!"sysreg"} 828 829 // AArch64: ![[M0]] = !{!"1:2:3:4:5"} 830 // AArch64: ![[M1]] = !{!"sysreg"} 831 832 // AArch64-v8_3-LABEL: @test_jcvt( 833 // AArch64-v8_3: call i32 @llvm.aarch64.fjcvtzs 834 #ifdef __ARM_64BIT_STATE 835 int32_t test_jcvt(double v) { 836 return __jcvt(v); 837 } 838 #endif 839