| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,344 @@ | ||
| // 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 | ||
|
|
||
| // Routines taken from libc/AOR_v20.02/string/aarch64 | ||
|
|
||
| #include "../assembly.h" | ||
|
|
||
| #ifdef __aarch64__ | ||
|
|
||
| #define L(l) .L ## l | ||
|
|
||
| // | ||
| // __arm_sc_memcpy / __arm_sc_memmove | ||
| // | ||
|
|
||
| #define dstin x0 | ||
| #define src x1 | ||
| #define count x2 | ||
| #define dst x3 | ||
| #define srcend1 x4 | ||
| #define dstend1 x5 | ||
| #define A_l x6 | ||
| #define A_lw w6 | ||
| #define A_h x7 | ||
| #define B_l x8 | ||
| #define B_lw w8 | ||
| #define B_h x9 | ||
| #define C_l x10 | ||
| #define C_lw w10 | ||
| #define C_h x11 | ||
| #define D_l x12 | ||
| #define D_h x13 | ||
| #define E_l x14 | ||
| #define E_h x15 | ||
| #define F_l x16 | ||
| #define F_h x17 | ||
| #define G_l count | ||
| #define G_h dst | ||
| #define H_l src | ||
| #define H_h srcend1 | ||
| #define tmp1 x14 | ||
|
|
||
| /* This implementation handles overlaps and supports both memcpy and memmove | ||
| from a single entry point. It uses unaligned accesses and branchless | ||
| sequences to keep the code small, simple and improve performance. | ||
| Copies are split into 3 main cases: small copies of up to 32 bytes, medium | ||
| copies of up to 128 bytes, and large copies. The overhead of the overlap | ||
| check is negligible since it is only required for large copies. | ||
| Large copies use a software pipelined loop processing 64 bytes per iteration. | ||
| The destination pointer is 16-byte aligned to minimize unaligned accesses. | ||
| The loop tail is handled by always copying 64 bytes from the end. | ||
| */ | ||
|
|
||
| DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sc_memcpy) | ||
| add srcend1, src, count | ||
| add dstend1, dstin, count | ||
| cmp count, 128 | ||
| b.hi L(copy_long) | ||
| cmp count, 32 | ||
| b.hi L(copy32_128) | ||
|
|
||
| /* Small copies: 0..32 bytes. */ | ||
| cmp count, 16 | ||
| b.lo L(copy16) | ||
| ldp A_l, A_h, [src] | ||
| ldp D_l, D_h, [srcend1, -16] | ||
| stp A_l, A_h, [dstin] | ||
| stp D_l, D_h, [dstend1, -16] | ||
| ret | ||
|
|
||
| /* Copy 8-15 bytes. */ | ||
| L(copy16): | ||
| tbz count, 3, L(copy8) | ||
| ldr A_l, [src] | ||
| ldr A_h, [srcend1, -8] | ||
| str A_l, [dstin] | ||
| str A_h, [dstend1, -8] | ||
| ret | ||
|
|
||
| .p2align 3 | ||
| /* Copy 4-7 bytes. */ | ||
| L(copy8): | ||
| tbz count, 2, L(copy4) | ||
| ldr A_lw, [src] | ||
| ldr B_lw, [srcend1, -4] | ||
| str A_lw, [dstin] | ||
| str B_lw, [dstend1, -4] | ||
| ret | ||
|
|
||
| /* Copy 0..3 bytes using a branchless sequence. */ | ||
| L(copy4): | ||
| cbz count, L(copy0) | ||
| lsr tmp1, count, 1 | ||
| ldrb A_lw, [src] | ||
| ldrb C_lw, [srcend1, -1] | ||
| ldrb B_lw, [src, tmp1] | ||
| strb A_lw, [dstin] | ||
| strb B_lw, [dstin, tmp1] | ||
| strb C_lw, [dstend1, -1] | ||
| L(copy0): | ||
| ret | ||
|
|
||
| .p2align 4 | ||
| /* Medium copies: 33..128 bytes. */ | ||
| L(copy32_128): | ||
| ldp A_l, A_h, [src] | ||
| ldp B_l, B_h, [src, 16] | ||
| ldp C_l, C_h, [srcend1, -32] | ||
| ldp D_l, D_h, [srcend1, -16] | ||
| cmp count, 64 | ||
| b.hi L(copy128) | ||
| stp A_l, A_h, [dstin] | ||
| stp B_l, B_h, [dstin, 16] | ||
| stp C_l, C_h, [dstend1, -32] | ||
| stp D_l, D_h, [dstend1, -16] | ||
| ret | ||
|
|
||
| .p2align 4 | ||
| /* Copy 65..128 bytes. */ | ||
| L(copy128): | ||
| ldp E_l, E_h, [src, 32] | ||
| ldp F_l, F_h, [src, 48] | ||
| cmp count, 96 | ||
| b.ls L(copy96) | ||
| ldp G_l, G_h, [srcend1, -64] | ||
| ldp H_l, H_h, [srcend1, -48] | ||
| stp G_l, G_h, [dstend1, -64] | ||
| stp H_l, H_h, [dstend1, -48] | ||
| L(copy96): | ||
| stp A_l, A_h, [dstin] | ||
| stp B_l, B_h, [dstin, 16] | ||
| stp E_l, E_h, [dstin, 32] | ||
| stp F_l, F_h, [dstin, 48] | ||
| stp C_l, C_h, [dstend1, -32] | ||
| stp D_l, D_h, [dstend1, -16] | ||
| ret | ||
|
|
||
| .p2align 4 | ||
| /* Copy more than 128 bytes. */ | ||
| L(copy_long): | ||
| /* Use backwards copy if there is an overlap. */ | ||
| sub tmp1, dstin, src | ||
| cbz tmp1, L(copy0) | ||
| cmp tmp1, count | ||
| b.lo L(copy_long_backwards) | ||
|
|
||
| /* Copy 16 bytes and then align dst to 16-byte alignment. */ | ||
|
|
||
| ldp D_l, D_h, [src] | ||
| and tmp1, dstin, 15 | ||
| bic dst, dstin, 15 | ||
| sub src, src, tmp1 | ||
| add count, count, tmp1 /* Count is now 16 too large. */ | ||
| ldp A_l, A_h, [src, 16] | ||
| stp D_l, D_h, [dstin] | ||
| ldp B_l, B_h, [src, 32] | ||
| ldp C_l, C_h, [src, 48] | ||
| ldp D_l, D_h, [src, 64]! | ||
| subs count, count, 128 + 16 /* Test and readjust count. */ | ||
| b.ls L(copy64_from_end) | ||
| L(loop64): | ||
| stp A_l, A_h, [dst, 16] | ||
| ldp A_l, A_h, [src, 16] | ||
| stp B_l, B_h, [dst, 32] | ||
| ldp B_l, B_h, [src, 32] | ||
| stp C_l, C_h, [dst, 48] | ||
| ldp C_l, C_h, [src, 48] | ||
| stp D_l, D_h, [dst, 64]! | ||
| ldp D_l, D_h, [src, 64]! | ||
| subs count, count, 64 | ||
| b.hi L(loop64) | ||
|
|
||
| /* Write the last iteration and copy 64 bytes from the end. */ | ||
| L(copy64_from_end): | ||
| ldp E_l, E_h, [srcend1, -64] | ||
| stp A_l, A_h, [dst, 16] | ||
| ldp A_l, A_h, [srcend1, -48] | ||
| stp B_l, B_h, [dst, 32] | ||
| ldp B_l, B_h, [srcend1, -32] | ||
| stp C_l, C_h, [dst, 48] | ||
| ldp C_l, C_h, [srcend1, -16] | ||
| stp D_l, D_h, [dst, 64] | ||
| stp E_l, E_h, [dstend1, -64] | ||
| stp A_l, A_h, [dstend1, -48] | ||
| stp B_l, B_h, [dstend1, -32] | ||
| stp C_l, C_h, [dstend1, -16] | ||
| ret | ||
|
|
||
| .p2align 4 | ||
|
|
||
| /* Large backwards copy for overlapping copies. | ||
| Copy 16 bytes and then align dst to 16-byte alignment. */ | ||
| L(copy_long_backwards): | ||
| ldp D_l, D_h, [srcend1, -16] | ||
| and tmp1, dstend1, 15 | ||
| sub srcend1, srcend1, tmp1 | ||
| sub count, count, tmp1 | ||
| ldp A_l, A_h, [srcend1, -16] | ||
| stp D_l, D_h, [dstend1, -16] | ||
| ldp B_l, B_h, [srcend1, -32] | ||
| ldp C_l, C_h, [srcend1, -48] | ||
| ldp D_l, D_h, [srcend1, -64]! | ||
| sub dstend1, dstend1, tmp1 | ||
| subs count, count, 128 | ||
| b.ls L(copy64_from_start) | ||
|
|
||
| L(loop64_backwards): | ||
| stp A_l, A_h, [dstend1, -16] | ||
| ldp A_l, A_h, [srcend1, -16] | ||
| stp B_l, B_h, [dstend1, -32] | ||
| ldp B_l, B_h, [srcend1, -32] | ||
| stp C_l, C_h, [dstend1, -48] | ||
| ldp C_l, C_h, [srcend1, -48] | ||
| stp D_l, D_h, [dstend1, -64]! | ||
| ldp D_l, D_h, [srcend1, -64]! | ||
| subs count, count, 64 | ||
| b.hi L(loop64_backwards) | ||
|
|
||
| /* Write the last iteration and copy 64 bytes from the start. */ | ||
| L(copy64_from_start): | ||
| ldp G_l, G_h, [src, 48] | ||
| stp A_l, A_h, [dstend1, -16] | ||
| ldp A_l, A_h, [src, 32] | ||
| stp B_l, B_h, [dstend1, -32] | ||
| ldp B_l, B_h, [src, 16] | ||
| stp C_l, C_h, [dstend1, -48] | ||
| ldp C_l, C_h, [src] | ||
| stp D_l, D_h, [dstend1, -64] | ||
| stp G_l, G_h, [dstin, 48] | ||
| stp A_l, A_h, [dstin, 32] | ||
| stp B_l, B_h, [dstin, 16] | ||
| stp C_l, C_h, [dstin] | ||
| ret | ||
| END_COMPILERRT_OUTLINE_FUNCTION(__arm_sc_memcpy) | ||
|
|
||
| DEFINE_COMPILERRT_FUNCTION_ALIAS(__arm_sc_memmove, __arm_sc_memcpy) | ||
|
|
||
|
|
||
| // | ||
| // __arm_sc_memset | ||
| // | ||
|
|
||
| #define dstin x0 | ||
| #define val x1 | ||
| #define valw w1 | ||
| #define count x2 | ||
| #define dst x3 | ||
| #define dstend2 x4 | ||
| #define zva_val x5 | ||
|
|
||
| DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sc_memset) | ||
| dup v0.16B, valw | ||
| add dstend2, dstin, count | ||
|
|
||
| cmp count, 96 | ||
| b.hi L(set_long) | ||
| cmp count, 16 | ||
| b.hs L(set_medium) | ||
| mov val, v0.D[0] | ||
|
|
||
| /* Set 0..15 bytes. */ | ||
| tbz count, 3, 1f | ||
| str val, [dstin] | ||
| str val, [dstend2, -8] | ||
| ret | ||
| nop | ||
| 1: tbz count, 2, 2f | ||
| str valw, [dstin] | ||
| str valw, [dstend2, -4] | ||
| ret | ||
| 2: cbz count, 3f | ||
| strb valw, [dstin] | ||
| tbz count, 1, 3f | ||
| strh valw, [dstend2, -2] | ||
| 3: ret | ||
|
|
||
| /* Set 17..96 bytes. */ | ||
| L(set_medium): | ||
| str q0, [dstin] | ||
| tbnz count, 6, L(set96) | ||
| str q0, [dstend2, -16] | ||
| tbz count, 5, 1f | ||
| str q0, [dstin, 16] | ||
| str q0, [dstend2, -32] | ||
| 1: ret | ||
|
|
||
| .p2align 4 | ||
| /* Set 64..96 bytes. Write 64 bytes from the start and | ||
| 32 bytes from the end. */ | ||
| L(set96): | ||
| str q0, [dstin, 16] | ||
| stp q0, q0, [dstin, 32] | ||
| stp q0, q0, [dstend2, -32] | ||
| ret | ||
|
|
||
| .p2align 4 | ||
| L(set_long): | ||
| and valw, valw, 255 | ||
| bic dst, dstin, 15 | ||
| str q0, [dstin] | ||
| cmp count, 160 | ||
| ccmp valw, 0, 0, hs | ||
| b.ne L(no_zva) | ||
|
|
||
| #ifndef SKIP_ZVA_CHECK | ||
| mrs zva_val, dczid_el0 | ||
| and zva_val, zva_val, 31 | ||
| cmp zva_val, 4 /* ZVA size is 64 bytes. */ | ||
| b.ne L(no_zva) | ||
| #endif | ||
| str q0, [dst, 16] | ||
| stp q0, q0, [dst, 32] | ||
| bic dst, dst, 63 | ||
| sub count, dstend2, dst /* Count is now 64 too large. */ | ||
| sub count, count, 128 /* Adjust count and bias for loop. */ | ||
|
|
||
| .p2align 4 | ||
| L(zva_loop): | ||
| add dst, dst, 64 | ||
| dc zva, dst | ||
| subs count, count, 64 | ||
| b.hi L(zva_loop) | ||
| stp q0, q0, [dstend2, -64] | ||
| stp q0, q0, [dstend2, -32] | ||
| ret | ||
|
|
||
| L(no_zva): | ||
| sub count, dstend2, dst /* Count is 16 too large. */ | ||
| sub dst, dst, 16 /* Dst is biased by -32. */ | ||
| sub count, count, 64 + 16 /* Adjust count and bias for loop. */ | ||
| L(no_zva_loop): | ||
| stp q0, q0, [dst, 32] | ||
| stp q0, q0, [dst, 64]! | ||
| subs count, count, 64 | ||
| b.hi L(no_zva_loop) | ||
| stp q0, q0, [dstend2, -64] | ||
| stp q0, q0, [dstend2, -32] | ||
| ret | ||
| END_COMPILERRT_OUTLINE_FUNCTION(__arm_sc_memset) | ||
|
|
||
| #endif // __aarch64__ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,298 @@ | ||
| //=== feature_bits.c - Update RISC-V Feature Bits Structure -*- 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #define RISCV_FEATURE_BITS_LENGTH 1 | ||
| struct { | ||
| unsigned length; | ||
| unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; | ||
| } __riscv_feature_bits __attribute__((visibility("hidden"), nocommon)); | ||
|
|
||
| #define RISCV_VENDOR_FEATURE_BITS_LENGTH 1 | ||
| struct { | ||
| unsigned vendorID; | ||
| unsigned length; | ||
| unsigned long long features[RISCV_VENDOR_FEATURE_BITS_LENGTH]; | ||
| } __riscv_vendor_feature_bits __attribute__((visibility("hidden"), nocommon)); | ||
|
|
||
| // NOTE: Should sync-up with RISCVFeatures.td | ||
| // TODO: Maybe generate a header from tablegen then include it. | ||
| #define A_GROUPID 0 | ||
| #define A_BITMASK (1ULL << 0) | ||
| #define C_GROUPID 0 | ||
| #define C_BITMASK (1ULL << 2) | ||
| #define D_GROUPID 0 | ||
| #define D_BITMASK (1ULL << 3) | ||
| #define F_GROUPID 0 | ||
| #define F_BITMASK (1ULL << 5) | ||
| #define I_GROUPID 0 | ||
| #define I_BITMASK (1ULL << 8) | ||
| #define M_GROUPID 0 | ||
| #define M_BITMASK (1ULL << 12) | ||
| #define V_GROUPID 0 | ||
| #define V_BITMASK (1ULL << 21) | ||
| #define ZACAS_GROUPID 0 | ||
| #define ZACAS_BITMASK (1ULL << 26) | ||
| #define ZBA_GROUPID 0 | ||
| #define ZBA_BITMASK (1ULL << 27) | ||
| #define ZBB_GROUPID 0 | ||
| #define ZBB_BITMASK (1ULL << 28) | ||
| #define ZBC_GROUPID 0 | ||
| #define ZBC_BITMASK (1ULL << 29) | ||
| #define ZBKB_GROUPID 0 | ||
| #define ZBKB_BITMASK (1ULL << 30) | ||
| #define ZBKC_GROUPID 0 | ||
| #define ZBKC_BITMASK (1ULL << 31) | ||
| #define ZBKX_GROUPID 0 | ||
| #define ZBKX_BITMASK (1ULL << 32) | ||
| #define ZBS_GROUPID 0 | ||
| #define ZBS_BITMASK (1ULL << 33) | ||
| #define ZFA_GROUPID 0 | ||
| #define ZFA_BITMASK (1ULL << 34) | ||
| #define ZFH_GROUPID 0 | ||
| #define ZFH_BITMASK (1ULL << 35) | ||
| #define ZFHMIN_GROUPID 0 | ||
| #define ZFHMIN_BITMASK (1ULL << 36) | ||
| #define ZICBOZ_GROUPID 0 | ||
| #define ZICBOZ_BITMASK (1ULL << 37) | ||
| #define ZICOND_GROUPID 0 | ||
| #define ZICOND_BITMASK (1ULL << 38) | ||
| #define ZIHINTNTL_GROUPID 0 | ||
| #define ZIHINTNTL_BITMASK (1ULL << 39) | ||
| #define ZIHINTPAUSE_GROUPID 0 | ||
| #define ZIHINTPAUSE_BITMASK (1ULL << 40) | ||
| #define ZKND_GROUPID 0 | ||
| #define ZKND_BITMASK (1ULL << 41) | ||
| #define ZKNE_GROUPID 0 | ||
| #define ZKNE_BITMASK (1ULL << 42) | ||
| #define ZKNH_GROUPID 0 | ||
| #define ZKNH_BITMASK (1ULL << 43) | ||
| #define ZKSED_GROUPID 0 | ||
| #define ZKSED_BITMASK (1ULL << 44) | ||
| #define ZKSH_GROUPID 0 | ||
| #define ZKSH_BITMASK (1ULL << 45) | ||
| #define ZKT_GROUPID 0 | ||
| #define ZKT_BITMASK (1ULL << 46) | ||
| #define ZTSO_GROUPID 0 | ||
| #define ZTSO_BITMASK (1ULL << 47) | ||
| #define ZVBB_GROUPID 0 | ||
| #define ZVBB_BITMASK (1ULL << 48) | ||
| #define ZVBC_GROUPID 0 | ||
| #define ZVBC_BITMASK (1ULL << 49) | ||
| #define ZVFH_GROUPID 0 | ||
| #define ZVFH_BITMASK (1ULL << 50) | ||
| #define ZVFHMIN_GROUPID 0 | ||
| #define ZVFHMIN_BITMASK (1ULL << 51) | ||
| #define ZVKB_GROUPID 0 | ||
| #define ZVKB_BITMASK (1ULL << 52) | ||
| #define ZVKG_GROUPID 0 | ||
| #define ZVKG_BITMASK (1ULL << 53) | ||
| #define ZVKNED_GROUPID 0 | ||
| #define ZVKNED_BITMASK (1ULL << 54) | ||
| #define ZVKNHA_GROUPID 0 | ||
| #define ZVKNHA_BITMASK (1ULL << 55) | ||
| #define ZVKNHB_GROUPID 0 | ||
| #define ZVKNHB_BITMASK (1ULL << 56) | ||
| #define ZVKSED_GROUPID 0 | ||
| #define ZVKSED_BITMASK (1ULL << 57) | ||
| #define ZVKSH_GROUPID 0 | ||
| #define ZVKSH_BITMASK (1ULL << 58) | ||
| #define ZVKT_GROUPID 0 | ||
| #define ZVKT_BITMASK (1ULL << 59) | ||
|
|
||
| #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; | ||
| } | ||
|
|
||
| #define RISCV_HWPROBE_KEY_MVENDORID 0 | ||
| #define RISCV_HWPROBE_KEY_MARCHID 1 | ||
| #define RISCV_HWPROBE_KEY_MIMPID 2 | ||
| #define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 | ||
| #define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1ULL << 0) | ||
| #define RISCV_HWPROBE_KEY_IMA_EXT_0 4 | ||
| #define RISCV_HWPROBE_IMA_FD (1ULL << 0) | ||
| #define RISCV_HWPROBE_IMA_C (1ULL << 1) | ||
| #define RISCV_HWPROBE_IMA_V (1ULL << 2) | ||
| #define RISCV_HWPROBE_EXT_ZBA (1ULL << 3) | ||
| #define RISCV_HWPROBE_EXT_ZBB (1ULL << 4) | ||
| #define RISCV_HWPROBE_EXT_ZBS (1ULL << 5) | ||
| #define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6) | ||
| #define RISCV_HWPROBE_EXT_ZBC (1ULL << 7) | ||
| #define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8) | ||
| #define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9) | ||
| #define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10) | ||
| #define RISCV_HWPROBE_EXT_ZKND (1ULL << 11) | ||
| #define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12) | ||
| #define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13) | ||
| #define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14) | ||
| #define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15) | ||
| #define RISCV_HWPROBE_EXT_ZKT (1ULL << 16) | ||
| #define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17) | ||
| #define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18) | ||
| #define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19) | ||
| #define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20) | ||
| #define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21) | ||
| #define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22) | ||
| #define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23) | ||
| #define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24) | ||
| #define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25) | ||
| #define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26) | ||
| #define RISCV_HWPROBE_EXT_ZFH (1ULL << 27) | ||
| #define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28) | ||
| #define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29) | ||
| #define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30) | ||
| #define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) | ||
| #define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) | ||
| #define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) | ||
| #define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) | ||
| #define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) | ||
| #define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36) | ||
| #define RISCV_HWPROBE_KEY_CPUPERF_0 5 | ||
| #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) | ||
| #define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0) | ||
| #define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0) | ||
| #define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) | ||
| #define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) | ||
| #define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) | ||
| #define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 | ||
| /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ | ||
|
|
||
| struct riscv_hwprobe { | ||
| long long key; | ||
| unsigned long long value; | ||
| }; | ||
|
|
||
| #define __NR_riscv_hwprobe 258 | ||
| static long initHwProbe(struct riscv_hwprobe *Hwprobes, int len) { | ||
| return syscall_impl_5_args(__NR_riscv_hwprobe, (long)Hwprobes, len, 0, 0, 0); | ||
| } | ||
|
|
||
| #define SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(EXTNAME) \ | ||
| SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_EXT_##EXTNAME, EXTNAME) | ||
|
|
||
| #define SET_SINGLE_IMAEXT_RISCV_FEATURE(HWPROBE_BITMASK, EXT) \ | ||
| SET_SINGLE_RISCV_FEATURE(IMAEXT0Value &HWPROBE_BITMASK, EXT) | ||
|
|
||
| #define SET_SINGLE_RISCV_FEATURE(COND, EXT) \ | ||
| if (COND) { \ | ||
| SET_RISCV_FEATURE(EXT); \ | ||
| } | ||
|
|
||
| #define SET_RISCV_FEATURE(EXT) features[EXT##_GROUPID] |= EXT##_BITMASK | ||
|
|
||
| static void initRISCVFeature(struct riscv_hwprobe Hwprobes[]) { | ||
|
|
||
| // Note: If a hwprobe key is unknown to the kernel, its key field | ||
| // will be cleared to -1, and its value set to 0. | ||
| // This unsets all extension bitmask bits. | ||
|
|
||
| // Init vendor extension | ||
| __riscv_vendor_feature_bits.length = 0; | ||
| __riscv_vendor_feature_bits.vendorID = Hwprobes[2].value; | ||
|
|
||
| // Init standard extension | ||
| // TODO: Maybe Extension implied generate from tablegen? | ||
| __riscv_feature_bits.length = RISCV_FEATURE_BITS_LENGTH; | ||
|
|
||
| unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; | ||
| int i; | ||
|
|
||
| for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++) | ||
| features[i] = 0; | ||
|
|
||
| // Check RISCV_HWPROBE_KEY_BASE_BEHAVIOR | ||
| unsigned long long BaseValue = Hwprobes[0].value; | ||
| if (BaseValue & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) { | ||
| SET_RISCV_FEATURE(I); | ||
| SET_RISCV_FEATURE(M); | ||
| SET_RISCV_FEATURE(A); | ||
| } | ||
|
|
||
| // Check RISCV_HWPROBE_KEY_IMA_EXT_0 | ||
| unsigned long long IMAEXT0Value = Hwprobes[1].value; | ||
| if (IMAEXT0Value & RISCV_HWPROBE_IMA_FD) { | ||
| SET_RISCV_FEATURE(F); | ||
| SET_RISCV_FEATURE(D); | ||
| } | ||
|
|
||
| SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_C, C); | ||
| SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_V, V); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBA); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBB); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBS); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICBOZ); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBC); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKB); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKC); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKX); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKND); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNE); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNH); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSED); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSH); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKT); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBB); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBC); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKB); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKG); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNED); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHA); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHB); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSED); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSH); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKT); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFH); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFHMIN); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTNTL); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTPAUSE); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFH); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFHMIN); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFA); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZTSO); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZACAS); | ||
| SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICOND); | ||
|
|
||
| for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++) | ||
| __riscv_feature_bits.features[i] = features[i]; | ||
| } | ||
|
|
||
| #endif // defined(__linux__) | ||
|
|
||
| static int FeaturesBitCached = 0; | ||
|
|
||
| void __init_riscv_feature_bits() { | ||
|
|
||
| if (FeaturesBitCached) | ||
| return; | ||
|
|
||
| #if defined(__linux__) | ||
| struct riscv_hwprobe Hwprobes[] = { | ||
| {RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, | ||
| {RISCV_HWPROBE_KEY_IMA_EXT_0, 0}, | ||
| {RISCV_HWPROBE_KEY_MVENDORID, 0}, | ||
| }; | ||
| if (initHwProbe(Hwprobes, sizeof(Hwprobes) / sizeof(Hwprobes[0]))) | ||
| return; | ||
|
|
||
| initRISCVFeature(Hwprobes); | ||
| #endif // defined(__linux__) | ||
|
|
||
| FeaturesBitCached = 1; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| ! Test passing polymorphic variable for non-polymorphic dummy arguments: | ||
| ! RUN: bbc -emit-hlfir -o - -I nowhere %s | FileCheck %s | ||
|
|
||
| subroutine test_sequence_association(x) | ||
| type t | ||
| integer :: i | ||
| end type | ||
| interface | ||
| subroutine sequence_assoc(x, n) | ||
| import :: t | ||
| type(t) :: x(n) | ||
| end subroutine | ||
| end interface | ||
| class(t) :: x(:, :) | ||
| call sequence_assoc(x, 100) | ||
| end subroutine | ||
| ! CHECK-LABEL: func.func @_QPtest_sequence_association( | ||
| ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>> | ||
| ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>> | ||
| ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] | ||
| ! CHECK: %[[REBOX:.*]] = fir.rebox %[[VAL_3]]#0 : (!fir.class<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>) -> !fir.box<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>> | ||
| ! CHECK: %[[VAL_5:.*]]:2 = hlfir.copy_in %[[REBOX]] to %[[VAL_1]] : (!fir.box<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>>>) -> (!fir.box<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>, i1) | ||
| ! CHECK: %[[VAL_6:.*]] = fir.box_addr %[[VAL_5]]#0 : (!fir.box<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>) -> !fir.ref<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>> | ||
| ! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (!fir.ref<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>) -> !fir.ref<!fir.array<?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>> | ||
| ! CHECK: fir.call @_QPsequence_assoc(%[[VAL_7]], %{{.*}}) | ||
| ! CHECK: hlfir.copy_out %[[VAL_1]], %[[VAL_5]]#1 to %[[REBOX]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>>>, i1, !fir.box<!fir.array<?x?x!fir.type<_QFtest_sequence_associationTt{i:i32}>>>) -> () |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s | ||
|
|
||
| ! CHECK: not yet implemented: Unsupported atomic type | ||
| subroutine character_atomic | ||
| character :: l, r | ||
| !$omp atomic read | ||
| l = r | ||
| end subroutine |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s | ||
|
|
||
| ! CHECK: not yet implemented: Unsupported atomic type | ||
| subroutine complex_atomic | ||
| complex :: l, r | ||
| !$omp atomic read | ||
| l = r | ||
| end subroutine |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| ! RUN: %flang_fc1 -emit-hlfir -o - -fopenmp %s | FileCheck %s | ||
| ! RUN: bbc -emit-hlfir -o - -fopenmp %s | FileCheck %s | ||
|
|
||
| program lastprivate_allocatable | ||
| integer, allocatable :: a | ||
| integer :: i | ||
| ! a is unallocated here | ||
| !$omp parallel do lastprivate(a) | ||
| do i=1,1 | ||
| a = 42 | ||
| enddo | ||
| !$omp end parallel do | ||
| ! a should be allocated here | ||
| end program | ||
|
|
||
| ! CHECK-LABEL: func.func @_QQmain() | ||
| ! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "a", uniq_name = "_QFEa"} | ||
| ! CHECK: %[[VAL_1:.*]] = fir.zero_bits !fir.heap<i32> | ||
| ! CHECK: %[[VAL_2:.*]] = fir.embox %[[VAL_1]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>> | ||
| ! CHECK: fir.store %[[VAL_2]] to %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<i32>>> | ||
| ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = {{.*}}<allocatable>, uniq_name = "_QFEa"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) | ||
| ! CHECK: omp.parallel { | ||
| ! create original copy of private variable | ||
| ! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = {{.*}}<allocatable>, uniq_name = "_QFEa"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) | ||
| ! CHECK: %[[VAL_17:.*]] = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFEi"} | ||
| ! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) | ||
| ! CHECK: omp.wsloop { | ||
| ! CHECK: omp.loop_nest | ||
| ! [...] | ||
| ! if this is the last iteration | ||
| ! CHECK: fir.if %{{.*}} { | ||
| ! store loop IV | ||
| ! CHECK: fir.store %{{.*}} to %[[VAL_18]]#1 : !fir.ref<i32> | ||
| ! assign private variable to original copy: realloc | ||
| ! CHECK: hlfir.assign %[[VAL_16]]#0 to %[[VAL_3]]#0 realloc : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>> | ||
| ! CHECK-NEXT: } | ||
| ! CHECK-NEXT: omp.yield | ||
| ! CHECK-NEXT: } |