https://gcc.gnu.org/g:5c2283f478e908718024e5b3b53dc8c4db3a8fe9

commit 5c2283f478e908718024e5b3b53dc8c4db3a8fe9
Author: Michael Meissner <meiss...@linux.ibm.com>
Date:   Wed Sep 4 11:36:25 2024 -0400

    Add support for the TAR register.
    
    2024-09-04  Michael Meissner  <meiss...@linux.ibm.com>
    
    gcc/
    
            * config/rs6000/constraints.md (h constraint): Add TAR register to 
the
            documentation.
            (wt constraint): New constraint.
            * config/rs6000/rs6000-cpus.def (ISA_3_0_MASKS_SERVER): Add -mtar.
            (POWERPC_MASKS): Likewise.
            * config/rs6000/rs6000.cc (rs6000_reg_names): Add TAR register 
support.
            (alt_reg_names): Likewise.
            (rs6000_hard_regno_mode_ok_uncached): Restrict SPR registers to only
            hold scalar integer modes of an appropriate size.  Add TAR register
            support.
            (rs6000_debug_reg_global): Print the register class that wt maps 
too.
            (rs6000_init_hard_regno_mode_ok): Add TAR register support.
            (rs6000_conditional_register_usage): Add TAR register support.
            (print_operand): Likewise.
            (rs6000_debugger_regno): Likewise.
            (rs6000_opt_masks): Add support for -mtar.
            * config/rs6000/rs6000.h (FIRST_PSEUDO_REGISTER): Add TAR register
            support.
            (FIXED_REGISTERS): Likewise.
            (CALL_REALLY_USED_REGISTERS): Likewise.
            (REG_ALLOC_ORDER): Likewise.
            (enum reg_class): Likewise.
            (REG_CLASS_NAMES): Likewise.
            (REG_CLASS_CONTENTS): Likewise.
            (enum r6000_reg_class_enum): Add support for the wt constraint.
            * config/rs6000/rs6000.md (TAR_REGNO): New constant.
            (call_indirect_nonlocal_sysv<mode>): Likewise.
            (call_value_indirect_nonlocal_sysv<mode>): Likewise.
            (call_indirect_aix<mode>): Likewise.
            (call_value_indirect_aix<mode>): Likewise.
            (call_indirect_elfv2<mode>): Likewise.
            (call_indirect_pcrel<mode>): Likewise.
            (call_value_indirect_elfv2<mode>): Likewise.
            (call_value_indirect_pcrel<mode>): Likewise.
            (*sibcall_indirect_nonlocal_sysv<mode>): Likewise.
            (sibcall_value_indirect_nonlocal_sysv<mode>): Likewise.
            (indirect_jump<mode>): Likewise.
            (@indirect_jump<mode>_nospec): Likewise.
            (@tablejump<mode>_insn_normal): Likewise.
            (@tablejump<mode>_insn_nospec): Likewise.
            * config/rs6000/rs6000.opt (-mtar): New option.
    
    gcc/testsuite/
    
            * gcc.target/powerpc/ppc-switch-1.c: Update test for the TAR 
register.
            * gcc.target/powerpc/pr51513.c: Likewise.
            * gcc.target/powerpc/safe-indirect-jump-2.c: Likewise.
            * gcc.target/powerpc/safe-indirect-jump-3.c: Likewise.
            * gcc.target/powerpc/tar-register.c: New test.

Diff:
---
 gcc/config/rs6000/constraints.md                   |  5 +-
 gcc/config/rs6000/rs6000-cpus.def                  |  4 +-
 gcc/config/rs6000/rs6000.cc                        | 58 +++++++++++++++++++---
 gcc/config/rs6000/rs6000.h                         | 31 +++++++-----
 gcc/config/rs6000/rs6000.md                        | 33 ++++++------
 gcc/config/rs6000/rs6000.opt                       |  4 ++
 gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c    |  4 +-
 gcc/testsuite/gcc.target/powerpc/pr51513.c         |  4 +-
 .../gcc.target/powerpc/safe-indirect-jump-2.c      |  2 +-
 .../gcc.target/powerpc/safe-indirect-jump-3.c      |  2 +-
 gcc/testsuite/gcc.target/powerpc/tar-register.c    | 34 +++++++++++++
 11 files changed, 138 insertions(+), 43 deletions(-)

diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index 369a7b75042..14f0465d7ae 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -57,7 +57,7 @@
   "@internal A compatibility alias for @code{wa}.")
 
 (define_register_constraint "h" "SPECIAL_REGS"
-  "@internal A special register (@code{vrsave}, @code{ctr}, or @code{lr}).")
+  "@internal A special register (@code{vrsave}, @code{ctr}, @code{lr} or 
@code{tar}).")
 
 (define_register_constraint "c" "CTR_REGS"
   "The count register, @code{ctr}.")
@@ -91,6 +91,9 @@
   "@internal Like @code{r}, if @option{-mpowerpc64} is used; otherwise,
    @code{NO_REGS}.")
 
+(define_register_constraint "wt" "rs6000_constraints[RS6000_CONSTRAINT_wt]"
+  "The tar register, @code{tar}.")
+
 (define_register_constraint "wx" "rs6000_constraints[RS6000_CONSTRAINT_wx]"
   "@internal Like @code{d}, if @option{-mpowerpc-gfxopt} is used; otherwise,
    @code{NO_REGS}.")
diff --git a/gcc/config/rs6000/rs6000-cpus.def 
b/gcc/config/rs6000/rs6000-cpus.def
index e73d9ef51f8..a7ecd38f8ee 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -64,7 +64,8 @@
                                  | OPTION_MASK_MODULO                  \
                                  | OPTION_MASK_P9_MINMAX               \
                                  | OPTION_MASK_P9_MISC                 \
-                                 | OPTION_MASK_P9_VECTOR)              \
+                                 | OPTION_MASK_P9_VECTOR               \
+                                 | OPTION_MASK_TAR)                    \
                                 & ~OTHER_FUSION_MASKS)
 
 /* Support for the IEEE 128-bit floating point hardware requires a lot of the
@@ -150,6 +151,7 @@
                                 | OPTION_MASK_RECIP_PRECISION          \
                                 | OPTION_MASK_SOFT_FLOAT               \
                                 | OPTION_MASK_STRICT_ALIGN_OPTIONAL    \
+                                | OPTION_MASK_TAR                      \
                                 | OPTION_MASK_VSX)
 
 #endif
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index f320d1762c3..1b6a9366c22 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -1226,8 +1226,8 @@ char rs6000_reg_names[][8] =
      "lr", "ctr", "ca", "ap",
   /* cr0..cr7 */
       "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",
-  /* vrsave vscr sfp */
-      "vrsave", "vscr", "sfp",
+  /* vrsave vscr sfp, tar */
+      "vrsave", "vscr", "sfp", "tar",
 };
 
 #ifdef TARGET_REGNAMES
@@ -1252,8 +1252,8 @@ static const char alt_reg_names[][8] =
     "lr",  "ctr",   "ca",   "ap",
   /* cr0..cr7 */
   "%cr0",  "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
-  /* vrsave vscr sfp */
-  "vrsave", "vscr", "sfp",
+  /* vrsave vscr sfp, tar */
+  "vrsave", "vscr", "sfp", "tar"
 };
 #endif
 
@@ -1937,9 +1937,13 @@ static int
 rs6000_hard_regno_mode_ok_uncached (int regno, machine_mode mode)
 {
   int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1;
+  bool orig_complex_p = false;
 
   if (COMPLEX_MODE_P (mode))
-    mode = GET_MODE_INNER (mode);
+    {
+      mode = GET_MODE_INNER (mode);
+      orig_complex_p = true;
+    }
 
   /* Vector pair modes need even/odd VSX register pairs.  Only allow vector
      registers.  */
@@ -2021,6 +2025,26 @@ rs6000_hard_regno_mode_ok_uncached (int regno, 
machine_mode mode)
   if (CA_REGNO_P (regno))
     return mode == Pmode || mode == SImode;
 
+  /* Restrict SPR registers to only hold an appropriate sized integer mode.  In
+     partciular, do not allow condition codes, complex values, small integers,
+     or floating point.  VRSAVE and VSCR can only hold 32-bit values.  If we
+     allow any mode other than the appropriate integer, the register allocator
+     will use the SPR registers as a temporary register.  */
+  switch (regno)
+    {
+    case VRSAVE_REGNO:
+    case VSCR_REGNO:
+      return (!orig_complex_p && mode == SImode);
+
+    case LR_REGNO:
+    case CTR_REGNO:
+    case TAR_REGNO:
+      return (!orig_complex_p && mode == Pmode);
+
+    default:
+      break;
+    }
+
   /* AltiVec only in AldyVec registers.  */
   if (ALTIVEC_REGNO_P (regno))
     return (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
@@ -2393,6 +2417,7 @@ rs6000_debug_reg_global (void)
                          "vs");
   rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr");
   rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr");
+  rs6000_debug_reg_print (TAR_REGNO, TAR_REGNO, "tar");
   rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr");
   rs6000_debug_reg_print (CA_REGNO, CA_REGNO, "ca");
   rs6000_debug_reg_print (VRSAVE_REGNO, VRSAVE_REGNO, "vrsave");
@@ -2409,6 +2434,7 @@ rs6000_debug_reg_global (void)
           "wa reg_class = %s\n"
           "we reg_class = %s\n"
           "wr reg_class = %s\n"
+          "wt reg_class = %s\n"
           "wx reg_class = %s\n"
           "wA reg_class = %s\n"
           "\n",
@@ -2417,6 +2443,7 @@ rs6000_debug_reg_global (void)
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wa]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_we]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
+          reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]],
           reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wA]]);
 
