Bug 9702 - [ARM] Constant pools are not shared among functions
Summary: [ARM] Constant pools are not shared among functions
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.3
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks: 16996
  Show dependency treegraph
 
Reported: 2003-02-14 09:36 UTC by Arpad Beszedes
Modified: 2013-12-08 23:22 UTC (History)
3 users (show)

See Also:
Host:
Target: arm*-* sh*-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-06-22 16:21:59


Attachments
cp-sharing.tar.gz (756 bytes, application/x-gzip )
2003-05-21 15:17 UTC, Arpad Beszedes
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Arpad Beszedes 2003-02-14 09:36:01 UTC
Currently all functions have their own constant pool even if they use the same constants. Gcc should merge appropriate constant pools and place this common pool to a location accessible from all appropriate functions.

Release:
gcc version 3.3 20030210 (prerelease)

Environment:
BUILD & HOST: Linux 2.4.20 i686 unknown
TARGET: arm-unknown-elf

How-To-Repeat:
Use the command line below to compile the specified source code:
arm-elf-gcc -S -g0 -Os -o 02.s ./02.c

Attached is the original assembly output where constant pools labeled by .L2 and .L5 could be merged together as shown in the manually edited assembly file.

// 02.c:

# 1 "02.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "02.c"
unsigned int a;
int f1()
{
  return a+2;
}
int f3()
{
  a=12;
}
int main ()
{
  f3();
  return f1();
}
Comment 1 Arpad Beszedes 2003-02-14 09:36:01 UTC
Fix:
If unit-at-a-time compilation is implemented in gcc, this issue could be solved within gcc more easily.
Comment 2 Andrew Pinski 2003-05-26 21:57:23 UTC
Can you try with the mainline of gcc where unit-at-a-time is implemented and shared 
constant pools are too?
Comment 3 Gábor Lóki 2003-05-30 13:13:16 UTC
Hello,

>Can you try with the mainline of gcc where unit-at-a-time is implemented
>and shared constant pools are too?

This behavior is still present on mainline (20030530) with unit-at-a-time.
The result is the same as in the attached example.

Regards,
  Gabor Loki
Comment 4 Andrew Pinski 2003-05-30 13:16:26 UTC
To get unit-at-a-time on the mainline, you have to compile with -O3 or -funit-at-a-time, I forgot 
to mention that in my pervious comment.
Comment 5 Andrew Pinski 2003-06-02 04:32:12 UTC
Okay I read your feedback wrong, it still happens on the mainline with unit-at-a-time.  No 
need for more feedback.
Comment 6 Steven Bosscher 2009-06-22 16:21:59 UTC
Is there anything in the tool chain that handles this right now (linker maybe)?
Comment 7 Daniel Jacobowitz 2009-06-23 15:49:38 UTC
Nope.  It would be somewhere between hard and impossible to do in the linker, because these have to go in the middle of the .text section, and within compile-time known offsets from the using functions (to accommodate limited range pc-relative displacements).
Comment 8 Oleg Endo 2013-07-28 19:23:30 UTC
The same applies to SH and probably other targets that use constant pools in the text sections.
Comment 9 Oleg Endo 2013-12-08 23:22:23 UTC
As it has been mentioned in https://bugs.launchpad.net/gcc-linaro/+bug/625233 the ARM back end does not use GCC's constant pool handling for constants (in varasm.c), but rather implements its own per-function constant pool handling.  So does the SH back end.  Both do very similar things, as both architectures have almost the same constraints/properties in this regard.

On SH PC relative constants must be ahead of the instruction that does the PC relative load and it must be within a certain range.  The assembler does not allow PC relative loads across sections, as this would require it to be able to alter the code in case something goes out of range.  This means that constant pools must be in the same section as the compiled function.

After collecting all the referenced constants during compilation of a function, the SH machine dependent reorg pass inserts constant pools after barriers and splits basic blocks if needed in order to satisfy the displacement constraints of PC relative load instructions.  The ARM reorg pass does pretty much the same.

As far as I understand it, the constant pool handling in varasm.c does not have such functionality.  Constant pool sharing (among multiple functions) is done by recording all referenced constants while functions are being compiled and then dumping the whole pool at once.  This is not good enough for ARM or SH.

Since constant pool placement has an impact on instruction lengths of branch instructions, shared constant pools would require running some sort of IPA before running the machine dependent reorg RTL passes on each function, which is not possible (see comment in function.h above #define crtl).  Even if that worked, when -ffunction-sections is used, sharing of constant pools becomes impossible at compile time and must be done at link time after sorting/reordering and merging the function text sections.

On SH there's a relaxation option which will annotate the assembly output with .uses pseudo ops.  This allows the linker to shorten branch instructions and eliminate branch offsets which are stored in the constant pool (unfortunately binutils support for this has been broken for a while).  The same approach could be used for dealing with constant pools in general, maybe with some additional annotations.