public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work146-dmf)] Add paddis support.
@ 2023-11-17 20:36 Michael Meissner
  0 siblings, 0 replies; only message in thread
From: Michael Meissner @ 2023-11-17 20:36 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:8732b12fc5f9dd3907f5630d20d6dec3af43f8be

commit 8732b12fc5f9dd3907f5630d20d6dec3af43f8be
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Fri Nov 17 15:35:16 2023 -0500

    Add paddis support.
    
    2023-11-17  Michael Meissner  <meissner@linux.ibm.com>
    
    gcc/
    
            * config/rs6000/constraints.md (eU): New constraint.
            (eV): Likewise.
            * config/rs6000/predicates.md (paddis_operand): New predicate.
            (paddis_paddi_operand): Likewise.
            (add_operand): Add paddis support.
            * config/rs6000/rs6000-cpus.def (ISA_FUTURE_MASKS): Add -mpaddis
            support.
            (POWERPC_MASKS): Likewise.
            * config/rs6000/rs6000.cc (num_insns_constant_gpr): Add -mpaddis
            support.
            (num_insns_constant_multi): Likewise.
            (print_operand): Add %B<n> for paddis support.
            (rs6000_opt_masks): Add -mpaddis.
            & config/rs6000/rs6000.h (SIGNED_INTEGER_32BIT_P): New macro.
            * config/rs6000/rs6000.md (isa attribute): Add -mpaddis support.
            (enabled attribute); Likewise.
            (add<mode>3): Likewise.
            (adddi3 splitter): New splitter for paddis.
            (movdi_internal64): Add -mpaddis support.
            (movdi splitter): New splitter for -mpaddis.
            * config/rs6000/rs6000.opt (-mpaddis): New switch.

Diff:
---
 gcc/config/rs6000/constraints.md | 10 +++++
 gcc/config/rs6000/predicates.md  | 52 +++++++++++++++++++++-
 gcc/config/rs6000/rs6000.cc      | 40 +++++++++++++++++
 gcc/config/rs6000/rs6000.h       |  1 +
 gcc/config/rs6000/rs6000.md      | 96 ++++++++++++++++++++++++++++++++++------
 gcc/config/rs6000/rs6000.opt     |  4 ++
 6 files changed, 189 insertions(+), 14 deletions(-)

diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index 218e41d82a8..a2530630a9f 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -222,6 +222,16 @@
   "An IEEE 128-bit constant that can be loaded into VSX registers."
   (match_operand 0 "easy_vector_constant_ieee128"))
 
+(define_constraint "eU"
+  "@internal integer constant that can be loaded with paddis"
+  (and (match_code "const_int")
+       (match_operand 0 "paddis_operand")))
+
+(define_constraint "eV"
+  "@internal integer constant that can be loaded with paddis + paddi"
+  (and (match_code "const_int")
+       (match_operand 0 "paddis_paddi_operand")))
+
 ;; Floating-point constraints.  These two are defined so that insn
 ;; length attributes can be calculated exactly.
 
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 4bcf1893949..8bd7fdbde4f 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -369,6 +369,53 @@
   return SIGNED_INTEGER_34BIT_P (INTVAL (op));
 })
 
+;; Return 1 if op is a 64-bit constant that uses the paddis instruction
+(define_predicate "paddis_operand"
+  (match_code "const_int")
+{
+  if (!TARGET_PADDIS && TARGET_POWERPC64)
+    return 0;
+
+  /* If addi, addis, or paddi can handle the number, don't return true.  */
+  HOST_WIDE_INT value = INTVAL (op);
+  if (SIGNED_INTEGER_34BIT_P (value))
+    return false;
+
+  /* If the number is too large for padds, return false.  */
+  if (!SIGNED_INTEGER_32BIT_P (value >> 32))
+    return false;
+
+  /* If the bottom 32-bits are non-zero, paddis can't handle it.  */
+  if ((value & HOST_WIDE_INT_C(0xffffffff)) != 0)
+    return false;
+
+  return true;
+})
+
+;; Return 1 if op is a 64-bit constant that needs the paddis instruction and an
+;; addi/addis/paddi instruction combination.
+(define_predicate "paddis_paddi_operand"
+  (match_code "const_int")
+{
+  if (!TARGET_PADDIS && TARGET_POWERPC64)
+    return 0;
+
+  /* If addi, addis, or paddi can handle the number, don't return true.  */
+  HOST_WIDE_INT value = INTVAL (op);
+  if (SIGNED_INTEGER_34BIT_P (value))
+    return false;
+
+  /* If the number is too large for padds, return false.  */
+  if (!SIGNED_INTEGER_32BIT_P (value >> 32))
+    return false;
+
+  /* If the bottom 32-bits are zero, we can use paddis alone to handle it.  */
+  if ((value & HOST_WIDE_INT_C(0xffffffff)) == 0)
+    return false;
+
+  return true;
+})
+
 ;; Return 1 if op is a register that is not special.
 ;; Disallow (SUBREG:SF (REG:SI)) and (SUBREG:SI (REG:SF)) on VSX systems where
 ;; you need to be careful in moving a SFmode to SImode and vice versa due to
