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}     } } */

Reply via email to