@@ -2873,6 +2900,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
 
   rs6000_regno_regclass[LR_REGNO] = LINK_REGS;
   rs6000_regno_regclass[CTR_REGNO] = CTR_REGS;
+  rs6000_regno_regclass[TAR_REGNO] = TAR_REGS;
   rs6000_regno_regclass[CA_REGNO] = NO_REGS;
   rs6000_regno_regclass[VRSAVE_REGNO] = VRSAVE_REGS;
   rs6000_regno_regclass[VSCR_REGNO] = VRSAVE_REGS;
@@ -2892,6 +2920,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   reg_class_to_reg_type[(int)VSCR_REGS] = SPR_REG_TYPE;
   reg_class_to_reg_type[(int)LINK_REGS] = SPR_REG_TYPE;
   reg_class_to_reg_type[(int)CTR_REGS] = SPR_REG_TYPE;
+  reg_class_to_reg_type[(int)TAR_REGS] = SPR_REG_TYPE;
   reg_class_to_reg_type[(int)LINK_OR_CTR_REGS] = SPR_REG_TYPE;
   reg_class_to_reg_type[(int)CR_REGS] = CR_REG_TYPE;
   reg_class_to_reg_type[(int)CR0_REGS] = CR_REG_TYPE;
@@ -3081,6 +3110,10 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   if (TARGET_DIRECT_MOVE_128)
     rs6000_constraints[RS6000_CONSTRAINT_we] = VSX_REGS;
 
+  /* Power9 adds a TAR register that can hold the target of a jump.  */
+  if (TARGET_TAR)
+    rs6000_constraints[RS6000_CONSTRAINT_wt] = TAR_REGS;
+
   /* Set up the reload helper and direct move functions.  */
   if (TARGET_VSX || TARGET_ALTIVEC)
     {
@@ -10286,6 +10319,9 @@ rs6000_conditional_register_usage (void)
        for (i = FIRST_ALTIVEC_REGNO + 20; i < FIRST_ALTIVEC_REGNO + 32; ++i)
          fixed_regs[i] = call_used_regs[i] = 1;
     }
+
+  if (TARGET_TAR)
+    fixed_regs[TAR_REGNO] = 0;
 }
 
 
@@ -14434,10 +14470,13 @@ print_operand (FILE *file, rtx x, int code)
       if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PLTSEQ)
        x = XVECEXP (x, 0, 0);
       if (!REG_P (x) || (REGNO (x) != LR_REGNO
-                        && REGNO (x) != CTR_REGNO))
+                        && REGNO (x) != CTR_REGNO
+                        && REGNO (x) != TAR_REGNO))
        output_operand_lossage ("invalid %%T value");
       else if (REGNO (x) == LR_REGNO)
        fputs ("lr", file);
+      else if (REGNO (x) == TAR_REGNO)
+       fputs ("tar", file);
       else
        fputs ("ctr", file);
       return;
@@ -24268,6 +24307,8 @@ rs6000_debugger_regno (unsigned int regno, unsigned int 
format)
        return 108;
       if (regno == CTR_REGNO)
        return 109;
