https://gcc.gnu.org/g:9833d3d84694c57e10af82f5284c9d3e03d15d91

commit r17-5572-g9833d3d84694c57e10af82f5284c9d3e03d15d91
Author: Kishan Parmar <[email protected]>
Date:   Mon Oct 26 16:55:01 2026 +0530

    rs6000: Add POWER10 wide-immediate fusion patterns [PR108018]
    
    POWER10 has instruction fusion for addis+addi pairs. However,
    the scheduler was breaking these pairs apart to optimize for
    dependency chains, losing the fusion benefit.
    
    This patch implements "fake" instructions that represent both
    instructions as a single pattern. This prevents the scheduler from
    reordering them while still generating the correct two-instruction
    sequence.
    
    Existing high/low patterns are guarded to
    prevent conflicts with the new fusion patterns.
    
    Bootstrapped and tested on powerpc64le-linux-gnu with no regressions.
    Bootstrapped and tested on powerpc64-linux-gnu with no regressions.
    Bootstrapped and tested on powerpc-ibm-aix with no regressions.
    
    2026-10-26  Vijay Shankar  <[email protected]>
    
    gcc/ChangeLog:
            PR target/108018
            * config/rs6000/rs6000.md (largetoc_high): Add guards.
            (largetoc_high_aix<mode>): Likewise.
            (largetoc_high_plus): Likewise.
            (largetoc_high_plus_aix<mode>): Likewise.
            (largetoc_low): Likewise.
            (largetoc_low_aix<mode>): Likewise.
            (largetocp10): New define_insn.
            (largetocp10_aix<mode>): Likewise.
            (largetocp10_plus): Likewise.
            (largetocp10_plus_aix<mode>): Likewise.
            (tocref<mode>): Add guards.
    
    gcc/testsuite/ChangeLog:
            PR target/108018
            * gcc.target/powerpc/pr108018-aix.c: New test.
            * gcc.target/powerpc/pr108018-elf.c: New test.

Diff:
---
 gcc/config/rs6000/rs6000.md                     | 62 ++++++++++++++++++++++---
 gcc/testsuite/gcc.target/powerpc/pr108018-aix.c | 15 ++++++
 gcc/testsuite/gcc.target/powerpc/pr108018-elf.c | 16 +++++++
 3 files changed, 86 insertions(+), 7 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 9144b894bf56..5e47b68ad6c3 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -11594,7 +11594,8 @@
          (unspec [(match_operand:DI 1 "" "")
                   (match_operand:DI 2 "gpc_reg_operand" "b")]
                  UNSPEC_TOCREL)))]
-   "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+   "!TARGET_P10_FUSION
+    && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
    "addis %0,%2,%1@toc@ha")
 
 (define_insn "*largetoc_high_aix<mode>"
@@ -11603,7 +11604,8 @@
          (unspec [(match_operand:P 1 "" "")
                   (match_operand:P 2 "gpc_reg_operand" "b")]
                  UNSPEC_TOCREL)))]
-   "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
+   "!TARGET_P10_FUSION
+    && TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
    "addis %0,%1@u(%2)")
 
 (define_insn "*largetoc_high_plus"
@@ -11614,7 +11616,8 @@
                     (match_operand:DI 2 "gpc_reg_operand" "b")]
                    UNSPEC_TOCREL)
            (match_operand:DI 3 "add_cint_operand" "n"))))]
-   "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+   "!TARGET_P10_FUSION
+    && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
    "addis %0,%2,%1+%3@toc@ha")
 
 (define_insn "*largetoc_high_plus_aix<mode>"
@@ -11625,28 +11628,73 @@
                     (match_operand:P 2 "gpc_reg_operand" "b")]
                    UNSPEC_TOCREL)
            (match_operand:P 3 "add_cint_operand" "n"))))]
-   "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
+   "!TARGET_P10_FUSION
+    && TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
    "addis %0,%1+%3@u(%2)")
 
 (define_insn "*largetoc_low"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
         (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
                   (match_operand:DI 2 "" "")))]
