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