Index: clang/include/clang/Basic/BuiltinsAArch64.def =================================================================== --- clang/include/clang/Basic/BuiltinsAArch64.def +++ clang/include/clang/Basic/BuiltinsAArch64.def @@ -59,22 +59,22 @@ TARGET_BUILTIN(__builtin_arm_crc32cd, "UiUiWUi", "nc", "crc") // Memory Tagging Extensions (MTE) -BUILTIN(__builtin_arm_irg, "v*v*Ui", "t") -BUILTIN(__builtin_arm_addg, "v*v*Ui", "t") -BUILTIN(__builtin_arm_gmi, "Uiv*Ui", "t") -BUILTIN(__builtin_arm_ldg, "v*v*", "t") -BUILTIN(__builtin_arm_stg, "vv*", "t") -BUILTIN(__builtin_arm_subp, "Uiv*v*", "t") +TARGET_BUILTIN(__builtin_arm_irg, "v*v*Ui", "t", "mte") +TARGET_BUILTIN(__builtin_arm_addg, "v*v*Ui", "t", "mte") +TARGET_BUILTIN(__builtin_arm_gmi, "Uiv*Ui", "t", "mte") +TARGET_BUILTIN(__builtin_arm_ldg, "v*v*", "t", "mte") +TARGET_BUILTIN(__builtin_arm_stg, "vv*", "t", "mte") +TARGET_BUILTIN(__builtin_arm_subp, "Uiv*v*", "t", "mte") // Memory Operations -BUILTIN(__builtin_arm_mops_memset_tag, "v*v*iz", "") +TARGET_BUILTIN(__builtin_arm_mops_memset_tag, "v*v*iz", "", "mte,mops") // Memory barrier BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") BUILTIN(__builtin_arm_isb, "vUi", "nc") -BUILTIN(__builtin_arm_jcvt, "Zid", "nc") +TARGET_BUILTIN(__builtin_arm_jcvt, "Zid", "nc", "v8.3a") // Prefetch BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc") @@ -101,30 +101,30 @@ BUILTIN(__builtin_sponentry, "v*", "c") // Transactional Memory Extension -BUILTIN(__builtin_arm_tstart, "WUi", "nj") -BUILTIN(__builtin_arm_tcommit, "v", "n") -BUILTIN(__builtin_arm_tcancel, "vWUIi", "n") -BUILTIN(__builtin_arm_ttest, "WUi", "nc") +TARGET_BUILTIN(__builtin_arm_tstart, "WUi", "nj", "tme") +TARGET_BUILTIN(__builtin_arm_tcommit, "v", "n", "tme") +TARGET_BUILTIN(__builtin_arm_tcancel, "vWUIi", "n", "tme") +TARGET_BUILTIN(__builtin_arm_ttest, "WUi", "nc", "tme") // Armv8.5-A FP rounding intrinsics -BUILTIN(__builtin_arm_rint32zf, "ff", "") -BUILTIN(__builtin_arm_rint32z, "dd", "") -BUILTIN(__builtin_arm_rint64zf, "ff", "") -BUILTIN(__builtin_arm_rint64z, "dd", "") -BUILTIN(__builtin_arm_rint32xf, "ff", "") -BUILTIN(__builtin_arm_rint32x, "dd", "") -BUILTIN(__builtin_arm_rint64xf, "ff", "") -BUILTIN(__builtin_arm_rint64x, "dd", "") +TARGET_BUILTIN(__builtin_arm_rint32zf, "ff", "", "v8.5a") +TARGET_BUILTIN(__builtin_arm_rint32z, "dd", "", "v8.5a") +TARGET_BUILTIN(__builtin_arm_rint64zf, "ff", "", "v8.5a") +TARGET_BUILTIN(__builtin_arm_rint64z, "dd", "", "v8.5a") +TARGET_BUILTIN(__builtin_arm_rint32xf, "ff", "", "v8.5a") +TARGET_BUILTIN(__builtin_arm_rint32x, "dd", "", "v8.5a") +TARGET_BUILTIN(__builtin_arm_rint64xf, "ff", "", "v8.5a") +TARGET_BUILTIN(__builtin_arm_rint64x, "dd", "", "v8.5a") // Armv8.5-A Random number generation intrinsics -BUILTIN(__builtin_arm_rndr, "iWUi*", "n") -BUILTIN(__builtin_arm_rndrrs, "iWUi*", "n") +TARGET_BUILTIN(__builtin_arm_rndr, "iWUi*", "n", "rand") +TARGET_BUILTIN(__builtin_arm_rndrrs, "iWUi*", "n", "rand") // Armv8.7-A load/store 64-byte intrinsics -BUILTIN(__builtin_arm_ld64b, "vvC*WUi*", "n") -BUILTIN(__builtin_arm_st64b, "vv*WUiC*", "n") -BUILTIN(__builtin_arm_st64bv, "WUiv*WUiC*", "n") -BUILTIN(__builtin_arm_st64bv0, "WUiv*WUiC*", "n") +TARGET_BUILTIN(__builtin_arm_ld64b, "vvC*WUi*", "n", "ls64") +TARGET_BUILTIN(__builtin_arm_st64b, "vv*WUiC*", "n", "ls64") +TARGET_BUILTIN(__builtin_arm_st64bv, "WUiv*WUiC*", "n", "ls64") +TARGET_BUILTIN(__builtin_arm_st64bv0, "WUiv*WUiC*", "n", "ls64") TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") Index: clang/lib/Headers/arm_acle.h =================================================================== --- clang/lib/Headers/arm_acle.h +++ clang/lib/Headers/arm_acle.h @@ -14,6 +14,9 @@ #error "ACLE intrinsics support not enabled." #endif +#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE +#include +#endif #include #if defined(__cplusplus) @@ -589,122 +592,123 @@ #endif /* 9.7 CRC32 intrinsics */ -#if defined(__ARM_FEATURE_CRC32) && __ARM_FEATURE_CRC32 -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +#if (defined(__ARM_FEATURE_CRC32) && __ARM_FEATURE_CRC32) || \ + (defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32b(uint32_t __a, uint8_t __b) { return __builtin_arm_crc32b(__a, __b); } -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32h(uint32_t __a, uint16_t __b) { return __builtin_arm_crc32h(__a, __b); } -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32w(uint32_t __a, uint32_t __b) { return __builtin_arm_crc32w(__a, __b); } -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32d(uint32_t __a, uint64_t __b) { return __builtin_arm_crc32d(__a, __b); } -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32cb(uint32_t __a, uint8_t __b) { return __builtin_arm_crc32cb(__a, __b); } -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32ch(uint32_t __a, uint16_t __b) { return __builtin_arm_crc32ch(__a, __b); } -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32cw(uint32_t __a, uint32_t __b) { return __builtin_arm_crc32cw(__a, __b); } -static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__, target("crc"))) __crc32cd(uint32_t __a, uint64_t __b) { return __builtin_arm_crc32cd(__a, __b); } #endif /* Armv8.3-A Javascript conversion intrinsic */ -#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE && defined(__ARM_FEATURE_JCVT) -static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__, target("v8.3a"))) __jcvt(double __a) { return __builtin_arm_jcvt(__a); } #endif /* Armv8.5-A FP rounding intrinsics */ -#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE && defined(__ARM_FEATURE_FRINT) -static __inline__ float __attribute__((__always_inline__, __nodebug__)) +#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE +static __inline__ float __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint32zf(float __a) { return __builtin_arm_rint32zf(__a); } -static __inline__ double __attribute__((__always_inline__, __nodebug__)) +static __inline__ double __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint32z(double __a) { return __builtin_arm_rint32z(__a); } -static __inline__ float __attribute__((__always_inline__, __nodebug__)) +static __inline__ float __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint64zf(float __a) { return __builtin_arm_rint64zf(__a); } -static __inline__ double __attribute__((__always_inline__, __nodebug__)) +static __inline__ double __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint64z(double __a) { return __builtin_arm_rint64z(__a); } -static __inline__ float __attribute__((__always_inline__, __nodebug__)) +static __inline__ float __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint32xf(float __a) { return __builtin_arm_rint32xf(__a); } -static __inline__ double __attribute__((__always_inline__, __nodebug__)) +static __inline__ double __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint32x(double __a) { return __builtin_arm_rint32x(__a); } -static __inline__ float __attribute__((__always_inline__, __nodebug__)) +static __inline__ float __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint64xf(float __a) { return __builtin_arm_rint64xf(__a); } -static __inline__ double __attribute__((__always_inline__, __nodebug__)) +static __inline__ double __attribute__((__always_inline__, __nodebug__, target("v8.5a"))) __rint64x(double __a) { return __builtin_arm_rint64x(__a); } #endif /* Armv8.7-A load/store 64-byte intrinsics */ -#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE && defined(__ARM_FEATURE_LS64) +#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE typedef struct { uint64_t val[8]; } data512_t; -static __inline__ data512_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ data512_t __attribute__((__always_inline__, __nodebug__, target("ls64"))) __arm_ld64b(const void *__addr) { - data512_t __value; - __builtin_arm_ld64b(__addr, __value.val); - return __value; + data512_t __value; + __builtin_arm_ld64b(__addr, __value.val); + return __value; } -static __inline__ void __attribute__((__always_inline__, __nodebug__)) +static __inline__ void __attribute__((__always_inline__, __nodebug__, target("ls64"))) __arm_st64b(void *__addr, data512_t __value) { - __builtin_arm_st64b(__addr, __value.val); + __builtin_arm_st64b(__addr, __value.val); } -static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__, target("ls64"))) __arm_st64bv(void *__addr, data512_t __value) { - return __builtin_arm_st64bv(__addr, __value.val); + return __builtin_arm_st64bv(__addr, __value.val); } -static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__)) +static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__, target("ls64"))) __arm_st64bv0(void *__addr, data512_t __value) { - return __builtin_arm_st64bv0(__addr, __value.val); + return __builtin_arm_st64bv0(__addr, __value.val); } #endif @@ -721,23 +725,74 @@ #define __arm_wsrf64(sysreg, v) __arm_wsr64(sysreg, __builtin_bit_cast(uint64_t, v)) /* Memory Tagging Extensions (MTE) Intrinsics */ -#if defined(__ARM_FEATURE_MEMORY_TAGGING) && __ARM_FEATURE_MEMORY_TAGGING -#define __arm_mte_create_random_tag(__ptr, __mask) __builtin_arm_irg(__ptr, __mask) -#define __arm_mte_increment_tag(__ptr, __tag_offset) __builtin_arm_addg(__ptr, __tag_offset) -#define __arm_mte_exclude_tag(__ptr, __excluded) __builtin_arm_gmi(__ptr, __excluded) -#define __arm_mte_get_tag(__ptr) __builtin_arm_ldg(__ptr) -#define __arm_mte_set_tag(__ptr) __builtin_arm_stg(__ptr) -#define __arm_mte_ptrdiff(__ptra, __ptrb) __builtin_arm_subp(__ptra, __ptrb) -#endif +#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE +static __inline__ void* __attribute__((__always_inline__, __nodebug__, target("mte"))) +__arm_mte_create_random_tag(void *__ptr, uint64_t __mask) { + return __builtin_arm_irg(__ptr, __mask); +} +static __inline__ void *__attribute__((__always_inline__, __nodebug__, target("mte"))) +__arm_mte_increment_tag(void *__ptr, unsigned __tag_offset) { + switch (__tag_offset % 16) { + case 0: + return __builtin_arm_addg(__ptr, 0); + case 1: + return __builtin_arm_addg(__ptr, 1); + case 2: + return __builtin_arm_addg(__ptr, 2); + case 3: + return __builtin_arm_addg(__ptr, 3); + case 4: + return __builtin_arm_addg(__ptr, 4); + case 5: + return __builtin_arm_addg(__ptr, 5); + case 6: + return __builtin_arm_addg(__ptr, 6); + case 7: + return __builtin_arm_addg(__ptr, 7); + case 8: + return __builtin_arm_addg(__ptr, 8); + case 9: + return __builtin_arm_addg(__ptr, 9); + case 10: + return __builtin_arm_addg(__ptr, 10); + case 11: + return __builtin_arm_addg(__ptr, 11); + case 12: + return __builtin_arm_addg(__ptr, 12); + case 13: + return __builtin_arm_addg(__ptr, 13); + case 14: + return __builtin_arm_addg(__ptr, 14); + case 15: + return __builtin_arm_addg(__ptr, 15); + } +} +static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__, target("mte"))) +__arm_mte_exclude_tag(void *__ptr, uint64_t __excluded) { + return __builtin_arm_gmi(__ptr, __excluded); +} +static __inline__ void* __attribute__((__always_inline__, __nodebug__, target("mte"))) +__arm_mte_get_tag(void *__ptr) { + return __builtin_arm_ldg(__ptr); +} +static __inline__ void __attribute__((__always_inline__, __nodebug__, target("mte"))) +__arm_mte_set_tag(void *__ptr) { + __builtin_arm_stg(__ptr); +} +static __inline__ ptrdiff_t __attribute__((__always_inline__, __nodebug__, target("mte"))) +__arm_mte_ptrdiff(void *__ptra, void *__ptrb) { + return __builtin_arm_subp(__ptra, __ptrb); +} /* Memory Operations Intrinsics */ -#if defined(__ARM_FEATURE_MOPS) && __ARM_FEATURE_MOPS && defined(__ARM_FEATURE_MEMORY_TAGGING) && __ARM_FEATURE_MEMORY_TAGGING -#define __arm_mops_memset_tag(__tagged_address, __value, __size) \ - __builtin_arm_mops_memset_tag(__tagged_address, __value, __size) +static __inline__ void* __attribute__((__always_inline__, __nodebug__, target("mte,mops"))) +__arm_mops_memset_tag(void *__tagged_address, int __value, size_t __size) { + return __builtin_arm_mops_memset_tag(__tagged_address, __value, __size); +} #endif /* Transactional Memory Extension (TME) Intrinsics */ -#if defined(__ARM_FEATURE_TME) && __ARM_FEATURE_TME +#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE #define _TMFAILURE_REASON 0x00007fffu #define _TMFAILURE_RTRY 0x00008000u @@ -751,20 +806,32 @@ #define _TMFAILURE_INT 0x00800000u #define _TMFAILURE_TRIVIAL 0x01000000u -#define __tstart() __builtin_arm_tstart() -#define __tcommit() __builtin_arm_tcommit() -#define __tcancel(__arg) __builtin_arm_tcancel(__arg) -#define __ttest() __builtin_arm_ttest() +static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__, target("tme"))) +__tstart(void) { + __builtin_arm_tstart(); +} +static __inline__ void __attribute__((__always_inline__, __nodebug__, target("tme"))) +__tcommit(void) { + __builtin_arm_tcommit(); +} +static __inline__ void __attribute__((__always_inline__, __nodebug__, target("tme"))) +__tcancel(void) { +} +#define __tcancel(__arg) __tcancel();__builtin_arm_tcancel(__arg) -#endif /* __ARM_FEATURE_TME */ +static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__, target("tme"))) +__ttest(void) { + return __builtin_arm_ttest(); +} +#endif /* Armv8.5-A Random number generation intrinsics */ -#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE && defined(__ARM_FEATURE_RNG) -static __inline__ int __attribute__((__always_inline__, __nodebug__)) +#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE +static __inline__ int __attribute__((__always_inline__, __nodebug__, target("rand"))) __rndr(uint64_t *__p) { return __builtin_arm_rndr(__p); } -static __inline__ int __attribute__((__always_inline__, __nodebug__)) +static __inline__ int __attribute__((__always_inline__, __nodebug__, target("rand"))) __rndrrs(uint64_t *__p) { return __builtin_arm_rndrrs(__p); } Index: clang/test/CodeGen/aarch64-mops.c =================================================================== --- clang/test/CodeGen/aarch64-mops.c +++ clang/test/CodeGen/aarch64-mops.c @@ -1,77 +1,69 @@ -// RUN: %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -target-feature +mops -target-feature +mte -w -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-MOPS %s -// RUN: %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -target-feature +mops -Wno-implicit-function-declaration -w -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-NOMOPS %s -// RUN: %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -Wno-implicit-function-declaration -target-feature +mte -w -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-NOMOPS %s -// RUN: %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -Wno-implicit-function-declaration -w -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-NOMOPS %s +// RUN: %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -target-feature +mops -target-feature +mte -w -S -emit-llvm -o - %s 2>&1 | FileCheck --check-prefix=CHECK-MOPS %s +// RUN: not %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -Wno-implicit-function-declaration -target-feature +mte -w -S -emit-llvm -o - %s 2>&1 | FileCheck --check-prefix=CHECK-NOMOPS %s +// RUN: not %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -target-feature +mops -Wno-implicit-function-declaration -w -S -emit-llvm -o - %s 2>&1 | FileCheck --check-prefix=CHECK-NOMTE %s +// RUN: not %clang_cc1 -triple aarch64-arm-unknown-eabi -Wno-int-conversion -Wno-implicit-function-declaration -w -S -emit-llvm %s -o - 2>&1 | FileCheck --check-prefix=CHECK-NOMTE %s #include #include // CHECK-LABEL: @bzero_0( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag +// CHECK-NOMTE: error: always_inline function '__arm_mops_memset_tag' requires target feature 'mte', but would be inlined into function 'bzero_0' that is compiled without support for 'mte' +// CHECK-NOMOPS: error: always_inline function '__arm_mops_memset_tag' requires target feature 'mops', but would be inlined into function 'bzero_0' that is compiled without support for 'mops' void *bzero_0(void *dst) { return __arm_mops_memset_tag(dst, 0, 0); } // CHECK-LABEL: @bzero_1( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *bzero_1(void *dst) { return __arm_mops_memset_tag(dst, 0, 1); } // CHECK-LABEL: @bzero_10( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *bzero_10(void *dst) { return __arm_mops_memset_tag(dst, 0, 10); } // CHECK-LABEL: @bzero_10000( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *bzero_10000(void *dst) { return __arm_mops_memset_tag(dst, 0, 10000); } // CHECK-LABEL: @bzero_n( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *bzero_n(void *dst, size_t size) { return __arm_mops_memset_tag(dst, 0, size); } // CHECK-LABEL: @memset_0( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *memset_0(void *dst, int value) { return __arm_mops_memset_tag(dst, value, 0); } // CHECK-LABEL: @memset_1( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *memset_1(void *dst, int value) { return __arm_mops_memset_tag(dst, value, 1); } // CHECK-LABEL: @memset_10( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *memset_10(void *dst, int value) { return __arm_mops_memset_tag(dst, value, 10); } // CHECK-LABEL: @memset_10000( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *memset_10000(void *dst, int value) { return __arm_mops_memset_tag(dst, value, 10000); } // CHECK-LABEL: @memset_n( // CHECK-MOPS: @llvm.aarch64.mops.memset.tag -// CHECK-NOMOPS-NOT: @llvm.aarch64.mops.memset.tag void *memset_n(void *dst, int value, size_t size) { return __arm_mops_memset_tag(dst, value, size); } Index: clang/test/CodeGen/aarch64-tme.cpp =================================================================== --- clang/test/CodeGen/aarch64-tme.cpp +++ clang/test/CodeGen/aarch64-tme.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple aarch64-eabi -target-feature +tme -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -DUSE_ACLE -triple aarch64-eabi -target-feature +tme -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -DUSE_ACLE -triple aarch64-eabi -target-feature +tme -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK_ACLE +// RUN: not %clang_cc1 -DUSE_ACLE -triple aarch64-eabi -S -emit-llvm %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NO_TME #define A -1 constexpr int f() { return 65536; } @@ -28,15 +29,32 @@ // CHECK: call void @llvm.aarch64.tcancel(i64 30874) // CHECK: call void @llvm.aarch64.tcancel(i64 65535) +// CHECK_ACLE: call i64 @llvm.aarch64.tstart() +// CHECK_ACLE: call i64 @llvm.aarch64.ttest() +// CHECK_ACLE: call void @llvm.aarch64.tcommit() +// CHECK_ACLE: call void @llvm.aarch64.tcancel(i64 30874) +// CHECK_ACLE: call void @llvm.aarch64.tcancel(i64 65535) + // CHECK: declare i64 @llvm.aarch64.tstart() #1 // CHECK: declare i64 @llvm.aarch64.ttest() #1 // CHECK: declare void @llvm.aarch64.tcommit() #1 // CHECK: declare void @llvm.aarch64.tcancel(i64 immarg) #1 +// CHECK_ACLE: declare void @llvm.aarch64.tcancel(i64 immarg) #1 +// CHECK_ACLE: define{{.*}} void @arm_feature_tme_defined() +// CHECK_ACLE: declare i64 @llvm.aarch64.tstart() #1 +// CHECK_ACLE: declare i64 @llvm.aarch64.ttest() #1 +// CHECK_ACLE: declare void @llvm.aarch64.tcommit() #1 + +// CHECK_NO_TME: error: always_inline function '__tstart' requires target feature 'tme', but would be inlined into function 'test_tme_funcs' that is compiled without support for 'tme' +// CHECK_NO_TME: error: always_inline function '__ttest' requires target feature 'tme', but would be inlined into function 'test_tme_funcs' that is compiled without support for 'tme' +// CHECK_NO_TME: error: always_inline function '__tcommit' requires target feature 'tme', but would be inlined into function 'test_tme_funcs' that is compiled without support for 'tme' +// CHECK_NO_TME: error: always_inline function '__tcancel' requires target feature 'tme', but would be inlined into function 'test_tme_funcs' that is compiled without support for 'tme' +// CHECK_NO_TME: error: always_inline function '__tcancel' requires target feature 'tme', but would be inlined into function 'test_tme_funcs' that is compiled without support for 'tme' + #ifdef __ARM_FEATURE_TME extern "C" void arm_feature_tme_defined() {} #endif -// CHECK: define{{.*}} void @arm_feature_tme_defined() // CHECK: attributes #1 = { nounwind willreturn } Index: clang/test/CodeGen/arm64-mte.c =================================================================== --- clang/test/CodeGen/arm64-mte.c +++ clang/test/CodeGen/arm64-mte.c @@ -6,7 +6,7 @@ // CHECK-LABEL: define{{.*}} i32* @create_tag1 int *create_tag1(int *a, unsigned b) { // CHECK: [[T0:%[0-9]+]] = bitcast i32* %a to i8* -// CHECK: [[T1:%[0-9]+]] = zext i32 %b to i64 +// CHECK: [[T1:%[0-9a-z]+]] = zext i32 %b to i64 // CHECK: [[T2:%[0-9]+]] = tail call i8* @llvm.aarch64.irg(i8* [[T0]], i64 [[T1]]) // CHECK: bitcast i8* [[T2]] to i32* return __arm_mte_create_random_tag(a,b); @@ -15,7 +15,7 @@ // CHECK-LABEL: define{{.*}} i16* @create_tag2 short *create_tag2(short *a, unsigned b) { // CHECK: [[T0:%[0-9]+]] = bitcast i16* %a to i8* -// CHECK: [[T1:%[0-9]+]] = zext i32 %b to i64 +// CHECK: [[T1:%[0-9a-z]+]] = zext i32 %b to i64 // CHECK: [[T2:%[0-9]+]] = tail call i8* @llvm.aarch64.irg(i8* [[T0]], i64 [[T1]]) // CHECK: bitcast i8* [[T2]] to i16* return __arm_mte_create_random_tag(a,b); @@ -23,7 +23,7 @@ // CHECK-LABEL: define{{.*}} i8* @create_tag3 char *create_tag3(char *a, unsigned b) { -// CHECK: [[T1:%[0-9]+]] = zext i32 %b to i64 +// CHECK: [[T1:%[0-9a-z]+]] = zext i32 %b to i64 // CHECK: [[T2:%[0-9]+]] = tail call i8* @llvm.aarch64.irg(i8* %a, i64 [[T1]]) // CHECK: ret i8* [[T2:%[0-9]+]] return __arm_mte_create_random_tag(a,b); @@ -45,8 +45,8 @@ // CHECK-LABEL: define{{.*}} i32 @exclude_tag unsigned exclude_tag(int *a, unsigned m) { -// CHECK: [[T0:%[0-9]+]] = zext i32 %m to i64 // CHECK: [[T1:%[0-9]+]] = bitcast i32* %a to i8* +// CHECK: [[T0:%[0-9a-z]+]] = zext i32 %m to i64 // CHECK: [[T2:%[0-9]+]] = tail call i64 @llvm.aarch64.gmi(i8* [[T1]], i64 [[T0]]) // CHECK: trunc i64 [[T2]] to i32 return __arm_mte_exclude_tag(a, m); @@ -86,7 +86,7 @@ // CHECK-LABEL: define{{.*}} i64 @subtract_pointers_null_1 ptrdiff_t subtract_pointers_null_1(int *a) { -// CHECK: [[T0:%[0-9]+]] = bitcast i32* %a to i8* +// CHECK: [[T0:%[0-9a-z]+]] = bitcast i32* %a to i8* // CHECK: [[T1:%[0-9]+]] = tail call i64 @llvm.aarch64.subp(i8* [[T0]], i8* null) // CHECK: ret i64 [[T1]] return __arm_mte_ptrdiff(a, NULL); @@ -94,8 +94,8 @@ // CHECK-LABEL: define{{.*}} i64 @subtract_pointers_null_2 ptrdiff_t subtract_pointers_null_2(int *a) { -// CHECK: [[T0:%[0-9]+]] = bitcast i32* %a to i8* -// CHECK: [[T1:%[0-9]+]] = tail call i64 @llvm.aarch64.subp(i8* null, i8* [[T0]]) +// CHECK: [[T0:%[0-9a-z]+]] = bitcast i32* %a to i8* +// CHECK: [[T1:%[0-9a-z]+]] = tail call i64 @llvm.aarch64.subp(i8* null, i8* [[T0]]) // CHECK: ret i64 [[T1]] return __arm_mte_ptrdiff(NULL, a); } @@ -103,7 +103,7 @@ // Check arithmetic promotion on return type // CHECK-LABEL: define{{.*}} i32 @subtract_pointers4 int subtract_pointers4(void* a, void *b) { -// CHECK: [[T0:%[0-9]+]] = tail call i64 @llvm.aarch64.subp(i8* %a, i8* %b) +// CHECK: [[T0:%[0-9a-z]+]] = tail call i64 @llvm.aarch64.subp(i8* %a, i8* %b) // CHECK-NEXT: %cmp = icmp slt i64 [[T0]], 1 // CHECK-NEXT: = zext i1 %cmp to i32 return __arm_mte_ptrdiff(a,b) <= 0; Index: clang/test/CodeGen/arm_acle.c =================================================================== --- clang/test/CodeGen/arm_acle.c +++ clang/test/CodeGen/arm_acle.c @@ -124,7 +124,7 @@ __sevl(); } -#if __ARM_32BIT_STATE +#ifdef __ARM_32BIT_STATE // AArch32-LABEL: @test_dbg( // AArch32-NEXT: entry: // AArch32-NEXT: call void @llvm.arm.dbg(i32 0) @@ -1656,7 +1656,7 @@ #endif } -#ifdef __ARM_64BIT_STATE +#if defined(__ARM_64BIT_STATE) && defined(__ARM_FEATURE_JCVT) // AArch6483-LABEL: @test_jcvt( // AArch6483-NEXT: entry: // AArch6483-NEXT: [[TMP0:%.*]] = call i32 @llvm.aarch64.fjcvtzs(double [[V:%.*]]) @@ -1668,7 +1668,7 @@ #endif -#if __ARM_64BIT_STATE && defined(__ARM_FEATURE_RNG) +#if defined(__ARM_64BIT_STATE) && defined(__ARM_FEATURE_RNG) // AArch6485-LABEL: @test_rndr( // AArch6485-NEXT: entry: Index: clang/test/CodeGen/builtins-arm64.c =================================================================== --- clang/test/CodeGen/builtins-arm64.c +++ clang/test/CodeGen/builtins-arm64.c @@ -59,6 +59,7 @@ // CHECK: call {{.*}} @llvm.prefetch.p0i8(i8* null, i32 0, i32 3, i32 0) } +__attribute__((target("v8.5a"))) int32_t jcvt(double v) { //CHECK-LABEL: @jcvt( //CHECK: call i32 @llvm.aarch64.fjcvtzs @@ -133,6 +134,7 @@ // CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 // CHECK-NEXT: ret i32 [[TMP3]] // +__attribute__((target("rand"))) int rndr(uint64_t *__addr) { return __builtin_arm_rndr(__addr); } @@ -146,6 +148,7 @@ // CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 // CHECK-NEXT: ret i32 [[TMP3]] // +__attribute__((target("rand"))) int rndrrs(uint64_t *__addr) { return __builtin_arm_rndrrs(__addr); } Index: clang/test/Sema/aarch64-tme-errors.c =================================================================== --- clang/test/Sema/aarch64-tme-errors.c +++ clang/test/Sema/aarch64-tme-errors.c @@ -3,6 +3,6 @@ #include "arm_acle.h" void test_no_tme_funcs(void) { - __tstart(); // expected-error{{call to undeclared function '__tstart'; ISO C99 and later do not support implicit function declarations}} + __tstart(); // ACLE always provides intrinsics. __builtin_tstart(); // expected-error{{use of unknown builtin '__builtin_tstart'}} } Index: clang/test/Sema/builtins-arm64-mte.c =================================================================== --- clang/test/Sema/builtins-arm64-mte.c +++ clang/test/Sema/builtins-arm64-mte.c @@ -4,133 +4,236 @@ #include int *create_tag1(int a, unsigned b) { +#ifdef __cplusplus + // expected-error@+2 {{no matching function for call to '__arm_mte_create_random_tag'}} + // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'void *'}} + return __arm_mte_create_random_tag(a,b); // expected-note@arm_acle.h:* {{candidate function not viable: no known conversion from}} +#else + // expected-error@+1 {{incompatible integer to pointer conversion passing 'int' to parameter of type 'void *'}} + return __arm_mte_create_random_tag(a,b); // expected-note@* {{passing argument to parameter}} +#endif +} + +int *create_tag1builtin(int a, unsigned b) { // expected-error@+1 {{first argument of MTE builtin function must be a pointer ('int' invalid)}} - return __arm_mte_create_random_tag(a,b); + return __builtin_arm_irg(a,b); } int *create_tag2(int *a, unsigned *b) { +#ifdef __cplusplus + // expected-error@+2 {{no matching function for call to '__arm_mte_create_random_tag'}} + // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'void *'}} + return __arm_mte_create_random_tag(a,b); // expected-note@arm_acle.h:* {{candidate function not viable: no known conversion from}} +#else + // expected-error@+1 {{incompatible pointer to integer conversion passing 'unsigned int *' to parameter of type 'uint64_t'}} + return __arm_mte_create_random_tag(a,b); // expected-note@* {{passing argument to parameter}} +#endif +} + +int *create_tag2builtin(int *a, unsigned *b) { // expected-error@+1 {{second argument of MTE builtin function must be an integer type ('unsigned int *' invalid)}} - return __arm_mte_create_random_tag(a,b); + return __builtin_arm_irg(a,b); } int *create_tag3(const int *a, unsigned b) { +#ifdef __cplusplus + // expected-error@+2 {{no matching function for call to '__arm_mte_create_random_tag'}} + // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'void *'}} + return __arm_mte_create_random_tag(a,b); // expected-note@arm_acle.h:* {{candidate function not viable: no known conversion from}} +#else + // expected-warning@+1 {{passing 'const int *' to parameter of type 'void *' discards qualifiers}} + return __arm_mte_create_random_tag(a,b); // expected-note@* {{passing argument to parameter}} +#endif +} + +int *create_tag3builtin(const int *a, unsigned b) { #ifdef __cplusplus // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'const int *'}} - return __arm_mte_create_random_tag(a,b); + return __builtin_arm_irg(a,b); #else // expected-warning@+1 {{returning 'const int *' from a function with result type 'int *' discards qualifiers}} - return __arm_mte_create_random_tag(a,b); + return __builtin_arm_irg(a,b); #endif } int *create_tag4(volatile int *a, unsigned b) { +#ifdef __cplusplus + // expected-error@+2 {{no matching function for call to '__arm_mte_create_random_tag'}} + // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'void *'}} + return __arm_mte_create_random_tag(a,b); // expected-note@arm_acle.h:* {{candidate function not viable: no known conversion from}} +#else + // expected-warning@+1 {{passing 'volatile int *' to parameter of type 'void *' discards qualifiers}} + return __arm_mte_create_random_tag(a,b); // expected-note@* {{passing argument to parameter}} +#endif +} + +int *create_tag4builtin(volatile int *a, unsigned b) { #ifdef __cplusplus // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'volatile int *'}} - return __arm_mte_create_random_tag(a,b); + return __builtin_arm_irg(a,b); #else // expected-warning@+1 {{returning 'volatile int *' from a function with result type 'int *' discards qualifiers}} - return __arm_mte_create_random_tag(a,b); + return __builtin_arm_irg(a,b); #endif } - int *increment_tag1(int *a, unsigned b) { - // expected-error@+1 {{argument to '__builtin_arm_addg' must be a constant integer}} + // ACLE intrinsics can take a variable. +#ifdef __cplusplus + return reinterpret_cast(__arm_mte_increment_tag(reinterpret_cast(a),b)); +#else return __arm_mte_increment_tag(a,b); +#endif +} + +int *increment_tag1builtin(int *a, unsigned b) { + // expected-error@+1 {{argument to '__builtin_arm_addg' must be a constant integer}} + return __builtin_arm_addg(a,b); } int *increment_tag2(int *a) { // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}} - return __arm_mte_increment_tag(a,16); + return __builtin_arm_addg(a,16); } int *increment_tag3(int *a) { // expected-error@+1 {{argument value -1 is outside the valid range [0, 15]}} - return __arm_mte_increment_tag(a,-1); + return __builtin_arm_addg(a,-1); } int *increment_tag4(const int *a) { +#ifdef __cplusplus + // expected-error@+1 {{no matching function for call to '__arm_mte_increment_tag'}} + return (int*)__arm_mte_increment_tag(a,5); // expected-note@arm_acle.h:* {{candidate function not viable: no known conversion from}} +#else + // expected-warning@+1 {{passing 'const int *' to parameter of type 'void *' discards qualifiers}} + return __arm_mte_increment_tag(a,5); // expected-note@* {{passing argument to parameter}} +#endif +} + +int *increment_tag4builtin(const int *a) { #ifdef __cplusplus // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'const int *'}} - return __arm_mte_increment_tag(a,5); + return __builtin_arm_addg(a,5); #else // expected-warning@+1 {{returning 'const int *' from a function with result type 'int *' discards qualifiers}} - return __arm_mte_increment_tag(a,5); + return __builtin_arm_addg(a,5); #endif } int *increment_tag5(const volatile int *a) { #ifdef __cplusplus // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'const volatile int *'}} - return __arm_mte_increment_tag(a,5); + return __builtin_arm_addg(a,5); #else // expected-warning@+1 {{returning 'const volatile int *' from a function with result type 'int *' discards qualifiers}} - return __arm_mte_increment_tag(a,5); + return __builtin_arm_addg(a,5); #endif } unsigned exclude_tag1(int *ptr, unsigned m) { // expected-error@+1 {{first argument of MTE builtin function must be a pointer ('int' invalid)}} - return __arm_mte_exclude_tag(*ptr, m); + return __builtin_arm_gmi(*ptr, m); } unsigned exclude_tag2(int *ptr, int *m) { // expected-error@+1 {{second argument of MTE builtin function must be an integer type ('int *' invalid)}} - return __arm_mte_exclude_tag(ptr, m); + return __builtin_arm_gmi(ptr, m); } void get_tag1(void) { +#ifdef __cplusplus + // expected-error@+1 {{no matching function for call to '__arm_mte_get_tag'}} + __arm_mte_get_tag(); // expected-note@arm_acle.h:* {{candidate function not viable: requires single argument}} +#else + // expected-error@+1 {{too few arguments to function call, single argument '__ptr' was not specified}} + __arm_mte_get_tag(); // expected-note@arm_acle.h:* {{'__arm_mte_get_tag' declared here}} +#endif +} + +void get_tag1builtin(void) { // expected-error@+1 {{too few arguments to function call, expected 1, have 0}} - __arm_mte_get_tag(); + __builtin_arm_ldg(); } int *get_tag2(int ptr) { // expected-error@+1 {{first argument of MTE builtin function must be a pointer ('int' invalid)}} - return __arm_mte_get_tag(ptr); + return __builtin_arm_ldg(ptr); } int *get_tag3(const volatile int *ptr) { +#ifdef __cplusplus + // expected-error@+2 {{no matching function for call to '__arm_mte_get_tag'}} + // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'void *'}} + return __arm_mte_get_tag(ptr); // expected-note@arm_acle.h:* {{candidate function not viable: no known conversion}} +#else + // expected-warning@+1 {{passing 'const volatile int *' to parameter of type 'void *' discards qualifiers}} + return __arm_mte_get_tag(ptr); // expected-note@arm_acle.h:* {{passing argument to parameter}} +#endif +} + +int *get_tag3builtin(const volatile int *ptr) { #ifdef __cplusplus // expected-error@+1 {{cannot initialize return object of type 'int *' with an rvalue of type 'const volatile int *'}} - return __arm_mte_get_tag(ptr); + return __builtin_arm_ldg(ptr); #else // expected-warning@+1 {{returning 'const volatile int *' from a function with result type 'int *' discards qualifiers}} - return __arm_mte_get_tag(ptr); + return __builtin_arm_ldg(ptr); #endif } void set_tag1(void) { // expected-error@+1 {{too few arguments to function call, expected 1, have 0}} - __arm_mte_set_tag(); + __builtin_arm_stg(); } void set_tag2(int ptr) { // expected-error@+1 {{first argument of MTE builtin function must be a pointer ('int' invalid)}} - __arm_mte_set_tag(ptr); + __builtin_arm_stg(ptr); } ptrdiff_t subtract_pointers1(int a, int *b) { - // expected-error@+1 {{first argument of MTE builtin function must be a null or a pointer ('int' invalid)}} - return __arm_mte_ptrdiff(a, b); +#ifdef __cplusplus + // expected-error@+1 {{no matching function for call to '__arm_mte_ptrdiff'}} + return __arm_mte_ptrdiff(a, b);// expected-note@arm_acle.h:* {{candidate function not viable: no known conversion from}} +#else + // expected-error@+1 {{incompatible integer to pointer conversion passing}} + return __arm_mte_ptrdiff(a, b);// expected-note@arm_acle.h:* {{passing argument to parameter}} +#endif } ptrdiff_t subtract_pointers2(int *a, int b) { +#ifdef __cplusplus + // expected-error@+1 {{no matching function for call to '__arm_mte_ptrdiff'}} + return __arm_mte_ptrdiff(a, b);// expected-note@arm_acle.h:* {{candidate function not viable: no known conversion from}} +#else + // expected-error@+1 {{incompatible integer to pointer conversion passing}} + return __arm_mte_ptrdiff(a, b);// expected-note@arm_acle.h:* {{passing argument to parameter}} +#endif +} + +ptrdiff_t subtract_pointers1_builtin(int a, int *b) { + // expected-error@+1 {{first argument of MTE builtin function must be a null or a pointer ('int' invalid)}} + return __builtin_arm_subp(a, b); +} + +ptrdiff_t subtract_pointers2_builtin(int *a, int b) { // expected-error@+1 {{second argument of MTE builtin function must be a null or a pointer ('int' invalid)}} - return __arm_mte_ptrdiff(a, b); + return __builtin_arm_subp(a, b); } ptrdiff_t subtract_pointers3(char *a, int *b) { // expected-error@+1 {{'char *' and 'int *' are not pointers to compatible types}} - return __arm_mte_ptrdiff(a, b); + return __builtin_arm_subp(a, b); } ptrdiff_t subtract_pointers4(int *a, char *b) { // expected-error@+1 {{'int *' and 'char *' are not pointers to compatible types}} - return __arm_mte_ptrdiff(a, b); + return __builtin_arm_subp(a, b); } #ifdef __cplusplus ptrdiff_t subtract_pointers5() { // expected-error@+1 {{at least one argument of MTE builtin function must be a pointer ('std::nullptr_t', 'std::nullptr_t' invalid)}} - return __arm_mte_ptrdiff(nullptr, nullptr); + return __builtin_arm_subp(nullptr, nullptr); } #endif