From 183bfdafc6f1f98711c5400498a7268cc1441096 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 29 Oct 2019 08:45:44 +0000 Subject: [PATCH] [AArch64] Add FFR and FFRT registers This patch adds the First Fault Register to the AArch64 port, as well as a fake register known as the FFR Token or FFRT. The main ACLE patch explains what the FFRT does and how it works. 2019-10-29 Richard Sandiford gcc/ * config/aarch64/aarch64.md (FFR_REGNUM, FFRT_REGNUM): New constants. * config/aarch64/aarch64.h (FIRST_PSEUDO_REGISTER): Bump to FFRT_REGNUM + 1. (FFR_REGS, PR_AND_FFR_REGS): New register classes. (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add entries for them. * config/aarch64/aarch64.c (pr_or_ffr_regnum_p): New function. (aarch64_hard_regno_nregs): Handle the new register classes. (aarch64_hard_regno_mode_ok): Likewise. (aarch64_regno_regclass): Likewise. (aarch64_class_max_nregs): Likewise. (aarch64_register_move_cost): Likewise. (aarch64_conditional_register_usage): Don't treat FFR and FFRT as general register_operands. From-SVN: r277561 --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/config/aarch64/aarch64.c | 33 ++++++++++++++++++++++++++++++--- gcc/config/aarch64/aarch64.h | 14 +++++++++++++- gcc/config/aarch64/aarch64.md | 4 ++++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b6eeeaddc8e..a80a8e1090c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2019-10-29 Richard Sandiford + + * config/aarch64/aarch64.md (FFR_REGNUM, FFRT_REGNUM): New constants. + * config/aarch64/aarch64.h (FIRST_PSEUDO_REGISTER): Bump to + FFRT_REGNUM + 1. + (FFR_REGS, PR_AND_FFR_REGS): New register classes. + (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add entries for them. + * config/aarch64/aarch64.c (pr_or_ffr_regnum_p): New function. + (aarch64_hard_regno_nregs): Handle the new register classes. + (aarch64_hard_regno_mode_ok): Likewise. + (aarch64_regno_regclass): Likewise. + (aarch64_class_max_nregs): Likewise. + (aarch64_register_move_cost): Likewise. + (aarch64_conditional_register_usage): Don't treat FFR and FFRT + as general register_operands. + 2019-10-29 Martin Liska * ggc-common.c: One can't subtract unsigned types diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index a19494e9469..466910dabce 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1426,6 +1426,14 @@ aarch64_err_no_fpadvsimd (machine_mode mode) " vector types", "+nofp"); } +/* Return true if REGNO is P0-P15 or one of the special FFR-related + registers. */ +inline bool +pr_or_ffr_regnum_p (unsigned int regno) +{ + return PR_REGNUM_P (regno) || regno == FFR_REGNUM || regno == FFRT_REGNUM; +} + /* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS. The register allocator chooses POINTER_AND_FP_REGS if FP_REGS and GENERAL_REGS have the same cost - even if POINTER_AND_FP_REGS has a much @@ -1810,6 +1818,8 @@ aarch64_hard_regno_nregs (unsigned regno, machine_mode mode) case PR_REGS: case PR_LO_REGS: case PR_HI_REGS: + case FFR_REGS: + case PR_AND_FFR_REGS: return 1; default: return CEIL (lowest_size, UNITS_PER_WORD); @@ -1836,10 +1846,10 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode) return false; if (vec_flags & VEC_SVE_PRED) - return PR_REGNUM_P (regno); + return pr_or_ffr_regnum_p (regno); - if (PR_REGNUM_P (regno)) - return 0; + if (pr_or_ffr_regnum_p (regno)) + return false; if (regno == SP_REGNUM) /* The purpose of comparing with ptr_mode is to support the @@ -9163,6 +9173,9 @@ aarch64_regno_regclass (unsigned regno) if (PR_REGNUM_P (regno)) return PR_LO_REGNUM_P (regno) ? PR_LO_REGS : PR_HI_REGS; + if (regno == FFR_REGNUM || regno == FFRT_REGNUM) + return FFR_REGS; + return NO_REGS; } @@ -9461,6 +9474,8 @@ aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode) case PR_REGS: case PR_LO_REGS: case PR_HI_REGS: + case FFR_REGS: + case PR_AND_FFR_REGS: return 1; case NO_REGS: @@ -11641,6 +11656,14 @@ aarch64_register_move_cost (machine_mode mode, if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS) from = GENERAL_REGS; + /* Make RDFFR very expensive. In particular, if we know that the FFR + contains a PTRUE (e.g. after a SETFFR), we must never use RDFFR + as a way of obtaining a PTRUE. */ + if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL + && hard_reg_set_subset_p (reg_class_contents[from_i], + reg_class_contents[FFR_REGS])) + return 80; + /* Moving between GPR and stack cost is the same as GP2GP. */ if ((from == GENERAL_REGS && to == STACK_REG) || (to == GENERAL_REGS && from == STACK_REG)) @@ -14802,6 +14825,10 @@ aarch64_conditional_register_usage (void) call_used_regs[i] = 1; } + /* Only allow the FFR and FFRT to be accessed via special patterns. */ + CLEAR_HARD_REG_BIT (operand_reg_set, FFR_REGNUM); + CLEAR_HARD_REG_BIT (operand_reg_set, FFRT_REGNUM); + /* When tracking speculation, we need a couple of call-clobbered registers to track the speculation state. It would be nice to just use IP0 and IP1, but currently there are numerous places that just diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index b68594d10de..070fdc94098 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -366,6 +366,9 @@ extern unsigned aarch64_architecture_version; P0-P7 Predicate low registers: valid in all predicate contexts P8-P15 Predicate high registers: used as scratch space + FFR First Fault Register, a fixed-use SVE predicate register + FFRT FFR token: a fake register used for modelling dependencies + VG Pseudo "vector granules" register VG is the number of 64-bit elements in an SVE vector. We define @@ -386,6 +389,7 @@ extern unsigned aarch64_architecture_version; 1, 1, 1, 1, /* SFP, AP, CC, VG */ \ 0, 0, 0, 0, 0, 0, 0, 0, /* P0 - P7 */ \ 0, 0, 0, 0, 0, 0, 0, 0, /* P8 - P15 */ \ + 1, 1 /* FFR and FFRT */ \ } /* X30 is marked as caller-saved which is in line with regular function call @@ -408,6 +412,7 @@ extern unsigned aarch64_architecture_version; 1, 1, 1, 1, /* SFP, AP, CC, VG */ \ 1, 1, 1, 1, 1, 1, 1, 1, /* P0 - P7 */ \ 1, 1, 1, 1, 1, 1, 1, 1, /* P8 - P15 */ \ + 1, 1 /* FFR and FFRT */ \ } #define REGISTER_NAMES \ @@ -423,6 +428,7 @@ extern unsigned aarch64_architecture_version; "sfp", "ap", "cc", "vg", \ "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", \ "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + "ffr", "ffrt" \ } /* Generate the register aliases for core register N */ @@ -471,7 +477,7 @@ extern unsigned aarch64_architecture_version; #define FRAME_POINTER_REGNUM SFP_REGNUM #define STACK_POINTER_REGNUM SP_REGNUM #define ARG_POINTER_REGNUM AP_REGNUM -#define FIRST_PSEUDO_REGISTER (P15_REGNUM + 1) +#define FIRST_PSEUDO_REGISTER (FFRT_REGNUM + 1) /* The number of (integer) argument register available. */ #define NUM_ARG_REGS 8 @@ -601,6 +607,8 @@ enum reg_class PR_LO_REGS, PR_HI_REGS, PR_REGS, + FFR_REGS, + PR_AND_FFR_REGS, ALL_REGS, LIM_REG_CLASSES /* Last */ }; @@ -621,6 +629,8 @@ enum reg_class "PR_LO_REGS", \ "PR_HI_REGS", \ "PR_REGS", \ + "FFR_REGS", \ + "PR_AND_FFR_REGS", \ "ALL_REGS" \ } @@ -638,6 +648,8 @@ enum reg_class { 0x00000000, 0x00000000, 0x00000ff0 }, /* PR_LO_REGS */ \ { 0x00000000, 0x00000000, 0x000ff000 }, /* PR_HI_REGS */ \ { 0x00000000, 0x00000000, 0x000ffff0 }, /* PR_REGS */ \ + { 0x00000000, 0x00000000, 0x00300000 }, /* FFR_REGS */ \ + { 0x00000000, 0x00000000, 0x003ffff0 }, /* PR_AND_FFR_REGS */ \ { 0xffffffff, 0xffffffff, 0x000fffff } /* ALL_REGS */ \ } diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index f127057bb60..3778109cb62 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -107,6 +107,10 @@ (P13_REGNUM 81) (P14_REGNUM 82) (P15_REGNUM 83) + (FFR_REGNUM 84) + ;; "FFR token": a fake register used for representing the scheduling + ;; restrictions on FFR-related operations. + (FFRT_REGNUM 85) ;; Scratch register used by stack clash protection to calculate ;; SVE CFA offsets during probing. (STACK_CLASH_SVE_CFA_REGNUM 11) -- 2.30.2