+      if (regno == TAR_REGNO)
+       return 111;
       if (regno == CA_REGNO)
        return 101;  /* XER */
       /* Special handling for CR for .debug_frame: rs6000_emit_prologue has
@@ -24285,7 +24326,7 @@ rs6000_debugger_regno (unsigned int regno, unsigned int 
format)
 
       /* These do not make much sense.  */
       if (regno == FRAME_POINTER_REGNUM)
-       return 111;
+       return FIRST_PSEUDO_REGISTER;
       if (regno == ARG_POINTER_REGNUM)
        return 67;
       if (regno == 64)
@@ -24308,6 +24349,8 @@ rs6000_debugger_regno (unsigned int regno, unsigned int 
format)
     return 65;
   if (regno == CTR_REGNO)
     return 66;
+  if (regno == TAR_REGNO)
+    return 111;
   if (regno == CA_REGNO)
     return 76;  /* XER */
   if (CR_REGNO_P (regno))
@@ -24579,6 +24622,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
   { "recip-precision",         OPTION_MASK_RECIP_PRECISION,    false, true  },
   { "save-toc-indirect",       OPTION_MASK_SAVE_TOC_INDIRECT,  false, true  },
   { "string",                  0,                              false, true  },
+  { "tar",                     OPTION_MASK_TAR,                false, true  },
   { "update",                  OPTION_MASK_NO_UPDATE,          true , true  },
   { "vsx",                     OPTION_MASK_VSX,                false, true  },
 #ifdef OPTION_MASK_64BIT
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 8cfd9faf77d..9c7718a237b 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -786,7 +786,7 @@ enum data_align { align_abi, align_opt, align_both };
    Another pseudo (not included in DWARF_FRAME_REGISTERS) is soft frame
    pointer, which is eventually eliminated in favor of SP or FP.  */
 
-#define FIRST_PSEUDO_REGISTER 111
+#define FIRST_PSEUDO_REGISTER 112
 
 /* Use standard DWARF numbering for DWARF debugging information.  */
 #define DEBUGGER_REGNO(REGNO) rs6000_debugger_regno ((REGNO), 0)
@@ -822,8 +822,8 @@ enum data_align { align_abi, align_opt, align_both };
    0, 0, 1, 1,                                    \
    /* cr0..cr7 */                                 \
    0, 0, 0, 0, 0, 0, 0, 0,                        \
-   /* vrsave vscr sfp */                          \
-   1, 1, 1                                        \
+   /* vrsave vscr sfp, tar */                     \
+   1, 1, 1, 1                                     \
 }
 
 /* Like `CALL_USED_REGISTERS' except this macro doesn't require that
@@ -846,8 +846,8 @@ enum data_align { align_abi, align_opt, align_both };
    1, 1, 1, 1,                                    \
    /* cr0..cr7 */                                 \
    1, 1, 0, 0, 0, 1, 1, 1,                        \
-   /* vrsave vscr sfp */                          \
-   0, 0, 0                                        \
+   /* vrsave vscr sfp, tar */                     \
+   0, 0, 0, 1                                     \
 }
 
 #define TOTAL_ALTIVEC_REGS     (LAST_ALTIVEC_REGNO - FIRST_ALTIVEC_REGNO + 1)
@@ -876,6 +876,7 @@ enum data_align { align_abi, align_opt, align_both };
        r0              (not saved; cannot be base reg)
        r31 - r13       (saved; order given to save least number)
        r12             (not saved; if used for DImode or DFmode would use r13)
+       tar             (not saved; tar is preferred over ctr or lr)
        ctr             (not saved; when we have the choice ctr is better)
        lr              (saved)
        r1, r2, ap, ca  (fixed)
@@ -918,7 +919,7 @@ enum data_align { align_abi, align_opt, align_both };
    3, EARLY_R12 11, 0,                                         \
    31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,         \
    18, 17, 16, 15, 14, 13, LATE_R12                            \
-   97, 96,                                                     \
+   111, 97, 96,                                                        \
    1, MAYBE_R2_FIXED 99, 98,                                   \
    /* AltiVec registers.  */                                   \
    64, 65,                                                     \
@@ -1095,6 +1096,7 @@ enum reg_class
   GEN_OR_VSX_REGS,
   LINK_REGS,
   CTR_REGS,
