https://gcc.gnu.org/g:7405bfd87451fbf7ac7586672bf025abc7218a55
commit 7405bfd87451fbf7ac7586672bf025abc7218a55 Author: Michael Meissner <meiss...@linux.ibm.com> Date: Fri Aug 8 20:41:52 2025 -0400 PR target/120681 - allow -mcmodel=large with PC relative addressing 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. This patch allows -mcmodel=large to use prefixed addressing on power10, power11, and possibly other future PowerPC processors in addition to the current -mcmodel=medium support. 2025-08-08 Michael Meissner <meiss...@linux.ibm.com> gcc/ PR target/120681 * config/rs6000/linux64.h (PCREL_SUPPORTED_BY_OS): Allow large code model as well as medium code model. * config/rs6000/rs6000.cc (rs6000_option_override_internal): Likewise. (rs6000_elf_declare_function_name): Don't create the local/non-local labels for large code model if we are using PC-relative addressing. gcc/testsuite/ PR target/120681 * gcc.target/powerpc/pr120681.c: New test. Diff: --- gcc/config/rs6000/linux64.h | 5 +-- gcc/config/rs6000/rs6000.cc | 13 +++++--- gcc/config/rs6000/rs6000.md | 26 ++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr108958.c | 47 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr120681.c | 34 +++++++++++++++++++++ 5 files changed, 118 insertions(+), 7 deletions(-) diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 0316d8cb65da..cf60ff14e108 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -564,7 +564,8 @@ extern int dot_symbols; /* Enable using prefixed PC-relative addressing on POWER10 if the ABI supports it. The ELF v2 ABI only supports PC-relative relocations for - the medium code model. */ + the medium/large code models. */ #define PCREL_SUPPORTED_BY_OS (TARGET_POWER10 && TARGET_PREFIXED \ && ELFv2_ABI_CHECK \ - && TARGET_CMODEL == CMODEL_MEDIUM) + && (TARGET_CMODEL == CMODEL_MEDIUM \ + || TARGET_CMODEL == CMODEL_LARGE)) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 17219bb5402e..781beb0a26a5 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -4373,12 +4373,15 @@ rs6000_option_override_internal (bool global_init_p) && (rs6000_isa_flags_explicit & OPTION_MASK_PCREL) == 0) rs6000_isa_flags |= OPTION_MASK_PCREL; - /* -mpcrel requires -mcmodel=medium, but we can't check TARGET_CMODEL until - after the subtarget override options are done. */ - else if (TARGET_PCREL && TARGET_CMODEL != CMODEL_MEDIUM) + /* -mpcrel requires medium or large code models, but we can't check + TARGET_CMODEL until after the subtarget override options are done. */ + else if (TARGET_PCREL + && TARGET_CMODEL != CMODEL_MEDIUM + && TARGET_CMODEL != CMODEL_LARGE) { if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0) - error ("%qs requires %qs", "-mpcrel", "-mcmodel=medium"); + error ("%qs requires %qs or %qs", "-mpcrel", "-mcmodel=medium", + "-mcmodel=large"); rs6000_isa_flags &= ~OPTION_MASK_PCREL; } @@ -21374,7 +21377,7 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl) ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); ASM_DECLARE_RESULT (file, DECL_RESULT (decl)); - if (TARGET_CMODEL == CMODEL_LARGE + if (TARGET_CMODEL == CMODEL_LARGE && !TARGET_PCREL && rs6000_global_entry_point_prologue_needed_p ()) { char buf[256]; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 925471fb561b..4b0467ba1b80 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -173,6 +173,7 @@ UNSPEC_XXSPLTIW_CONST UNSPEC_FMAX UNSPEC_FMIN + UNSPEC_ZERO_EXTEND ]) ;; @@ -969,6 +970,31 @@ (set_attr "dot" "yes") (set_attr "length" "4,8")]) +;; Optimize zero_extendsiti2 from a GPR to a GPR and then moving the GPR to a +;; VSX register +(define_peephole2 + [(set (match_operand:DI 0 "int_reg_operand") + (match_operand:DI 1 "int_reg_operand")) + (set (match_operand:DI 2 "int_reg_operand") + (const_int 0)) + (set (match_operand:TI 3 "vsx_register_operand") + (match_operand:TI 4 "int_reg_operand"))] + "TARGET_DIRECT_MOVE_64BIT + && (reg_or_subregno (operands[0]) + == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN) + && (reg_or_subregno (operands[2]) + == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN) + && peep2_reg_dead_p (3, operands[4])" + [(set (match_dup 3) + (unspec:TI [(match_dup 1)] UNSPEC_ZERO_EXTEND))]) + +(define_insn "*zero_extendsiti2_vsx" + [(set (match_operand:TI 0 "vsx_register_operand" "=wa") + (unspec:TI [(match_operand:DI 1 "int_reg_operand" "r")] + UNSPEC_ZERO_EXTEND))] + "TARGET_DIRECT_MOVE_64BIT" + "mtvsrdd %x0,0,%1" + [(set_attr "type" "mtvsr")]) ;; On power10, optimize zero extending a QI/HI/SI/DImode value from memory that ;; is going to a vector register target by generating a LXVR{B,H,W,D}X diff --git a/gcc/testsuite/gcc.target/powerpc/pr108958.c b/gcc/testsuite/gcc.target/powerpc/pr108958.c index e69de29bb2d1..21b3f2766918 100644 --- a/gcc/testsuite/gcc.target/powerpc/pr108958.c +++ b/gcc/testsuite/gcc.target/powerpc/pr108958.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target int128 } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-mdejagnu-cpu=power9 -O2" } */ + +#ifndef TYPE +#define TYPE unsigned long long +#endif + +/* PR target/108958, when zero extending a DImode to a TImode, and the TImode variable is in a VSX register, generate: + + mtvsrdd vreg,0,gpr + + instead of: + + mr tmp,gpr + li tmp+1,0 + mtvsrdd vreg,tmp+1,tmp. */ + +void +gpr_to_vsx (TYPE x, __uint128_t *p) +{ + /* mtvsrdd 0,0,3 + stvx 0,0(4) */ + + __uint128_t y = x; + __asm__ (" # %x0" : "+wa" (y)); + *p = y; +} + +void +gpr_to_gpr (TYPE x, __uint128_t *p) +{ + /* mr 2,3 + li 3,0 + std 2,0(4) + std 3,8(4) */ + + __uint128_t y = x; + __asm__ (" # %0" : "+r" (y)); + *p = y; +} + +/* { dg-final { scan-assembler-times {\mli\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mmtvsrdd .*,0,.*\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mstd\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mstxv\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr120681.c b/gcc/testsuite/gcc.target/powerpc/pr120681.c new file mode 100644 index 000000000000..d883d1c8a951 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr120681.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* { dg-require-effective-target powerpc_pcrel } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2 -mcmodel=large" } */ + +/* PR target/120681 -- verify that -mcpu=power10 -mcmodel=large uses PC + relative addressing instead of using TOC addressing. */ + +#ifndef TYPE +#define TYPE unsigned long +#endif + +extern TYPE global_var; + +void +set_global (TYPE value) +{ + /* + * Generate: + * pld 9,global_var@got@pcrel + * std 3,0(9) + * + * Not: + * addis 9,2,.LC0@toc@ha + * ld 9,.LC0@toc@l(9) + * std 3,0(9) + */ + + global_var = value; +} + +/* { dg-final { scan-assembler {@got@pcrel} } } */ +/* { dg-final { scan-assembler-not {@toc@ha} } } */ +/* { dg-final { scan-assembler-not {@toc@l} } } */