IBM Z: Handle unaligned symbols

The IBM Z ELF ABI mandates every symbol to reside on a 2 byte boundary
in order to be able to use the larl instruction. However, in some
situations it is difficult to enforce this, e.g. for common linker
scripts as used in the Linux kernel. This patch introduces the
-munaligned-symbols option. When that option is used, external symbols
without an explicit alignment are considered unaligned and its address
will be pushed into GOT or the literal pool.

If the symbol in the final linker step turns out end up on a 2 byte
boundary the linker is able to take this back and replace the indirect
reference with larl again. This should minimize the effect to symbols
which are actually unaligned in the end.

gcc/ChangeLog:

	* config/s390/s390.cc (s390_encode_section_info): Assume external
	symbols without explicit alignment to be unaligned if
	-munaligned-symbols has been specified.
	* config/s390/s390.opt (-munaligned-symbols): New option.

gcc/testsuite/ChangeLog:

	* gcc.target/s390/aligned-1.c: New test.
	* gcc.target/s390/unaligned-1.c: New test.
This commit is contained in:
Andreas Krebbel 2023-08-01 21:01:19 +02:00
parent 7c09e7e24b
commit 6cb2f2c7f3
4 changed files with 54 additions and 2 deletions

View file

@ -13709,8 +13709,13 @@ s390_encode_section_info (tree decl, rtx rtl, int first)
a larl/load-relative instruction. We only handle the cases
that can go wrong (i.e. no FUNC_DECLs).
All symbols without an explicit alignment are assumed to be 2
byte aligned as mandated by our ABI. */
if (DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) % 16)
byte aligned as mandated by our ABI. This behavior can be
overridden for external symbols with the -munaligned-symbols
switch. */
if (DECL_ALIGN (decl) % 16
&& (DECL_USER_ALIGN (decl)
|| (!SYMBOL_REF_LOCAL_P (XEXP (rtl, 0))
&& s390_unaligned_symbols_p)))
SYMBOL_FLAG_SET_NOTALIGN2 (XEXP (rtl, 0));
else if (DECL_ALIGN (decl) % 32)
SYMBOL_FLAG_SET_NOTALIGN4 (XEXP (rtl, 0));

View file

@ -329,3 +329,10 @@ Target Undocumented Var(unroll_only_small_loops) Init(0) Save
mpreserve-args
Target Var(s390_preserve_args_p) Init(0)
Store all argument registers on the stack.
munaligned-symbols
Target Var(s390_unaligned_symbols_p) Init(0)
Assume external symbols to be potentially unaligned. By default all
symbols without explicit alignment are assumed to reside on a 2 byte
boundary as mandated by the IBM Z ABI.

View file

@ -0,0 +1,20 @@
/* Even symbols without explicite alignment are assumed to reside on a
2 byte boundary, as mandated by the IBM Z ELF ABI, and therefore
can be accessed using the larl instruction. */
/* { dg-do compile } */
/* { dg-options "-O3 -march=z900 -fno-section-anchors" } */
extern unsigned char extern_implicitly_aligned;
extern unsigned char extern_explicitly_aligned __attribute__((aligned(2)));
unsigned char aligned;
unsigned char
foo ()
{
return extern_implicitly_aligned + extern_explicitly_aligned + aligned;
}
/* { dg-final { scan-assembler-times "larl\t%r\[0-9\]*,extern_implicitly_aligned\n" 1 } } */
/* { dg-final { scan-assembler-times "larl\t%r\[0-9\]*,extern_explicitly_aligned\n" 1 } } */
/* { dg-final { scan-assembler-times "larl\t%r\[0-9\]*,aligned\n" 1 } } */

View file

@ -0,0 +1,20 @@
/* With the -munaligned-symbols option all external symbols without
explicite alignment are assumed to be potentially unaligned and
therefore cannot be accessed with larl. */
/* { dg-do compile } */
/* { dg-options "-O3 -march=z900 -fno-section-anchors -munaligned-symbols" } */
extern unsigned char extern_unaligned;
extern unsigned char extern_explicitly_aligned __attribute__((aligned(2)));
unsigned char aligned;
unsigned char
foo ()
{
return extern_unaligned + extern_explicitly_aligned + aligned;
}
/* { dg-final { scan-assembler-times "larl\t%r\[0-9\]*,extern_unaligned\n" 0 } } */
/* { dg-final { scan-assembler-times "larl\t%r\[0-9\]*,extern_explicitly_aligned\n" 1 } } */
/* { dg-final { scan-assembler-times "larl\t%r\[0-9\]*,aligned\n" 1 } } */