[compiler-rt] [compiler-rt][RISCV] Implement __riscv_ifunc_select (PR #85790)
Piyou Chen via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 15 01:46:54 PDT 2024
================
@@ -0,0 +1,84 @@
+//=== ifunc_select.c - Check environment hardware feature -*- C -*-===========//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__linux__)
+
+static long syscall_impl_5_args(long number, long arg1, long arg2, long arg3,
+ long arg4, long arg5) {
+ register long a7 __asm__("a7") = number;
+ register long a0 __asm__("a0") = arg1;
+ register long a1 __asm__("a1") = arg2;
+ register long a2 __asm__("a2") = arg3;
+ register long a3 __asm__("a3") = arg4;
+ register long a4 __asm__("a4") = arg5;
+ __asm__ __volatile__("ecall\n\t"
+ : "=r"(a0)
+ : "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4)
+ : "memory");
+ return a0;
+}
+
+struct riscv_hwprobe {
+ long long key;
+ unsigned long long value;
+};
+
+/* Size definition for CPU sets. */
+#define __CPU_SETSIZE 1024
+#define __NCPUBITS (8 * sizeof(unsigned long int))
+
+/* Data structure to describe CPU mask. */
+typedef struct {
+ unsigned long int __bits[__CPU_SETSIZE / __NCPUBITS];
+} cpu_set_t;
+
+#define SYS_riscv_hwprobe 258
+static long sys_riscv_hwprobe(struct riscv_hwprobe *pairs, unsigned pair_count,
+ unsigned cpu_count, cpu_set_t *cpus,
+ unsigned int flags) {
+ return syscall_impl_5_args(SYS_riscv_hwprobe, (long)pairs, pair_count,
+ cpu_count, (long)cpus, flags);
+}
+
+static long initHwProbe(struct riscv_hwprobe *Hwprobes, int len) {
+ return sys_riscv_hwprobe(Hwprobes, len, 0, (cpu_set_t *)((void *)0), 0);
+}
+
+#endif // defined(__linux__)
+
+unsigned __riscv_ifunc_select(struct riscv_hwprobe *RequireKeys,
+ unsigned Length) {
+#if defined(__linux__)
+ // Init Hwprobe
+ struct riscv_hwprobe HwprobePairs[Length];
----------------
BeMg wrote:
No. That limit come from hwprobe system call's key. I expect the compiler will transform the feature inside `target_clones` into minimum hwprobe system call pair.
The pair from the arguments of __riscv_ifunc_select could be mapped into a `struct riscv_hwprobe`.
For example:
```
; query for version "arch=rv64im"
// CHECK: @__riscv_hwprobe_args = internal global [2 x %riscv_hwprobe_pair] [%riscv_hwprobe_pair { i64 3, i64 1 }, %riscv_hwprobe_pair { i64 4, i64 0 }]
; query for version "arch=+zbb,+zba,+zbc,+zbkb,+zknd,+zknh,+zksed,+zvksh,+zfh,+zfa,+v"
// CHECK: @__riscv_hwprobe_args.1 = internal global [2 x %riscv_hwprobe_pair.0] [%riscv_hwprobe_pair.0 { i64 3, i64 1 }, %riscv_hwprobe_pair.0 { i64 4, i64 4462766492 }]
// CHECK-LABEL: define weak_odr ptr @foo1.resolver() comdat {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args, i32 2)
...
// CHECK-LABEL: define weak_odr ptr @foo2.resolver() comdat {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @__riscv_hwprobe_args.1, i32 2)
// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
...
```
The "arch=+zbb,+zba,+zbc,+zbkb,+zknd,+zknh,+zksed,+zvksh,+zfh,+zfa,+v" version has more features than the "arch=rv64im" version, but only the pair value is updated during __riscv_ifunc_select invocation.
But we need to increase limit when hwprobe support more key for new feature.
https://github.com/llvm/llvm-project/pull/85790
More information about the llvm-commits
mailing list