[Bug middle-end/88345] -Os overrides -falign-functions=N on the command line

2023-01-12 Thread mark at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88345

Branko Drevensek  changed:

   What|Removed |Added

 CC||branko.drevensek at gmail dot 
com

Mark Rutland  changed:

   What|Removed |Added

 CC||mark at kernel dot org

--- Comment #8 from Branko Drevensek  ---
Size optimization turning function alignment off assumes function alignment is
an optimization only, while for some architectures it might be requirement for
certain functions, such as interrupt handlers on risc-v.
This makes it impossible to have those functions aligned using this
switch/attribute regardless of optimization level selected as -Os will cause
alignment setting to be ignored.

--- Comment #9 from Mark Rutland  ---
This appears to be one case of several where GCC drops the alignment specified
by `-falign-functions=N`. I'm commenting with the other cases here rather than
creating new tickets on the assumption that's preferable.

Dropping the alignment specified by `-falign-functions=N` is a functional issue
for the arm64 Linux kernel port affecting our 'ftrace' tracing mechanism. I see
this with GCC 12.1.0 (and have no tested other versions), and LLVM seems to
always respect the alignment specified by `-falign-functions=N`

The arm64 Linux kernel port needs to use `-falign-functions=8` along with
`-fpatchable-function-entry=N,2` to place a naturally-aligned 8-byte literal at
the start of functions. There's some detail of that at:

  https://lore.kernel.org/lkml/20230109135828.879136-1-mark.rutl...@arm.com/

As noted earlier in this ticket, GCC does not seem to respect
`-falign-functions=N` when using `-Os`. For my use-case we cvan work around the
issue by not passing `-Os`, and I have one patch to do so, but this is not
ideal:

  https://lore.kernel.org/lkml/20230109135828.879136-3-mark.rutl...@arm.com/


In addition, GCC seems to drop alignment for cold functions, whether those are
marked as cold explicitly or when determined by some interprocedural analysis.
I've noted this on LKML at:

  https://lore.kernel.org/lkml/Y77%2FqVgvaJidFpYt@FVFF77S0Q05N/

... the below summary is a copy-paste of that:

For example:

| [mark@lakrids:/mnt/data/tests/gcc-alignment]% cat test-cold.c 
| #define __cold \
| __attribute__((cold))
| 
| #define EXPORT_FUNC_PTR(func) \
| typeof((func)) *__ptr_##func = (func)
| 
| __cold
| void cold_func_a(void) { }
| 
| __cold
| void cold_func_b(void) { }
| 
| __cold
| void cold_func_c(void) { }
| 
| static __cold
| void static_cold_func_a(void) { }
| EXPORT_FUNC_PTR(static_cold_func_a);
| 
| static __cold
| void static_cold_func_b(void) { }
| EXPORT_FUNC_PTR(static_cold_func_b);
| 
| static __cold
| void static_cold_func_c(void) { }
| EXPORT_FUNC_PTR(static_cold_func_c);
| [mark@lakrids:/mnt/data/tests/gcc-alignment]% usekorg 12.1.0
aarch64-linux-gcc -falign-functions=16 -c test-cold.c -O1
| [mark@lakrids:/mnt/data/tests/gcc-alignment]% usekorg 12.1.0
aarch64-linux-objdump -d test-cold.o 
| 
| test-cold.o: file format elf64-littleaarch64
| 
| 
| Disassembly of section .text:
| 
|  :
|0:   d65f03c0ret
| 
| 0004 :
|4:   d65f03c0ret
| 
| 0008 :
|8:   d65f03c0ret
| 
| 000c :
|c:   d65f03c0ret
| 
| 0010 :
|   10:   d65f03c0ret
| 
| 0014 :
|   14:   d65f03c0ret
| [mark@lakrids:/mnt/data/tests/gcc-alignment]% usekorg 12.1.0
aarch64-linux-objdump -h test-cold.o
| 
| test-cold.o: file format elf64-littleaarch64
| 
| Sections:
| Idx Name  Size  VMA   LMA   File off 
Algn
|   0 .text 0018      0040 
2**2
|   CONTENTS, ALLOC, LOAD, READONLY, CODE
|   1 .data 0018      0058 
2**3
|   CONTENTS, ALLOC, LOAD, RELOC, DATA
|   2 .bss        0070 
2**0
|   ALLOC
|   3 .comment  0013      0070 
2**0
|   CONTENTS, READONLY
|   4 .note.GNU-stack       0083 
2**0
|   CONTENTS, READONLY
|   5 .eh_frame 0090      0088 
2**3
|   CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

