[v4,1/4] libatomic: atomic_16.S: Improve ENTRY, END and ALIAS macro interface

Message ID 20240124171853.3112540-2-victor.donascimento@arm.com
State New
Headers
Series Libatomic: Add LSE128 atomics support for AArch64 |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Testing passed

Commit Message

Victor Do Nascimento Jan. 24, 2024, 5:17 p.m. UTC
  The introduction of further architectural-feature dependent ifuncs
for AArch64 makes hard-coding ifunc `_i<n>' suffixes to functions
cumbersome to work with.  It is awkward to remember which ifunc maps
onto which arch feature and makes the code harder to maintain when new
ifuncs are added and their suffixes possibly altered.

This patch uses pre-processor `#define' statements to map each suffix to
a descriptive feature name macro, for example:

  #define LSE(NAME) NAME##_i1

Where we wish to generate ifunc names with the pre-processor's token
concatenation feature, we add a level of indirection to previous macro
calls.  If before we would have had`MACRO(<name>_i<n>)', we now have
`MACRO_FEAT(name, feature)'.  Where we wish to refer to base
functionality (i.e., functions where ifunc suffixes are absent), the
original `MACRO(<name>)' may be used to bypass suffixing.

Consequently, for base functionality, where the ifunc suffix is
absent, the macro interface remains the same.  For example, the entry
and endpoints of `libat_store_16' remain defined by:

  ENTRY (libat_store_16)

and

  END (libat_store_16)

For the LSE2 implementation of the same 16-byte atomic store, we now
have:

  ENTRY_FEAT (libat_store_16, LSE2)

and

  END_FEAT (libat_store_16, LSE2)

For the aliasing of function names, we define the following new
implementation of the ALIAS macro:

  ALIAS (FN_BASE_NAME, FROM_SUFFIX, TO_SUFFIX)

Defining the `CORE(NAME)' macro to be the identity operator, it
returns the base function name unaltered and allows us to alias
target-specific ifuncs to the corresponding base implementation.
For example, we'd alias the LSE2 `libat_exchange_16' to it base
implementation with:

  ALIAS (libat_exchange_16, LSE2, CORE)

