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