[compiler-rt] [AArch64][compiler-rt] Add memcpy, memset, memmove, memchr simple imp… (PR #77496)
Dinar Temirbulatov via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 12 00:50:17 PST 2024
https://github.com/dtemirbulatov updated https://github.com/llvm/llvm-project/pull/77496
>From 2db7921d5bedb3d5f834a7520dc3fee1e9903646 Mon Sep 17 00:00:00 2001
From: Dinar Temirbulatov <Dinar.Temirbulatov at arm.com>
Date: Tue, 9 Jan 2024 16:37:12 +0000
Subject: [PATCH 1/2] [AArch64][compiler-rt] Add memcpy, memset, memmove,
memchr simple implementation RT builtins.
Add naive implementation of memcpy, memset, memmove, memchr for SME targets.
Patch co-authored by David Sherwood <david.sherwood at arm.com>
---
compiler-rt/lib/builtins/CMakeLists.txt | 2 +-
.../lib/builtins/aarch64/sme-libc-routines.c | 102 ++++++++++
.../test/builtins/Unit/sme-string-test.c | 183 ++++++++++++++++++
3 files changed, 286 insertions(+), 1 deletion(-)
create mode 100644 compiler-rt/lib/builtins/aarch64/sme-libc-routines.c
create mode 100644 compiler-rt/test/builtins/Unit/sme-string-test.c
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index e5b52db175d960..79d3af1a4fd8d8 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -561,7 +561,7 @@ set(aarch64_SOURCES
)
if(COMPILER_RT_HAS_ASM_SME AND (COMPILER_RT_HAS_AUXV OR COMPILER_RT_BAREMETAL_BUILD))
- list(APPEND aarch64_SOURCES aarch64/sme-abi.S aarch64/sme-abi-init.c)
+ list(APPEND aarch64_SOURCES aarch64/sme-abi.S aarch64/sme-abi-init.c aarch64/sme-libc-routines.c)
message(STATUS "AArch64 SME ABI routines enabled")
else()
message(STATUS "AArch64 SME ABI routines disabled")
diff --git a/compiler-rt/lib/builtins/aarch64/sme-libc-routines.c b/compiler-rt/lib/builtins/aarch64/sme-libc-routines.c
new file mode 100644
index 00000000000000..c846daa51cc91f
--- /dev/null
+++ b/compiler-rt/lib/builtins/aarch64/sme-libc-routines.c
@@ -0,0 +1,102 @@
+#include <stdlib.h>
+
+// WARNING: When building the scalar versions of these functions you need to
+// use the compiler flag "-mllvm -disable-loop-idiom-all" to prevent clang
+// from recognising a loop idiom and planting calls to memcpy!
+
+static void *
+__arm_sc_memcpy_fwd(void *dest, const void *src,
+ size_t n) __arm_streaming_compatible __arm_preserves_za {
+ unsigned char *destp = (unsigned char *)dest;
+ const unsigned char *srcp = (const unsigned char *)src;
+
+ for (size_t i = 0; i < n; i++) {
+ destp[i] = srcp[i];
+ }
+
+ return dest;
+}
+
+// If dest and src overlap then behaviour is undefined, hence we can add the
+// restrict keywords here. This also matches the definition of the libc memcpy
+// according to the man page.
+void *__arm_sc_memcpy(void *__restrict__ dest, const void *__restrict__ src,
+ size_t n) __arm_streaming_compatible __arm_preserves_za {
+ return __arm_sc_memcpy_fwd(dest, src, n);
+}
+
+void *__arm_sc_memset(void *dest, int c,
+ size_t n) __arm_streaming_compatible __arm_preserves_za {
+ unsigned char *destp = (unsigned char *)dest;
+ unsigned char c8 = (unsigned char)c;
+
+ for (size_t i = 0; i < n; i++) {
+ destp[i] = c8;
+ }
+
+ return dest;
+}
+
+static void *
+__arm_sc_memcpy_rev(void *dest, const void *src,
+ size_t n) __arm_streaming_compatible __arm_preserves_za {
+ unsigned char *destp = (unsigned char *)dest;
+ const unsigned char *srcp = (const unsigned char *)src;
+
+ // TODO: Improve performance by copying larger chunks in reverse, or by
+ // using SVE.
+ while (n > 0) {
+ n--;
+ destp[n] = srcp[n];
+ }
+ return dest;
+}
+
+// Semantically a memmove is equivalent to the following:
+// 1. Copy the entire contents of src to a temporary array that does not
+// overlap with src or dest.
+// 2. Copy the contents of the temporary array into dest.
+void *__arm_sc_memmove(void *dest, const void *src,
+ size_t n) __arm_streaming_compatible __arm_preserves_za {
+ unsigned char *destp = (unsigned char *)dest;
+ const unsigned char *srcp = (const unsigned char *)src;
+
+ // If src and dest are identical there is nothing to do!
+ if ((destp == srcp) || (n == 0))
+ return destp;
+
+ // If src and dest don't overlap then just invoke memcpy
+ if ((srcp > (destp + n)) || (destp > (srcp + n)))
+ return __arm_sc_memcpy_fwd(dest, src, n);
+
+ // Overlap case 1:
+ // src: Low | -> | High
+ // dest: Low | -> | High
+ // Here src is always ahead of dest at a higher addres. If we first read a
+ // chunk of data from src we can safely write the same chunk to dest without
+ // corrupting future reads of src.
+ if (srcp > destp)
+ return __arm_sc_memcpy_fwd(dest, src, n);
+
+ // Overlap case 2:
+ // src: Low | -> | High
+ // dest: Low | -> | High
+ // While we're in the overlap region we're always corrupting future reads of
+ // src when writing to dest. An efficient way to do this is to copy the data
+ // in reverse by starting at the highest address.
+ return __arm_sc_memcpy_rev(dest, src, n);
+}
+
+const void *
+__arm_sc_memchr(const void *src, int c,
+ size_t n) __arm_streaming_compatible __arm_preserves_za {
+ const unsigned char *srcp = (const unsigned char *)src;
+ unsigned char c8 = (unsigned char)c;
+
+ for (size_t i = 0; i < n; i++) {
+ if (srcp[i] == c8)
+ return &srcp[i];
+ }
+
+ return NULL;
+}
diff --git a/compiler-rt/test/builtins/Unit/sme-string-test.c b/compiler-rt/test/builtins/Unit/sme-string-test.c
new file mode 100644
index 00000000000000..0b066c3c179c95
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/sme-string-test.c
@@ -0,0 +1,183 @@
+// REQUIRES: linux, aarch64-target-arch
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define N 1024
+#define NREPS 1234
+
+static uint8_t dst[N], src[N];
+
+extern void *__arm_sc_memcpy(void *, const void *, size_t);
+extern void *__arm_sc_memset(void *, int, size_t);
+extern void *__arm_sc_memmove(void *, const void *, size_t);
+extern void *__arm_sc_memchr(const void *, int, size_t);
+
+void init(void) {
+ for (int i = 0; i < N; i++) {
+ src[i] = i * 2;
+ dst[i] = i + 1;
+ }
+}
+
+void reinit_dst(int n) {
+ for (int i = 0; i < n; i++) {
+ dst[i] = i + 1;
+ }
+}
+
+int sum(uint8_t *dest, int n) {
+ int t = 0;
+ for (int i = 0; i < n; i++) {
+ t += dest[i];
+ }
+ return t;
+}
+
+long get_time_diff(struct timespec tv[2]) {
+ long us0 = (tv[0].tv_sec * 1000000) + (tv[0].tv_nsec / 1000);
+ long us1 = (tv[1].tv_sec * 1000000) + (tv[1].tv_nsec / 1000);
+ return us1 - us0;
+}
+
+int main() {
+ struct timespec tv[2];
+
+ init();
+
+ // Test correctness of memcpy
+ for (int i = 0; i < 67; i++) {
+ int t[2];
+ if (!__arm_sc_memcpy(dst, src, i)) {
+ fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memcpy!\n");
+ abort();
+ }
+ t[0] = sum(dst, N);
+ reinit_dst(i);
+ memcpy(dst, src, i);
+ t[1] = sum(dst, N);
+ reinit_dst(i);
+ if (t[0] != t[1]) {
+ fprintf(stderr, "__arm_sc_memcpy doesn't match memcpy behaviour!\n");
+ abort();
+ }
+ }
+
+#ifdef TEST_PERF
+ // Collect perf data for memcpy
+ clock_gettime(CLOCK_REALTIME, &tv[0]);
+ for (int r = 0; r < NREPS; r++) {
+ for (int i = 0; i < 67; i++) {
+ int t[2];
+ if (!__arm_sc_memcpy(dst, src, i)) {
+ fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memcpy!\n");
+ abort();
+ }
+ }
+ }
+ reinit_dst(67);
+ clock_gettime(CLOCK_REALTIME, &tv[1]);
+ printf("memcpy time = %ld\n", get_time_diff(tv));
+#endif
+
+ // Test correctness of memset
+ for (int i = 0; i < 67; i++) {
+ int t[2];
+ if (!__arm_sc_memset(dst, src[i], i)) {
+ fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memset!\n");
+ abort();
+ }
+ t[0] = sum(dst, N);
+ reinit_dst(i);
+ memset(dst, src[i], i);
+ t[1] = sum(dst, N);
+ reinit_dst(i);
+ if (t[0] != t[1]) {
+ fprintf(stderr, "__arm_sc_memcpy doesn't match memset behaviour!\n");
+ abort();
+ }
+ }
+
+#ifdef TEST_PERF
+ // Collect perf data for memset
+ clock_gettime(CLOCK_REALTIME, &tv[0]);
+ for (int r = 0; r < NREPS; r++) {
+ for (int i = 0; i < 67; i++) {
+ if (!__arm_sc_memset(dst, src[i], i)) {
+ fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memset!\n");
+ abort();
+ }
+ }
+ }
+ reinit_dst(67);
+ clock_gettime(CLOCK_REALTIME, &tv[1]);
+ printf("memset time = %ld\n", get_time_diff(tv));
+#endif
+
+ // Test correctness of memchr
+ for (int i = 0; i < 67; i++) {
+ for (int j = 0; j < 67; j++) {
+ uint8_t *t[2];
+ t[0] = __arm_sc_memchr(src, src[j], i);
+ t[1] = memchr(src, src[j], i);
+ if (t[0] != t[1]) {
+ fprintf(stderr, "__arm_sc_memchr doesn't match memchr behaviour!\n");
+ abort();
+ }
+ }
+ }
+
+#ifdef TEST_PERF
+ // Collect perf data for memchr
+ clock_gettime(CLOCK_REALTIME, &tv[0]);
+ for (int r = 0; r < NREPS; r++) {
+ for (int i = 0; i < 67; i++) {
+ for (int j = 0; j < 67; j++) {
+ __arm_sc_memchr(src, src[j], i);
+ }
+ }
+ }
+ clock_gettime(CLOCK_REALTIME, &tv[1]);
+ printf("memchr time = %ld\n", get_time_diff(tv));
+#endif
+
+ // Test correctness for memmove
+ for (int i = 0; i < 67; i++) {
+ for (int j = 0; j < 67; j++) {
+ int t[2];
+ if (!__arm_sc_memmove(&dst[66 - j], &dst[j], i)) {
+ fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memmove!\n");
+ abort();
+ }
+ t[0] = sum(dst, N);
+ reinit_dst(200);
+ memmove(&dst[66 - j], &dst[j], i);
+ t[1] = sum(dst, N);
+ reinit_dst(200);
+ if (t[0] != t[1]) {
+ fprintf(stderr, "__arm_sc_memmove doesn't match memmove behaviour!\n");
+ abort();
+ }
+ }
+ }
+
+#ifdef TEST_PERF
+ // Collect perf data for memmove
+ clock_gettime(CLOCK_REALTIME, &tv[0]);
+ for (int r = 0; r < NREPS; r++) {
+ for (int i = 0; i < 67; i++) {
+ for (int j = 0; j < 67; j++) {
+ __arm_sc_memmove(&dst[66 - j], &dst[j], i);
+ }
+ }
+ }
+ clock_gettime(CLOCK_REALTIME, &tv[1]);
+ printf("memmove time = %ld\n", get_time_diff(tv));
+#endif
+
+ return 0;
+}
>From 7e2df5bdaf7517730c7023273dc86ec5b099fa04 Mon Sep 17 00:00:00 2001
From: Dinar Temirbulatov <Dinar.Temirbulatov at arm.com>
Date: Fri, 12 Jan 2024 08:49:11 +0000
Subject: [PATCH 2/2] Addressed comments.
---
.../lib/builtins/aarch64/sme-libc-routines.c | 22 ++--
.../test/builtins/Unit/sme-string-test.c | 101 ++----------------
compiler-rt/test/lit.common.cfg.py | 3 +
compiler-rt/test/lit.common.configured.in | 1 +
.../unittests/lit.common.unit.configured.in | 1 +
5 files changed, 22 insertions(+), 106 deletions(-)
diff --git a/compiler-rt/lib/builtins/aarch64/sme-libc-routines.c b/compiler-rt/lib/builtins/aarch64/sme-libc-routines.c
index c846daa51cc91f..0e26a3ab030c85 100644
--- a/compiler-rt/lib/builtins/aarch64/sme-libc-routines.c
+++ b/compiler-rt/lib/builtins/aarch64/sme-libc-routines.c
@@ -4,9 +4,8 @@
// use the compiler flag "-mllvm -disable-loop-idiom-all" to prevent clang
// from recognising a loop idiom and planting calls to memcpy!
-static void *
-__arm_sc_memcpy_fwd(void *dest, const void *src,
- size_t n) __arm_streaming_compatible __arm_preserves_za {
+static void *__arm_sc_memcpy_fwd(void *dest, const void *src,
+ size_t n) __arm_streaming_compatible {
unsigned char *destp = (unsigned char *)dest;
const unsigned char *srcp = (const unsigned char *)src;
@@ -21,12 +20,11 @@ __arm_sc_memcpy_fwd(void *dest, const void *src,
// restrict keywords here. This also matches the definition of the libc memcpy
// according to the man page.
void *__arm_sc_memcpy(void *__restrict__ dest, const void *__restrict__ src,
- size_t n) __arm_streaming_compatible __arm_preserves_za {
+ size_t n) __arm_streaming_compatible {
return __arm_sc_memcpy_fwd(dest, src, n);
}
-void *__arm_sc_memset(void *dest, int c,
- size_t n) __arm_streaming_compatible __arm_preserves_za {
+void *__arm_sc_memset(void *dest, int c, size_t n) __arm_streaming_compatible {
unsigned char *destp = (unsigned char *)dest;
unsigned char c8 = (unsigned char)c;
@@ -37,9 +35,8 @@ void *__arm_sc_memset(void *dest, int c,
return dest;
}
-static void *
-__arm_sc_memcpy_rev(void *dest, const void *src,
- size_t n) __arm_streaming_compatible __arm_preserves_za {
+static void *__arm_sc_memcpy_rev(void *dest, const void *src,
+ size_t n) __arm_streaming_compatible {
unsigned char *destp = (unsigned char *)dest;
const unsigned char *srcp = (const unsigned char *)src;
@@ -57,7 +54,7 @@ __arm_sc_memcpy_rev(void *dest, const void *src,
// overlap with src or dest.
// 2. Copy the contents of the temporary array into dest.
void *__arm_sc_memmove(void *dest, const void *src,
- size_t n) __arm_streaming_compatible __arm_preserves_za {
+ size_t n) __arm_streaming_compatible {
unsigned char *destp = (unsigned char *)dest;
const unsigned char *srcp = (const unsigned char *)src;
@@ -87,9 +84,8 @@ void *__arm_sc_memmove(void *dest, const void *src,
return __arm_sc_memcpy_rev(dest, src, n);
}
-const void *
-__arm_sc_memchr(const void *src, int c,
- size_t n) __arm_streaming_compatible __arm_preserves_za {
+const void *__arm_sc_memchr(const void *src, int c,
+ size_t n) __arm_streaming_compatible {
const unsigned char *srcp = (const unsigned char *)src;
unsigned char c8 = (unsigned char)c;
diff --git a/compiler-rt/test/builtins/Unit/sme-string-test.c b/compiler-rt/test/builtins/Unit/sme-string-test.c
index 0b066c3c179c95..51c1ad9ed02a7c 100644
--- a/compiler-rt/test/builtins/Unit/sme-string-test.c
+++ b/compiler-rt/test/builtins/Unit/sme-string-test.c
@@ -1,14 +1,11 @@
-// REQUIRES: linux, aarch64-target-arch
+// REQUIRES: linux, aarch64-target-arch, sme-available
// RUN: %clang_builtins %s %librt -o %t && %run %t
#include <stdint.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <time.h>
#define N 1024
-#define NREPS 1234
static uint8_t dst[N], src[N];
@@ -38,146 +35,64 @@ int sum(uint8_t *dest, int n) {
return t;
}
-long get_time_diff(struct timespec tv[2]) {
- long us0 = (tv[0].tv_sec * 1000000) + (tv[0].tv_nsec / 1000);
- long us1 = (tv[1].tv_sec * 1000000) + (tv[1].tv_nsec / 1000);
- return us1 - us0;
-}
-
int main() {
- struct timespec tv[2];
init();
// Test correctness of memcpy
for (int i = 0; i < 67; i++) {
int t[2];
- if (!__arm_sc_memcpy(dst, src, i)) {
- fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memcpy!\n");
+ if (!__arm_sc_memcpy(dst, src, i))
abort();
- }
t[0] = sum(dst, N);
reinit_dst(i);
memcpy(dst, src, i);
t[1] = sum(dst, N);
reinit_dst(i);
- if (t[0] != t[1]) {
- fprintf(stderr, "__arm_sc_memcpy doesn't match memcpy behaviour!\n");
+ if (t[0] != t[1])
abort();
- }
}
-#ifdef TEST_PERF
- // Collect perf data for memcpy
- clock_gettime(CLOCK_REALTIME, &tv[0]);
- for (int r = 0; r < NREPS; r++) {
- for (int i = 0; i < 67; i++) {
- int t[2];
- if (!__arm_sc_memcpy(dst, src, i)) {
- fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memcpy!\n");
- abort();
- }
- }
- }
- reinit_dst(67);
- clock_gettime(CLOCK_REALTIME, &tv[1]);
- printf("memcpy time = %ld\n", get_time_diff(tv));
-#endif
-
// Test correctness of memset
for (int i = 0; i < 67; i++) {
int t[2];
- if (!__arm_sc_memset(dst, src[i], i)) {
- fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memset!\n");
+ if (!__arm_sc_memset(dst, src[i], i))
abort();
- }
t[0] = sum(dst, N);
reinit_dst(i);
memset(dst, src[i], i);
t[1] = sum(dst, N);
reinit_dst(i);
- if (t[0] != t[1]) {
- fprintf(stderr, "__arm_sc_memcpy doesn't match memset behaviour!\n");
+ if (t[0] != t[1])
abort();
- }
}
-#ifdef TEST_PERF
- // Collect perf data for memset
- clock_gettime(CLOCK_REALTIME, &tv[0]);
- for (int r = 0; r < NREPS; r++) {
- for (int i = 0; i < 67; i++) {
- if (!__arm_sc_memset(dst, src[i], i)) {
- fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memset!\n");
- abort();
- }
- }
- }
- reinit_dst(67);
- clock_gettime(CLOCK_REALTIME, &tv[1]);
- printf("memset time = %ld\n", get_time_diff(tv));
-#endif
-
// Test correctness of memchr
for (int i = 0; i < 67; i++) {
for (int j = 0; j < 67; j++) {
uint8_t *t[2];
t[0] = __arm_sc_memchr(src, src[j], i);
t[1] = memchr(src, src[j], i);
- if (t[0] != t[1]) {
- fprintf(stderr, "__arm_sc_memchr doesn't match memchr behaviour!\n");
+ if (t[0] != t[1])
abort();
- }
- }
- }
-
-#ifdef TEST_PERF
- // Collect perf data for memchr
- clock_gettime(CLOCK_REALTIME, &tv[0]);
- for (int r = 0; r < NREPS; r++) {
- for (int i = 0; i < 67; i++) {
- for (int j = 0; j < 67; j++) {
- __arm_sc_memchr(src, src[j], i);
- }
}
}
- clock_gettime(CLOCK_REALTIME, &tv[1]);
- printf("memchr time = %ld\n", get_time_diff(tv));
-#endif
// Test correctness for memmove
for (int i = 0; i < 67; i++) {
for (int j = 0; j < 67; j++) {
int t[2];
- if (!__arm_sc_memmove(&dst[66 - j], &dst[j], i)) {
- fprintf(stderr, "Unexpected NULL pointer from __arm_sc_memmove!\n");
+ if (!__arm_sc_memmove(&dst[66 - j], &dst[j], i))
abort();
- }
t[0] = sum(dst, N);
reinit_dst(200);
memmove(&dst[66 - j], &dst[j], i);
t[1] = sum(dst, N);
reinit_dst(200);
- if (t[0] != t[1]) {
- fprintf(stderr, "__arm_sc_memmove doesn't match memmove behaviour!\n");
+ if (t[0] != t[1])
abort();
- }
- }
- }
-
-#ifdef TEST_PERF
- // Collect perf data for memmove
- clock_gettime(CLOCK_REALTIME, &tv[0]);
- for (int r = 0; r < NREPS; r++) {
- for (int i = 0; i < 67; i++) {
- for (int j = 0; j < 67; j++) {
- __arm_sc_memmove(&dst[66 - j], &dst[j], i);
- }
}
}
- clock_gettime(CLOCK_REALTIME, &tv[1]);
- printf("memmove time = %ld\n", get_time_diff(tv));
-#endif
return 0;
}
diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py
index 1753a55508c7cf..d4960b3aabc2cc 100644
--- a/compiler-rt/test/lit.common.cfg.py
+++ b/compiler-rt/test/lit.common.cfg.py
@@ -454,6 +454,9 @@ def get_ios_commands_dir():
if config.has_lld:
config.available_features.add("lld-available")
+if config.sme:
+ config.available_features.add("sme-available")
+
if config.use_lld:
config.available_features.add("lld")
diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in
index 7c2d53520099a1..8e5de4eb5b081d 100644
--- a/compiler-rt/test/lit.common.configured.in
+++ b/compiler-rt/test/lit.common.configured.in
@@ -50,6 +50,7 @@ set_default("gwp_asan", @COMPILER_RT_HAS_GWP_ASAN_PYBOOL@)
set_default("expensive_checks", @LLVM_ENABLE_EXPENSIVE_CHECKS_PYBOOL@)
set_default("test_standalone_build_libs", @COMPILER_RT_TEST_STANDALONE_BUILD_LIBS_PYBOOL@)
set_default("has_compiler_rt_libatomic", @COMPILER_RT_BUILD_STANDALONE_LIBATOMIC_PYBOOL@)
+set_default("sme", @COMPILER_RT_HAS_ASM_SME@)
# True iff the test suite supports ignoring the test compiler's runtime library path
# and using `config.compiler_rt_libdir` instead. This only matters when the runtime
# library paths differ.
diff --git a/compiler-rt/unittests/lit.common.unit.configured.in b/compiler-rt/unittests/lit.common.unit.configured.in
index 3e42e83c9e70a2..b2681724628478 100644
--- a/compiler-rt/unittests/lit.common.unit.configured.in
+++ b/compiler-rt/unittests/lit.common.unit.configured.in
@@ -7,6 +7,7 @@ config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@")
config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@"
config.compiler_rt_libdir = lit_config.substitute("@COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR@")
+config.sme = "@COMPILER_RT_HAS_ASM_SME@"
config.enable_per_target_runtime_dir = @LLVM_ENABLE_PER_TARGET_RUNTIME_DIR_PYBOOL@
config.llvm_build_mode = lit_config.substitute("@LLVM_BUILD_MODE@")
config.host_arch = "@HOST_ARCH@"
More information about the llvm-commits
mailing list