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.