+  TAR_REGS,
   LINK_OR_CTR_REGS,
   SPECIAL_REGS,
   SPEC_OR_GEN_REGS,
@@ -1124,6 +1126,7 @@ enum reg_class
   "GEN_OR_VSX_REGS",                                                   \
   "LINK_REGS",                                                         \
   "CTR_REGS",                                                          \
+  "TAR_REGS",                                                          \
   "LINK_OR_CTR_REGS",                                                  \
   "SPECIAL_REGS",                                                      \
   "SPEC_OR_GEN_REGS",                                                  \
@@ -1164,22 +1167,24 @@ enum reg_class
   { 0x00000000, 0x00000000, 0x00000000, 0x00000001 },                  \
   /* CTR_REGS.  */                                                     \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000002 },                  \
+  /* TAR_REGS.  */                                                     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00008000 },                  \
   /* LINK_OR_CTR_REGS.  */                                             \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000003 },                  \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00008003 },                  \
   /* SPECIAL_REGS.  */                                                 \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00001003 },                  \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00009003 },                  \
   /* SPEC_OR_GEN_REGS.  */                                             \
-  { 0xffffffff, 0x00000000, 0x00000000, 0x0000500b },                  \
+  { 0xffffffff, 0x00000000, 0x00000000, 0x0000d00b },                  \
   /* CR0_REGS.  */                                                     \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000010 },                  \
   /* CR_REGS.  */                                                      \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000ff0 },                  \
   /* NON_FLOAT_REGS.  */                                               \
-  { 0xffffffff, 0x00000000, 0x00000000, 0x00004ffb },                  \
+  { 0xffffffff, 0x00000000, 0x00000000, 0x0000cffb },                  \
   /* CA_REGS.  */                                                      \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000004 },                  \
   /* ALL_REGS.  */                                                     \
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0x00007fff }                   \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff }                   \
 }
 
 /* The same information, inverted:
@@ -1201,6 +1206,7 @@ enum r6000_reg_class_enum {
   RS6000_CONSTRAINT_wa,                /* Any VSX register */
   RS6000_CONSTRAINT_we,                /* VSX register if ISA 3.0 vector. */
   RS6000_CONSTRAINT_wr,                /* GPR register if 64-bit  */
+  RS6000_CONSTRAINT_wt,                /* TAR register.  */
   RS6000_CONSTRAINT_wx,                /* FPR register for STFIWX */
   RS6000_CONSTRAINT_wA,                /* BASE_REGS if 64-bit.  */
   RS6000_CONSTRAINT_MAX
@@ -2079,7 +2085,8 @@ extern char rs6000_reg_names[][8];        /* register 
names (0 vs. %r0).  */
   &rs6000_reg_names[108][0],   /* vrsave  */                           \
   &rs6000_reg_names[109][0],   /* vscr  */                             \
                                                                        \
-  &rs6000_reg_names[110][0]    /* sfp  */                              \
+  &rs6000_reg_names[110][0],   /* sfp  */                              \
+  &rs6000_reg_names[111][0]    /* tar  */                              \
 }
 
 /* Table of additional register names to use in user input.  */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 6642a471796..2c932061b93 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -51,6 +51,7 @@
    (VRSAVE_REGNO               108)
    (VSCR_REGNO                 109)
    (FRAME_POINTER_REGNUM       110)
+   (TAR_REGNO                  111)
   ])
 
 ;;
@@ -11527,7 +11528,7 @@
 ;; which indicates how to set cr1
 
 (define_insn "*call_indirect_nonlocal_sysv<mode>"
-  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X"))
+  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "wtc,*l,X"))
         (match_operand 1))
    (use (match_operand:SI 2 "immediate_operand" "n,n,n"))
    (clobber (reg:P LR_REGNO))]
@@ -11597,7 +11598,7 @@
 
 (define_insn "*call_value_indirect_nonlocal_sysv<mode>"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
+       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "wtc,*l,X"))
              (match_operand:P 2 "unspec_tls" "")))
    (use (match_operand:SI 3 "immediate_operand" "n,n,n"))
    (clobber (reg:P LR_REGNO))]
