https://gcc.gnu.org/g:36b37616daeec9f84d6afa97a6e2d235bebe103d

commit 36b37616daeec9f84d6afa97a6e2d235bebe103d
Author: Michael Meissner <meiss...@linux.ibm.com>
Date:   Tue Apr 9 00:27:11 2024 -0400

    Add power10 wide immediate fusion
    
    2024-04-09  Michael Meissner  <meiss...@linux.ibm.com>
    
    gcc/
    
            PR target/108018
            * config/rs6000/rs6000.md (tocref<mode>_p10_fusion): New insn.
            (tocref<mode>): Don't allow tocrev<mode> if tocref<mode>_p10_fusion
            would be used.

Diff:
---
 gcc/config/rs6000/rs6000.md | 43 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index abc809448ad..1acd34ca0ee 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -11302,13 +11302,54 @@
    "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL"
    "la %0,%2@l(%1)")
 
+;; For power10 fusion, don't split the two pieces of the TOCREF, but keep them
+;; together so the instructions will fuse in case the user is using power10
+;; fusion via -mtune=power10 but is not enabling the PC-relative support.  If
+;; we split the instructions up, the scheduler will likely split the ADDIS and
+;; ADDI instruction.
+
+(define_insn "*tocref<mode>_p10_fusion"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+       (match_operand:P 1 "small_toc_ref" "R"))]
+   "TARGET_TOC && TARGET_P10_FUSION && TARGET_CMODEL != CMODEL_SMALL
+    && (TARGET_ELF || TARGET_XCOFF)
+    && legitimate_constant_pool_address_p (operands[1], QImode, false)"
+{
+  rtx op = operands[1];
+  machine_mode mode = <MODE>mode;
+  rtx offset = const0_rtx;
+
+  if (GET_CODE (op) == PLUS && add_cint_operand (XEXP (op, 1), mode))
+    {
+      offset = XEXP (op, 1);
+      op = XEXP (op, 0);
+    }
+
+    gcc_assert (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL);
+    operands[2] = XVECEXP (op, 0, 0);          /* symbol ref.  */
+    operands[3] = XVECEXP (op, 0, 1);          /* register, usually r2.  */
+    operands[4] = offset;
+
+    if (INTVAL (offset) == 0)
+      return (TARGET_ELF
+             ? "addis %0,%3,%2@toc@ha\;addi %0,%0,%2@toc@l"
+             : "addis %0,%2@u(%3)\;la %0,%2@l(%3)");
+    else
+      return (TARGET_ELF
+             ? "addis %0,%3,%2+%4@toc@ha\;addi %0,%0,%2+%4@toc@l"
+             : "addis %0,%2+%4@u(%3)\;la %0,%2+%4@l(%3)");
+}
+  [(set_attr "type" "*")
+   (set_attr "length" "8")])
+
 (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
+    && !(TARGET_P10_FUSION && (TARGET_ELF || TARGET_XCOFF))
     && legitimate_constant_pool_address_p (operands[1], QImode, false)"
    "la %0,%a1"
-   "&& TARGET_CMODEL != CMODEL_SMALL && reload_completed"
+   "&& TARGET_CMODEL != CMODEL_SMALL && !TARGET_P10_FUSION && reload_completed"
   [(set (match_dup 0) (high:P (match_dup 1)))
    (set (match_dup 0) (lo_sum:P (match_dup 0) (match_dup 1)))])

Reply via email to