https://gcc.gnu.org/g:c70a26f1539068db09f2a456df2784ad1429a181
commit c70a26f1539068db09f2a456df2784ad1429a181 Author: Michael Meissner <meiss...@linux.ibm.com> Date: Fri Sep 13 03:42:34 2024 -0400 Add support for the TAR register. 2024-09-13 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 369a7b75042d..14f0465d7ae5 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 e73d9ef51f8d..a7ecd38f8eef 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 aa67e7256bb9..2a8c3d7964c3 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 8cfd9faf77dc..9c7718a237b4 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 6642a4717963..2c932061b93a 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 0d71dbaf2fc1..9c5d0b4f66df 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 eb379a0f67d4..7c1031d1b396 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 1c72a75502a1..43c06da8f320 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 d6fc6a3e0b74..791537921c87 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 87881fb18fc5..f61a4dbfad83 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 000000000000..66e8e9ff6ff5 --- /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} } } */