@@ -1050,7 +1097,10 @@
   (if_then_else (match_code "const_int")
     (match_test "satisfies_constraint_I (op)
 		 || satisfies_constraint_L (op)
-		 || satisfies_constraint_eI (op)")
+		 || satisfies_constraint_eI (op)
+		 || satisfies_constraint_eU (op)
+		 || satisfies_constraint_eV (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.cc b/gcc/config/rs6000/rs6000.cc
index cf254bc21d6..012b595873e 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -4400,6 +4400,16 @@ rs6000_option_override_internal (bool global_init_p)
       rs6000_isa_flags &= ~OPTION_MASK_PCREL;
     }
 
+
+  /* -mpaddis requires -mcpu=future.  */
+  if (TARGET_PADDIS && !TARGET_FUTURE)
+    {
+      if (OPTION_SET_P (TARGET_PADDIS))
+	error ("%qs requires %qs", "-mpaddis", "-mcpu=future");
+
+      TARGET_PADDIS = 0;
+    }
+
   /* Print the options after updating the defaults.  */
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
@@ -6229,6 +6239,17 @@ num_insns_constant_gpr (HOST_WIDE_INT value)
   else if (TARGET_PREFIXED && SIGNED_INTEGER_34BIT_P (value))
     return 1;
 
+  /* PADDIS support.  */
+  else if (TARGET_PADDIS && TARGET_POWERPC64
+	   && !IN_RANGE (value >> 32, -1, 0)
+	   && (SIGNED_INTEGER_32BIT_P (value >> 32)))
+    {
+      fprintf (stderr, "=== 0x%lx ===\n", (long)value);
+      return ((value & HOST_WIDE_INT_C (0xffffffff)) == 0
+	      ? 1
+	      : 2);
+    }
+
   else if (TARGET_POWERPC64)
     {
       HOST_WIDE_INT low = sext_hwi (value, 32);
@@ -6261,6 +6282,14 @@ num_insns_constant_multi (HOST_WIDE_INT value, machine_mode mode)
 {
   int nregs = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   int total = 0;
+  if (nregs == 1
+      && TARGET_PADDIS && TARGET_POWERPC64
+      && !IN_RANGE (value >> 32, -1, 0)
+      && SIGNED_INTEGER_32BIT_P (value >> 32))
+    return ((value & HOST_WIDE_INT_C (0xffffffff)) == 0
+	    ? 1
+	    : 2);
+
   while (nregs-- > 0)
     {
       HOST_WIDE_INT low = sext_hwi (value, BITS_PER_WORD);
@@ -14303,6 +14332,14 @@ print_operand (FILE *file, rtx x, int code)
 	fprintf (file, "%d", (REGNO (x) - FIRST_FPR_REGNO) / 4);
       return;
 
+    case 'B':
+      /* Upper 32-bits of a constant.  */
+      if (!CONST_INT_P (x))
+	output_operand_lossage ("Not a constant.");
+
+      fprintf (file, "%" HOST_LONG_FORMAT "d", INTVAL (x) >> 32);
+      return;
+
     case 'D':
       /* Like 'J' but get to the GT bit only.  */
       if (!REG_P (x) || !CR_REGNO_P (REGNO (x)))
@@ -24823,6 +24860,9 @@ static struct rs6000_opt_var const rs6000_opt_vars[] =
   { "speculate-indirect-jumps",
     offsetof (struct gcc_options, x_rs6000_speculate_indirect_jumps),
     offsetof (struct cl_target_option, x_rs6000_speculate_indirect_jumps), },
+  { "paddis",
+    offsetof (struct gcc_options, x_TARGET_PADDIS),
+    offsetof (struct cl_target_option, x_TARGET_PADDIS), },
 };
 
 /* Inner function to handle attribute((target("..."))) and #pragma GCC target
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 5c0fb62fa69..a70a04339d2 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2493,6 +2493,7 @@ typedef struct GTY(()) machine_function
 	    (HOST_WIDE_INT_1 << ((N)-1)) - 1)
 
 #define SIGNED_INTEGER_16BIT_P(VALUE)	SIGNED_INTEGER_NBIT_P (VALUE, 16)
+#define SIGNED_INTEGER_32BIT_P(VALUE)	SIGNED_INTEGER_NBIT_P (VALUE, 32)
 #define SIGNED_INTEGER_34BIT_P(VALUE)	SIGNED_INTEGER_NBIT_P (VALUE, 34)
 
 /* Like SIGNED_INTEGER_16BIT_P and SIGNED_INTEGER_34BIT_P, but with an extra
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 13b0fc75676..8b233933b75 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -357,7 +357,7 @@
   (const (symbol_ref "(enum attr_cpu) rs6000_tune")))
 
 ;; The ISA we implement.
-(define_attr "isa" "any,p5,p6,p7,p7v,p8v,p9,p9v,p9kf,p9tf,p10,lxvp,stxvp,dm,not_dm"
+(define_attr "isa" "any,p5,p6,p7,p7v,p8v,p9,p9v,p9kf,p9tf,p10,lxvp,stxvp,dm,not_dm,paddis"
   (const_string "any"))
 
 ;; Is this alternative enabled for the current CPU/ISA/etc.?
@@ -421,6 +421,11 @@
      (and (eq_attr "isa" "not_dm")
 	  (match_test "!TARGET_DENSE_MATH"))
      (const_int 1)
+
+     (and (eq_attr "isa" "paddis")
+	  (match_test "TARGET_PADDIS"))
+     (const_int 1)
+
     ] (const_int 0)))
 
 ;; If this instruction is microcoded on the CELL processor
@@ -1826,17 +1831,42 @@
 })
 
 (define_insn "*add<mode>3"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r,r")
-	(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b,b")
-		  (match_operand:GPR 2 "add_operand" "r,I,L,eI")))]
+  [(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")))]
   ""
   "@
    add %0,%1,%2
    addi %0,%1,%2
    addis %0,%1,%v2
-   addi %0,%1,%2"
+   addi %0,%1,%2
+   paddis %0,%1,%B2
+   #"
   [(set_attr "type" "add")
-   (set_attr "isa" "*,*,*,p10")])
+   (set_attr "isa" "*,*,*,p10,paddis,paddis")
+   (set_attr "length" "*,*,*,*,12,24")
+   (set_attr "prefixed" "*,*,*,*,yes,yes")
+   (set_attr "maybe_prefixed" "*,*,*,*,no,no")])
+
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand")
+	(plus:DI (match_operand:DI 1 "gpc_reg_operand")
+		 (match_operand:DI 2 "paddis_paddi_operand")))]
+  "TARGET_PADDIS && TARGET_POWERPC64"
+  [(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));
+})
 
 (define_insn "*addsi3_high"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
@@ -9805,7 +9835,7 @@
   DONE;
 })
 
-;;	   GPR store   GPR load    GPR move
+;;	   GPR store   GPR load    GPR move    GPR paddis   GPR paddis+paddi
 ;;	   GPR li      GPR lis     GPR pli     GPR #
 ;;	   FPR store   FPR load    FPR move
 ;;	   AVX store   AVX store   AVX load    AVX load    VSX move
@@ -9815,7 +9845,7 @@
 ;;	   VSX->GPR    GPR->VSX
 (define_insn "*movdi_internal64"
   [(set (match_operand:DI 0 "nonimmediate_operand"
-	  "=YZ,        r,          r,
+	  "=YZ,        r,          r,          r,          b,
 	   r,          r,          r,          r,
 	   m,          ^d,         ^d,
 	   wY,         Z,          $v,         $v,         ^wa,
@@ -9824,7 +9854,7 @@
 	   r,          *h,         *h,
 	   ?r,         ?wa")
 	(match_operand:DI 1 "input_operand"
-	  "r,          YZ,         r,
+	  "r,          YZ,         r,          eU,         eV,
 	   I,          L,          eI,         nF,
 	   ^d,         m,          ^d,
 	   ^v,         $v,         wY,         Z,          ^wa,
@@ -9839,6 +9869,8 @@
    std%U0%X0 %1,%0
    ld%U1%X1 %0,%1
    mr %0,%1
+   paddis %0,0,%B1
+   #
    li %0,%1
    lis %0,%v1
    li %0,%1
@@ -9864,7 +9896,7 @@
    mfvsrd %0,%x1
    mtvsrd %x0,%1"
   [(set_attr "type"
-	  "store,      load,       *,
+	  "store,      load,       *,          *,          *,
 	   *,          *,          *,          *,
 	   fpstore,    fpload,     fpsimple,
 	   fpstore,    fpstore,    fpload,     fpload,     veclogical,
@@ -9874,7 +9906,7 @@
 	   mfvsr,      mtvsr")
    (set_attr "size" "64")
    (set_attr "length"
-	  "*,          *,          *,
+	  "*,          *,          *,          12,         24,
 	   *,          *,          *,          20,
 	   *,          *,          *,
 	   *,          *,          *,          *,          *,
@@ -9883,14 +9915,32 @@
 	   *,          *,          *,
 	   *,          *")
    (set_attr "isa"
-	  "*,          *,          *,
+	  "*,          *,          *,          paddis,     paddis,
 	   *,          *,          p10,        *,
 	   *,          *,          *,
 	   p9v,        p7v,        p9v,        p7v,        *,
 	   p9v,        p9v,        p7v,        *,          *,
 	   p7v,        p7v,
 	   *,          *,          *,
-	   p8v,        p8v")])
+	   p8v,        p8v")
+   (set_attr "prefixed"
+	  "*,          *,          *,          yes,        yes,
+	   *,          *,          *,          *,
+	   *,          *,          *,
+	   *,          *,          *,          *,          *,
+	   *,          *,          *,          *,          *,
+	   *,          *,
+	   *,          *,          *,
+	   *,          *")
+   (set_attr "maybe_prefixed"
+	  "*,          *,          *,          no,         no,
+	   *,          *,          *,          *,
+	   *,          *,          *,
+	   *,          *,          *,          *,          *,
+	   *,          *,          *,          *,          *,
+	   *,          *,
+	   *,          *,          *,
+	   *,          *")])
 
 ; Some DImode loads are best done as a load of -1 followed by a mask
 ; instruction.
@@ -9908,6 +9958,26 @@
 		(match_dup 1)))]
   "")
 
+;; Split a constant that can be generated by a paddis and paddi into 2
+;; instructions.
+(define_split
+  [(set (match_operand:DI 0 "int_reg_operand")
+	(match_operand:DI 1 "paddis_paddi_operand"))]
+  "TARGET_PADDIS && TARGET_POWERPC64"
+  [(set (match_dup 2)
+	(match_dup 3))
+   (set (match_dup 0)
+	(plus:DI (match_dup 2)
+		 (match_dup 4)))]
+{
+  HOST_WIDE_INT value = INTVAL (operands[1]);
+  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));
+})
+
 ;; Split a load of a large constant into the appropriate five-instruction
 ;; sequence.  Handle anything in a constant number of insns.
 ;; When non-easy constants can go in the TOC, this should use
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 3c09154d63b..f51aa636b9f 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -605,6 +605,10 @@ mstore-vector-pair
 Target Undocumented Mask(STORE_VECTOR_PAIR) Var(rs6000_isa_flags)
 Generate (do not generate) store vector pair instructions.
 
+mpaddis
+Target Undocumented Var(TARGET_PADDIS) Save
+Generate (do not generate) the paddis instruction.
+
 mrelative-jumptables
 Target Undocumented Var(rs6000_relative_jumptables) Init(1) Save

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-11-17 20:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-17 20:36 [gcc(refs/users/meissner/heads/work146-dmf)] Add paddis support Michael Meissner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).