On 25/03/26 6:41 PM, Avinash Jayakar wrote:
Hi Vijay,

On Mon, 2026-03-16 at 04:00 -0500, Vijay Shankar wrote:
POWER10 has instruction fusion for addis+addi pairs.
Please try not to line break early.
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 with !TARGET_POWER10 to
prevent conflicts with the new fusion patterns.

Existing high/low patterns are guarded with !TARGET_POWER10 to
prevent
conflicts with the new fusion patterns.
Please remove duplicate paragraph.
Bootstrapped and tested on powerpc64le-linux-gnu with no regressions.

2026-03-16  Vijay Shankar  <[email protected]>

gcc/ChangeLog:
        PR target/108018
        * config/rs6000/rs6000.md (*largetoc_high): Add
!TARGET_POWER10
        guard.
For this section, 80 is the limit so 'guard' can fit in the same line.
        (*largetoc_high_aix<mode>): Likewise.
        (*largetoc_high_plus): Likewise.
        (*largetoc_high_plus_aix<mode>): Likewise.
        (*largetoc_low): Likewise.
        (*largetoc_low_aix<mode>): Likewise.
        (*largetocp10_high_low_aix<mode>): New pattern for POWER10
        wide-immediate fusion.
"New define_insn." should suffice.
        (*largetocp10_high_low_plus_aix<mode>): Likewise.
        (*largetocp10_high_low): Likewise.
        (*largetocp10_high_low_plus): Likewise.
        (*tocref<mode>): Add !TARGET_POWER10 guard.

gcc/testsuite/ChangeLog:
        PR target/108018
        * gcc.target/powerpc/pr108018-1.c: New test for POWER10
fusion.
Likewise "New test." should suffice.
---
  gcc/config/rs6000/rs6000.md                   | 64
+++++++++++++++++--
  gcc/testsuite/gcc.target/powerpc/pr108018-1.c | 14 ++++
  2 files changed, 71 insertions(+), 7 deletions(-)
  create mode 100644 gcc/testsuite/gcc.target/powerpc/pr108018-1.c

diff --git a/gcc/config/rs6000/rs6000.md
b/gcc/config/rs6000/rs6000.md
index 308955155..cba6ff3d4 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -11283,7 +11283,8 @@
          (unspec [(match_operand:DI 1 "" "")
                   (match_operand:DI 2 "gpc_reg_operand" "b")]
                  UNSPEC_TOCREL)))]
-   "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+   "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL
+   && !TARGET_POWER10"
Additional space needed to align with TARGET_ELF in previous line.
Better would be to have this as a first condition, since TARGET_ELF &&
TARGET_CMODEL != CMODEL_SMALL is often true. Something like
"!TARGET_POWER10 && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"

     "addis %0,%2,%1@toc@ha")
 (define_insn "*largetoc_high_aix<mode>"
@@ -11292,7 +11293,8 @@
          (unspec [(match_operand:P 1 "" "")
                   (match_operand:P 2 "gpc_reg_operand" "b")]
                  UNSPEC_TOCREL)))]
-   "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
+   "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL
+   && !TARGET_POWER10"
Likewise.
     "addis %0,%1@u(%2)")
 (define_insn "*largetoc_high_plus"
@@ -11303,7 +11305,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_ELF && TARGET_CMODEL != CMODEL_SMALL
+   && !TARGET_POWER10"
Likewise.
     "addis %0,%2,%1+%3@toc@ha")
 (define_insn "*largetoc_high_plus_aix<mode>"
@@ -11314,28 +11317,75 @@
                     (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_XCOFF && TARGET_CMODEL != CMODEL_SMALL
+   && !TARGET_POWER10"
Likewise.
     "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_ELF && TARGET_CMODEL != CMODEL_SMALL
+   && !TARGET_POWER10"
Likewise.
     "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_XCOFF && TARGET_CMODEL != CMODEL_SMALL
+   && !TARGET_POWER10"
Likewise.
     "la %0,%2@l(%1)")
+(define_insn "*largetocp10_high_low_aix<mode>"
I think name can be simpler just "largetocp10" instead of high_low
suffix for all the new patterns.
+  [(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_XCOFF
+    && TARGET_POWER10
+    && TARGET_CMODEL != CMODEL_SMALL"
We can have the conditions in a similar order as mentioned above in one
line for all new patterns.
+   "addis %0,%1@u(%2)\;la %0,%1@l(%0)")
+
+(define_insn "*largetocp10_high_low_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_XCOFF
+    && TARGET_POWER10
+    && TARGET_CMODEL != CMODEL_SMALL"
+   "addis %0,%1+%3@u(%2)\;la %0,%1+%3@l(%0)")
+
+(define_insn "*largetocp10_high_low"
+  [(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_ELF
+    && TARGET_POWER10
+    && TARGET_CMODEL != CMODEL_SMALL"
+   "addis %0,%2,%1@toc@ha\;addi %0,%0,%1@toc@l")
+
+(define_insn "*largetocp10_high_low_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_ELF
+    && TARGET_POWER10
+    && TARGET_CMODEL != CMODEL_SMALL"
+   "addis %0,%2,%1+%3@toc@ha\;addi %0,%0,%1+%3@toc@l")
+
  (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_POWER10"
this exceeds 80 chars.
Just a suggestion, you can use the script in contrib folder
python contrib/check_GNU_style.py <patch_file>
to detect such styling issues.

     "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-1.c
b/gcc/testsuite/gcc.target/powerpc/pr108018-1.c
new file mode 100644
index 000000000..5d88ca5cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr108018-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
I believe fusion will work for aix as well, although presently I am
also not aware on how to test it for aix. Any help would be
appreciated.
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -mno-pcrel" } */
+
+/* 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 {addis [^\n]*\n\taddi } 3 } }
*/
This does not test the order in the assembly. I believe this test will
pass without the changes in rs6000.md as well. Better to check if
expected fusion sequence was generated or not with regex. Something
like:
/* { dg-final { scan-assembler-times {addis (r[0-9]+),[^\n]*\n\taddi
\1,} 3 } } */
Not sure if it will work as is, please change accordingly. Also please
make sure this test fails without the changes in rs6000.md.

It does fail without patch due to [^\n]*\n\taddi

Thanks and regards,
Avinash Jayakar

Reply via email to