@@ -11714,7 +11715,7 @@
 ;; Operand4 is the offset of the stack location holding the current TOC pointer
 
 (define_insn "*call_indirect_aix<mode>"
-  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X"))
+  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "wtc,*l,X"))
         (match_operand 1))
    (use (match_operand:SI 2 "immediate_operand" "n,n,n"))
    (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>,<ptrm>"))
@@ -11733,7 +11734,7 @@
 
 (define_insn "*call_value_indirect_aix<mode>"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
+       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "wtc,*l,X"))
              (match_operand:P 2 "unspec_tls" "")))
    (use (match_operand:SI 3 "immediate_operand" "n,n,n"))
    (use (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>,<ptrm>"))
@@ -11757,7 +11758,7 @@
 ;; Operand3 is the offset of the stack location holding the current TOC pointer
 
 (define_insn "*call_indirect_elfv2<mode>"
-  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X"))
+  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "wtc,*l,X"))
         (match_operand 1))
    (use (match_operand:SI 2 "immediate_operand" "n,n,n"))
    (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" 
"n,n,n")] UNSPEC_TOCSLOT))
@@ -11774,7 +11775,7 @@
                      (const_string "8")))])
 
 (define_insn "*call_indirect_pcrel<mode>"
-  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X"))
+  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "wtc,*l,X"))
         (match_operand 1))
    (use (match_operand:SI 2 "immediate_operand" "n,n,n"))
    (clobber (reg:P LR_REGNO))]
@@ -11791,7 +11792,7 @@
 
 (define_insn "*call_value_indirect_elfv2<mode>"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
+       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "wtc,*l,X"))
              (match_operand:P 2 "unspec_tls" "")))
    (use (match_operand:SI 3 "immediate_operand" "n,n,n"))
    (set (reg:P TOC_REGNUM)
@@ -11811,7 +11812,7 @@
 
 (define_insn "*call_value_indirect_pcrel<mode>"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
+       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "wtc,*l,X"))
              (match_operand:P 2 "unspec_tls" "")))
    (use (match_operand:SI 3 "immediate_operand" "n,n,n"))
    (clobber (reg:P LR_REGNO))]
@@ -11955,7 +11956,7 @@
    (set_attr "length" "4,8")])
 
 (define_insn "*sibcall_indirect_nonlocal_sysv<mode>"
-  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X"))
+  [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "wtc,*l,X"))
         (match_operand 1))
    (use (match_operand:SI 2 "immediate_operand" "n,n,n"))
    (simple_return)]
@@ -12004,7 +12005,7 @@
 
 (define_insn "*sibcall_value_indirect_nonlocal_sysv<mode>"
   [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
+       (call (mem:SI (match_operand:P 1 "indirect_call_operand" "wtc,*l,X"))
              (match_operand 2)))
    (use (match_operand:SI 3 "immediate_operand" "n,n,n"))
    (simple_return)]
