Hello,
Changes form v4:
* added AIX changes back
Changes form v3:
* use TARGET_P10_FUSION instead of tuning conditions
* disable test for 32 bit
Changes form v2:
* Removed AIX related changes
* update test case to check pattern directly
Changes form v1:
* Cleaned up naming in rs6000.md
* Cleaned up guards to be on same line.
* Test case use \m...\M instead of relying on space
Thank you,
Vijay.
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-03-16 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.c: New test.
---
gcc/config/rs6000/rs6000.md | 62 ++++++++++++++++---
.../gcc.target/powerpc/pr108018-aix.c | 16 +++++
.../gcc.target/powerpc/pr108018-elf.c | 16 +++++
3 files changed, 87 insertions(+), 7 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/powerpc/pr108018-aix.c
create mode 100644 gcc/testsuite/gcc.target/powerpc/pr108018-elf.c
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 8f694ac4d1c..7678d213616 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -11439,7 +11439,8 @@ (define_insn "*largetoc_high"
(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>"
@@ -11448,7 +11449,8 @@ (define_insn "*largetoc_high_aix<mode>"
(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"
@@ -11459,7 +11461,8 @@ (define_insn "*largetoc_high_plus"
(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>"
@@ -11470,28 +11473,73 @@ (define_insn "*largetoc_high_plus_aix<mode>"
(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 00000000000..510740ef321
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr108018-aix.c
@@ -0,0 +1,16 @@
+/* { 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 00000000000..3e7a416a74e
--- /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} } } */
--
2.52.0