https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120681

            Bug ID: 120681
           Summary: PowerPC GCC turns off pc-relative addressing on
                    power10 when -mcmodel=large is used
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: meissner at gcc dot gnu.org
  Target Milestone: ---

When I implemented the pc-relative support for power10 in GCC, I disabled using
pc-relative support for -mcmodel=large.  At the time, I didn't want to dig into
the issues.  It is now time to allow -mcmodel=large to generate pc-relative
code.

For example, consider this piece of code:

#ifndef TYPE
#define TYPE unsigned long
#endif

extern TYPE global_var;

void
set_global (TYPE value)
{
  global_var = value;
}

Currently -mcpu=power10 -mcmodel=large file.c generates:

        .file   "foo-addr3.c"
        .machine power10
        .machine altivec
        .abiversion 2
        .section        ".text"
        .section        ".toc","aw"
        .align 3
.LC0:
        .quad   global_var
        .section        ".text"
        .align 2
        .p2align 4,,15
        .globl set_global
        .type   set_global, @function
.LCL0:
        .quad .TOC.-.LCF0
set_global:
.LFB0:
        .cfi_startproc
.LCF0:
        .reloc .,R_PPC64_ENTRY
        ld 2,.LCL0-.LCF0(12)
        add 2,2,12
        .localentry     set_global,.-set_global
        addis 9,2,.LC0@toc@ha
        ld 9,.LC0@toc@l(9)
        std 3,0(9)
        blr
        .long 0
        .byte 0,0,0,0,0,0,0,0
        .cfi_endproc
.LFE0:
        .size   set_global,.-set_global
        .ident  "GCC: (GNU) 16.0.0 20250613 (experimental) work211 branch"
        .section        .note.GNU-stack,"",@progbits


I.e. the following instructions set up the non-local function address that
loads up r2 with the TOC address if the call was not a local call (r12 has the
function address in it):

        ld 2,.LCL0-.LCF0(12)
        add 2,2,12

The following instructions load up r9 to have the address of the global
variable after the dynamic loader updates all of the addresses by loading up
the 64-bit value at .LC0:

        addis 9,2,.LC0@toc@ha
        ld 9,.LC0@toc@l(9)

And then since r9 has the address of the global variable in it, the following
store will update the global variable:

        std 3,0(9)

Instead of forcing the use of the older TOC code, we could instead generate:

        .file   "foo-addr3.c"
        .machine power10
        .machine altivec
        .abiversion 2
        .section        ".text"
        .align 2
        .p2align 4,,15
        .globl set_global
        .type   set_global, @function
set_global:
.LFB0:
        .cfi_startproc
        pld 9,global_var@got@pcrel
        std 3,0(9)
        blr
        .long 0
        .byte 0,0,0,0,0,0,0,0
        .cfi_endproc
.LFE0:
        .size   set_global,.-set_global
        .ident  "GCC: (GNU) 16.0.0 20250613 (experimental) work211-cmodel
branch"
        .section        .note.GNU-stack,"",@progbits

In particular, we don't have to set up the TOC.  The linker will create a
location in the pc-relative area that will hold the address of the global
variable after the dynamic loader has run when the program is started using the
'@got@pcrel' relocation.  The 'pld' instruction will load this address up, and
then the normal store is done.

Reply via email to