In simple cases, alignment *can* be restored if an explicit function attribute
is used. For example:

| [mark@lakrids:/mnt/data/tests/gcc-alignment]% cat test-aligned-cold.c 
| #define __aligned(n) \
| __attribute__((aligned(n)))
| 
| #define __cold \
|

[Bug middle-end/88345] -Os overrides -falign-functions=N on the command line

2023-01-13 Thread mark at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88345

--- Comment #11 from Mark Rutland  ---
Further, at `-O1` and above GCC seems to silently drop the alignment of any
implementation of abort(), apparently implicitly marking it as cold.

I assume that may be true for other special functions.

For example:

[mark@lakrids:/mnt/data/tests/gcc-alignment]% cat abort.c 
void abort(void)
{
__builtin_trap();
}
[mark@lakrids:/mnt/data/tests/gcc-alignment]% usekorg 12.1.0 aarch64-linux-gcc
-falign-functions=16 -c abort.c -O2
[mark@lakrids:/mnt/data/tests/gcc-alignment]% usekorg 12.1.0
aarch64-linux-objdump -d abort.o 

abort.o: file format elf64-littleaarch64


Disassembly of section .text.unlikely:

 :
   0:   d4207d00brk #0x3e8
[mark@lakrids:/mnt/data/tests/gcc-alignment]% usekorg 12.1.0
aarch64-linux-objdump -h abort.o

abort.o: file format elf64-littleaarch64

Sections:
Idx Name  Size  VMA   LMA   File off  Algn
  0 .text       0040  2**0
  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data       0040  2**0
  CONTENTS, ALLOC, LOAD, DATA
  2 .bss        0040  2**0
  ALLOC
  3 .text.unlikely 0004      0040  2**2
  CONTENTS, ALLOC, LOAD, READONLY, CODE
  4 .comment  0013      0044  2**0
  CONTENTS, READONLY
  5 .note.GNU-stack       0057 
2**0
  CONTENTS, READONLY
  6 .eh_frame 0028      0058  2**3
  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

[Bug middle-end/88345] -Os overrides -falign-functions=N on the command line

2023-01-23 Thread mark at kernel dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88345

--- Comment #14 from Mark Rutland  ---
> Patch posted before, but seems like not everybody agree:
> https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603049.html

FWIW, from the arm64 kernel side all we need is a reliable mechanism to align
functions, so the `-malign-all-function` or `-falign-all-functions` options Jan
suggests there would be good enough going forwards. It's just unfortunate that
we don't currently have a reliable mechanism (and have to workaround that by
avoiding the use of `-Os` and the `__cold__` attribute), and I guess the new
option would not be back-ported to stable GCC releases.

I don't think we want this hidden behind a `-flive-patching` option, since may
also want the alignment when not live-patching (e.g. for our
DEBUG_FORCE_FUNCTION_ALIGN_64B option), and the arch-specific details vary
quite drastically (e.g. arm64 uses `-fpatchable-function-entry=M,N`, x86 uses
`-mfentry` for patching and `-fpatchable-function-entry` for some CFI-related
logic), and those details are liable to change over time. Being able to set the
alignment independent from those details is likely to be more future-proof.

If it's intended that '-falign-functions=N' is overridden in some cases, it
would be nice to have that more clearly documented.