https://gcc.gnu.org/g:548b061936e333fe5058321dd5a2e0634a67ce5f

commit 548b061936e333fe5058321dd5a2e0634a67ce5f
Author: Michael Meissner <[email protected]>
Date:   Tue Jun 9 20:39:09 2026 -0400

    Update paddis support.
    
    This patch fixes the previous patch for paddis.
    
    2026-06-09  Michael Meissner  <[email protected]>
    
    gcc/
    
            * config/rs6000/predicates.md (paddis_paddi_operand): Only handle
            postive values.  Simplify test for addis/rldicl.
            (add_cint_operand): Do not allow paddis+paddi operands here.
            (reg_or_add_cint_operand): Add paddis/paddi support here.
            * config/rs6000/rs6000.md (add<mode>3, define_expand): Use 
op0/op1/op2
            instead of operands[0]/operands[1]/operands[2].  If the add could 
be done via
            paddis + paddi/addi, split it here.
            (*add<mode>3, define_insn): Remove paddis+paddi support.
            (add<mode>3 splitter for paddis+paddi): Delete.
            (spliter to load constant int with paddis+paddi): Simplify code.

Diff:
---
 gcc/config/rs6000/predicates.md | 16 ++++---
 gcc/config/rs6000/rs6000.md     | 99 ++++++++++++++++++++---------------------
 2 files changed, 57 insertions(+), 58 deletions(-)

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index bab7fb103954..556ff755f5a0 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -421,13 +421,16 @@
   if (!SIGNED_INTEGER_64BIT_P (value))
     return false;
 
+  /* Don't worry about negative values at the moment.  */
+  if (value < 0)
+    return false;
+
   /* If paddi alone can handle the number, don't return true.  */
   if (SIGNED_INTEGER_34BIT_P (value))
     return false;
 
   /* If we can do the add or generate the constant via addis/rldicl, fail.  */
-  if (num_insns_constant (op, mode) == 2
-      && rs6000_is_valid_and_mask (op, mode))
+  if (rs6000_is_valid_and_mask (op, mode))
     return false;
 
   /* Only return true if we need both paddi and paddis.  */
@@ -635,14 +638,14 @@
                           + (mode == SImode ? 0x80000000 : 0x80008000))
                        < (unsigned HOST_WIDE_INT) 0x100000000ll")
            (match_operand 0 "cint34_operand")
-           (match_operand 0 "paddis_operand")
-           (match_operand 0 "paddis_paddi_operand"))))
+           (match_operand 0 "paddis_operand"))))
 
 ;; Return 1 if op is a constant integer valid for addition
 ;; or non-special register.
 (define_predicate "reg_or_add_cint_operand"
   (if_then_else (match_code "const_int")
-    (match_operand 0 "add_cint_operand")
+    (ior (match_operand 0 "add_cint_operand")
+        (match_operand 0 "paddis_paddi_operand"))
     (match_operand 0 "gpc_reg_operand")))
 
 ;; Return 1 if op is a constant integer valid for subtraction
@@ -1186,8 +1189,7 @@
     (match_test "satisfies_constraint_I (op)
                 || satisfies_constraint_L (op)
                 || satisfies_constraint_eI (op)
-                || satisfies_constraint_eU (op)
-                || satisfies_constraint_eV (op)")
+                || satisfies_constraint_eU (op)")
     (match_operand 0 "gpc_reg_operand")))
 
 ;; Return 1 if the operand is either a non-special register, or 0, or -1.
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 2c44e24a06db..567d1aca613e 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1797,14 +1797,18 @@
                  (match_operand:SDI 2 "reg_or_add_cint_operand")))]
   ""
 {
+  rtx op0 = operands[0];
+  rtx op1 = operands[1];
+  rtx op2 = operands[2];
+
   if (<MODE>mode == DImode && !TARGET_POWERPC64)
     {
-      rtx lo0 = gen_lowpart (SImode, operands[0]);
-      rtx lo1 = gen_lowpart (SImode, operands[1]);
-      rtx lo2 = gen_lowpart (SImode, operands[2]);
-      rtx hi0 = gen_highpart (SImode, operands[0]);
-      rtx hi1 = gen_highpart (SImode, operands[1]);
-      rtx hi2 = gen_highpart_mode (SImode, DImode, operands[2]);
+      rtx lo0 = gen_lowpart (SImode, op0);
+      rtx lo1 = gen_lowpart (SImode, op1);
+      rtx lo2 = gen_lowpart (SImode, op2);
+      rtx hi0 = gen_highpart (SImode, op0);
+      rtx hi1 = gen_highpart (SImode, op1);
+      rtx hi2 = gen_highpart_mode (SImode, DImode, op2);
 
       if (!reg_or_short_operand (lo2, SImode))
        lo2 = force_reg (SImode, lo2);
@@ -1816,24 +1820,40 @@
       DONE;
     }
 
-  if (CONST_INT_P (operands[2]) && !add_operand (operands[2], <MODE>mode))
+  if (CONST_INT_P (op2) && !add_operand (op2, <MODE>mode))
     {
-      rtx tmp = ((!can_create_pseudo_p ()
-                 || rtx_equal_p (operands[0], operands[1]))
-                ? operands[0] : gen_reg_rtx (<MODE>mode));
+      rtx tmp = ((!can_create_pseudo_p () || rtx_equal_p (op0, op1))
+                ? op0
+                : gen_reg_rtx (<MODE>mode));
 
       /* Adding a constant to r0 is not a valid insn, so use a different
         strategy in that case.  */
-      if (reg_or_subregno (operands[1]) == 0 || reg_or_subregno (tmp) == 0)
+      if (reg_or_subregno (op1) == 0 || reg_or_subregno (tmp) == 0)
        {
-         if (operands[0] == operands[1])
+         if (op0 == op1)
            FAIL;
-         rs6000_emit_move (operands[0], operands[2], <MODE>mode);
-         emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[0]));
+         rs6000_emit_move (op0, op2, <MODE>mode);
+         emit_insn (gen_add<mode>3 (op0, op1, op0));
+         DONE;
+       }
+
+      HOST_WIDE_INT val = INTVAL (op2);
+
+      /* If we have paddis, split the add into paddis and either addi or
+        paddi.  However, if we can generate addis and rldicl, do that
+        instead of doing paddis/paddi.  Emit the paddis first, just
+        in case this is a memory operation and we could fold the offset
+        into the memory ooperation.  */
+
+      if (TARGET_PADDIS && paddis_paddi_operand (op2, <MODE>mode))
+       {
+         const HOST_WIDE_INT mask = HOST_WIDE_INT_C(0xffffffff);
+
+         emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (val & ~mask)));
+         emit_insn (gen_add<mode>3 (op0, tmp, GEN_INT (val & mask)));
          DONE;
        }
 