libatomic/ChangeLog:
	* config/linux/aarch64/atomic_16.S (CORE): New macro.
	(LSE2): Likewise.
	(ENTRY_FEAT): Likewise.
	(ENTRY_FEAT1): Likewise.
	(END_FEAT): Likewise.
	(END_FEAT1): Likewise.
	(ALIAS): Modify macro to take in `arch' arguments.
	(ALIAS1): New.
---
 libatomic/config/linux/aarch64/atomic_16.S | 79 +++++++++++++---------
 1 file changed, 47 insertions(+), 32 deletions(-)
  

Comments

Richard Sandiford Jan. 25, 2024, 5:17 p.m. UTC | #1
Victor Do Nascimento <victor.donascimento@arm.com> writes:
> The introduction of further architectural-feature dependent ifuncs
> for AArch64 makes hard-coding ifunc `_i<n>' suffixes to functions
> cumbersome to work with.  It is awkward to remember which ifunc maps
> onto which arch feature and makes the code harder to maintain when new
> ifuncs are added and their suffixes possibly altered.
>
> This patch uses pre-processor `#define' statements to map each suffix to
> a descriptive feature name macro, for example:
>
>   #define LSE(NAME) NAME##_i1
>
> Where we wish to generate ifunc names with the pre-processor's token
> concatenation feature, we add a level of indirection to previous macro
> calls.  If before we would have had`MACRO(<name>_i<n>)', we now have
> `MACRO_FEAT(name, feature)'.  Where we wish to refer to base
> functionality (i.e., functions where ifunc suffixes are absent), the
> original `MACRO(<name>)' may be used to bypass suffixing.
>
> Consequently, for base functionality, where the ifunc suffix is
> absent, the macro interface remains the same.  For example, the entry
> and endpoints of `libat_store_16' remain defined by:
>
>   ENTRY (libat_store_16)
>
> and
>
>   END (libat_store_16)
>
> For the LSE2 implementation of the same 16-byte atomic store, we now
> have:
>
>   ENTRY_FEAT (libat_store_16, LSE2)
>
> and
>
>   END_FEAT (libat_store_16, LSE2)
>
> For the aliasing of function names, we define the following new
> implementation of the ALIAS macro:
>
>   ALIAS (FN_BASE_NAME, FROM_SUFFIX, TO_SUFFIX)
>
> Defining the `CORE(NAME)' macro to be the identity operator, it
> returns the base function name unaltered and allows us to alias
> target-specific ifuncs to the corresponding base implementation.
> For example, we'd alias the LSE2 `libat_exchange_16' to it base
> implementation with:
>
>   ALIAS (libat_exchange_16, LSE2, CORE)
>
> libatomic/ChangeLog:
> 	* config/linux/aarch64/atomic_16.S (CORE): New macro.
> 	(LSE2): Likewise.
> 	(ENTRY_FEAT): Likewise.
> 	(ENTRY_FEAT1): Likewise.
> 	(END_FEAT): Likewise.
> 	(END_FEAT1): Likewise.
> 	(ALIAS): Modify macro to take in `arch' arguments.
> 	(ALIAS1): New.
> ---
>  libatomic/config/linux/aarch64/atomic_16.S | 79 +++++++++++++---------
>  1 file changed, 47 insertions(+), 32 deletions(-)
>
> diff --git a/libatomic/config/linux/aarch64/atomic_16.S b/libatomic/config/linux/aarch64/atomic_16.S
> index ad14f8f2e6e..16a42925903 100644
> --- a/libatomic/config/linux/aarch64/atomic_16.S
> +++ b/libatomic/config/linux/aarch64/atomic_16.S
> @@ -40,22 +40,38 @@
>  
>  	.arch	armv8-a+lse
>  
> -#define ENTRY(name)		\
> -	.global name;		\
> -	.hidden name;		\
> -	.type name,%function;	\
> +#define LSE2(NAME) 	NAME##_i1
> +#define CORE(NAME) 	NAME
> +
> +#define ENTRY(NAME) ENTRY_FEAT1 (NAME)
> +
> +#define ENTRY_FEAT(NAME, FEAT)  \
> +	ENTRY_FEAT1 (FEAT (NAME))
> +
> +#define ENTRY_FEAT1(NAME)	\
> +	.global NAME;		\
> +	.hidden NAME;		\
> +	.type NAME,%function;	\

I don't think ENTRY_FEAT1 is necessary now.  It should be possible
to keep ENTRY as it was and use:

#define ENTRY_FEAT(NAME, FEAT)  \
	ENTRY (FEAT (NAME))

Similarly for END/END_FEAT.

OK with those changes, thanks.

Richard

>  	.p2align 4;		\
> -name:				\
> -	.cfi_startproc;		\
> +NAME:				\
> +	.cfi_startproc;	\
>  	hint	34	// bti c
>  
> -#define END(name)		\
> +#define END(NAME) END_FEAT1 (NAME)
> +
> +#define END_FEAT(NAME, FEAT)	\
> +	END_FEAT1 (FEAT (NAME))
> +
> +#define END_FEAT1(NAME)	\
>  	.cfi_endproc;		\
> -	.size name, .-name;
> +	.size NAME, .-NAME;
> +
> +#define ALIAS(NAME, FROM, TO)	\
> +	ALIAS1 (FROM (NAME),TO (NAME))
>  
> -#define ALIAS(alias,name)	\
> -	.global alias;		\
> -	.set alias, name;
> +#define ALIAS1(ALIAS, NAME)	\
> +	.global ALIAS;		\
> +	.set ALIAS, NAME;
>  
>  #define res0 x0
>  #define res1 x1
> @@ -108,7 +124,7 @@ ENTRY (libat_load_16)
>  END (libat_load_16)
>  
>  
> -ENTRY (libat_load_16_i1)
> +ENTRY_FEAT (libat_load_16, LSE2)
>  	cbnz	w1, 1f
>  
>  	/* RELAXED.  */
> @@ -128,7 +144,7 @@ ENTRY (libat_load_16_i1)
>  	ldp	res0, res1, [x0]
>  	dmb	ishld
>  	ret
> -END (libat_load_16_i1)
> +END_FEAT (libat_load_16, LSE2)
>  
>  
>  ENTRY (libat_store_16)
> @@ -148,7 +164,7 @@ ENTRY (libat_store_16)
>  END (libat_store_16)
>  
>  
> -ENTRY (libat_store_16_i1)
> +ENTRY_FEAT (libat_store_16, LSE2)
>  	cbnz	w4, 1f
>  
>  	/* RELAXED.  */
> @@ -160,7 +176,7 @@ ENTRY (libat_store_16_i1)
>  	stlxp	w4, in0, in1, [x0]
>  	cbnz	w4, 1b
>  	ret
> -END (libat_store_16_i1)
> +END_FEAT (libat_store_16, LSE2)
>  
>  
>  ENTRY (libat_exchange_16)
> @@ -237,7 +253,7 @@ ENTRY (libat_compare_exchange_16)
>  END (libat_compare_exchange_16)
>  
>  
> -ENTRY (libat_compare_exchange_16_i1)
> +ENTRY_FEAT (libat_compare_exchange_16, LSE2)
>  	ldp	exp0, exp1, [x1]
>  	mov	tmp0, exp0
>  	mov	tmp1, exp1
> @@ -270,7 +286,7 @@ ENTRY (libat_compare_exchange_16_i1)
>  	/* ACQ_REL/SEQ_CST.  */
>  4:	caspal	exp0, exp1, in0, in1, [x0]
>  	b	0b
> -END (libat_compare_exchange_16_i1)
> +END_FEAT (libat_compare_exchange_16, LSE2)
>  
>  
>  ENTRY (libat_fetch_add_16)
> @@ -556,21 +572,20 @@ END (libat_test_and_set_16)
>  
>  /* Alias entry points which are the same in baseline and LSE2.  */
>  
> -ALIAS (libat_exchange_16_i1, libat_exchange_16)
> -ALIAS (libat_fetch_add_16_i1, libat_fetch_add_16)
> -ALIAS (libat_add_fetch_16_i1, libat_add_fetch_16)
> -ALIAS (libat_fetch_sub_16_i1, libat_fetch_sub_16)
> -ALIAS (libat_sub_fetch_16_i1, libat_sub_fetch_16)
> -ALIAS (libat_fetch_or_16_i1, libat_fetch_or_16)
> -ALIAS (libat_or_fetch_16_i1, libat_or_fetch_16)
> -ALIAS (libat_fetch_and_16_i1, libat_fetch_and_16)
> -ALIAS (libat_and_fetch_16_i1, libat_and_fetch_16)
> -ALIAS (libat_fetch_xor_16_i1, libat_fetch_xor_16)
> -ALIAS (libat_xor_fetch_16_i1, libat_xor_fetch_16)
> -ALIAS (libat_fetch_nand_16_i1, libat_fetch_nand_16)
> -ALIAS (libat_nand_fetch_16_i1, libat_nand_fetch_16)
> -ALIAS (libat_test_and_set_16_i1, libat_test_and_set_16)
> -
> +ALIAS (libat_exchange_16, LSE2, CORE)
> +ALIAS (libat_fetch_add_16, LSE2, CORE)
> +ALIAS (libat_add_fetch_16, LSE2, CORE)
> +ALIAS (libat_fetch_sub_16, LSE2, CORE)
> +ALIAS (libat_sub_fetch_16, LSE2, CORE)
> +ALIAS (libat_fetch_or_16, LSE2, CORE)
> +ALIAS (libat_or_fetch_16, LSE2, CORE)
> +ALIAS (libat_fetch_and_16, LSE2, CORE)
> +ALIAS (libat_and_fetch_16, LSE2, CORE)
> +ALIAS (libat_fetch_xor_16, LSE2, CORE)
> +ALIAS (libat_xor_fetch_16, LSE2, CORE)
> +ALIAS (libat_fetch_nand_16, LSE2, CORE)
> +ALIAS (libat_nand_fetch_16, LSE2, CORE)
> +ALIAS (libat_test_and_set_16, LSE2, CORE)
>  
>  /* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code.  */
>  #define FEATURE_1_AND 0xc0000000
  

Patch

diff --git a/libatomic/config/linux/aarch64/atomic_16.S b/libatomic/config/linux/aarch64/atomic_16.S
index ad14f8f2e6e..16a42925903 100644
--- a/libatomic/config/linux/aarch64/atomic_16.S
+++ b/libatomic/config/linux/aarch64/atomic_16.S
@@ -40,22 +40,38 @@ 
 
 	.arch	armv8-a+lse
 
-#define ENTRY(name)		\
-	.global name;		\
-	.hidden name;		\
-	.type name,%function;	\
+#define LSE2(NAME) 	NAME##_i1
+#define CORE(NAME) 	NAME
+
+#define ENTRY(NAME) ENTRY_FEAT1 (NAME)
+
+#define ENTRY_FEAT(NAME, FEAT)  \
+	ENTRY_FEAT1 (FEAT (NAME))
+
+#define ENTRY_FEAT1(NAME)	\
+	.global NAME;		\
+	.hidden NAME;		\
+	.type NAME,%function;	\
 	.p2align 4;		\
-name:				\
-	.cfi_startproc;		\
+NAME:				\
+	.cfi_startproc;	\
 	hint	34	// bti c
 
-#define END(name)		\
+#define END(NAME) END_FEAT1 (NAME)
+
+#define END_FEAT(NAME, FEAT)	\
+	END_FEAT1 (FEAT (NAME))
+
+#define END_FEAT1(NAME)	\
 	.cfi_endproc;		\
-	.size name, .-name;
+	.size NAME, .-NAME;
+
+#define ALIAS(NAME, FROM, TO)	\
+	ALIAS1 (FROM (NAME),TO (NAME))
 
-#define ALIAS(alias,name)	\
-	.global alias;		\
-	.set alias, name;
+#define ALIAS1(ALIAS, NAME)	\
+	.global ALIAS;		\
+	.set ALIAS, NAME;
 
 #define res0 x0
 #define res1 x1
@@ -108,7 +124,7 @@  ENTRY (libat_load_16)
 END (libat_load_16)
 
 
-ENTRY (libat_load_16_i1)
+ENTRY_FEAT (libat_load_16, LSE2)
 	cbnz	w1, 1f
 
 	/* RELAXED.  */
@@ -128,7 +144,7 @@  ENTRY (libat_load_16_i1)
 	ldp	res0, res1, [x0]
 	dmb	ishld
 	ret
-END (libat_load_16_i1)
+END_FEAT (libat_load_16, LSE2)
 
 
 ENTRY (libat_store_16)
@@ -148,7 +164,7 @@  ENTRY (libat_store_16)
 END (libat_store_16)
 
 
-ENTRY (libat_store_16_i1)
+ENTRY_FEAT (libat_store_16, LSE2)
 	cbnz	w4, 1f
 
 	/* RELAXED.  */
@@ -160,7 +176,7 @@  ENTRY (libat_store_16_i1)
 	stlxp	w4, in0, in1, [x0]
 	cbnz	w4, 1b
 	ret
-END (libat_store_16_i1)
+END_FEAT (libat_store_16, LSE2)
 
 
 ENTRY (libat_exchange_16)
@@ -237,7 +253,7 @@  ENTRY (libat_compare_exchange_16)
 END (libat_compare_exchange_16)
 
 
-ENTRY (libat_compare_exchange_16_i1)
+ENTRY_FEAT (libat_compare_exchange_16, LSE2)
 	ldp	exp0, exp1, [x1]
 	mov	tmp0, exp0
 	mov	tmp1, exp1
@@ -270,7 +286,7 @@  ENTRY (libat_compare_exchange_16_i1)
 	/* ACQ_REL/SEQ_CST.  */
 4:	caspal	exp0, exp1, in0, in1, [x0]
 	b	0b
-END (libat_compare_exchange_16_i1)
+END_FEAT (libat_compare_exchange_16, LSE2)
 
 
 ENTRY (libat_fetch_add_16)
@@ -556,21 +572,20 @@  END (libat_test_and_set_16)
 
 /* Alias entry points which are the same in baseline and LSE2.  */
 
-ALIAS (libat_exchange_16_i1, libat_exchange_16)
-ALIAS (libat_fetch_add_16_i1, libat_fetch_add_16)
-ALIAS (libat_add_fetch_16_i1, libat_add_fetch_16)
-ALIAS (libat_fetch_sub_16_i1, libat_fetch_sub_16)
-ALIAS (libat_sub_fetch_16_i1, libat_sub_fetch_16)
-ALIAS (libat_fetch_or_16_i1, libat_fetch_or_16)
-ALIAS (libat_or_fetch_16_i1, libat_or_fetch_16)
-ALIAS (libat_fetch_and_16_i1, libat_fetch_and_16)
-ALIAS (libat_and_fetch_16_i1, libat_and_fetch_16)
-ALIAS (libat_fetch_xor_16_i1, libat_fetch_xor_16)
-ALIAS (libat_xor_fetch_16_i1, libat_xor_fetch_16)
-ALIAS (libat_fetch_nand_16_i1, libat_fetch_nand_16)
-ALIAS (libat_nand_fetch_16_i1, libat_nand_fetch_16)
-ALIAS (libat_test_and_set_16_i1, libat_test_and_set_16)
-
+ALIAS (libat_exchange_16, LSE2, CORE)
+ALIAS (libat_fetch_add_16, LSE2, CORE)
+ALIAS (libat_add_fetch_16, LSE2, CORE)
+ALIAS (libat_fetch_sub_16, LSE2, CORE)
+ALIAS (libat_sub_fetch_16, LSE2, CORE)
+ALIAS (libat_fetch_or_16, LSE2, CORE)
+ALIAS (libat_or_fetch_16, LSE2, CORE)
+ALIAS (libat_fetch_and_16, LSE2, CORE)
+ALIAS (libat_and_fetch_16, LSE2, CORE)
+ALIAS (libat_fetch_xor_16, LSE2, CORE)
+ALIAS (libat_xor_fetch_16, LSE2, CORE)
+ALIAS (libat_fetch_nand_16, LSE2, CORE)
+ALIAS (libat_nand_fetch_16, LSE2, CORE)
+ALIAS (libat_test_and_set_16, LSE2, CORE)
 
 /* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code.  */
 #define FEATURE_1_AND 0xc0000000