-   "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+   "!TARGET_P10_FUSION
+    && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
    "addi %0,%1,%2@l")
 
 (define_insn "*largetoc_low_aix<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
         (lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b")
                   (match_operand:P 2 "" "")))]
-   "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
+   "!TARGET_P10_FUSION
+    && TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
    "la %0,%2@l(%1)")
 
+(define_insn "*largetocp10"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+       (unspec [(match_operand:DI 1 "" "")
+                (match_operand:DI 2 "gpc_reg_operand" "b")]
+               UNSPEC_TOCREL))]
+   "TARGET_P10_FUSION
+    && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+   "addis %0,%2,%1@toc@ha\;addi %0,%0,%1@toc@l")
+
+(define_insn "*largetocp10_aix<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+        (unspec [(match_operand:P 1 "" "")
+                 (match_operand:P 2 "gpc_reg_operand" "b")]
+                UNSPEC_TOCREL))]
+   "TARGET_P10_FUSION
+    && TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
+   "addis %0,%1@u(%2)\;la %0,%2@l(%1)")
+
+(define_insn "*largetocp10_plus"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+       (plus:DI
+         (unspec [(match_operand:DI 1 "" "")
+                  (match_operand:DI 2 "gpc_reg_operand" "b")]
+                 UNSPEC_TOCREL)
+         (match_operand:DI 3 "add_cint_operand" "n")))]
+   "TARGET_P10_FUSION
+    && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+   "addis %0,%2,%1+%3@toc@ha\;addi %0,%0,%1+%3@toc@l")
+
+(define_insn "*largetocp10_plus_aix<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+        (plus:P
+          (unspec [(match_operand:P 1 "" "")
+                   (match_operand:P 2 "gpc_reg_operand" "b")]
+                  UNSPEC_TOCREL)
+          (match_operand:P 3 "add_cint_operand" "n")))]
+   "TARGET_P10_FUSION
+    && TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
+   "addis %0,%1+%3@u(%2);la %0,%2+%3@l(%1)")
+
+
 (define_insn_and_split "*tocref<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=b")
        (match_operand:P 1 "small_toc_ref" "R"))]
    "TARGET_TOC
-    && legitimate_constant_pool_address_p (operands[1], QImode, false)"
+    && legitimate_constant_pool_address_p (operands[1], QImode, false)
+    && !TARGET_P10_FUSION"
    "la %0,%a1"
    "&& TARGET_CMODEL != CMODEL_SMALL && reload_completed"
   [(set (match_dup 0) (high:P (match_dup 1)))
diff --git a/gcc/testsuite/gcc.target/powerpc/pr108018-aix.c 
b/gcc/testsuite/gcc.target/powerpc/pr108018-aix.c
new file mode 100644
index 000000000000..388215798516
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr108018-aix.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { } { "powerpc*-*-aix*" } } */
+/* { dg-options "-O2 -dp -mcpu=power9 -mtune=power10" } */
+/* { dg-additional-options "-mcmodel=large" } */
+
+/* Verify that the test case from PR108018 won't fail.  */
+
+static int foo, bar;
+
+unsigned long test(void)
+{
+        return (unsigned long)&foo + (unsigned long)&bar;
+}
+
+/* { dg-final { scan-assembler-times {\m.*largetocp10_aix.*\M} 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr108018-elf.c 
b/gcc/testsuite/gcc.target/powerpc/pr108018-elf.c
new file mode 100644
index 000000000000..3e7a416a74e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr108018-elf.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-skip-if "" { *-*-aix* } } */
+/* { dg-options "-O2 -dp -mcpu=power9 -mtune=power10" } */
+
+/* Verify that the test case from PR108018 won't fail.  */
+
+static int foo, bar;
+
+unsigned long test(void)
+{
+        return (unsigned long)&foo + (unsigned long)&bar;
+}
+
+/* { dg-final { scan-assembler {\m.*largetocp10.*\M} } } */
+/* { dg-final { scan-assembler {\m.*largetocp10_plus.*\M} } } */

Reply via email to