@@ -13524,14 +13525,14 @@
 
 (define_insn "*indirect_jump<mode>"
   [(set (pc)
-       (match_operand:P 0 "register_operand" "c,*l"))]
+       (match_operand:P 0 "register_operand" "wt,c,*l"))]
   "rs6000_speculate_indirect_jumps"
   "b%T0"
   [(set_attr "type" "jmpreg")])
 
 (define_insn "@indirect_jump<mode>_nospec"
-  [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))
-   (clobber (match_operand:CC 1 "cc_reg_operand" "=y,y"))]
+  [(set (pc) (match_operand:P 0 "register_operand" "wt,c,*l"))
+   (clobber (match_operand:CC 1 "cc_reg_operand" "=y,y,y"))]
   "!rs6000_speculate_indirect_jumps"
   "crset %E1\;beq%T0- %1\;b $"
   [(set_attr "type" "jmpreg")
@@ -13637,7 +13638,7 @@
 
 (define_insn "@tablejump<mode>_insn_normal"
   [(set (pc)
-       (match_operand:P 0 "register_operand" "c,*l"))
+       (match_operand:P 0 "register_operand" "wt,c,*l"))
    (use (label_ref (match_operand 1)))]
   "rs6000_speculate_indirect_jumps"
   "b%T0"
@@ -13645,9 +13646,9 @@
 
 (define_insn "@tablejump<mode>_insn_nospec"
   [(set (pc)
-       (match_operand:P 0 "register_operand" "c,*l"))
+       (match_operand:P 0 "register_operand" "wt,c,*l"))
    (use (label_ref (match_operand 1)))
-   (clobber (match_operand:CC 2 "cc_reg_operand" "=y,y"))]
+   (clobber (match_operand:CC 2 "cc_reg_operand" "=y,y,y"))]
   "!rs6000_speculate_indirect_jumps"
   "crset %E2\;beq%T0- %2\;b $"
   [(set_attr "type" "jmpreg")
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 0d71dbaf2fc..9c5d0b4f66d 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -631,6 +631,10 @@ mieee128-constant
 Target Var(TARGET_IEEE128_CONSTANT) Init(1) Save
 Generate (do not generate) code that uses the LXVKQ instruction.
 
+mtar
+Target Undocumented Mask(TAR) Var(rs6000_isa_flags)
+Allow (do not allow) use the TAR register.
+
 ; Documented parameters
 
 -param=rs6000-vect-unroll-limit=
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c 
b/gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c
index eb379a0f67d..7c1031d1b39 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c
@@ -1,8 +1,8 @@
 /* { dg-do compile { target { powerpc*-*-* } } } */
 /* { dg-skip-if "" { powerpc*-*-darwin* } } */
 /* { dg-options "-O2 --param case-values-threshold=2" } */
-/* { dg-final { scan-assembler "mtctr" } } */
-/* { dg-final { scan-assembler "bctr" } } */
+/* { dg-final { scan-assembler "mt\(ctr\|tar\)" } } */
+/* { dg-final { scan-assembler "b\(ctr\|tar\)" } } */
 
 /* Force using a dispatch table even though by default we would generate
    ifs.  */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr51513.c 
b/gcc/testsuite/gcc.target/powerpc/pr51513.c
index 1c72a75502a..43c06da8f32 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr51513.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr51513.c
@@ -1,8 +1,8 @@
 /* { dg-do compile { target { powerpc*-*-linux* } } } */
 /* { dg-options "-O2 -fjump-tables --param case-values-threshold=1" } */
 /* Verify we created a jump table.  */
-/* { dg-final { scan-assembler-times "mtctr "  1 } } */
-/* { dg-final { scan-assembler-times "bctr" 1 } } */
+/* { dg-final { scan-assembler-times "mt\(ctr\|tar\) "  1 } } */
+/* { dg-final { scan-assembler-times "b\(ctr\|tar\)" 1 } } */
 /* Verify we eliminated the range check.  */
 /* { dg-final { scan-assembler-not "cmpldi" } } */
 /* { dg-final { scan-assembler-not "cmplwi" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c 
b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c
index d6fc6a3e0b7..791537921c8 100644
--- a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c
@@ -28,5 +28,5 @@ int foo (int x)
 }
 
 /* { dg-final { scan-assembler "crset" } } */
-/* { dg-final { scan-assembler "beqctr-" } } */
+/* { dg-final { scan-assembler "beq\(ctr\|tar\)-" } } */
 /* { dg-final { scan-assembler {b \$} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c 
b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c
index 87881fb18fc..f61a4dbfad8 100644
--- a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c
@@ -47,5 +47,5 @@ int foo (int x)
 }
 
 /* { dg-final { scan-assembler "crset" } } */
-/* { dg-final { scan-assembler "beqctr-" } } */
+/* { dg-final { scan-assembler "beq\(ctr\|tar\)-" } } */
 /* { dg-final { scan-assembler {b \$} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/tar-register.c 
b/gcc/testsuite/gcc.target/powerpc/tar-register.c
new file mode 100644
index 00000000000..66e8e9ff6ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/tar-register.c
@@ -0,0 +1,34 @@
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
+
+/* Test to see if both the CTR and TAR registers are used on power10.  */
+
+long foo (long value, long n, int cond)
+{
+  long i;
+  long sum = 0;
+  void *label = ((cond > 0) ? &&label1 : &&label2);
+
+  for (i = 0; i < n; i++)
+    {
+      if (value)
+       goto *label;
+      continue;
+
+    label1:
+      sum += value;
+      continue;
+
+    label2:
+      sum -= value;
+      continue;
+    }
+
+  return sum;
+}
+
+
+/* { dg-final { scan-assembler     {\mmtctr\M} } } */
+/* { dg-final { scan-assembler     {\mmttar\M} } } */
+/* { dg-final { scan-assembler-not {\mbctr\M}  } } */
+/* { dg-final { scan-assembler     {\mbtar\M}  } } */

Reply via email to