-      HOST_WIDE_INT val = INTVAL (operands[2]);
       HOST_WIDE_INT low = sext_hwi (val, 16);
       HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
 
@@ -1843,52 +1863,28 @@
       /* The ordering here is important for the prolog expander.
         When space is allocated from the stack, adding 'low' first may
         produce a temporary deallocation (which would be bad).  */
-      emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (rest)));
-      emit_insn (gen_add<mode>3 (operands[0], tmp, GEN_INT (low)));
+      emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (rest)));
+      emit_insn (gen_add<mode>3 (op0, tmp, GEN_INT (low)));
       DONE;
     }
 })
 
 (define_insn "*add<mode>3"
-  [(set (match_operand:GPR 0 "gpc_reg_operand"           "=r,r,r, r, r, b")
-       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b, b, b, b")
-                 (match_operand:GPR 2 "add_operand"      "r,I,L,eI,eU,eV")))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand"           "=r,r,r, r, r")
+       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b, b, b")
+                 (match_operand:GPR 2 "add_operand"      "r,I,L,eI,eU")))]
   ""
   "@
    add %0,%1,%2
    addi %0,%1,%2
    addis %0,%1,%v2
    addi %0,%1,%2
-   paddis %0,%1,%B2
-   #"
+   paddis %0,%1,%B2"
   [(set_attr "type" "add")
-   (set_attr "isa" "*,*,*,p10,paddis,paddis")
-   (set_attr "length" "*,*,*,*,12,24")
-   (set_attr "prefixed" "*,*,*,*,yes,yes")
-   (set_attr "maybe_prefixed" "*,*,*,*,no,no")])
-
-;; We can't split r0 + large_number due to encoding issues, so use base
-;; registers only.
-
-(define_split
-  [(set (match_operand:DI 0 "base_reg_operand")
-       (plus:DI (match_operand:DI 1 "base_reg_operand")
-                (match_operand:DI 2 "paddis_paddi_operand")))]
-  "TARGET_PADDIS"
-  [(set (match_dup 3)
-       (plus:DI (match_dup 1)
-                (match_dup 4)))
-   (set (match_dup 0)
-       (plus:DI (match_dup 3)
-                (match_dup 5)))]
-{
-  HOST_WIDE_INT value = INTVAL (operands[2]);
-  operands[3] = (can_create_pseudo_p ()
-                ? gen_reg_rtx (DImode)
-                : operands[0]);
-  operands[4] = GEN_INT (value & ~HOST_WIDE_INT_C (0xffffffff));
-  operands[5] = GEN_INT (value & HOST_WIDE_INT_C (0xffffffff));
-})
+   (set_attr "isa" "*,*,*,p10,paddis")
+   (set_attr "length" "*,*,*,*,12")
+   (set_attr "prefixed" "*,*,*,*,yes")
+   (set_attr "maybe_prefixed" "*,*,*,*,no")])
 
 (define_insn "*addsi3_high"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
@@ -10052,11 +10048,12 @@
                 (match_dup 4)))]
 {
   HOST_WIDE_INT value = INTVAL (operands[1]);
+  const HOST_WIDE_INT mask = HOST_WIDE_INT_C (0xffffffff);
   operands[2] = (can_create_pseudo_p ()
                 ? gen_reg_rtx (DImode)
                 : operands[0]);
-  operands[3] = GEN_INT (value & ~HOST_WIDE_INT_C (0xffffffff));
-  operands[4] = GEN_INT (value & HOST_WIDE_INT_C (0xffffffff));
+  operands[3] = GEN_INT (value & ~mask);
+  operands[4] = GEN_INT (value & mask);
 })
 
 ;; Split a load of a large constant into the appropriate five-instruction

Reply via email to