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.


Thanks and regards,
Avinash Jayakar

Reply via email to